Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,18 +1,8 @@
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
"""
|
| 3 |
-
Code Flow Analyzer with Gradio Interface - Colab Compatible
|
| 4 |
-
A single-file application that uses LangChain agents to analyze code structure
|
| 5 |
and generate Mermaid.js flowchart diagrams through a web interface.
|
| 6 |
-
|
| 7 |
-
For Google Colab:
|
| 8 |
-
1. Run this cell to install dependencies and start the app
|
| 9 |
-
2. Enter your GROQ_API_KEY when prompted
|
| 10 |
-
3. The Gradio interface will appear inline
|
| 11 |
-
|
| 12 |
-
For local usage:
|
| 13 |
-
1. Set your API key: export GROQ_API_KEY="your-key-here"
|
| 14 |
-
2. Run: python code_flow_analyzer.py
|
| 15 |
-
3. Open the provided URL in your browser
|
| 16 |
"""
|
| 17 |
|
| 18 |
import ast
|
|
@@ -30,21 +20,22 @@ try:
|
|
| 30 |
print("π’ Running in Google Colab")
|
| 31 |
except ImportError:
|
| 32 |
IN_COLAB = False
|
| 33 |
-
print("π‘ Running locally")
|
| 34 |
|
| 35 |
# Install dependencies if in Colab
|
| 36 |
if IN_COLAB:
|
| 37 |
print("π¦ Installing dependencies...")
|
| 38 |
-
os.system("pip install -q gradio langchain langgraph langchain-
|
| 39 |
print("β
Dependencies installed")
|
| 40 |
|
| 41 |
import gradio as gr
|
| 42 |
from langchain.chat_models import init_chat_model
|
|
|
|
| 43 |
from langchain.tools import tool
|
| 44 |
from langgraph.prebuilt import create_react_agent
|
| 45 |
from langgraph.checkpoint.memory import MemorySaver
|
| 46 |
|
| 47 |
-
# Sample code examples
|
| 48 |
SAMPLE_PYTHON = '''def main():
|
| 49 |
user_input = get_user_input()
|
| 50 |
if user_input:
|
|
@@ -147,29 +138,29 @@ SAMPLE_JAVA = '''public class Calculator {
|
|
| 147 |
}
|
| 148 |
}'''
|
| 149 |
|
| 150 |
-
#
|
| 151 |
def setup_api_key():
|
| 152 |
-
"""Setup API key for
|
| 153 |
-
api_key = os.getenv("
|
| 154 |
|
| 155 |
if not api_key:
|
| 156 |
if IN_COLAB:
|
| 157 |
-
print("π Please enter your
|
| 158 |
-
print(" Get a
|
| 159 |
-
api_key = getpass.getpass("
|
| 160 |
if api_key:
|
| 161 |
-
os.environ["
|
| 162 |
print("β
API key set successfully")
|
| 163 |
else:
|
| 164 |
print("β οΈ No API key provided - agent features will be disabled")
|
| 165 |
else:
|
| 166 |
-
print("β οΈ
|
| 167 |
-
print("
|
| 168 |
-
print("
|
| 169 |
else:
|
| 170 |
-
print("β
|
| 171 |
|
| 172 |
-
return api_key or os.getenv("
|
| 173 |
|
| 174 |
# Setup API key
|
| 175 |
api_key = setup_api_key()
|
|
@@ -181,15 +172,16 @@ agent_executor = None
|
|
| 181 |
|
| 182 |
if api_key:
|
| 183 |
try:
|
| 184 |
-
model =
|
|
|
|
| 185 |
memory = MemorySaver()
|
| 186 |
-
print("β
Groq model initialized successfully")
|
| 187 |
except Exception as e:
|
| 188 |
-
print(f"β Could not initialize
|
| 189 |
-
print(" Please check your API key and internet connection")
|
| 190 |
model = None
|
| 191 |
memory = None
|
| 192 |
|
|
|
|
| 193 |
@tool
|
| 194 |
def analyze_code_structure(source_code: str) -> Dict[str, Any]:
|
| 195 |
"""
|
|
@@ -481,7 +473,7 @@ def analyze_code_with_agent(source_code: str, language: str = "auto") -> Tuple[s
|
|
| 481 |
return "", "No code provided", [], 0, "Please enter some source code to analyze"
|
| 482 |
|
| 483 |
if not agent_executor:
|
| 484 |
-
return "", "Agent not available", [], 0, "β LangChain agent not initialized. Please check your
|
| 485 |
|
| 486 |
try:
|
| 487 |
# Detect language if auto
|
|
@@ -497,62 +489,46 @@ def analyze_code_with_agent(source_code: str, language: str = "auto") -> Tuple[s
|
|
| 497 |
else:
|
| 498 |
language = "Unknown"
|
| 499 |
|
| 500 |
-
config = {
|
|
|
|
|
|
|
|
|
|
| 501 |
|
|
|
|
| 502 |
prompt = f"""
|
| 503 |
-
You are a code analysis expert. Analyze the following {language} source code
|
| 504 |
-
|
| 505 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 506 |
```{language.lower()}
|
| 507 |
{source_code}
|
| 508 |
```
|
| 509 |
-
|
| 510 |
-
Please follow these steps exactly:
|
| 511 |
-
1. First use the analyze_code_structure tool to understand the code structure
|
| 512 |
-
2. Then use the generate_mermaid_diagram tool to create a flowchart
|
| 513 |
-
3. Use the calculate_complexity_score tool to assess code complexity
|
| 514 |
-
4. Provide a brief summary of what the code does and its structure
|
| 515 |
-
|
| 516 |
-
Important guidelines:
|
| 517 |
-
- Focus on the main flow between functions and important control structures
|
| 518 |
-
- Keep the diagram clean and readable
|
| 519 |
-
- Identify all functions and their relationships
|
| 520 |
-
- Note any loops, conditionals, and function calls
|
| 521 |
-
- Provide insights about code organization and complexity
|
| 522 |
-
|
| 523 |
-
Please be thorough in your analysis and make sure to use all three tools in order.
|
| 524 |
"""
|
| 525 |
|
| 526 |
-
# Execute the agent
|
| 527 |
result = agent_executor.invoke(
|
| 528 |
{"messages": [{"role": "user", "content": prompt}]},
|
| 529 |
config
|
| 530 |
)
|
| 531 |
|
| 532 |
if result and "messages" in result:
|
| 533 |
-
|
| 534 |
-
|
| 535 |
# Extract Mermaid diagram
|
| 536 |
-
mermaid_match = re.search(r'```mermaid\n(.*?)\n```',
|
| 537 |
-
if
|
| 538 |
-
mermaid_match = re.search(r'flowchart TD.*?(?=\n\n|\Z)', response, re.DOTALL)
|
| 539 |
-
|
| 540 |
-
mermaid_diagram = mermaid_match.group(1) if mermaid_match else mermaid_match.group(0) if mermaid_match else ""
|
| 541 |
-
|
| 542 |
-
# If no mermaid found in response, try to generate directly
|
| 543 |
-
if not mermaid_diagram:
|
| 544 |
-
print("β οΈ No Mermaid diagram found in response, generating fallback...")
|
| 545 |
-
# Fallback: analyze directly
|
| 546 |
-
analysis_result = analyze_code_structure.invoke({"source_code": source_code})
|
| 547 |
-
mermaid_diagram = generate_mermaid_diagram.invoke({"analysis_data": analysis_result})
|
| 548 |
|
| 549 |
# Extract complexity score
|
| 550 |
-
complexity_match = re.search(r'complexity.*?(\d+)',
|
| 551 |
-
complexity_score = int(complexity_match.group(1)) if complexity_match else
|
| 552 |
|
| 553 |
# Extract functions
|
| 554 |
functions_found = []
|
| 555 |
-
func_matches = re.findall(r'Functions found:.*?([^\n]+)',
|
| 556 |
if func_matches:
|
| 557 |
functions_found = [f.strip() for f in func_matches[0].split(',')]
|
| 558 |
else:
|
|
@@ -561,17 +537,26 @@ def analyze_code_with_agent(source_code: str, language: str = "auto") -> Tuple[s
|
|
| 561 |
functions_found = [f["name"] for f in analysis_result.get("functions", [])]
|
| 562 |
|
| 563 |
# Clean up the response for summary
|
| 564 |
-
summary = re.sub(r'```mermaid.*?```', '',
|
| 565 |
summary = re.sub(r'flowchart TD.*?(?=\n\n|\Z)', '', summary, flags=re.DOTALL)
|
| 566 |
summary = summary.strip()
|
| 567 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 568 |
return mermaid_diagram, summary, functions_found, complexity_score, ""
|
| 569 |
|
| 570 |
except Exception as e:
|
| 571 |
error_msg = f"β Analysis failed: {str(e)}"
|
| 572 |
-
print(f"Error details: {traceback.format_exc()}")
|
| 573 |
return "", "", [], 0, error_msg
|
| 574 |
|
|
|
|
| 575 |
def create_gradio_interface():
|
| 576 |
"""Create and configure the Gradio interface"""
|
| 577 |
|
|
@@ -633,7 +618,10 @@ def create_gradio_interface():
|
|
| 633 |
""")
|
| 634 |
|
| 635 |
# API Status
|
| 636 |
-
|
|
|
|
|
|
|
|
|
|
| 637 |
gr.Markdown(f"**Status:** {api_status}")
|
| 638 |
|
| 639 |
with gr.Row():
|
|
@@ -728,16 +716,16 @@ def create_gradio_interface():
|
|
| 728 |
)
|
| 729 |
|
| 730 |
# Footer
|
| 731 |
-
environment_info = "Google Colab" if IN_COLAB else "Local Environment"
|
| 732 |
gr.Markdown(f"""
|
| 733 |
---
|
| 734 |
**π οΈ Running in:** {environment_info}
|
| 735 |
|
| 736 |
-
**π¦ Dependencies:** gradio, langchain, langgraph, langchain-
|
| 737 |
|
| 738 |
-
**π§ Powered by:** LangChain Agents,
|
| 739 |
|
| 740 |
-
**π Get
|
| 741 |
""")
|
| 742 |
|
| 743 |
return interface
|
|
@@ -746,37 +734,29 @@ def main():
|
|
| 746 |
"""Main function to run the application"""
|
| 747 |
print("π Code Flow Analyzer with Gradio")
|
| 748 |
print("=" * 50)
|
| 749 |
-
print(f"π Environment: {'Google Colab' if IN_COLAB else 'Local'}")
|
| 750 |
|
| 751 |
if agent_executor:
|
| 752 |
print("β
LangChain agent ready")
|
| 753 |
else:
|
| 754 |
print("β LangChain agent not available")
|
| 755 |
if IN_COLAB:
|
| 756 |
-
print(" π‘ Restart this cell and enter your
|
|
|
|
|
|
|
| 757 |
|
| 758 |
print("\nπ Starting Gradio interface...")
|
| 759 |
|
| 760 |
# Create and launch the interface
|
| 761 |
interface = create_gradio_interface()
|
| 762 |
|
| 763 |
-
# Launch configuration for Colab vs local
|
| 764 |
-
|
| 765 |
-
|
| 766 |
-
|
| 767 |
-
|
| 768 |
-
|
| 769 |
-
|
| 770 |
-
show_error=True
|
| 771 |
-
)
|
| 772 |
-
else:
|
| 773 |
-
# For local usage
|
| 774 |
-
interface.launch(
|
| 775 |
-
server_name="0.0.0.0",
|
| 776 |
-
server_port=7860,
|
| 777 |
-
share=False, # Disable sharing for local use
|
| 778 |
-
debug=False
|
| 779 |
-
)
|
| 780 |
|
| 781 |
# Auto-run if in Colab or when script is executed directly
|
| 782 |
if __name__ == "__main__" or IN_COLAB:
|
|
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
"""
|
| 3 |
+
Code Flow Analyzer with Gradio Interface - Hugging Face Spaces & Colab Compatible
|
| 4 |
+
A single-file application that uses LangChain agents with the Gemini model to analyze code structure
|
| 5 |
and generate Mermaid.js flowchart diagrams through a web interface.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
"""
|
| 7 |
|
| 8 |
import ast
|
|
|
|
| 20 |
print("π’ Running in Google Colab")
|
| 21 |
except ImportError:
|
| 22 |
IN_COLAB = False
|
| 23 |
+
print("π‘ Running locally or in Hugging Face Spaces")
|
| 24 |
|
| 25 |
# Install dependencies if in Colab
|
| 26 |
if IN_COLAB:
|
| 27 |
print("π¦ Installing dependencies...")
|
| 28 |
+
os.system("pip install -q gradio langchain langgraph langchain-google-genai")
|
| 29 |
print("β
Dependencies installed")
|
| 30 |
|
| 31 |
import gradio as gr
|
| 32 |
from langchain.chat_models import init_chat_model
|
| 33 |
+
from langchain_google_genai import ChatGoogleGenerativeAI
|
| 34 |
from langchain.tools import tool
|
| 35 |
from langgraph.prebuilt import create_react_agent
|
| 36 |
from langgraph.checkpoint.memory import MemorySaver
|
| 37 |
|
| 38 |
+
# Sample code examples (unchanged)
|
| 39 |
SAMPLE_PYTHON = '''def main():
|
| 40 |
user_input = get_user_input()
|
| 41 |
if user_input:
|
|
|
|
| 138 |
}
|
| 139 |
}'''
|
| 140 |
|
| 141 |
+
# --- Gemini API Key Setup ---
|
| 142 |
def setup_api_key():
|
| 143 |
+
"""Setup API key for Colab, Hugging Face Spaces, and local environments"""
|
| 144 |
+
api_key = os.getenv("GOOGLE_API_KEY")
|
| 145 |
|
| 146 |
if not api_key:
|
| 147 |
if IN_COLAB:
|
| 148 |
+
print("π Please enter your Google API key:")
|
| 149 |
+
print(" Get a key from: https://aistudio.google.com/app/apikey")
|
| 150 |
+
api_key = getpass.getpass("GOOGLE_API_KEY: ")
|
| 151 |
if api_key:
|
| 152 |
+
os.environ["GOOGLE_API_KEY"] = api_key
|
| 153 |
print("β
API key set successfully")
|
| 154 |
else:
|
| 155 |
print("β οΈ No API key provided - agent features will be disabled")
|
| 156 |
else:
|
| 157 |
+
print("β οΈ GOOGLE_API_KEY not found in environment variables")
|
| 158 |
+
print(" Set it with: export GOOGLE_API_KEY='your-key-here'")
|
| 159 |
+
print(" In Hugging Face Spaces, use the 'Secrets' tab to set the key.")
|
| 160 |
else:
|
| 161 |
+
print("β
Google API key found")
|
| 162 |
|
| 163 |
+
return api_key or os.getenv("GOOGLE_API_KEY")
|
| 164 |
|
| 165 |
# Setup API key
|
| 166 |
api_key = setup_api_key()
|
|
|
|
| 172 |
|
| 173 |
if api_key:
|
| 174 |
try:
|
| 175 |
+
model = ChatGoogleGenerativeAI(model="gemini-pro", temperature=0)
|
| 176 |
+
print("β
Gemini model initialized successfully: gemini-pro")
|
| 177 |
memory = MemorySaver()
|
|
|
|
| 178 |
except Exception as e:
|
| 179 |
+
print(f"β Could not initialize Gemini model: {e}")
|
| 180 |
+
print(" Please check your API key and internet connection.")
|
| 181 |
model = None
|
| 182 |
memory = None
|
| 183 |
|
| 184 |
+
# --- Tool Definitions (unchanged) ---
|
| 185 |
@tool
|
| 186 |
def analyze_code_structure(source_code: str) -> Dict[str, Any]:
|
| 187 |
"""
|
|
|
|
| 473 |
return "", "No code provided", [], 0, "Please enter some source code to analyze"
|
| 474 |
|
| 475 |
if not agent_executor:
|
| 476 |
+
return "", "Agent not available", [], 0, "β LangChain agent not initialized. Please check your GOOGLE_API_KEY"
|
| 477 |
|
| 478 |
try:
|
| 479 |
# Detect language if auto
|
|
|
|
| 489 |
else:
|
| 490 |
language = "Unknown"
|
| 491 |
|
| 492 |
+
config = {
|
| 493 |
+
"configurable": {"thread_id": f"session_{hash(source_code) % 10000}"},
|
| 494 |
+
"recursion_limit": 100
|
| 495 |
+
}
|
| 496 |
|
| 497 |
+
# Refined prompt for better tool use
|
| 498 |
prompt = f"""
|
| 499 |
+
You are a code analysis expert. Analyze the following {language} source code.
|
| 500 |
+
Your task is to:
|
| 501 |
+
1. Use the 'analyze_code_structure' tool with the full source code provided below.
|
| 502 |
+
2. Use the 'generate_mermaid_diagram' tool with the output of the first tool.
|
| 503 |
+
3. Use the 'calculate_complexity_score' tool with the output of the first tool.
|
| 504 |
+
4. Provide a brief, human-readable summary of the analysis, including the generated Mermaid diagram, complexity score, and a list of functions found.
|
| 505 |
+
5. Present the final result in a clear, easy-to-read format.
|
| 506 |
+
|
| 507 |
+
Source Code to Analyze:
|
| 508 |
```{language.lower()}
|
| 509 |
{source_code}
|
| 510 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 511 |
"""
|
| 512 |
|
|
|
|
| 513 |
result = agent_executor.invoke(
|
| 514 |
{"messages": [{"role": "user", "content": prompt}]},
|
| 515 |
config
|
| 516 |
)
|
| 517 |
|
| 518 |
if result and "messages" in result:
|
| 519 |
+
response_content = result["messages"][-1].content
|
| 520 |
+
|
| 521 |
# Extract Mermaid diagram
|
| 522 |
+
mermaid_match = re.search(r'```mermaid\n(.*?)\n```', response_content, re.DOTALL)
|
| 523 |
+
mermaid_diagram = mermaid_match.group(1) if mermaid_match else ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 524 |
|
| 525 |
# Extract complexity score
|
| 526 |
+
complexity_match = re.search(r'complexity.*?(\d+)', response_content, re.IGNORECASE)
|
| 527 |
+
complexity_score = int(complexity_match.group(1)) if complexity_match else 0
|
| 528 |
|
| 529 |
# Extract functions
|
| 530 |
functions_found = []
|
| 531 |
+
func_matches = re.findall(r'Functions found:.*?([^\n]+)', response_content, re.IGNORECASE)
|
| 532 |
if func_matches:
|
| 533 |
functions_found = [f.strip() for f in func_matches[0].split(',')]
|
| 534 |
else:
|
|
|
|
| 537 |
functions_found = [f["name"] for f in analysis_result.get("functions", [])]
|
| 538 |
|
| 539 |
# Clean up the response for summary
|
| 540 |
+
summary = re.sub(r'```mermaid.*?```', '', response_content, flags=re.DOTALL)
|
| 541 |
summary = re.sub(r'flowchart TD.*?(?=\n\n|\Z)', '', summary, flags=re.DOTALL)
|
| 542 |
summary = summary.strip()
|
| 543 |
|
| 544 |
+
if not mermaid_diagram and not summary:
|
| 545 |
+
# Last resort fallback if agent fails entirely
|
| 546 |
+
analysis_result = analyze_code_structure.invoke({"source_code": source_code})
|
| 547 |
+
mermaid_diagram = generate_mermaid_diagram.invoke({"analysis_data": analysis_result})
|
| 548 |
+
complexity_score = calculate_complexity_score.invoke({"analysis_data": analysis_result})
|
| 549 |
+
functions_found = [f["name"] for f in analysis_result.get("functions", [])]
|
| 550 |
+
summary = "Agent failed to provide a detailed summary, but a fallback analysis was successful."
|
| 551 |
+
|
| 552 |
return mermaid_diagram, summary, functions_found, complexity_score, ""
|
| 553 |
|
| 554 |
except Exception as e:
|
| 555 |
error_msg = f"β Analysis failed: {str(e)}"
|
| 556 |
+
print(f"Error details: {traceback.format_exc()}")
|
| 557 |
return "", "", [], 0, error_msg
|
| 558 |
|
| 559 |
+
# --- Gradio Interface Setup (unchanged) ---
|
| 560 |
def create_gradio_interface():
|
| 561 |
"""Create and configure the Gradio interface"""
|
| 562 |
|
|
|
|
| 618 |
""")
|
| 619 |
|
| 620 |
# API Status
|
| 621 |
+
model_info = ""
|
| 622 |
+
if agent_executor and model:
|
| 623 |
+
model_info = " (Gemini LLM)"
|
| 624 |
+
api_status = f"π’ Gemini LangChain Agent Ready{model_info}" if agent_executor else "π΄ Agent Not Available (Check GOOGLE_API_KEY)"
|
| 625 |
gr.Markdown(f"**Status:** {api_status}")
|
| 626 |
|
| 627 |
with gr.Row():
|
|
|
|
| 716 |
)
|
| 717 |
|
| 718 |
# Footer
|
| 719 |
+
environment_info = "Google Colab" if IN_COLAB else "Hugging Face Spaces or Local Environment"
|
| 720 |
gr.Markdown(f"""
|
| 721 |
---
|
| 722 |
**π οΈ Running in:** {environment_info}
|
| 723 |
|
| 724 |
+
**π¦ Dependencies:** gradio, langchain, langgraph, langchain-google-genai
|
| 725 |
|
| 726 |
+
**π§ Powered by:** LangChain Agents, Google Gemini, Mermaid.js, Gradio
|
| 727 |
|
| 728 |
+
**π Get Google API Key:** [aistudio.google.com/app/apikey](https://aistudio.google.com/app/apikey)
|
| 729 |
""")
|
| 730 |
|
| 731 |
return interface
|
|
|
|
| 734 |
"""Main function to run the application"""
|
| 735 |
print("π Code Flow Analyzer with Gradio")
|
| 736 |
print("=" * 50)
|
| 737 |
+
print(f"π Environment: {'Google Colab' if IN_COLAB else 'Hugging Face Spaces or Local'}")
|
| 738 |
|
| 739 |
if agent_executor:
|
| 740 |
print("β
LangChain agent ready")
|
| 741 |
else:
|
| 742 |
print("β LangChain agent not available")
|
| 743 |
if IN_COLAB:
|
| 744 |
+
print(" π‘ Restart this cell and enter your GOOGLE_API_KEY when prompted")
|
| 745 |
+
else:
|
| 746 |
+
print(" π‘ Please set your GOOGLE_API_KEY as an environment variable or secret")
|
| 747 |
|
| 748 |
print("\nπ Starting Gradio interface...")
|
| 749 |
|
| 750 |
# Create and launch the interface
|
| 751 |
interface = create_gradio_interface()
|
| 752 |
|
| 753 |
+
# Launch configuration for Colab vs local/Spaces
|
| 754 |
+
interface.launch(
|
| 755 |
+
share=True if IN_COLAB else False,
|
| 756 |
+
debug=False,
|
| 757 |
+
height=600,
|
| 758 |
+
show_error=True
|
| 759 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 760 |
|
| 761 |
# Auto-run if in Colab or when script is executed directly
|
| 762 |
if __name__ == "__main__" or IN_COLAB:
|