ReAct.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import re
  2. from llm_client import HelloAgentsLLM
  3. from tools import ToolExecutor, search
  4. # (此处省略 REACT_PROMPT_TEMPLATE 的定义)
  5. REACT_PROMPT_TEMPLATE = """
  6. 请注意,你是一个有能力调用外部工具的智能助手。
  7. 可用工具如下:
  8. {tools}
  9. 请严格按照以下格式进行回应:
  10. Thought: 你的思考过程,用于分析问题、拆解任务和规划下一步行动。
  11. Action: 你决定采取的行动,必须是以下格式之一:
  12. - `{{tool_name}}[{{tool_input}}]`:调用一个可用工具。
  13. - `Finish[最终答案]`:当你认为已经获得最终答案时。
  14. - 当你收集到足够的信息,能够回答用户的最终问题时,你必须在`Action:`字段后使用 `Finish[最终答案]` 来输出最终答案。
  15. 现在,请开始解决以下问题:
  16. Question: {question}
  17. History: {history}
  18. """
  19. class ReActAgent:
  20. def __init__(self, llm_client: HelloAgentsLLM, tool_executor: ToolExecutor, max_steps: int = 5):
  21. self.llm_client = llm_client
  22. self.tool_executor = tool_executor
  23. self.max_steps = max_steps
  24. self.history = []
  25. def run(self, question: str):
  26. self.history = []
  27. current_step = 0
  28. while current_step < self.max_steps:
  29. current_step += 1
  30. print(f"\n--- 第 {current_step} 步 ---")
  31. tools_desc = self.tool_executor.getAvailableTools()
  32. history_str = "\n".join(self.history)
  33. prompt = REACT_PROMPT_TEMPLATE.format(tools=tools_desc, question=question, history=history_str)
  34. messages = [{"role": "user", "content": prompt}]
  35. response_text = self.llm_client.think(messages=messages)
  36. if not response_text:
  37. print("错误:LLM未能返回有效响应。"); break
  38. thought, action = self._parse_output(response_text)
  39. if thought: print(f"🤔 思考: {thought}")
  40. if not action: print("警告:未能解析出有效的Action,流程终止。"); break
  41. if action.startswith("Finish"):
  42. # 如果是Finish指令,提取最终答案并结束
  43. final_answer = self._parse_action_input(action)
  44. print(f"🎉 最终答案: {final_answer}")
  45. return final_answer
  46. tool_name, tool_input = self._parse_action(action)
  47. if not tool_name or not tool_input:
  48. self.history.append("Observation: 无效的Action格式,请检查。"); continue
  49. print(f"🎬 行动: {tool_name}[{tool_input}]")
  50. tool_function = self.tool_executor.getTool(tool_name)
  51. observation = tool_function(tool_input) if tool_function else f"错误:未找到名为 '{tool_name}' 的工具。"
  52. print(f"👀 观察: {observation}")
  53. self.history.append(f"Action: {action}")
  54. self.history.append(f"Observation: {observation}")
  55. print("已达到最大步数,流程终止。")
  56. return None
  57. def _parse_output(self, text: str):
  58. # Thought: 匹配到 Action: 或文本末尾
  59. thought_match = re.search(r"Thought:\s*(.*?)(?=\nAction:|$)", text, re.DOTALL)
  60. # Action: 匹配到文本末尾
  61. action_match = re.search(r"Action:\s*(.*?)$", text, re.DOTALL)
  62. thought = thought_match.group(1).strip() if thought_match else None
  63. action = action_match.group(1).strip() if action_match else None
  64. return thought, action
  65. def _parse_action(self, action_text: str):
  66. match = re.match(r"(\w+)\[(.*)\]", action_text, re.DOTALL)
  67. return (match.group(1), match.group(2)) if match else (None, None)
  68. def _parse_action_input(self, action_text: str):
  69. match = re.match(r"\w+\[(.*)\]", action_text, re.DOTALL)
  70. return match.group(1) if match else ""
  71. if __name__ == '__main__':
  72. llm = HelloAgentsLLM()
  73. tool_executor = ToolExecutor()
  74. search_desc = "一个网页搜索引擎。当你需要回答关于时事、事实以及在你的知识库中找不到的信息时,应使用此工具。"
  75. tool_executor.registerTool("Search", search_desc, search)
  76. agent = ReActAgent(llm_client=llm, tool_executor=tool_executor)
  77. question = "华为最新的手机是哪一款?它的主要卖点是什么?"
  78. agent.run(question)