expert_agents.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. """专家Agent模块 - 处理不同类型的问题"""
  2. from abc import ABC, abstractmethod
  3. from typing import Dict, Any, List
  4. from loguru import logger
  5. from openai import OpenAI
  6. from ..models.schemas import QuestionType, AgentContext, RAGResult, ToolCallResult
  7. class BaseExpertAgent(ABC):
  8. """专家Agent基类"""
  9. def __init__(self, openai_client: OpenAI):
  10. self.client = openai_client
  11. @abstractmethod
  12. async def need_rag(self, user_question: str) -> bool:
  13. """判断是否需要RAG查询"""
  14. pass
  15. @abstractmethod
  16. async def need_tool_call(self, user_question: str, context: AgentContext) -> bool:
  17. """判断是否需要工具调用"""
  18. pass
  19. @abstractmethod
  20. async def generate_response(self, context: AgentContext) -> str:
  21. """生成最终回复"""
  22. pass
  23. class PageNavigationAgent(BaseExpertAgent):
  24. """页面跳转引导专家Agent"""
  25. async def need_rag(self, user_question: str) -> bool:
  26. """页面跳转通常需要查询页面路径信息"""
  27. return True
  28. async def need_tool_call(self, user_question: str, context: AgentContext) -> bool:
  29. """页面跳转需要调用跳转工具"""
  30. return True
  31. async def generate_response(self, context: AgentContext) -> str:
  32. """生成页面跳转引导回复"""
  33. try:
  34. prompt = f"""
  35. 你是MES系统的页面跳转助手。用户想要执行某个操作,请根据以下信息生成友好的引导回复:
  36. 用户问题:{context.user_question}
  37. RAG查询结果:
  38. {self._format_rag_results(context.rag_results)}
  39. 工具调用结果:
  40. {self._format_tool_results(context.tool_call_results)}
  41. 请生成一个友好、明确的回复,告诉用户如何完成他们想要的操作。
  42. """
  43. response = self.client.chat.completions.create(
  44. model="gpt-3.5-turbo",
  45. messages=[{"role": "user", "content": prompt}],
  46. temperature=0.7,
  47. max_tokens=300
  48. )
  49. return response.choices[0].message.content.strip()
  50. except Exception as e:
  51. logger.error(f"页面跳转Agent生成回复失败: {e}")
  52. return "抱歉,页面跳转引导暂时无法使用,请稍后再试。"
  53. def _format_rag_results(self, rag_results: List[RAGResult]) -> str:
  54. """格式化RAG结果"""
  55. if not rag_results:
  56. return "无相关信息"
  57. formatted = []
  58. for result in rag_results:
  59. formatted.append(f"- {result.content} (来源: {result.source})")
  60. return "\n".join(formatted)
  61. def _format_tool_results(self, tool_results: List[ToolCallResult]) -> str:
  62. """格式化工具调用结果"""
  63. if not tool_results:
  64. return "无工具调用"
  65. formatted = []
  66. for result in tool_results:
  67. status = "成功" if result.success else f"失败: {result.error_message}"
  68. formatted.append(f"- 工具 {result.tool_name}: {status}")
  69. return "\n".join(formatted)
  70. class SystemGuideAgent(BaseExpertAgent):
  71. """系统使用引导专家Agent"""
  72. async def need_rag(self, user_question: str) -> bool:
  73. """系统引导总是需要查询知识库"""
  74. return True
  75. async def need_tool_call(self, user_question: str, context: AgentContext) -> bool:
  76. """系统引导通常不需要工具调用"""
  77. return False
  78. async def generate_response(self, context: AgentContext) -> str:
  79. """生成系统使用引导回复"""
  80. try:
  81. prompt = f"""
  82. 你是MES系统的使用引导专家。请根据以下信息为用户提供详细的使用指导:
  83. 用户问题:{context.user_question}
  84. 知识库信息:
  85. {self._format_rag_results(context.rag_results)}
  86. 请生成一个详细、易懂的使用指导,包含具体步骤。
  87. """
  88. response = self.client.chat.completions.create(
  89. model="gpt-3.5-turbo",
  90. messages=[{"role": "user", "content": prompt}],
  91. temperature=0.5,
  92. max_tokens=500
  93. )
  94. return response.choices[0].message.content.strip()
  95. except Exception as e:
  96. logger.error(f"系统引导Agent生成回复失败: {e}")
  97. return "抱歉,系统使用引导暂时无法使用,请稍后再试。"
  98. def _format_rag_results(self, rag_results: List[RAGResult]) -> str:
  99. """格式化RAG结果"""
  100. if not rag_results:
  101. return "无相关文档"
  102. formatted = []
  103. for result in rag_results:
  104. formatted.append(f"- {result.content}")
  105. return "\n".join(formatted)
  106. class ProductionQAAgent(BaseExpertAgent):
  107. """生产QA专家Agent"""
  108. async def need_rag(self, user_question: str) -> bool:
  109. """生产QA可能需要RAG查询历史数据"""
  110. return True
  111. async def need_tool_call(self, user_question: str, context: AgentContext) -> bool:
  112. """生产QA可能需要查询数据库"""
  113. return True
  114. async def generate_response(self, context: AgentContext) -> str:
  115. """生成生产QA回复"""
  116. try:
  117. prompt = f"""
  118. 你是MES系统的生产数据分析专家。请根据以下信息回答用户关于生产情况的问题:
  119. 用户问题:{context.user_question}
  120. RAG查询结果:
  121. {self._format_rag_results(context.rag_results)}
  122. 数据库查询结果:
  123. {self._format_tool_results(context.tool_call_results)}
  124. 请生成一个数据驱动的专业回复。
  125. """
  126. response = self.client.chat.completions.create(
  127. model="gpt-3.5-turbo",
  128. messages=[{"role": "user", "content": prompt}],
  129. temperature=0.3,
  130. max_tokens=400
  131. )
  132. return response.choices[0].message.content.strip()
  133. except Exception as e:
  134. logger.error(f"生产QA Agent生成回复失败: {e}")
  135. return "抱歉,生产数据查询暂时无法使用,请稍后再试。"
  136. def _format_rag_results(self, rag_results: List[RAGResult]) -> str:
  137. """格式化RAG结果"""
  138. if not rag_results:
  139. return "无历史数据"
  140. formatted = []
  141. for result in rag_results:
  142. formatted.append(f"- {result.content}")
  143. return "\n".join(formatted)
  144. def _format_tool_results(self, tool_results: List[ToolCallResult]) -> str:
  145. """格式化工具调用结果"""
  146. if not tool_results:
  147. return "无数据库查询结果"
  148. formatted = []
  149. for result in tool_results:
  150. if result.success:
  151. formatted.append(f"- {result.tool_name}: {result.result}")
  152. else:
  153. formatted.append(f"- {result.tool_name}: 查询失败 - {result.error_message}")
  154. return "\n".join(formatted)
  155. class ChatAgent(BaseExpertAgent):
  156. """闲聊专家Agent"""
  157. async def need_rag(self, user_question: str) -> bool:
  158. """闲聊通常不需要RAG"""
  159. return False
  160. async def need_tool_call(self, user_question: str, context: AgentContext) -> bool:
  161. """闲聊通常不需要工具调用"""
  162. return False
  163. async def generate_response(self, context: AgentContext) -> str:
  164. """生成闲聊回复"""
  165. try:
  166. prompt = f"""
  167. 你是一个友好的MES系统助手。用户在进行日常闲聊,请以友好、自然的方式回复:
  168. 用户问题:{context.user_question}
  169. 请生成一个友好、自然的回复,同时可以适当引导用户使用MES系统的功能。
  170. """
  171. response = self.client.chat.completions.create(
  172. model="gpt-3.5-turbo",
  173. messages=[{"role": "user", "content": prompt}],
  174. temperature=0.8,
  175. max_tokens=200
  176. )
  177. return response.choices[0].message.content.strip()
  178. except Exception as e:
  179. logger.error(f"闲聊Agent生成回复失败: {e}")
  180. return "你好!我是MES系统助手,很高兴为您服务。有什么我可以帮助您的吗?"
  181. class ExpertAgentFactory:
  182. """专家Agent工厂类"""
  183. @staticmethod
  184. def create_agent(question_type: QuestionType, openai_client: OpenAI) -> BaseExpertAgent:
  185. """根据问题类型创建对应的专家Agent"""
  186. agent_mapping = {
  187. QuestionType.PAGE_NAVIGATION: PageNavigationAgent,
  188. QuestionType.SYSTEM_GUIDE: SystemGuideAgent,
  189. QuestionType.PRODUCTION_QA: ProductionQAAgent,
  190. QuestionType.CHAT: ChatAgent,
  191. }
  192. agent_class = agent_mapping.get(question_type, ChatAgent)
  193. return agent_class(openai_client)