self_check_trend_graph.py 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import json
  2. import logging
  3. from typing import TypedDict, Optional
  4. from langgraph.graph import StateGraph, START, END
  5. from langchain_core.messages import SystemMessage, HumanMessage
  6. from app.llm.client import get_llm
  7. from app.monitoring import monitor_agent
  8. from app.prompt_service import get_prompt
  9. logger = logging.getLogger(__name__)
  10. SYSTEM_PROMPT = """分析用户近3次五维自检趋势,输出:
  11. - aiInsight: 趋势解读(2-3句,指出最大变化维度和可能原因,口语化)
  12. - trendSummary: 各维度 delta 简写(如"身-2 智+1 富0 行-1 心+2")
  13. 返回 JSON:{"aiInsight": "...", "trendSummary": "..."}
  14. """
  15. class TrendState(TypedDict):
  16. history: list
  17. user_id: int
  18. insight: Optional[dict]
  19. error: Optional[str]
  20. class SelfCheckTrendAgent:
  21. def __init__(self):
  22. self.llm = get_llm()
  23. @monitor_agent("self_check_trend")
  24. async def run(self, history: list, user_id: int) -> dict:
  25. try:
  26. if len(history) < 2:
  27. return {"insight": {"aiInsight": "自检次数不足,建议完成至少2次自检后查看趋势", "trendSummary": ""}, "error": None}
  28. history_text = "\n".join(
  29. f"{h.get('createdAt', '')}: 总分{h.get('totalScore', 0)}," +
  30. " ".join(f"{d.get('name','')}{d.get('score',0)}分" for d in h.get('dimensions', []))
  31. for h in history[-3:]
  32. )
  33. messages = [
  34. SystemMessage(content=await get_prompt("self_check_trend") or SYSTEM_PROMPT),
  35. HumanMessage(content=f"用户{user_id}的自检历史:\n{history_text}"),
  36. ]
  37. response = await self.llm.ainvoke(messages)
  38. text = response.content.strip()
  39. if "```json" in text:
  40. text = text.split("```json")[1].split("```")[0].strip()
  41. elif "```" in text:
  42. text = text.split("```")[1].split("```")[0].strip()
  43. data = json.loads(text)
  44. return {"insight": data, "error": None}
  45. except Exception as e:
  46. logger.warning("趋势分析失败: %s", e)
  47. return {"insight": {"aiInsight": "", "trendSummary": ""}, "error": str(e)}
  48. def build_trend_graph():
  49. agent = SelfCheckTrendAgent()
  50. async def call_llm(state: TrendState) -> dict:
  51. return await agent.run(state["history"], state["user_id"])
  52. graph = StateGraph(TrendState)
  53. graph.add_node("llm", call_llm)
  54. graph.add_edge(START, "llm")
  55. graph.add_edge("llm", END)
  56. return graph.compile()
  57. _trend_graph = None
  58. def get_trend_graph():
  59. global _trend_graph
  60. if _trend_graph is None:
  61. _trend_graph = build_trend_graph()
  62. return _trend_graph