article_quiz_graph.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. from langchain_openai import ChatOpenAI
  2. from langchain_core.messages import SystemMessage, HumanMessage
  3. from app.config import settings
  4. from app.monitoring import monitor_agent
  5. from app.prompt_service import get_prompt
  6. import json
  7. import logging
  8. logger = logging.getLogger(__name__)
  9. SYSTEM_PROMPT = """你是一位家庭教育出题助手。根据给定的文章内容,为读者生成 3 道单项选择题。
  10. 要求:
  11. 1. 每题 4 个选项,选项以 "A. "、"B. "、"C. "、"D. " 开头
  12. 2. 题目考察文章核心内容的理解,适合青少年读者
  13. 3. 每题标注所属五维(body/mind/wisdom/action/wealth),缺省为 wisdom
  14. 4. 以 JSON 数组格式返回,不要返回其他文字,只返回 JSON 数组
  15. 输出格式:
  16. [
  17. {"question": "问题", "options": ["A. xxx", "B. xxx", "C. xxx", "D. xxx"], "answer": "A", "dimension": "wisdom", "explanation": "解析"}
  18. ]
  19. """
  20. class ArticleQuizAgent:
  21. def __init__(self):
  22. self.llm = ChatOpenAI(
  23. model=settings.llm_model,
  24. api_key=settings.llm_api_key,
  25. base_url=settings.llm_base_url,
  26. temperature=settings.llm_temperature,
  27. )
  28. @monitor_agent("article_quiz")
  29. async def run(self, article_title: str, article_content: str, profile_summary: str = "") -> dict:
  30. """根据文章内容生成 3 道选择题,失败返回空 questions"""
  31. try:
  32. human = f"文章标题:{article_title}\n文章内容:{article_content}"
  33. if profile_summary:
  34. human += f"\n用户画像摘要:{profile_summary}"
  35. messages = [
  36. SystemMessage(content=await get_prompt("article_quiz") or SYSTEM_PROMPT),
  37. HumanMessage(content=human),
  38. ]
  39. response = await self.llm.ainvoke(messages)
  40. content = response.content.strip()
  41. if "```json" in content:
  42. content = content.split("```json")[1].split("```")[0].strip()
  43. elif "```" in content:
  44. content = content.split("```")[1].split("```")[0].strip()
  45. questions = json.loads(content)
  46. if not isinstance(questions, list):
  47. return {"questions": [], "fallback_used": True}
  48. return {"questions": questions, "fallback_used": False}
  49. except Exception as e:
  50. logger.warning("文章出题生成失败: %s", e)
  51. return {"questions": [], "fallback_used": True}