ReAct框架深度解析:让Agent会思考再行动
Reasoning Acting | 思维链 工具调用 | 数学原理 代码实现 | LangChain实战 | 完整项目代码 什么是ReAct框架核心思想ReAct Reasoning推理 Acting行动传统LLM: 输入 → 直接输出答案 ReAct: 输入 → 思考 → 行动 → 观察 → 思考 → 行动 → ... → 输出关键洞察人类解决问题时会交替进行思考和行动纯思维链CoT缺乏外部信息纯工具调用缺乏推理过程ReAct结合两者优势为什么需要ReAct问题1纯LLM的局限# 问题2023年诺贝尔文学奖得主的出生地人口是多少 # 纯LLM回答 llm.invoke(2023年诺贝尔文学奖得主的出生地人口是多少) # 输出: 抱歉我不知道 ❌ # 原因训练数据截止无法获取最新信息问题2纯工具调用的局限# 直接调用搜索工具 search(2023年诺贝尔文学奖得主) # 输出: Jon Fosse search(Jon Fosse 出生地) # 输出: Haugesund, Norway search(Haugesund 人口) # 输出: 37,000 # 问题 # - 没有推理过程难以调试 # - 无法处理复杂逻辑 # - 容易陷入死循环ReAct的解决方案Thought: 我需要先找到2023年诺贝尔文学奖得主 Action: search[2023年诺贝尔文学奖得主] Observation: Jon Fosse Thought: 现在我知道得主是Jon Fosse需要找他的出生地 Action: search[Jon Fosse 出生地] Observation: Haugesund, Norway Thought: 我找到了出生地是Haugesund现在需要查这个城市的人口 Action: search[Haugesund 人口] Observation: 37,000 Thought: 我已经获得了所有信息可以给出最终答案 Final Answer: 2023年诺贝尔文学奖得主Jon Fosse的出生地Haugesund人口约为37,000人 ✅优势✅ 有清晰的推理过程✅ 可以获取实时信息✅ 易于调试和优化✅ 可解释性强️ ReAct架构详解核心组件┌─────────────────────────────────────────┐ │ ReAct Agent │ ├─────────────────────────────────────────┤ │ │ │ ┌──────────┐ ┌──────────┐ │ │ │ Thought │───→│ Action │ │ │ │ (推理) │ │ (行动) │ │ │ └──────────┘ └────┬─────┘ │ │ ↑ │ │ │ │ ┌────▼─────┐ │ │ │ │Observation│ │ │ │ │ (观察) │ │ │ │ └──────────┘ │ │ │ │ │ │ └───────────────┘ │ │ 迭代循环 │ └─────────────────────────────────────────┘执行流程Step 1: 接收用户问题 ↓ Step 2: Thought - 分析问题决定下一步 ↓ Step 3: Action - 选择并执行工具 ↓ Step 4: Observation - 获取工具返回结果 ↓ Step 5: 判断是否完成 ├─ 是 → Final Answer └─ 否 → 回到 Step 2状态机模型class ReActState: ReAct状态机 def __init__(self): self.question: str # 原始问题 self.thoughts: List[str] [] # 思考历史 self.actions: List[dict] [] # 行动历史 self.observations: List[str] [] # 观察历史 self.final_answer: str None # 最终答案 self.step_count: int 0 # 步数计数 self.max_steps: int 10 # 最大步数️ ReAct数学原理形式化定义ReAct可以看作一个马尔可夫决策过程MDP状态空间 S:s_t (q, h_t)q: 原始问题h_t: 历史轨迹 {(thought_1, action_1, obs_1), ..., (thought_t, action_t, obs_t)}动作空间 A:a_t ∈ {Tool_1, Tool_2, ..., Tool_n, Finish}可以选择的工具或结束转移函数 T:s_{t1} T(s_t, a_t)执行动作a_t获得观察obs_t更新历史奖励函数 R:R 1 如果最终答案正确R 0 否则目标:最大化期望奖励max E[R | policy]policy: π(a_t | s_t) - 策略函数与传统方法的对比方法公式特点Standard PromptingP(y | x)直接生成答案Chain-of-ThoughtP(y, r | x)生成推理答案Tool UseP(a | x) → y选择工具→执行ReActP(r, a, o | x, h)推理行动观察其中x: 输入问题y: 最终答案r: 推理thoughta: 行动actiono: 观察observationh: 历史轨迹 ReAct代码实现方案1从零实现ReActfrom typing import List, Dict, Optional import re class ReActAgent: ReAct Agent实现 def __init__(self, llm, tools: List[callable], max_steps: int 10): self.llm llm self.tools {tool.__name__: tool for tool in tools} self.max_steps max_steps # 历史记录 self.thoughts [] self.actions [] self.observations [] def run(self, question: str) - str: 运行ReAct流程 Args: question: 用户问题 Returns: 最终答案 print(f 问题: {question}\n) for step in range(self.max_steps): print(f--- Step {step 1} ---) # Step 1: Thought - 生成思考 thought self._generate_thought(question) self.thoughts.append(thought) print(f Thought: {thought}) # Step 2: Action - 解析并执行行动 action_name, action_input self._parse_action(thought) if action_name Finish: # 完成任务 final_answer action_input print(f✅ Final Answer: {final_answer}) return final_answer # 执行工具 if action_name in self.tools: observation self.tools[action_name](action_input) self.actions.append({name: action_name, input: action_input}) self.observations.append(observation) print(f Action: {action_name}({action_input})) print(f️ Observation: {observation}\n) else: observation f未知工具: {action_name} print(f❌ {observation}\n) # 超过最大步数 return 抱歉我无法在限定步数内解决这个问题 def _generate_thought(self, question: str) - str: 生成思考内容 # 构建提示词 history self._format_history() prompt f你是一个智能助手使用ReAct框架解决问题。 可用工具 {self._format_tools()} 当前问题{question} {history} 请按照以下格式回答 Thought: 你的思考 Action: 工具名[参数] 或者如果你已经知道答案 Thought: 我已经知道了答案 Action: Finish[最终答案] response self.llm.invoke(prompt).content return response def _parse_action(self, thought: str) - tuple: 解析行动 # 提取Action行 action_match re.search(rAction:\s*(\w)\[(.?)\], thought) if action_match: action_name action_match.group(1) action_input action_match.group(2) return action_name, action_input # 如果没有找到Action默认Finish return Finish, thought def _format_history(self) - str: 格式化历史记录 if not self.thoughts: return history_parts [] for i, (thought, obs) in enumerate(zip(self.thoughts, self.observations)): history_parts.append(fStep {i1}:) history_parts.append(fThought: {thought}) if i len(self.actions): action self.actions[i] history_parts.append(fAction: {action[name]}[{action[input]}]) if obs: history_parts.append(fObservation: {obs}) history_parts.append() return \n.join(history_parts) def _format_tools(self) - str: 格式化工具列表 tools_desc [] for name, tool in self.tools.items(): doc tool.__doc__ or 无描述 tools_desc.append(f- {name}: {doc.split(chr(10))[0]}) return \n.join(tools_desc) # 工具定义 def search(query: str) - str: 搜索网络信息 # 模拟搜索引擎 knowledge_base { 2023年诺贝尔文学奖得主: Jon Fosse, Jon Fosse 出生地: Haugesund, Norway, Haugesund 人口: 37,000, Python最新版本: Python 3.12, 北京天气: 晴25°C } return knowledge_base.get(query, f未找到{query}的信息) def calculate(expression: str) - str: 计算数学表达式 try: result eval(expression, {__builtins__: {}}, {}) return str(result) except: return 计算错误 # 使用示例 def example_react_agent(): ReAct Agent使用示例 from langchain_openai import ChatOpenAI # 创建LLM llm ChatOpenAI(modelgpt-4, temperature0) # 创建Agent agent ReActAgent( llmllm, tools[search, calculate], max_steps10 ) # 测试问题 question 2023年诺贝尔文学奖得主的出生地人口是多少 answer agent.run(question) print(f\n 最终答案: {answer}) if __name__ __main__: example_react_agent()方案2使用LangChain ReActfrom langchain.agents import create_react_agent, AgentExecutor from langchain.tools import tool from langchain_openai import ChatOpenAI from langchain.prompts import PromptTemplate # 定义工具 tool def search_knowledge(query: str) - str: 搜索知识库获取信息 knowledge_base { 2023年诺贝尔文学奖: Jon Fosse, Jon Fosse: 挪威作家出生于Haugesund, Haugesund: 挪威城市人口约37,000 } for key, value in knowledge_base.items(): if key in query: return value return 未找到相关信息 tool def calculate_math(expression: str) - str: 计算数学表达式 try: result eval(expression, {__builtins__: {}}, {}) return str(result) except: return 计算错误 # 创建ReAct Agent def create_react_agent_example(): 创建LangChain ReAct Agent llm ChatOpenAI(modelgpt-4, temperature0) tools [search_knowledge, calculate_math] # ReAct提示词模板 react_prompt PromptTemplate.from_template( Answer the following questions as best you can. You have access to the following tools: {tools} Use the following format: Question: the input question you must answer Thought: you should always think about what to do Action: the action to take, should be one of [{tool_names}] Action Input: the input to the action Observation: the result of the action ... (this Thought/Action/Action Input/Observation can repeat N times) Thought: I now know the final answer Final Answer: the final answer to the original input question Begin! Question: {input} Thought:{agent_scratchpad} ) # 创建Agent agent create_react_agent(llm, tools, react_prompt) # 创建执行器 agent_executor AgentExecutor( agentagent, toolstools, verboseTrue, max_iterations10, handle_parsing_errorsTrue ) return agent_executor # 使用示例 def example_langchain_react(): LangChain ReAct示例 agent create_react_agent_example() question 2023年诺贝尔文学奖得主的出生地人口是多少 result agent.invoke({input: question}) print(f\n✅ 答案: {result[output]}) if __name__ __main__: example_langchain_react() ReAct优化技巧1. 提示词工程优化# 好的ReAct提示词 react_prompt 你是一个智能助手使用ReAct框架逐步解决问题。 可用工具 - search: 搜索信息 - calculate: 数学计算 - get_weather: 查询天气 重要规则 1. 每次只执行一个动作 2. 仔细观察每个动作的结果 3. 基于观察结果进行下一步推理 4. 当确信知道答案时使用Finish 格式 Thought: 推理过程 Action: 工具名[参数] Observation: 工具返回 ... Final Answer: 最终答案 2. 工具设计优化# 好的工具设计 tool def search_precise(query: str) - str: 精确搜索特定信息 参数应该是具体的查询词如 - 2023年诺贝尔文学奖得主 - Python 3.12发布日期 避免模糊查询。 pass # 不好的工具设计 tool def search(x): 搜索 pass3. 早期停止策略class SmartReActAgent(ReActAgent): 智能ReAct Agent - 带早期停止 def _should_stop(self, thought: str, observation: str) - bool: 判断是否应该停止 # 策略1观察到明确答案 if 答案是 in observation or 结果是 in observation: return True # 策略2重复观察可能陷入循环 if observation in self.observations[-3:]: return True # 策略3达到置信度阈值 confidence self._estimate_confidence(thought, observation) if confidence 0.9: return True return False def _estimate_confidence(self, thought: str, observation: str) - float: 估计答案置信度 # 简化实现基于关键词 confidence_keywords [确定, 确认, 显然是, 毫无疑问] score sum(1 for kw in confidence_keywords if kw in thought) return min(score / len(confidence_keywords), 1.0)4. 并行探索Tree of Thoughts扩展class ParallelReActAgent(ReActAgent): 并行ReAct - 同时探索多个思路 def run_parallel(self, question: str, num_paths: int 3) - str: 并行运行多个ReAct路径 results [] for i in range(num_paths): # 每个路径独立运行 agent_copy self.clone() result agent_copy.run(question) results.append({ path: i 1, answer: result, steps: agent_copy.step_count }) # 投票选择最佳答案 best_answer self._vote(results) return best_answer def _vote(self, results: List[dict]) - str: 投票机制 # 统计相同答案的出现次数 answer_counts {} for r in results: answer r[answer] answer_counts[answer] answer_counts.get(answer, 0) 1 # 返回出现最多的答案 return max(answer_counts, keyanswer_counts.get) ReAct性能评估评估指标指标说明目标值准确率正确答案比例 85%平均步数完成任务的平均步数 5步成功率成功完成任务的比例 90%响应时间从输入到输出的时间 10秒Token消耗每次任务的Token数 2000基准测试def benchmark_react(): ReAct性能基准测试 test_cases [ { question: 2023年诺贝尔文学奖得主的出生地人口是多少, expected_answer: 37000 }, { question: 计算 (123 456) * 789, expected_answer: 456831 }, { question: Python的最新版本是什么, expected_answer: 3.12 } ] agent ReActAgent(llm, tools[search, calculate]) results [] for test in test_cases: start_time time.time() answer agent.run(test[question]) elapsed time.time() - start_time # 评估准确性 is_correct test[expected_answer] in answer results.append({ question: test[question], correct: is_correct, steps: agent.step_count, time: elapsed }) # 统计结果 accuracy sum(1 for r in results if r[correct]) / len(results) avg_steps sum(r[steps] for r in results) / len(results) avg_time sum(r[time] for r in results) / len(results) print(f准确率: {accuracy:.2%}) print(f平均步数: {avg_steps:.1f}) print(f平均时间: {avg_time:.2f}秒) ReAct vs 其他框架对比分析框架优点缺点适用场景ReAct推理行动可解释性强步数多速度慢复杂多步任务CoT简单快速无法获取外部信息纯推理任务Toolformer自动学习工具使用训练成本高大规模部署Self-Ask分解子问题需要预定义分解结构化问题选择建议任务类型判断 ├─ 需要外部信息 │ ├─ 是 → ReAct 或 Self-Ask │ └─ 否 → CoT │ ├─ 需要多步推理 │ ├─ 是 → ReAct │ └─ 否 → Standard Prompting │ └─ 需要高可解释性 ├─ 是 → ReAct └─ 否 → Toolformer 最佳实践总结1. 提示词设计# ✅ 好的提示词 prompt 按以下步骤思考 1. 理解问题的核心 2. 确定需要的信息 3. 选择合适的工具 4. 执行并观察结果 5. 基于结果继续推理 # ❌ 不好的提示词 prompt 回答问题2. 工具粒度# ✅ 细粒度工具推荐 tool def search_person(name: str): ... tool def search_place(place: str): ... tool def search_number(query: str): ... # ❌ 粗粒度工具 tool def search_anything(query: str): ...3. 错误处理try: observation tool(action_input) except Exception as e: observation f工具执行失败: {str(e)} # 在下一步Thought中处理错误4. 调试技巧# 启用详细日志 agent ReActAgent(llm, tools, verboseTrue) # 保存执行轨迹 trajectory { thoughts: agent.thoughts, actions: agent.actions, observations: agent.observations } save_to_file(trajectory, debug.json) 相关资源ReAct论文LangChain ReAct文档配套项目代码 总结ReAct框架通过结合推理Reasoning和行动Acting让Agent能够✅像人类一样思考- 清晰的推理过程✅获取外部信息- 调用工具弥补知识盲区✅自我修正- 基于观察调整策略✅可解释性强- 每一步都有据可查掌握ReAct框架你就能构建出真正智能的Agent系统下一步动手实现一个ReAct Agent从简单的问答开始逐步增加复杂度。专栏AI Agent实战专栏日期2026年5月12日系列Agent底层原理与前沿技术系列第1篇