Naz786's picture
Update app.py
7702100 verified
import difflib
import streamlit as st
from groq import Groq
import os
# --- Set page config FIRST! ---
st.set_page_config(page_title="AI Code Assistant", layout="wide")
# --- Custom CSS for Professional Look ---
st.markdown("""
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap');
html, body, [class*="css"] {
font-family: 'Inter', sans-serif;
background-color: #f7f9fb;
}
.stApp {
background-color: #f7f9fb;
}
.stSidebar {
background-color: #22304a !important;
}
.stButton>button {
background-color: #22304a;
color: #fff;
border-radius: 6px;
border: none;
font-weight: 600;
padding: 0.5rem 1.5rem;
margin-top: 0.5rem;
margin-bottom: 0.5rem;
transition: background 0.2s;
}
.stButton>button:hover {
background-color: #1a2333;
color: #fff;
}
.stTextInput>div>div>input, .stTextArea>div>textarea {
background: #fff;
border: 1px solid #d1d5db;
border-radius: 6px;
color: #22304a;
font-size: 1rem;
}
.stDownloadButton>button {
background-color: #22304a;
color: #fff;
border-radius: 6px;
border: none;
font-weight: 600;
padding: 0.5rem 1.5rem;
margin-top: 0.5rem;
margin-bottom: 0.5rem;
transition: background 0.2s;
}
.stDownloadButton>button:hover {
background-color: #1a2333;
color: #fff;
}
.stExpanderHeader {
font-weight: 600;
color: #22304a;
font-size: 1.1rem;
}
.stMarkdown {
color: #22304a;
}
.stAlert {
border-radius: 6px;
}
</style>
""", unsafe_allow_html=True)
# --- Groq API Setup ---
GROQ_API_KEY = os.environ.get("GROQ_API_KEY")
if not GROQ_API_KEY:
st.error("GROQ_API_KEY environment variable not set. Please set it in your Hugging Face Space secrets.")
st.stop()
client = Groq(api_key=GROQ_API_KEY)
# --- Blackbox AI Agent Setup ---
BLACKBOX_API_KEY = os.environ.get("BLACKBOX_API_KEY")
if not BLACKBOX_API_KEY:
st.error("BLACKBOX_API_KEY environment variable not set. Please set it in your Hugging Face Space secrets.")
st.stop()
# Chat history management
if "chat_history" not in st.session_state:
st.session_state.chat_history = []
def groq_api_call(prompt):
chat_completion = client.chat.completions.create(
messages=[{"role": "user", "content": prompt}],
model="llama3-70b-8192",
)
return chat_completion.choices[0].message.content
def blackbox_ai_call(messages):
# This is a placeholder for actual Blackbox AI API call using BLACKBOX_API_KEY
# For demonstration, we simulate a response by echoing last user message
last_user_message = messages[-1]["content"] if messages else ""
response = f"Blackbox AI response to: {last_user_message}"
return response
def get_diff_html(original, modified):
original_lines = original.splitlines()
modified_lines = modified.splitlines()
differ = difflib.HtmlDiff(tabsize=4, wrapcolumn=80)
return differ.make_table(original_lines, modified_lines, "Original", "Modified", context=True, numlines=2)
def code_complexity(code):
lines = code.count('\n') + 1
functions = code.count('def ')
classes = code.count('class ')
comments = code.count('#')
return f"Lines: {lines}, Functions: {functions}, Classes: {classes}, Comments: {comments}"
def detect_code_type(code, programming_language):
backend_keywords = [
'flask', 'django', 'express', 'fastapi', 'spring', 'controller', 'api', 'server', 'database', 'sql', 'mongoose'
]
frontend_keywords = [
'react', 'vue', 'angular', 'component', 'html', 'css', 'document.getelementbyid', 'window.', 'render', 'jsx',
'<html', '<body', '<script', '<div', 'getelementbyid', 'queryselector', 'addeventlistener', 'innerhtml'
]
data_science_keywords = [
'pandas', 'numpy', 'sklearn', 'matplotlib', 'seaborn', 'plt', 'train_test_split', 'randomforestclassifier', 'classification_report'
]
code_lower = code.lower()
if any(word in code_lower for word in data_science_keywords):
return 'data_science'
if any(word in code_lower for word in frontend_keywords):
return 'frontend'
if programming_language.lower() in ['python', 'java', 'c#']:
if any(word in code_lower for word in backend_keywords):
return 'backend'
if programming_language.lower() in ['javascript', 'typescript', 'java', 'c#']:
if any(word in code_lower for word in frontend_keywords):
return 'frontend'
if programming_language.lower() in ['python', 'java', 'c#']:
return 'backend'
if programming_language.lower() in ['javascript', 'typescript']:
return 'frontend'
return 'unknown'
def code_matches_language(code: str, language: str) -> bool:
code = code.strip().lower()
if language.lower() == "python":
return "def " in code or "import " in code or ".py" in code
if language.lower() == "c++":
return "#include" in code or "int main" in code or ".cpp" in code or "std::" in code
if language.lower() == "java":
return "public class" in code or "public static void main" in code or ".java" in code
if language.lower() == "c#":
return "using system" in code or "namespace" in code or ".cs" in code
if language.lower() == "javascript":
return "function " in code or "const " in code or "let " in code or "var " in code or ".js" in code
if language.lower() == "typescript":
return "function " in code or "const " in code or "let " in code or "var " in code or ": string" in code or ".ts" in code
if language.lower() == "html":
return "<html" in code or "<!doctype html" in code
return True # fallback
def agentic_workflow(code, skill_level, programming_language, explanation_language, user_role):
timeline = []
suggestions = []
explain_prompt = (
f"Explain the following {programming_language} code line by line or function by function "
f"for a {skill_level.lower()} {user_role} in {explanation_language}:\n{code}"
)
explanation = groq_api_call(explain_prompt)
timeline.append({
"step": "Explain",
"description": "Step-by-step explanation of your code.",
"output": explanation,
"code": code
})
suggestions.append("Refactor your code for better readability and performance.")
refactor_prompt = (
f"Refactor the following {programming_language} code for better readability, performance, and structure. "
f"Explain what changes you made and why, for a {skill_level.lower()} {user_role} in {explanation_language}:\n{code}"
)
refactor_response = groq_api_call(refactor_prompt)
if "```" in refactor_response:
parts = refactor_response.split("```")
refactor_explanation = parts[0].strip()
refactored_code = ""
for i in range(1, len(parts)):
if parts[i].strip().startswith(programming_language.lower()):
refactored_code = parts[i].strip().split('\n', 1)[1] if '\n' in parts[i] else ""
break
elif i == 1:
refactored_code = parts[i].strip().split('\n', 1)[1] if '\n' in parts[i] else ""
if not refactored_code:
refactored_code = refactor_response.strip()
else:
refactor_explanation = "Refactored code below."
refactored_code = refactor_response.strip()
timeline.append({
"step": "Refactor",
"description": refactor_explanation,
"output": refactored_code,
"code": refactored_code
})
suggestions.append("Review the refactored code for best practices and improvements.")
review_prompt = (
f"Provide a code review for the following {programming_language} code. "
f"Include feedback on best practices, code smells, optimization, and security issues, for a {skill_level.lower()} {user_role} in {explanation_language}:\n{refactored_code}"
)
review_feedback = groq_api_call(review_prompt)
timeline.append({
"step": "Review",
"description": "AI code review and feedback.",
"output": review_feedback,
"code": refactored_code
})
suggestions.append("Generate unit tests for your code.")
test_prompt = (
f"Write unit tests for the following {programming_language} code. "
f"Use pytest style and cover all functions. For a {skill_level.lower()} {user_role} in {explanation_language}:\n{refactored_code}"
)
test_code = groq_api_call(test_prompt)
timeline.append({
"step": "Test Generation",
"description": "AI-generated unit tests for your code.",
"output": test_code,
"code": test_code
})
suggestions.append("Run the generated tests in your local environment.")
return timeline, suggestions
st.markdown(
"<h2 style='text-align: center; color: #22304a; font-weight: 600; margin-bottom: 0.5em;'>AI Code Assistant</h2>",
unsafe_allow_html=True
)
with st.sidebar:
st.title("Settings")
programming_language = st.selectbox(
"Programming Language",
["Python", "C++", "Java", "C#", "JavaScript", "TypeScript", "HTML"]
)
explanation_language = st.selectbox(
"Explanation Language",
["English", "Urdu", "Chinese", "Spanish"]
)
skill_level = st.selectbox("Skill Level", ["Beginner", "Intermediate", "Expert"])
user_role = st.selectbox(
"Choose Role",
["Data Scientist", "Backend Developer", "Frontend Developer", "Student"]
)
st.markdown("---")
st.markdown("<span style='color:#fff;'>Powered by <b>BLACKBOX.AI</b></span>", unsafe_allow_html=True)
if "code" not in st.session_state:
st.session_state.code = ""
if "timeline" not in st.session_state:
st.session_state.timeline = []
if "suggestions" not in st.session_state:
st.session_state.suggestions = []
if "chat_history" not in st.session_state:
st.session_state.chat_history = []
col1, col2 = st.columns([2, 3], gap="large")
with col1:
st.subheader(f"{programming_language} Code")
uploaded_file = st.file_uploader(f"Upload .{programming_language.lower()} file", type=[programming_language.lower()])
code_input = st.text_area(
"Paste or edit your code here:",
height=300,
value=st.session_state.code,
key="main_code_input"
)
if uploaded_file is not None:
code = uploaded_file.read().decode("utf-8")
st.session_state.code = code
st.success("File uploaded successfully.")
elif code_input:
st.session_state.code = code_input
st.markdown(f"<b>Complexity:</b> {code_complexity(st.session_state.code)}", unsafe_allow_html=True)
st.markdown("---")
st.markdown("#### Agent Suggestions")
for suggestion in st.session_state.suggestions[-3:]:
st.markdown(f"- {suggestion}")
st.markdown("---")
st.markdown("#### Download Full Report")
if st.session_state.timeline:
report = ""
for step in st.session_state.timeline:
report += f"## {step['step']}\n{step['description']}\n\n{step['output']}\n\n"
st.download_button("Download Report", report, file_name="ai_code_assistant_report.txt")
with col2:
st.subheader("Agentic Workflow")
if st.button("Run Full AI Agent Workflow"):
if not st.session_state.code.strip():
st.warning("Please enter or upload code first.")
else:
# Language check
if not code_matches_language(st.session_state.code, programming_language):
st.error(f"It looks like you provided code in a different language. Please provide {programming_language} code.")
else:
code_type = detect_code_type(st.session_state.code, programming_language)
# Role/code type enforcement
if code_type == "data_science" and user_role != "Data Scientist":
st.error("It looks like you provided data science code. Please select 'Data Scientist' as your role.")
elif code_type == "frontend" and user_role != "Frontend Developer":
st.error("It looks like you provided frontend code. Please select 'Frontend Developer' as your role.")
elif code_type == "backend" and user_role != "Backend Developer":
st.error("It looks like you provided backend code. Please select 'Backend Developer' as your role.")
elif code_type == "unknown":
st.warning("Could not determine the code type. Please make sure your code is complete and clear.")
else:
with st.spinner("AI Agent is working through all steps..."):
timeline, suggestions = agentic_workflow(
st.session_state.code,
skill_level,
programming_language,
explanation_language,
user_role
)
st.session_state.timeline = timeline
st.session_state.suggestions = suggestions
st.success("Agentic workflow complete. See timeline below.")
# Chatbox with history using Blackbox AI agent
st.subheader("Chat with Blackbox AI Agent")
user_input = st.text_input("Enter your message:", key="chat_input")
if user_input:
st.session_state.chat_history.append({"role": "user", "content": user_input})
response = blackbox_ai_call(st.session_state.chat_history)
st.session_state.chat_history.append({"role": "assistant", "content": response})
for chat in st.session_state.chat_history:
if chat["role"] == "user":
st.markdown(f"**You:** {chat['content']}")
else:
st.markdown(f"**Blackbox AI:** {chat['content']}")
st.markdown("---")
st.markdown('<div style="text-align: center; color: #22304a; font-size: 1rem; margin-top: 2em;">Powered by <b>BLACKBOX.AI</b></div>', unsafe_allow_html=True)