Spaces:
Sleeping
Sleeping
File size: 14,310 Bytes
23e009d b36d2b4 23e009d 7702100 23e009d 7702100 23e009d 7702100 23e009d 7702100 23e009d 7702100 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 |
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)
|