Spaces:
Sleeping
Sleeping
| import json | |
| import logging | |
| import sympy as sp | |
| from typing import Dict, Any, List | |
| from app.llm_client import get_llm_client | |
| logger = logging.getLogger(__name__) | |
| class SolverAgent: | |
| def __init__(self): | |
| self.llm = get_llm_client() | |
| async def solve(self, semantic_data: Dict[str, Any], engine_result: Dict[str, Any]) -> Dict[str, Any]: | |
| """ | |
| Solves the geometric problem based on coordinates and the target question. | |
| Returns a 'solution' dictionary with answer, steps, and symbolic_expression. | |
| """ | |
| target_question = semantic_data.get("target_question") | |
| if not target_question: | |
| # If no question, just return an empty solution structure | |
| return { | |
| "answer": None, | |
| "steps": [], | |
| "symbolic_expression": None | |
| } | |
| logger.info(f"==[SolverAgent] Solving for: '{target_question}'==") | |
| input_text = semantic_data.get("input_text", "") | |
| coordinates = engine_result.get("coordinates", {}) | |
| # We provide the coordinates and semantic context to the LLM to help it reason. | |
| # The LLM is tasked with generating the solution structure directly. | |
| system_prompt = """ | |
| You are a Geometry Solver Agent. Your goal is to provide a step-by-step solution for a specific geometric question. | |
| === DATA PROVIDED === | |
| 1. Target Question: The specific question to answer. | |
| 2. Geometry Data: Entities and values extracted from the problem. | |
| 3. Coordinates: Calculated coordinates for all points. | |
| === REQUIREMENTS === | |
| - Provide the solution in the SAME LANGUAGE as the user's input. | |
| - Use SymPy concepts if appropriate. | |
| - Steps should be clear, concise, and logical. | |
| - The final answer should be numerically or symbolically accurate based on the coordinates and geometric properties. | |
| - For geometric proofs (e.g., "Is AB perpendicular to AC?"), explain the reasoning based on the data. | |
| Output ONLY a JSON object with this structure: | |
| { | |
| "answer": "Chuỗi văn bản kết quả cuối cùng (kèm đơn vị nếu có)", | |
| "steps": [ | |
| "Bước 1: ...", | |
| "Bước 2: ...", | |
| ... | |
| ], | |
| "symbolic_expression": "Biểu thức toán học rút gọn (LaTeX format optional)" | |
| } | |
| """ | |
| user_content = f""" | |
| INPUT_TEXT: {input_text} | |
| TARGET_QUESTION: {target_question} | |
| SEMANTIC_DATA: {json.dumps(semantic_data, ensure_ascii=False)} | |
| COORDINATES: {json.dumps(coordinates)} | |
| """ | |
| logger.debug("[SolverAgent] Requesting solution from LLM...") | |
| try: | |
| raw = await self.llm.chat_completions_create( | |
| messages=[ | |
| {"role": "system", "content": system_prompt}, | |
| {"role": "user", "content": user_content} | |
| ], | |
| response_format={"type": "json_object"} | |
| ) | |
| clean_raw = raw.strip() | |
| # Handle potential markdown code blocks if the response_format wasn't strictly honored | |
| if clean_raw.startswith("```"): | |
| import re | |
| match = re.search(r"```(?:json)?\s*(.*?)\s*```", clean_raw, re.DOTALL) | |
| if match: | |
| clean_raw = match.group(1).strip() | |
| try: | |
| solution = json.loads(clean_raw) | |
| except json.JSONDecodeError: | |
| # Last resort: try to find anything between { and } | |
| import re | |
| json_match = re.search(r'(\{.*\})', clean_raw, re.DOTALL) | |
| if json_match: | |
| solution = json.loads(json_match.group(1)) | |
| else: | |
| raise | |
| logger.info("[SolverAgent] Solution generated successfully.") | |
| return solution | |
| except Exception as e: | |
| logger.error(f"[SolverAgent] Error generating solution: {e}") | |
| logger.debug(f"[SolverAgent] Raw LLM output was: \n{raw if 'raw' in locals() else 'N/A'}") | |
| return { | |
| "answer": "Không thể tính toán lời giải tại thời điểm này.", | |
| "steps": ["Đã xảy ra lỗi trong quá trình xử lý lời giải."], | |
| "symbolic_expression": None | |
| } | |