Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -36,63 +36,102 @@ if not hf_token:
|
|
| 36 |
|
| 37 |
metrics_tracker = MimirMetrics(save_file="Mimir_metrics.json")
|
| 38 |
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
name: str = "create_graph"
|
| 50 |
-
description: str = """
|
| 51 |
-
|
| 52 |
-
REQUIRED FORMAT:
|
| 53 |
-
- data_json: A JSON dictionary where keys are category names and values are numbers
|
| 54 |
-
Example: '{"Math": 85, "Science": 92, "English": 78}'
|
| 55 |
-
- labels_json: A JSON list, only needed for pie charts if you want custom labels different from the data keys. For bar/line charts, use empty list: '[]'
|
| 56 |
-
Example for pie: '["Mathematics", "Science", "English Literature"]'
|
| 57 |
-
Example for bar/line: '[]'
|
| 58 |
-
|
| 59 |
-
EXAMPLES:
|
| 60 |
-
Bar chart: data_json='{"Q1": 1000, "Q2": 1200, "Q3": 950}', labels_json='[]'
|
| 61 |
-
Line chart: data_json='{"Jan": 100, "Feb": 120, "Mar": 110}', labels_json='[]'
|
| 62 |
-
Pie chart: data_json='{"A": 30, "B": 45, "C": 25}', labels_json='["Category A", "Category B", "Category C"]'
|
| 63 |
-
|
| 64 |
-
Always use proper JSON formatting with quotes around keys and string values."""
|
| 65 |
-
args_schema: Type[BaseModel] = GraphInput
|
| 66 |
|
| 67 |
-
def _run(self,
|
| 68 |
-
|
| 69 |
try:
|
| 70 |
-
#
|
| 71 |
-
|
| 72 |
-
try:
|
| 73 |
-
data_parsed = json.loads(data_json)
|
| 74 |
-
labels_parsed = json.loads(labels_json)
|
| 75 |
-
|
| 76 |
-
# Validate data structure
|
| 77 |
-
if not isinstance(data_parsed, dict):
|
| 78 |
-
return "<p style='color:red;'>data_json must be a JSON dictionary with string keys and numeric values.</p>"
|
| 79 |
-
|
| 80 |
-
if not isinstance(labels_parsed, list):
|
| 81 |
-
return "<p style='color:red;'>labels_json must be a JSON list (use [] if no custom labels needed).</p>"
|
| 82 |
-
|
| 83 |
-
except json.JSONDecodeError as json_error:
|
| 84 |
-
return f"<p style='color:red;'>Invalid JSON format: {str(json_error)}. Ensure proper JSON formatting with quotes.</p>"
|
| 85 |
-
|
| 86 |
-
return generate_plot(
|
| 87 |
-
data_json=data_json,
|
| 88 |
-
labels_json=labels_json,
|
| 89 |
-
plot_type=plot_type,
|
| 90 |
-
title=title,
|
| 91 |
-
x_label=x_label,
|
| 92 |
-
y_label=y_label
|
| 93 |
-
)
|
| 94 |
except Exception as e:
|
| 95 |
-
|
|
|
|
| 96 |
|
| 97 |
|
| 98 |
# --- System Prompt ---
|
|
@@ -404,35 +443,6 @@ class Qwen25SmallLLM(LLM):
|
|
| 404 |
@property
|
| 405 |
def _llm_type(self) -> str:
|
| 406 |
return "qwen25_small"
|
| 407 |
-
|
| 408 |
-
def create_langchain_agent():
|
| 409 |
-
"""Creates the LangChain agent with educational graph capabilities."""
|
| 410 |
-
logger.info("Creating educational LangChain agent...")
|
| 411 |
-
|
| 412 |
-
# Use the smaller local model
|
| 413 |
-
llm = Qwen25SmallLLM()
|
| 414 |
-
|
| 415 |
-
# Use the educational graph tool
|
| 416 |
-
tools = [create_educational_graph_tool()]
|
| 417 |
-
memory = ConversationBufferWindowMemory(
|
| 418 |
-
memory_key="chat_history",
|
| 419 |
-
k=10,
|
| 420 |
-
return_messages=True
|
| 421 |
-
)
|
| 422 |
-
|
| 423 |
-
# Use standard agent type
|
| 424 |
-
agent = initialize_agent(
|
| 425 |
-
tools=tools,
|
| 426 |
-
llm=llm,
|
| 427 |
-
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
|
| 428 |
-
memory=memory,
|
| 429 |
-
verbose=False, # Set to True for debugging
|
| 430 |
-
max_iterations=3,
|
| 431 |
-
early_stopping_method="generate"
|
| 432 |
-
)
|
| 433 |
-
|
| 434 |
-
logger.info("Educational LangChain agent created successfully!")
|
| 435 |
-
return agent
|
| 436 |
|
| 437 |
# Example of how the AI should use the tool
|
| 438 |
def example_usage_for_ai():
|
|
|
|
| 36 |
|
| 37 |
metrics_tracker = MimirMetrics(save_file="Mimir_metrics.json")
|
| 38 |
|
| 39 |
+
from langchain.tools import Tool
|
| 40 |
+
import json
|
| 41 |
+
|
| 42 |
+
def create_educational_graph_tool():
|
| 43 |
+
"""
|
| 44 |
+
Creates a graph tool for the AI to autonomously generate educational visualizations.
|
| 45 |
+
"""
|
| 46 |
+
|
| 47 |
+
def graph_wrapper(graph_config: str) -> str:
|
| 48 |
+
"""
|
| 49 |
+
Wrapper that calls your generate_plot function with the JSON config.
|
| 50 |
+
|
| 51 |
+
Args:
|
| 52 |
+
graph_config (str): JSON string with plot configuration
|
| 53 |
+
|
| 54 |
+
Returns:
|
| 55 |
+
str: HTML with embedded graph
|
| 56 |
+
"""
|
| 57 |
+
try:
|
| 58 |
+
# Validate it's proper JSON
|
| 59 |
+
config = json.loads(graph_config)
|
| 60 |
+
|
| 61 |
+
# Add educational context if provided
|
| 62 |
+
educational_context = config.get("educational_context", "")
|
| 63 |
+
|
| 64 |
+
# Call your generate_plot function (which now takes single JSON input)
|
| 65 |
+
graph_html = generate_plot(graph_config)
|
| 66 |
+
|
| 67 |
+
# Add educational context if provided
|
| 68 |
+
if educational_context:
|
| 69 |
+
context_html = f'<div style="margin: 10px 0; padding: 10px; background: #f8f9fa; border-left: 4px solid #007bff; font-style: italic;">💡 {educational_context}</div>'
|
| 70 |
+
return context_html + graph_html
|
| 71 |
+
|
| 72 |
+
return graph_html
|
| 73 |
+
|
| 74 |
+
except json.JSONDecodeError as e:
|
| 75 |
+
logger.error(f"Invalid JSON provided to graph tool: {e}")
|
| 76 |
+
return '<p style="color:red;">Graph generation failed - invalid JSON format</p>'
|
| 77 |
+
except Exception as e:
|
| 78 |
+
logger.error(f"Error in graph generation: {e}")
|
| 79 |
+
return f'<p style="color:red;">Error creating graph: {str(e)}</p>'
|
| 80 |
+
|
| 81 |
+
return Tool(
|
| 82 |
+
name="create_graph",
|
| 83 |
+
description="""Create educational graphs and charts to help explain concepts to students.
|
| 84 |
+
|
| 85 |
+
Use this tool when teaching concepts that would benefit from visual representation, such as:
|
| 86 |
+
- Mathematical functions and relationships (quadratic equations, exponential growth)
|
| 87 |
+
- Statistical distributions and data analysis (normal curves, survey results)
|
| 88 |
+
- Scientific trends and comparisons (temperature changes, population growth)
|
| 89 |
+
- Economic models and business metrics (profit over time, market shares)
|
| 90 |
+
- Grade distributions or performance analysis (test score ranges)
|
| 91 |
+
- Any quantitative concept that's clearer with visualization
|
| 92 |
+
|
| 93 |
+
Input should be a JSON string with this structure:
|
| 94 |
+
{
|
| 95 |
+
"data": {"Category A": 25, "Category B": 40, "Category C": 35},
|
| 96 |
+
"plot_type": "bar",
|
| 97 |
+
"title": "Student Performance by Subject",
|
| 98 |
+
"x_label": "Subjects",
|
| 99 |
+
"y_label": "Average Score",
|
| 100 |
+
"educational_context": "This visualization helps students see performance patterns across subjects"
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
Plot types:
|
| 104 |
+
- "bar": Best for comparing categories, showing distributions, or discrete data
|
| 105 |
+
- "line": Best for showing trends over time or continuous relationships
|
| 106 |
+
- "pie": Best for showing parts of a whole or proportions
|
| 107 |
+
|
| 108 |
+
Always create meaningful educational data that illustrates the concept you're teaching.
|
| 109 |
+
Include educational_context to explain why the visualization helps learning.
|
| 110 |
+
|
| 111 |
+
Examples of when to use:
|
| 112 |
+
- Student asks about probability → Create histogram showing dice roll outcomes
|
| 113 |
+
- Teaching compound interest → Line chart showing money growth over time
|
| 114 |
+
- Explaining survey methods → Pie chart of sample demographic breakdown
|
| 115 |
+
- Discussing functions → Line plot comparing linear vs exponential growth
|
| 116 |
+
- Analyzing test performance → Bar chart of score distributions
|
| 117 |
+
""",
|
| 118 |
+
func=graph_wrapper
|
| 119 |
+
)
|
| 120 |
+
|
| 121 |
+
# If you want to keep using your existing CreateGraphTool approach,
|
| 122 |
+
# update it to work with the new single-input generate_plot function:
|
| 123 |
+
class CreateGraphToolFixed(BaseTool):
|
| 124 |
name: str = "create_graph"
|
| 125 |
+
description: str = """Generate educational graphs to supplement explanations. Create realistic data that illustrates educational concepts."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 126 |
|
| 127 |
+
def _run(self, tool_input: str) -> str:
|
| 128 |
+
"""Single input version that works with your updated generate_plot function."""
|
| 129 |
try:
|
| 130 |
+
# tool_input should be the JSON config string
|
| 131 |
+
return generate_plot(tool_input)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
except Exception as e:
|
| 133 |
+
logger.error(f"Error in graph tool: {e}")
|
| 134 |
+
return f'<p style="color:red;">Error creating graph: {str(e)}</p>'
|
| 135 |
|
| 136 |
|
| 137 |
# --- System Prompt ---
|
|
|
|
| 443 |
@property
|
| 444 |
def _llm_type(self) -> str:
|
| 445 |
return "qwen25_small"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 446 |
|
| 447 |
# Example of how the AI should use the tool
|
| 448 |
def example_usage_for_ai():
|