profile_extraction_agent.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. """用户画像提取子Agent
  2. 将用户画像提取逻辑封装为独立的 SimpleAgent 子类,使其成为多智能体系统中的
  3. 一个专门子代理,而不是在服务层直接调用 LLM。
  4. """
  5. from hello_agents import SimpleAgent, HelloAgentsLLM
  6. # ============ Agent 系统提示词 ============
  7. SYSTEM_PROMPT = """你是一个用户偏好分析专家。你的任务是根据用户的对话消息,提取该用户的旅行偏好。
  8. ## 核心规则
  9. 1. 只从「用户消息」中提取用户**自己表达**的偏好,不要提取AI助手的建议或推荐
  10. 2. 如果用户消息需要结合对话历史才能理解(如"好的"、"这个不错"、"是的"),参考上下文来推断用户偏好
  11. 3. 不要提取一次性信息(如"明天去故宫"),只提取稳定的偏好特征(如"喜欢历史文化景点")
  12. 4. 每条控制在20字以内,总条目不超过8条
  13. 5. 宁缺毋滥,只输出有明显依据的偏好
  14. ## 冲突处理(重要)
  15. 将新提取的偏好与「已有画像」逐条对比:
  16. - **冲突**:如果新消息表达的偏好与某条旧画像矛盾(如"喜欢安静" vs "喜欢热闹"),删除旧条目,用新条目替代
  17. - **一致**:如果新消息与旧画像一致,保留旧画像条目(不重复添加)
  18. - **新增**:如果新消息表达了旧画像中没有的偏好,作为新条目添加
  19. - **无关**:如果用户消息不包含偏好信息,跳过本轮提取
  20. ## 输出格式
  21. 只输出更新后的完整画像,每行一条,以"- "开头,不要输出任何其他内容:
  22. - 偏好1
  23. - 偏好2
  24. """
  25. class ProfileExtractionAgent(SimpleAgent):
  26. """用户画像提取子Agent
  27. 专门从用户对话消息中提取旅行偏好,与已有画像合并更新。
  28. 不需要工具调用,纯 LLM 文本分析任务。
  29. """
  30. def __init__(self, llm: HelloAgentsLLM):
  31. """
  32. 初始化画像提取 Agent
  33. Args:
  34. llm: LLM 实例
  35. """
  36. super().__init__(
  37. name="用户画像提取专家",
  38. llm=llm,
  39. system_prompt=SYSTEM_PROMPT,
  40. enable_tool_calling=False, # 纯文本分析,无需工具
  41. )
  42. def extract(
  43. self,
  44. existing_profile: str,
  45. conversation_context: str,
  46. user_message: str,
  47. ) -> str:
  48. """
  49. 从用户消息中提取偏好,与已有画像对比合并
  50. Args:
  51. existing_profile: 已有画像文本("- "开头的条目),无则传空字符串
  52. conversation_context: 对话上下文文本(含历史会话摘要+当前会话最近消息)
  53. user_message: 最新用户消息
  54. Returns:
  55. 更新后的完整画像文本("- "开头的行),若无可提取内容则返回空字符串
  56. """
  57. input_text = (
  58. f"已有画像:\n{existing_profile or '(无)'}\n\n"
  59. f"对话历史(用于理解上下文):\n{conversation_context or '(无)'}\n\n"
  60. f"最新用户消息:{user_message}\n\n"
  61. f"请输出更新后的完整画像:"
  62. )
  63. result = self.run(input_text)
  64. return result.strip()