import streamlit as st import difflib import os import re import hashlib from groq import Groq # --- Page config --- st.set_page_config(page_title="π AI Assistant with Workflow + Semantic Search", layout="wide") # --- Groq API Setup --- GROQ_API_KEY = os.environ.get("GROQ_API_KEY") if not GROQ_API_KEY: st.error("β Please set your GROQ_API_KEY environment variable.") st.stop() client = Groq(api_key=GROQ_API_KEY) # --- Cache for embeddings --- embedding_cache = {} def get_embedding(text): key = hashlib.sha256(text.encode()).hexdigest() if key in embedding_cache: return embedding_cache[key] embedding = [ord(c) % 100 / 100 for c in text[:512]] embedding_cache[key] = embedding return embedding def cosine_similarity(vec1, vec2): dot = sum(a*b for a,b in zip(vec1, vec2)) norm1 = sum(a*a for a in vec1) ** 0.5 norm2 = sum(b*b for b in vec2) ** 0.5 return dot / (norm1 * norm2 + 1e-8) def split_code_into_chunks(code, lang): if lang.lower() == "python": pattern = r'(def\s+\w+\(.*?\):|class\s+\w+\(?.*?\)?:)' splits = re.split(pattern, code) chunks = [] for i in range(1, len(splits), 2): header = splits[i] body = splits[i+1] if (i+1) < len(splits) else "" chunks.append(header + body) return chunks if chunks else [code] else: return [code] def groq_call(prompt): resp = client.chat.completions.create( messages=[{"role": "user", "content": prompt}], model="llama3-70b-8192", ) return resp.choices[0].message.content def semantic_search_improved(code, question, lang, skill, role, explain_lang): chunks = split_code_into_chunks(code, lang) question_emb = get_embedding(question) scored_chunks = [] for chunk in chunks: emb = get_embedding(chunk) score = cosine_similarity(question_emb, emb) scored_chunks.append((score, chunk)) scored_chunks.sort(key=lambda x: x[0], reverse=True) top_chunks = [c for _, c in scored_chunks[:3]] combined_code = "\n\n".join(top_chunks) prompt = ( f"You are a friendly and insightful {lang} expert helping a {skill} {role}.\n" f"Based on these relevant code snippets:\n{combined_code}\n" f"Answer this question in {explain_lang}:\n{question}\n" f"Explain which parts handle the question and how to modify them if needed." ) return groq_call(prompt) def error_detection_and_fixes(refactored_code, lang, skill, role, explain_lang): prompt = ( f"You are a senior {lang} developer. Analyze this code for bugs, security flaws, " f"and performance issues. Suggest fixes with explanations in {explain_lang}:\n\n{refactored_code}" ) return groq_call(prompt) def agentic_workflow(code, skill_level, programming_language, explanation_language, user_role): timeline = [] suggestions = [] # Explanation explain_prompt = ( f"You are a friendly and insightful {programming_language} expert helping a {skill_level} {user_role}. " f"Explain this code in {explanation_language} with clear examples, analogies, and why each part matters:\n\n{code}" ) explanation = groq_call(explain_prompt) timeline.append({"step": "Explain", "description": "Detailed explanation", "output": explanation, "code": code}) suggestions.append("Consider refactoring your code to improve readability and performance.") # Refactor refactor_prompt = ( f"Refactor this {programming_language} code. Explain the changes like a mentor helping a {skill_level} {user_role}. " f"Include best practices and improvements:\n\n{code}" ) refactor_response = groq_call(refactor_prompt) if "```" in refactor_response: parts = refactor_response.split("```") refactored_code = "" for part in parts: if part.strip().startswith(programming_language.lower()): refactored_code = part.strip().split('\n', 1)[1] if '\n' in part else "" break if not refactored_code: refactored_code = refactor_response else: refactored_code = refactor_response timeline.append({"step": "Refactor", "description": "Refactored code with improvements", "output": refactored_code, "code": refactored_code}) suggestions.append("Review the refactored code and adapt it to your style or project needs.") # Review review_prompt = ( f"As a senior {programming_language} developer, review the refactored code. " f"Give constructive feedback on strengths, weaknesses, performance, security, and improvements in {explanation_language}:\n\n{refactored_code}" ) review = groq_call(review_prompt) timeline.append({"step": "Review", "description": "Code review and suggestions", "output": review, "code": refactored_code}) suggestions.append("Incorporate review feedback for cleaner, robust code.") # Error detection & fixes errors = error_detection_and_fixes(refactored_code, programming_language, skill_level, user_role, explanation_language) timeline.append({"step": "Error Detection", "description": "Bugs, security, performance suggestions", "output": errors, "code": refactored_code}) suggestions.append("Apply fixes to improve code safety and performance.") # Test generation test_prompt = ( f"Write clear, effective unit tests for this {programming_language} code. " f"Explain what each test does in {explanation_language}, for a {skill_level} {user_role}:\n\n{refactored_code}" ) tests = groq_call(test_prompt) timeline.append({"step": "Test Generation", "description": "Generated unit tests", "output": tests, "code": tests}) suggestions.append("Run generated tests locally to validate changes.") return timeline, suggestions def get_inline_diff_html(original, modified): differ = difflib.HtmlDiff(tabsize=4, wrapcolumn=80) html = differ.make_table( original.splitlines(), modified.splitlines(), "Original", "Refactored", context=True, numlines=2 ) return f'