| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- import json
- from typing import Optional, List
- from hello_agents import ReActAgent, HelloAgentsLLM, Config, Message, ToolRegistry
- from dotenv import load_dotenv
- MY_REACT_PROMPT = """
- 请注意,你是一个有能力调用外部工具的智能助手。
- 可用工具如下:
- {tools}
- 请严格按照以下格式进行回应:
- 示例1:
- {{
- "Thought": "我需要先查询今天的美元兑人民币汇率,然后计算出净收益。",
- "Action": {{"tool_name": "Search", "tool_input": "今天美元兑人民币汇率"}},
- "Finish": []
- }}
- 示例2:
- {{
- "Thought": "完成思考,准备给出最终答案。",
- "Action": {{}},
- "Finish": ["子任务1描述", "子任务2描述", "子任务3描述"]
- }}
- 格式说明如下:
- Thought: 你的思考过程,用于分析问题、拆解任务和规划下一步行动。
- Action: 你决定采取的行动,格式必须是:`{{"tool_name": "Search", "tool_input": "今天美元兑人民币汇率"}}`,如果不采取行动,该项必须设置为{{}}。
- Finish: 当你收集到足够的信息,能够回答用户的最终问题时,你必须在此处输出最终结果;如果没有,该项必须设置为[]。
- 现在,请开始解决以下问题:
- Question: {question}
- History: {history}
- """
- # 加载环境变量
- load_dotenv()
- class NewReActAgent(ReActAgent):
- """
- 重写的ReAct Agent - 推理与行动结合的智能体
- """
- def __init__(
- self,
- name: str,
- llm: HelloAgentsLLM,
- tool_registry: ToolRegistry,
- system_prompt: Optional[str] = None,
- config: Optional[Config] = None,
- max_steps: int = 5,
- custom_prompt: Optional[str] = None
- ):
- super().__init__(name, llm, system_prompt, config)
- self.tool_registry = tool_registry
- self.max_steps = max_steps
- self.current_history: List[str] = []
- self.prompt_template = custom_prompt if custom_prompt else MY_REACT_PROMPT
- print(f"✅ {name} 初始化完成,最大步数: {max_steps}")
- def run(self, input_text: str, **kwargs) -> str:
- """运行ReAct Agent"""
- self.current_history = []
- current_step = 0
- print(f"\n🤖 {self.name} 开始处理问题: {input_text}")
- while current_step < self.max_steps:
- current_step += 1
- print(f"\n--- 第 {current_step} 步 ---")
- # 1. 构建提示词
- tools_desc = self.tool_registry.get_tools_description()
- history_str = "\n".join(self.current_history)
- prompt = self.prompt_template.format(
- tools=tools_desc,
- question=input_text,
- history=history_str
- )
- # 2. 调用LLM
- messages = [{"role": "user", "content": prompt}]
- response_text = self.llm.invoke(messages, **kwargs)
- print(response_text)
- # 3. 解析输出
- thought, action, finish = self._parse_output(response_text)
- # 4. 检查完成条件
- if finish:
- final_answer = finish
- return final_answer
- # 5. 执行工具调用
- if action:
- tool_name, tool_input = self._parse_action(action)
- observation = self.tool_registry.execute_tool(tool_name, tool_input)
- self.current_history.append(f"Action: {action}")
- self.current_history.append(f"Observation: {observation}")
- # 达到最大步数:让 LLM 一次性输出最终答案
- print(f"\n⚠️ 达到最大步数 {self.max_steps},开始生成最终答案")
- history_str = "\n".join(self.current_history)
- final_prompt = self.prompt_template.format(
- tools="",
- question=input_text,
- history=history_str +
- "\n\n请基于以上信息一次性给出最终答案(必须填入 Finish 字段)"
- )
- messages = [{"role": "user", "content": final_prompt}]
- final_response = self.llm.invoke(messages, **kwargs)
- thought, action, finish = self._parse_output(final_response)
- if finish:
- final_answer = finish
- return final_answer
- else:
- print("警告:在生成最终答案时,没有找到 Finish 字段。")
- return "抱歉,尝试生成最终答案时出错。"
- def _parse_output(self, text: str):
- # 清理模型输出,尝试提取JSON部分
- cleaned_text = self._extract_json_from_response(text)
- try:
- data = json.loads(cleaned_text)
- thought = data.get("Thought", "")
- action = data.get("Action")
- finish = data.get("Finish", [])
- return thought, action, finish
- except json.JSONDecodeError as e:
- print(f"警告:LLM返回的文本不是有效的JSON格式。原始文本: {text}")
- print(f"JSON解析错误: {e}")
- return "", None, ""
- def _extract_json_from_response(self, text: str) -> str:
- """从模型响应中提取JSON部分"""
- start = text.find('{')
- end = text.rfind('}')
- if start != -1 and end != -1 and start < end:
- candidate = text[start:end+1]
- # 验证这是否是有效的JSON
- try:
- json.loads(candidate)
- return candidate
- except json.JSONDecodeError:
- pass
- def _parse_action(self, action_text: dict):
- # 提取 tool_name 和 tool_input
- if not action_text or not isinstance(action_text, dict):
- return None, None
- tool_name = action_text.get("tool_name")
- tool_input = action_text.get("tool_input")
- return tool_name, tool_input
- if __name__ == "__main__":
- llm = HelloAgentsLLM()
- tool_registry = ToolRegistry()
- agent = NewReActAgent(
- name="Agent",
- llm=llm,
- tool_registry=tool_registry,
- max_steps=5
- )
- question = "请简单介绍你自己"
- try:
- answer = agent.run(question)
- print(f"最终答案: {answer}")
- except Exception as e:
- print(f"执行过程中出现错误: {e}")
|