from fastapi import APIRouter from pydantic import BaseModel from typing import Optional from app.graphs.analysis_graph import create_analysis_graph router = APIRouter(prefix="/api/v1", tags=["analyze"]) _graph = None def get_graph(): global _graph if _graph is None: _graph = create_analysis_graph() return _graph class AnalyzeRequest(BaseModel): report_id: int user_id: int focus: Optional[str] = None class AnalyzeResponse(BaseModel): analysis: str = "" recommendations: list[str] = [] trace_id: str = "" @router.post("/analyze", response_model=AnalyzeResponse) async def analyze(req: AnalyzeRequest): graph = get_graph() import uuid trace_id = str(uuid.uuid4()) # MemorySaver/AsyncSqliteSaver 均要求 config 提供 thread_id,缺省会抛 # "Checkpointer requires one or more of the following 'configurable' keys" config = { "configurable": {"thread_id": f"analyze_{req.user_id}_{trace_id}"}, } result = await graph.ainvoke({ "report_id": req.report_id, "user_id": req.user_id, "focus": req.focus, "report_data": None, "survey_data": None, "dimension_scores": None, "analysis": None, "recommendations": [], }, config) return AnalyzeResponse(analysis=result.get("analysis", ""), trace_id=trace_id)