|
import gradio as gr |
|
from langgraph.graph import StateGraph |
|
from typing import TypedDict, Annotated, List, Dict |
|
from langgraph.graph.message import add_messages |
|
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage |
|
import json |
|
import requests |
|
import os |
|
from dotenv import load_dotenv |
|
import time |
|
|
|
|
|
load_dotenv() |
|
|
|
|
|
class State(TypedDict): |
|
messages: Annotated[list[SystemMessage | HumanMessage | AIMessage], add_messages] |
|
current_step: str |
|
code: str |
|
style_analysis: Dict |
|
security_analysis: Dict |
|
performance_analysis: Dict |
|
architecture_analysis: Dict |
|
final_recommendations: Dict |
|
|
|
def call_huggingface_api(prompt: str, max_retries=3) -> Dict: |
|
"""Call Hugging Face API with retry logic and proper error handling.""" |
|
api_key = os.getenv("HUGGINGFACE_API_KEY") |
|
if not api_key: |
|
raise ValueError("HUGGINGFACE_API_KEY not found in environment variables") |
|
|
|
|
|
API_URL = "https://api-inference.huggingface.co/models/mistralai/Mixtral-8x7B-Instruct-v0.1" |
|
headers = {"Authorization": f"Bearer {api_key}"} |
|
|
|
for attempt in range(max_retries): |
|
try: |
|
response = requests.post( |
|
API_URL, |
|
headers=headers, |
|
json={ |
|
"inputs": prompt, |
|
"parameters": { |
|
"max_new_tokens": 1000, |
|
"temperature": 0.7, |
|
"top_p": 0.95, |
|
"return_full_text": False |
|
} |
|
} |
|
) |
|
|
|
if response.status_code == 200: |
|
result = response.json() |
|
if isinstance(result, list) and len(result) > 0: |
|
|
|
text = result[0].get('generated_text', '') |
|
|
|
try: |
|
|
|
if "```json" in text: |
|
json_str = text.split("```json")[1].split("```")[0].strip() |
|
else: |
|
json_str = text.strip() |
|
return json.loads(json_str) |
|
except json.JSONDecodeError: |
|
return {"error": "Failed to parse JSON from response", "raw_text": text} |
|
|
|
|
|
if response.status_code == 503: |
|
wait_time = 2 ** attempt |
|
time.sleep(wait_time) |
|
continue |
|
|
|
except Exception as e: |
|
if attempt == max_retries - 1: |
|
return {"error": f"API call failed: {str(e)}"} |
|
time.sleep(2 ** attempt) |
|
|
|
return {"error": "Maximum retries reached"} |
|
|
|
def analyze_code_style(state: State) -> dict: |
|
"""Analyze code style and best practices.""" |
|
code = state["code"] |
|
prompt = f"""You are a senior code reviewer focused on code style and best practices. Analyze this code: |
|
|
|
{code} |
|
|
|
Focus on: |
|
1. Code readability and clarity |
|
2. Adherence to common style guides |
|
3. Variable/function naming |
|
4. Code organization |
|
5. Documentation quality |
|
|
|
Provide your response in JSON format with these exact keys: |
|
{{ |
|
"issues": ["list of identified style issues"], |
|
"suggestions": ["list of improvement suggestions"], |
|
"overall_rating": "1-10 score as a number", |
|
"primary_concerns": ["list of main style concerns"] |
|
}}""" |
|
|
|
analysis = call_huggingface_api(prompt) |
|
if "error" in analysis: |
|
analysis = { |
|
"issues": ["Error analyzing code style"], |
|
"suggestions": ["Try again later"], |
|
"overall_rating": 0, |
|
"primary_concerns": ["Analysis failed"] |
|
} |
|
|
|
messages = state["messages"] + [AIMessage(content="Completed code style analysis")] |
|
return {**state, "messages": messages, "style_analysis": analysis, "current_step": "security"} |
|
|
|
def analyze_security(state: State) -> dict: |
|
"""Analyze security vulnerabilities.""" |
|
code = state["code"] |
|
prompt = f"""You are a security expert. Analyze this code for security vulnerabilities: |
|
|
|
{code} |
|
|
|
Focus on: |
|
1. Input validation |
|
2. Authentication/Authorization |
|
3. Data exposure |
|
4. Common vulnerabilities |
|
5. Security best practices |
|
|
|
Provide your response in JSON format with these exact keys: |
|
{{ |
|
"vulnerabilities": ["list of potential security issues"], |
|
"risk_levels": {{"vulnerability": "risk level"}}, |
|
"recommendations": ["list of security improvements"], |
|
"overall_security_score": "1-10 score as a number" |
|
}}""" |
|
|
|
analysis = call_huggingface_api(prompt) |
|
if "error" in analysis: |
|
analysis = { |
|
"vulnerabilities": ["Error analyzing security"], |
|
"risk_levels": {"Error": "High"}, |
|
"recommendations": ["Try again later"], |
|
"overall_security_score": 0 |
|
} |
|
|
|
messages = state["messages"] + [AIMessage(content="Completed security analysis")] |
|
return {**state, "messages": messages, "security_analysis": analysis, "current_step": "performance"} |
|
|
|
def analyze_performance(state: State) -> dict: |
|
"""Analyze code performance.""" |
|
code = state["code"] |
|
prompt = f"""You are a performance optimization expert. Analyze this code for performance issues: |
|
|
|
{code} |
|
|
|
Focus on: |
|
1. Time complexity |
|
2. Space complexity |
|
3. Resource usage |
|
4. Bottlenecks |
|
5. Optimization opportunities |
|
|
|
Provide your response in JSON format with these exact keys: |
|
{{ |
|
"bottlenecks": ["list of identified performance bottlenecks"], |
|
"complexity_analysis": {{ |
|
"time_complexity": "Big O notation", |
|
"space_complexity": "Big O notation", |
|
"critical_sections": ["list of critical sections"] |
|
}}, |
|
"optimization_suggestions": ["list of performance improvements"], |
|
"performance_score": "1-10 score as a number" |
|
}}""" |
|
|
|
analysis = call_huggingface_api(prompt) |
|
if "error" in analysis: |
|
analysis = { |
|
"bottlenecks": ["Error analyzing performance"], |
|
"complexity_analysis": { |
|
"time_complexity": "Unknown", |
|
"space_complexity": "Unknown", |
|
"critical_sections": [] |
|
}, |
|
"optimization_suggestions": ["Try again later"], |
|
"performance_score": 0 |
|
} |
|
|
|
messages = state["messages"] + [AIMessage(content="Completed performance analysis")] |
|
return {**state, "messages": messages, "performance_analysis": analysis, "current_step": "architecture"} |
|
|
|
def analyze_architecture(state: State) -> dict: |
|
"""Analyze code architecture patterns.""" |
|
code = state["code"] |
|
prompt = f"""You are a software architect. Analyze this code's architectural patterns: |
|
|
|
{code} |
|
|
|
Focus on: |
|
1. Design patterns used |
|
2. Code modularity |
|
3. Component relationships |
|
4. Architectural anti-patterns |
|
5. System design principles |
|
|
|
Provide your response in JSON format with these exact keys: |
|
{{ |
|
"patterns_identified": ["list of design patterns found"], |
|
"architectural_issues": ["list of architectural concerns"], |
|
"improvement_suggestions": ["list of architectural improvements"], |
|
"architecture_score": "1-10 score as a number" |
|
}}""" |
|
|
|
analysis = call_huggingface_api(prompt) |
|
if "error" in analysis: |
|
analysis = { |
|
"patterns_identified": ["Error analyzing architecture"], |
|
"architectural_issues": ["Analysis failed"], |
|
"improvement_suggestions": ["Try again later"], |
|
"architecture_score": 0 |
|
} |
|
|
|
messages = state["messages"] + [AIMessage(content="Completed architecture analysis")] |
|
return {**state, "messages": messages, "architecture_analysis": analysis, "current_step": "recommendations"} |
|
|
|
def generate_final_recommendations(state: State) -> dict: |
|
"""Generate final recommendations based on all analyses.""" |
|
code = state["code"] |
|
prompt = f"""Analyze all previous results and provide final recommendations for this code: |
|
|
|
Style Analysis: {json.dumps(state.get('style_analysis', {}))} |
|
Security Analysis: {json.dumps(state.get('security_analysis', {}))} |
|
Performance Analysis: {json.dumps(state.get('performance_analysis', {}))} |
|
Architecture Analysis: {json.dumps(state.get('architecture_analysis', {}))} |
|
|
|
Provide your response in JSON format with these exact keys: |
|
{{ |
|
"critical_issues": ["list of most critical issues"], |
|
"priority_improvements": ["list of high-priority improvements"], |
|
"quick_wins": ["list of easy-to-implement improvements"], |
|
"long_term_suggestions": ["list of long-term improvements"], |
|
"overall_health_score": "1-10 score as a number" |
|
}}""" |
|
|
|
recommendations = call_huggingface_api(prompt) |
|
if "error" in recommendations: |
|
recommendations = { |
|
"critical_issues": ["Error generating recommendations"], |
|
"priority_improvements": ["Try again later"], |
|
"quick_wins": [], |
|
"long_term_suggestions": [], |
|
"overall_health_score": 0 |
|
} |
|
|
|
messages = state["messages"] + [AIMessage(content="Generated final recommendations")] |
|
return {**state, "messages": messages, "final_recommendations": recommendations, "current_step": "end"} |
|
|
|
def format_output(state: State) -> str: |
|
"""Format the analysis results into a readable output.""" |
|
output = """π Code Analysis Report |
|
|
|
π¨ Style & Best Practices |
|
""" |
|
style = state.get("style_analysis", {}) |
|
output += f"Rating: {style.get('overall_rating', 'N/A')}/10\n" |
|
output += "Issues:\n" + "\n".join([f"β’ {issue}" for issue in style.get("issues", [])]) + "\n\n" |
|
|
|
output += """π Security Analysis |
|
""" |
|
security = state.get("security_analysis", {}) |
|
output += f"Score: {security.get('overall_security_score', 'N/A')}/10\n" |
|
vulnerabilities = security.get("vulnerabilities", []) |
|
risk_levels = security.get("risk_levels", {}) |
|
output += "Vulnerabilities:\n" + "\n".join([f"β’ {v} ({risk_levels.get(v, 'Unknown')})" for v in vulnerabilities]) + "\n\n" |
|
|
|
output += """β‘ Performance Analysis |
|
""" |
|
perf = state.get("performance_analysis", {}) |
|
output += f"Score: {perf.get('performance_score', 'N/A')}/10\n" |
|
output += "Bottlenecks:\n" + "\n".join([f"β’ {b}" for b in perf.get("bottlenecks", [])]) + "\n\n" |
|
|
|
output += """ποΈ Architecture Analysis |
|
""" |
|
arch = state.get("architecture_analysis", {}) |
|
output += f"Score: {arch.get('architecture_score', 'N/A')}/10\n" |
|
output += "Patterns:\n" + "\n".join([f"β’ {p}" for p in arch.get("patterns_identified", [])]) + "\n\n" |
|
|
|
output += """π Final Recommendations |
|
""" |
|
final = state.get("final_recommendations", {}) |
|
output += f"Overall Health Score: {final.get('overall_health_score', 'N/A')}/10\n\n" |
|
output += "Critical Issues:\n" + "\n".join([f"β’ {i}" for i in final.get("critical_issues", [])]) + "\n\n" |
|
output += "Priority Improvements:\n" + "\n".join([f"β’ {i}" for i in final.get("priority_improvements", [])]) |
|
|
|
return output |
|
|
|
|
|
workflow = StateGraph(State) |
|
|
|
|
|
workflow.add_node("style", analyze_code_style) |
|
workflow.add_node("security", analyze_security) |
|
workflow.add_node("performance", analyze_performance) |
|
workflow.add_node("architecture", analyze_architecture) |
|
workflow.add_node("recommendations", generate_final_recommendations) |
|
|
|
|
|
workflow.add_edge("style", "security") |
|
workflow.add_edge("security", "performance") |
|
workflow.add_edge("performance", "architecture") |
|
workflow.add_edge("architecture", "recommendations") |
|
|
|
|
|
workflow.set_entry_point("style") |
|
workflow.set_finish_point("recommendations") |
|
|
|
|
|
agent = workflow.compile() |
|
|
|
def analyze_code(code: str) -> str: |
|
"""Analyze the provided code using multiple perspectives.""" |
|
initial_state = State( |
|
messages=[SystemMessage(content="Starting code analysis...")], |
|
current_step="style", |
|
code=code, |
|
style_analysis={}, |
|
security_analysis={}, |
|
performance_analysis={}, |
|
architecture_analysis={}, |
|
final_recommendations={} |
|
) |
|
|
|
final_state = agent.invoke(initial_state) |
|
return format_output(final_state) |
|
|
|
|
|
iface = gr.Interface( |
|
fn=analyze_code, |
|
inputs=gr.Code( |
|
label="Enter your code for analysis", |
|
language="python", |
|
lines=20 |
|
), |
|
outputs=gr.Textbox( |
|
label="Analysis Results", |
|
lines=25 |
|
), |
|
title="π Code Architecture Critic", |
|
description="Paste your code to get a comprehensive analysis of style, security, performance, and architecture.", |
|
examples=[ |
|
['''def process_data(data): |
|
result = [] |
|
for i in range(len(data)): |
|
for j in range(len(data)): |
|
if data[i] + data[j] == 10: |
|
result.append((data[i], data[j])) |
|
return result |
|
|
|
def save_to_db(user_input): |
|
query = "INSERT INTO users VALUES ('" + user_input + "')" |
|
db.execute(query) |
|
|
|
API_KEY = "sk_test_123456789"'''] |
|
], |
|
theme=gr.themes.Soft() |
|
) |
|
|
|
if __name__ == "__main__": |
|
iface.launch() |