Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| import json | |
| import re | |
| from datetime import datetime | |
| from agents.state import MathMentorState | |
| from llm.client import get_llm | |
| from tools.plotter import plot_function | |
| EXPLAINER_PROMPT = """\ | |
| You are a friendly math tutor explaining a solution to a JEE student. | |
| Problem: {problem_text} | |
| Solution: {solution} | |
| Steps: {steps} | |
| Topic: {topic} | |
| Write a clear, step-by-step explanation in markdown. Use LaTeX for all math expressions: | |
| - Inline math: \\(x^2 + 1\\) | |
| - Display math: $$x = \\frac{{-b \\pm \\sqrt{{b^2 - 4ac}}}}{{2a}}$$ | |
| Guidelines: | |
| 1. Explain each step in simple, student-friendly language | |
| 2. Use LaTeX for ALL math expressions (never write raw math like x^2, always wrap in LaTeX) | |
| 3. Highlight key concepts and formulas used | |
| 4. Mention common mistakes to avoid | |
| 5. End with the final answer clearly stated | |
| Do NOT wrap your response in JSON or code fences. Write plain markdown directly. | |
| """ | |
| PLOT_EXTRACT_PROMPT = """\ | |
| Given this math problem and solution, extract a numpy-compatible Python expression to plot. | |
| Use 'x' as the variable and numpy functions prefixed with 'np.' (e.g. np.sin, np.exp, np.sqrt, np.log). | |
| Problem: {problem_text} | |
| Solution: {solution} | |
| Rules: | |
| - Use ** for powers: x**2 not x^2 | |
| - Use np.sin(x), np.cos(x), np.tan(x), np.exp(x), np.log(x), np.sqrt(x), np.abs(x) | |
| - Use np.pi for pi, np.e for e | |
| - For polynomials just write them: x**3 - 2*x**2 + 1 | |
| - Only output the expression, nothing else. No explanation, no code fences. | |
| - If there's no clear function to plot, respond with exactly: NONE | |
| Expression:""" | |
| def _try_generate_plot(problem_text: str, solution: str) -> str: | |
| """Ask the LLM to extract a plottable expression and generate a diagram.""" | |
| try: | |
| llm = get_llm(temperature=0.0) | |
| response = llm.invoke( | |
| PLOT_EXTRACT_PROMPT.format(problem_text=problem_text, solution=solution) | |
| ) | |
| expr = response.content.strip() | |
| # Clean up | |
| if expr.startswith("```"): | |
| expr = expr.split("\n", 1)[1] if "\n" in expr else expr[3:] | |
| if expr.endswith("```"): | |
| expr = expr[:-3].strip() | |
| if not expr or expr.upper() == "NONE" or len(expr) > 200: | |
| return "" | |
| # Generate the plot | |
| path = plot_function( | |
| expression=expr, | |
| title=f"y = {expr}", | |
| ) | |
| return path | |
| except Exception: | |
| return "" | |
| def explainer_node(state: MathMentorState) -> dict: | |
| parsed = state.get("parsed_problem", {}) | |
| problem_text = parsed.get("problem_text", state.get("extracted_text", "")) | |
| solution = state.get("solution", "") | |
| steps = state.get("solution_steps", []) | |
| topic = state.get("problem_topic", "math") | |
| llm = get_llm(temperature=0.3) | |
| response = llm.invoke( | |
| EXPLAINER_PROMPT.format( | |
| problem_text=problem_text, | |
| solution=solution, | |
| steps=json.dumps(steps), | |
| topic=topic, | |
| ) | |
| ) | |
| explanation = response.content if hasattr(response, "content") else str(response) | |
| # Strip any accidental code fences | |
| explanation = explanation.strip() | |
| if explanation.startswith("```"): | |
| explanation = explanation.split("\n", 1)[1] if "\n" in explanation else explanation[3:] | |
| if explanation.endswith("```"): | |
| explanation = explanation[:-3].strip() | |
| # Generate diagram if router requested plotter | |
| diagram_path = "" | |
| tools_needed = state.get("tools_needed", []) | |
| if "plotter" in tools_needed: | |
| diagram_path = _try_generate_plot(problem_text, solution) | |
| return { | |
| "explanation": explanation, | |
| "diagram_path": diagram_path, | |
| "agent_trace": state.get("agent_trace", []) | |
| + [ | |
| { | |
| "agent": "explainer", | |
| "action": "explained", | |
| "summary": "Generated explanation" + (" + diagram" if diagram_path else ""), | |
| "timestamp": datetime.now().isoformat(), | |
| } | |
| ], | |
| } | |