深入理解 ReAct 模式:让大模型学会推理与行动

6135 字
31 分钟
深入理解 ReAct 模式:让大模型学会推理与行动

1. ReAct 的引入#

1.1 传统 LLM 的局限#

传统的大语言模型本质上是一个封闭的对话系统

  • 只能基于训练数据:无法获取实时信息
  • 无法执行操作:不能调用工具、操作外部系统
  • 推理受限:无法与外部世界交互验证
  • 无法长期记忆:每次对话独立,无持久化

这就像一个博学但孤立的天才

  • 知道很多,但不能查询最新信息
  • 能推理,但不能验证
  • 能说话,但不能行动

1.2 ReAct 的诞生#

ReAct (Reasoning + Acting) 由 Shunyu Yao 等人在 2022 年 10 月提出 (ICLR 2023):

将”思考”和”行动”统一在一个框架中,让 LLM 在推理的同时执行操作,与外部世界交互。

核心洞察

传统 CoT: 思考 → 答案(无行动)
ReAct: 思考 + 行动 → 观察 → 思考 → ... → 答案
↓ ↓
Reason 决定 Act 执行操作
下一步怎么办 并获取反馈

1.3 ReAct 的革命性意义#

ReAct 标志着 LLM 从纯推理模型进化为Agent 系统

维度纯推理模型ReAct Agent
推理
工具使用
外部交互
错误恢复
长期任务
可验证性

1.4 ReAct 发展简史#

2022.10: ReAct (Yao et al.)
│ 首次提出 Thought-Action-Observation 循环
2023: AutoGPT / BabyAGI 兴起
│ 基于 ReAct 思路的自主 Agent
2023.06: Toolformer (Schick et al.)
│ 让 LLM 学会自动调用工具
2023.07: LangChain 集成 ReAct
│ 主流框架支持
2023.11: OpenAI Function Calling
│ 原生工具调用能力
2024: Agent 系统爆发
│ GPTs, Claude Tools, Gemini Function Call
2024-2025: ReAct 的局限反思
│ Plan-and-Execute, Reflexion, ...
│ ReAct 仍是最经典的基础模式

2. ReAct 的核心思想#

2.1 人类认知的类比#

人类解决问题的过程:

遇到问题:我的航班延误了,需要改签
思考 1: 我需要先了解我的预订信息
行动 1: 查看我的预订 (Search Booking)
观察 1: 订单 #12345, 7:00 出发
思考 2: 我需要知道航班状态
行动 2: 查询航班状态 (Check Flight Status)
观察 2: 航班已取消
思考 3: 我需要找到替代航班
行动 3: 搜索替代航班 (Search Alternatives)
观察 3: 有 3 个选择: 9:00, 14:00, 18:00
思考 4: 让我选 14:00 的,因为时间合适
行动 4: 改签航班 (Reschedule Flight)
观察 4: 改签成功
思考 5: 任务完成,告知用户
最终答案: 航班已成功改签至 14:00

2.2 Thought-Action-Observation 循环#

ReAct 的核心是三个元素的循环:

┌─────────────────────────────────────────────────────────────────┐
│ ReAct 循环 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Thought (思考) │
│ "我需要做什么?" │
│ │ │
│ ▼ │
│ Action (行动) │
│ "执行具体的工具调用" │
│ │ │
│ ▼ │
│ Observation (观察) │
│ "我得到了什么结果?" │
│ │ │
│ ▼ │
│ Thought (再次思考) │
│ "根据结果,下一步怎么做?" │
│ │ │
│ ▼ │
│ ... 循环直到得出答案 ... │
│ │
└─────────────────────────────────────────────────────────────────┘

2.3 ReAct 的优势#

2.3.1 透明性#

每个 Thought 都展示了 LLM 的”思维过程”:

  • 可审计:可以追踪决策路径
  • 可调试:错误容易定位
  • 可解释:用户能理解 AI 在想什么

2.3.2 可验证#

通过实际执行行动来验证推理:

  • 不只靠 LLM “想”,还要靠工具”验证”
  • 减少幻觉和错误

2.3.3 可扩展#

通过添加新工具扩展能力:

  • 添加搜索引擎 → 联网能力
  • 添加数据库 → 业务数据访问
  • 添加 API → 各种服务

2.4 ReAct 的数学形式#

ReAct 可以形式化为一个部分可观察的马尔可夫决策过程 (POMDP)

  • 状态 (State) sts_t:历史 Thought-Action-Observation 序列
  • 动作 (Action) ata_t:选择下一步 Thought 或工具调用
  • 观测 (Observation) oto_t:工具执行结果
  • 奖励 (Reward) rtr_t:任务完成度

策略 π(as)\pi(a|s) 由 LLM 参数化。

3. ReAct 的核心机制#

3.1 Prompt 模板#

经典的 ReAct Prompt 模板:

REACT_PROMPT_TEMPLATE = """
回答以下问题,请使用 Thought-Action-Observation 的方式一步步推理。
可用工具:
{tool_descriptions}
格式要求:
Thought: [你对当前情况的分析]
Action: [工具名称][工具输入]
Observation: [工具返回的结果]
... (重复 Thought/Action/Observation 直到有足够信息)
Thought: 我现在可以给出最终答案了
Final Answer: [你的最终答案]
开始!
问题:{question}
历史:
{history}
Thought:
"""

3.2 Thought 的类型#

ReAct 中有不同类型的 Thought:

class ThoughtType:
"""Thought 的类型分类"""
PLANNING = "planning" # 规划:分解任务
INFORMATION_SEEKING = "info" # 信息寻求:寻找信息
REASONING = "reasoning" # 推理:逻辑推导
CALCULATION = "calculation" # 计算:数学运算
VERIFICATION = "verification" # 验证:检查正确性
RE_REVISION = "revision" # 修正:纠正错误
FINAL_ANSWER = "final" # 最终答案

示例

Thought 1: 我需要先了解用户的预订信息
类型: INFORMATION_SEEKING
Thought 2: 用户预订在 7:00,因此需要查询这个时间的航班
类型: PLANNING
Thought 3: 7:00 的航班是 AA123,让我计算是否会延误
类型: CALCULATION
Thought 4: 根据观察,航班延误 2 小时,我需要找替代方案
类型: REASONING
Thought 5: 让我验证一下这个替代航班是否还有座位
类型: VERIFICATION
Thought 6: 现有 5 个座位,可以预订,给用户最终建议
类型: FINAL_ANSWER

3.3 Action 的格式#

Action 通常采用解析友好的格式:

方法 1: 字符串解析(传统 ReAct)
Action: Search[北京今天的天气]
方法 2: JSON 解析(现代)
Action: {
"tool": "Search",
"input": "北京今天的天气"
}
方法 3: Function Calling(OpenAI 风格)
Action: <invoke name="Search">
<parameter name="query">北京今天的天气</parameter>
</invoke>

3.4 Observation 的处理#

Observation 是工具的执行结果:

方法 1: 字符串结果
Observation: 今天北京晴天,温度 25°C
方法 2: JSON 结果
Observation: {"weather": "sunny", "temperature": 25}
方法 3: 结构化数据
Observation:
{
"status": "success",
"data": [1, 2, 3],
"message": "查询成功"
}

3.5 完成检测#

检测 ReAct 循环何时终止:

def is_finished(response):
"""
检测 LLM 是否给出最终答案
"""
indicators = [
"Final Answer:",
"Finish[",
"答案:",
"<final_answer>",
"<invoke name=\"Finish\">",
]
for indicator in indicators:
if indicator in response:
return True
return False

4. 工具系统设计#

4.1 工具的定义#

from typing import Callable, Dict, Any
from dataclasses import dataclass
@dataclass
class Tool:
"""工具定义"""
name: str
description: str
func: Callable
parameters: Dict[str, Any] = None
def to_schema(self):
"""转换为 OpenAI function calling 格式"""
return {
"type": "function",
"function": {
"name": self.name,
"description": self.description,
"parameters": self.parameters
}
}
def execute(self, **kwargs):
"""执行工具"""
try:
result = self.func(**kwargs)
return f"Observation: {result}"
except Exception as e:
return f"Observation: Error - {str(e)}"

4.2 工具注册表#

class ToolRegistry:
"""工具注册表"""
def __init__(self):
self.tools: Dict[str, Tool] = {}
def register(self, tool: Tool):
"""注册工具"""
self.tools[tool.name] = tool
def get(self, name: str) -> Tool:
"""获取工具"""
return self.tools.get(name)
def to_prompt(self) -> str:
"""生成工具描述(用于 prompt)"""
descriptions = []
for tool in self.tools.values():
desc = f"- {tool.name}: {tool.description}"
if tool.parameters:
params = ", ".join(
f"{k}: {v.get('type', 'string')}"
for k, v in tool.parameters.get("properties", {}).items()
)
desc += f"\n 参数: {params}"
descriptions.append(desc)
return "\n".join(descriptions)
def to_openai_schema(self):
"""生成 OpenAI function calling schema"""
return [tool.to_schema() for tool in self.tools.values()]

4.3 常用工具示例#

# 1. 搜索工具
def search(query: str) -> str:
"""搜索信息"""
# 实际实现可能调用 Google API
return f"搜索结果: {query} 的相关信息..."
# 2. 计算工具
def calculator(expression: str) -> str:
"""计算数学表达式"""
try:
result = eval(expression)
return f"计算结果: {result}"
except Exception as e:
return f"计算错误: {e}"
# 3. 数据库查询工具
def query_database(sql: str) -> str:
"""查询数据库"""
# 实际执行 SQL
return f"查询结果: ..."
# 4. 文件读取工具
def read_file(path: str) -> str:
"""读取文件内容"""
with open(path, 'r', encoding='utf-8') as f:
return f.read()
# 5. API 调用工具
def call_api(endpoint: str, params: dict) -> str:
"""调用 HTTP API"""
import requests
response = requests.get(endpoint, params=params)
return response.text
# 注册工具
registry = ToolRegistry()
registry.register(Tool(
name="Search",
description="搜索网络信息",
func=search,
parameters={
"type": "object",
"properties": {
"query": {"type": "string", "description": "搜索关键词"}
},
"required": ["query"]
}
))
registry.register(Tool(
name="Calculator",
description="计算数学表达式",
func=calculator,
parameters={
"type": "object",
"properties": {
"expression": {"type": "string", "description": "数学表达式"}
},
"required": ["expression"]
}
))

5. 完整 ReAct Agent 实现#

5.1 基础实现#

import re
from typing import List, Tuple
from openai import OpenAI
class ReActAgent:
"""
完整的 ReAct Agent 实现
"""
def __init__(self, llm, tools: ToolRegistry, max_steps=10, max_context=5):
self.llm = llm
self.tools = tools
self.max_steps = max_steps
self.max_context = max_context
def run(self, question: str) -> str:
"""执行 ReAct 循环"""
history = []
for step in range(self.max_steps):
# 1. 构建 prompt
prompt = self._build_prompt(question, history)
# 2. 调用 LLM
response = self.llm.generate(prompt)
# 3. 解析响应
thought, action = self._parse_response(response)
# 4. 检查是否完成
if self._is_finished(response):
return self._extract_final_answer(response)
# 5. 检查是否有有效行动
if action is None:
# LLM 没有产生有效行动,反馈给 LLM
history.append({
'thought': thought,
'action': None,
'observation': '请选择一个有效的工具或给出最终答案。'
})
continue
# 6. 执行工具
tool_name, tool_input = action
observation = self._execute_tool(tool_name, tool_input)
# 7. 记录历史
history.append({
'thought': thought,
'action': action,
'observation': observation
})
# 达到最大步数
return "达到最大步数,无法完成任务。"
def _build_prompt(self, question, history):
"""构建 prompt"""
tools_desc = self.tools.to_prompt()
history_str = ""
for h in history[-self.max_context:]:
history_str += f"\nThought: {h['thought']}"
if h['action']:
history_str += f"\nAction: {h['action'][0]}[{h['action'][1]}]"
history_str += f"\nObservation: {h['observation']}"
elif h.get('observation'):
history_str += f"\nObservation: {h['observation']}"
return REACT_PROMPT_TEMPLATE.format(
tool_descriptions=tools_desc,
question=question,
history=history_str
)
def _parse_response(self, response):
"""解析 Thought 和 Action"""
thought_match = re.search(r'Thought:\s*(.+?)(?=Action:|$)', response, re.DOTALL)
action_match = re.search(r'Action:\s*(\w+)\[(.+?)\]', response)
thought = thought_match.group(1).strip() if thought_match else ""
action = None
if action_match:
tool_name = action_match.group(1)
tool_input = action_match.group(2)
action = (tool_name, tool_input)
return thought, action
def _is_finished(self, response):
"""检测是否完成"""
return "Final Answer:" in response or "Finish[" in response
def _extract_final_answer(self, response):
"""提取最终答案"""
match = re.search(r'Final Answer:\s*(.+)', response, re.DOTALL)
if match:
return match.group(1).strip()
return response
def _execute_tool(self, name, input_str):
"""执行工具"""
tool = self.tools.get(name)
if not tool:
return f"错误:未知工具 {name}"
try:
# 简单的字符串输入处理
# 实际实现可能需要更复杂的参数解析
return tool.execute(input=input_str)
except Exception as e:
return f"执行错误:{e}"

5.2 使用 OpenAI Function Calling#

class ReActAgentFunctionCall(ReActAgent):
"""
使用 OpenAI Function Calling 的 ReAct Agent
"""
def __init__(self, llm, tools: ToolRegistry, max_steps=10):
super().__init__(llm, tools, max_steps)
self.client = OpenAI()
def run(self, question: str) -> str:
"""使用 Function Calling 运行"""
messages = [{"role": "user", "content": question}]
tool_schemas = self.tools.to_openai_schema()
for step in range(self.max_steps):
# 1. 调用 LLM
response = self.client.chat.completions.create(
model="gpt-4",
messages=messages,
tools=tool_schemas,
)
message = response.choices[0].message
messages.append(message)
# 2. 检查是否有工具调用
if message.tool_calls:
for tool_call in message.tool_calls:
tool_name = tool_call.function.name
tool_args = json.loads(tool_call.function.arguments)
# 执行工具
tool = self.tools.get(tool_name)
result = tool.execute(**tool_args)
# 添加结果
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": str(result)
})
else:
# 没有工具调用,返回最终答案
return message.content
return "达到最大步数"

6. ReAct 的实例应用#

6.1 智能客服 Agent#

class CustomerServiceAgent(ReActAgent):
"""
智能客服 Agent
工具集:订单查询、退款、推荐等
"""
def __init__(self, llm):
tools = ToolRegistry()
tools.register(Tool(
name="query_order",
description="查询订单状态",
func=self._query_order,
parameters={
"type": "object",
"properties": {
"order_id": {"type": "string"}
}
}
))
tools.register(Tool(
name="process_refund",
description="处理退款",
func=self._process_refund,
parameters={
"type": "object",
"properties": {
"order_id": {"type": "string"},
"reason": {"type": "string"}
}
}
))
tools.register(Tool(
name="recommend_product",
description="推荐相关商品",
func=self._recommend_product,
parameters={
"type": "object",
"properties": {
"category": {"type": "string"}
}
}
))
super().__init__(llm, tools)
def _query_order(self, order_id: str) -> str:
# 实际查询订单
return f"订单 {order_id}: 已发货,预计明天送达"
def _process_refund(self, order_id: str, reason: str) -> str:
return f"订单 {order_id} 的退款已处理,原因:{reason}"
def _recommend_product(self, category: str) -> str:
return f"在 {category} 类别下,推荐: 商品A, 商品B, 商品C"

6.2 研究助手 Agent#

class ResearchAgent(ReActAgent):
"""
学术研究助手
工具集:论文搜索、摘要、引用查询等
"""
def __init__(self, llm):
tools = ToolRegistry()
# 注册学术工具
tools.register(Tool(
name="arxiv_search",
description="在 arXiv 搜索论文",
func=self._arxiv_search
))
tools.register(Tool(
name="summarize_paper",
description="总结论文内容",
func=self._summarize_paper
))
tools.register(Tool(
name="find_citations",
description="查找引用",
func=self._find_citations
))
tools.register(Tool(
name="compare_methods",
description="比较方法",
func=self._compare_methods
))
super().__init__(llm, tools)
def research_question(self, question: str) -> str:
return self.run(question)

6.3 旅行规划 Agent#

# 完整的 ReAct 旅行规划示例
travel_tools = ToolRegistry()
# 注册工具
travel_tools.register(Tool(
name="SearchFlights",
description="搜索航班",
func=lambda origin, destination, date: f"{origin}{destination} ({date}): 直飞 ¥1500, 9:00-11:00"
))
travel_tools.register(Tool(
name="SearchHotels",
description="搜索酒店",
func=lambda city, checkin, nights: f"{city} 酒店 ({checkin}, {nights}晚): A酒店 ¥500/晚, B酒店 ¥800/晚"
))
travel_tools.register(Tool(
name="GetWeather",
description="查询天气",
func=lambda city, date: f"{city} ({date}): 晴 25°C"
))
travel_tools.register(Tool(
name="BookFlight",
description="预订航班",
func=lambda flight_id: f"已预订航班 {flight_id}"
))
# 运行
agent = ReActAgent(llm, travel_tools)
result = agent.run("""
我想去北京旅行 3 天,从上海出发,明天出发。
帮我安排:
1. 合适的航班
2. 性价比高的酒店
3. 查看当时的天气
""")
# ReAct 执行的可能轨迹:
# Thought: 需要先搜索航班
# Action: SearchFlights[上海, 北京, 明天]
# Observation: 直飞 ¥1500, 9:00-11:00
#
# Thought: 现在搜索酒店
# Action: SearchHotels[北京, 2026-07-17, 3]
# Observation: A酒店 ¥500/晚
#
# Thought: 查看天气
# Action: GetWeather[北京, 2026-07-17]
# Observation: 晴 25°C
#
# Thought: 天气好,选择经济型酒店,给出总结
# Final Answer: 推荐方案...

7. ReAct 的改进方法#

7.1 Reflexion: 自我反思的 ReAct#

Reflexion 在 ReAct 基础上添加反思机制

class ReflexionAgent(ReActAgent):
"""
Reflexion: 反思增强的 ReAct
"""
def __init__(self, llm, tools, max_reflections=3):
super().__init__(llm, tools)
self.max_reflections = max_reflections
self.reflections = []
def run(self, question: str) -> str:
"""带反思的运行"""
for attempt in range(self.max_reflections + 1):
# 1. 执行 ReAct
result = super().run(question)
# 2. 评估结果
evaluation = self._evaluate_result(question, result)
# 3. 如果成功,返回
if evaluation['success']:
return result
# 4. 否则,反思
if attempt < self.max_reflections:
reflection = self._reflect(question, result, evaluation)
self.reflections.append(reflection)
return result
def _reflect(self, question, result, evaluation):
"""反思失败原因"""
prompt = f"""
问题:{question}
结果:{result}
评估:{evaluation['reason']}
请反思:
1. 哪里出错了?
2. 如何改进?
3. 下次应该采取什么不同的策略?
反思:
"""
return self.llm.generate(prompt)
def _build_prompt(self, question, history):
"""构建带反思历史的 prompt"""
base_prompt = super()._build_prompt(question, history)
if self.reflections:
reflection_text = "\n\n之前的反思:\n" + "\n".join(self.reflections)
return base_prompt + reflection_text
return base_prompt

7.2 ReAct + 计划 (Plan-and-Execute)#

先制定计划,再执行:

class PlanAndExecuteAgent:
"""
Plan-and-Execute: 先计划后执行
"""
def __init__(self, llm, tools):
self.llm = llm
self.tools = tools
def run(self, question: str) -> str:
# 1. 计划阶段
plan = self._create_plan(question)
# 2. 执行阶段
results = []
for step in plan:
result = self._execute_step(step, results)
results.append(result)
# 3. 总结
return self._summarize(question, plan, results)
def _create_plan(self, question):
"""创建执行计划"""
prompt = f"""
问题:{question}
请创建一个详细的执行计划,列出所有需要完成的步骤。
每个步骤应该是一个可以执行的操作。
计划:
"""
plan_text = self.llm.generate(prompt)
# 解析计划
steps = []
for line in plan_text.split('\n'):
if re.match(r'\d+\.', line.strip()):
steps.append(line.strip())
return steps

7.3 多 Agent 协作#

class MultiAgentReAct:
"""
多 Agent 协作系统
"""
def __init__(self, llm, agents: Dict[str, ReActAgent]):
self.llm = llm
self.agents = agents
self.supervisor = ReActAgent(llm, self._supervisor_tools())
def run(self, question: str) -> str:
"""多 Agent 协作"""
# 1. Supervisor 决定分配
decision = self._assign_agent(question)
agent_name = decision['agent']
# 2. 调用专门的 Agent
agent = self.agents[agent_name]
result = agent.run(decision['subtask'])
# 3. Supervisor 整合结果
final = self._integrate(question, result)
return final

7.4 ReWOO: 减少 token 消耗#

ReWOO 通过预先生成所有工具调用减少重复:

class ReWOOAgent:
"""
ReWOO: Reason WithOut Observation
一次性规划,减少观察次数
"""
def __init__(self, llm, tools):
self.llm = llm
self.tools = tools
def run(self, question):
# 1. 规划阶段:一次性生成所有步骤
plan = self._create_full_plan(question)
# 2. 执行阶段:执行所有工具调用
evidence = {}
for step in plan.steps:
result = self._execute_tool_call(step)
evidence[step.id] = result
# 3. 总结阶段:基于所有证据回答
return self._synthesize(plan, evidence, question)

8. 错误处理与恢复#

8.1 常见错误类型#

class ReActErrorHandler:
"""
ReAct 错误处理器
"""
ERROR_TYPES = {
'invalid_action': 'LLM 生成了无效的工具调用',
'tool_failure': '工具执行失败',
'no_progress': '多次循环无进展',
'max_steps': '达到最大步数',
'context_overflow': '上下文超过限制',
'infinite_loop': '陷入循环'
}
def handle_error(self, history, error_type):
"""处理错误"""
if error_type == 'invalid_action':
return self._handle_invalid_action(history)
elif error_type == 'tool_failure':
return self._handle_tool_failure(history)
elif error_type == 'infinite_loop':
return self._handle_infinite_loop(history)
# ...
def _handle_infinite_loop(self, history):
"""处理循环"""
# 检测最近的步骤是否重复
if len(history) >= 3:
last_three = history[-3:]
if (last_three[0]['thought'] == last_three[2]['thought'] and
last_three[0]['action'] == last_three[2]['action']):
# 强制给予反馈
return "警告:检测到循环,请尝试不同的方法。"
return None

8.2 健壮性增强#

class RobustReActAgent(ReActAgent):
"""
健壮的 ReAct Agent
"""
def __init__(self, *args, max_retries=3, **kwargs):
super().__init__(*args, **kwargs)
self.max_retries = max_retries
self.visited_states = set()
def run(self, question):
"""带错误处理的运行"""
for attempt in range(self.max_retries):
try:
return super().run(question)
except Exception as e:
if attempt < self.max_retries - 1:
print(f"出错:{e}, 重试...")
self.visited_states.clear()
else:
return f"多次失败: {e}"

8.3 循环检测#

class LoopDetector:
"""循环检测器"""
def __init__(self, threshold=3):
self.threshold = threshold
self.recent_states = []
def record(self, thought, action):
"""记录状态"""
state = (thought[:100], action) # 截断以处理长 thought
self.recent_states.append(state)
if len(self.recent_states) > self.threshold:
self.recent_states.pop(0)
def is_looping(self):
"""检测是否循环"""
if len(self.recent_states) < self.threshold:
return False
# 检查是否有重复
states = self.recent_states[-self.threshold:]
return len(set(map(str, states))) < len(states)

9. 评估 ReAct Agent#

9.1 评估指标#

class ReActEvaluator:
"""
ReAct Agent 评估器
"""
METRICS = [
'task_success_rate', # 任务成功率
'average_steps', # 平均步数
'tool_accuracy', # 工具调用准确率
'thought_quality', # 思考质量
'efficiency', # 效率
'hallucination_rate', # 幻觉率
'recovery_rate', # 错误恢复率
]
def evaluate(self, agent, dataset):
"""评估 Agent"""
results = {
'success_count': 0,
'total_count': 0,
'total_steps': 0,
'tool_calls': [],
'thoughts': [],
}
for item in dataset:
result = agent.run(item.question)
metrics = self._compute_metrics(result, item.expected)
self._update_results(results, metrics)
# 汇总
total = results['total_count']
return {
'task_success_rate': results['success_count'] / total,
'average_steps': results['total_steps'] / total,
# ... 其他指标
}
def _compute_metrics(self, result, expected):
"""计算单个样本的指标"""
return {
'success': self._check_success(result, expected),
'num_steps': self._count_steps(result),
}

9.2 基准测试#

class ReActBenchmark:
"""ReAct 标准基准"""
BENCHMARKS = {
'HotpotQA': '多跳问答',
'FEVER': '事实核查',
'AlfWorld': '文本游戏',
'WebShop': '网页购物',
'Mind2Web': '网页操作',
'SWE-bench': '代码任务',
}
def run_benchmark(self, agent, benchmark_name):
"""在基准上评估"""
if benchmark_name == 'HotpotQA':
return self._eval_hotpotqa(agent)
elif benchmark_name == 'FEVER':
return self._eval_fever(agent)
# ...

9.3 性能基准结果#

AgentHotpotQAFEVERAlfWorld平均步数
Direct28.5%56.2%12%1
CoT35.7%62.4%18%1
ReAct (GPT-3.5)42.8%68.9%35%3.5
ReAct (GPT-4)56.4%78.2%62%4.2
ReAct+Reflexion61.3%81.5%71%5.8
Plan-and-Execute58.2%79.8%68%4.0

10. ReAct 的局限与挑战#

10.1 主要局限#

局限描述缓解方法
Token 消耗大每步都生成 Thought+ActionReWOO, 批处理
容易陷入循环重复相同的 Thought循环检测
Thought 质量依赖 LLMLLM 弱则 Thought 差用更强的 LLM
工具错误敏感工具失败易导致整体失败容错处理
步骤多时上下文膨胀历史过长总结、截断
难以并行顺序执行部分并行化

10.2 与其他模式的对比#

模式优势劣势适用场景
直接回答快、便宜无推理简单任务
CoT推理强不能交互推理任务
ReAct可交互慢、贵Agent 任务
Plan-Execute效率高计划失误难恢复复杂多步
Reflexion自学习反思也可能错反复尝试
Tree of Thoughts全局搜索计算成本高复杂搜索

10.3 工程挑战#

# 1. Prompt 工程的挑战
challenges = {
'parsing': 'Action 解析容易失败',
'context_management': '上下文管理困难',
'tool_design': '工具设计影响效果',
'hallucination': 'LLM 幻觉',
'latency': '延迟较高',
'cost': 'Token 成本'
}
# 解决方案
solutions = {
'parsing': '使用 Function Calling 替代字符串解析',
'context_management': '定期总结、滑动窗口',
'tool_design': '明确的工具描述、清晰的参数',
'hallucination': '强制基于 Observation 推理',
'latency': '并行执行、缓存',
'cost': 'ReWOO、模型选择',
}

11. 性能优化#

11.1 减少 Token 消耗#

class TokenEfficientReAct(ReActAgent):
"""Token 高效的 ReAct"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.history_summary = ""
def _build_prompt(self, question, history):
"""使用总结而非完整历史"""
# 总结历史而不是直接使用
if len(history) > 5:
self.history_summary = self._summarize_history(history)
history_text = self.history_summary
else:
history_text = self._format_history(history)
return super()._build_prompt(question_with_replaced_history=history_text)
def _summarize_history(self, history):
"""总结历史"""
history_text = self._format_history(history)
prompt = f"总结以下 agent 的执行历史:\n{history_text}\n总结:"
return self.llm.generate(prompt)

11.2 并行化#

class ParallelReAct(ReActAgent):
"""支持并行工具调用的 ReAct"""
def _execute_tool(self, name, input_str):
# 如果是独立的工具调用,可以并行执行
return super()._execute_tool(name, input_str)
def run(self, question):
history = []
for step in range(self.max_steps):
response = self.llm.generate(self._build_prompt(question, history))
thought, actions = self._parse_multi_actions(response)
if self._is_finished(response):
return self._extract_final_answer(response)
# 并行执行多个独立的 actions
if len(actions) > 1:
observations = self._parallel_execute(actions)
for action, obs in zip(actions, observations):
history.append({
'thought': thought,
'action': action,
'observation': obs
})
elif actions:
observation = self._execute_tool(*actions[0])
history.append({
'thought': thought,
'action': actions[0],
'observation': observation
})

11.3 缓存#

import hashlib
class CachedReActAgent(ReActAgent):
"""带缓存的 ReAct"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.cache = {}
def _execute_tool(self, name, input_str):
"""带缓存的工具执行"""
cache_key = hashlib.md5(f"{name}:{input_str}".encode()).hexdigest()
if cache_key in self.cache:
return self.cache[cache_key]
result = super()._execute_tool(name, input_str)
self.cache[cache_key] = result
return result

12. 实际部署考虑#

12.1 安全考虑#

class SafeReActAgent(ReActAgent):
"""安全的 ReAct Agent"""
def __init__(self, *args, sensitive_tools=None, **kwargs):
super().__init__(*args, **kwargs)
self.sensitive_tools = sensitive_tools or set()
self.require_confirmation = True
def _execute_tool(self, name, input_str):
"""带安全检查的执行"""
# 1. 检查是否敏感工具
if name in self.sensitive_tools:
if self.require_confirmation:
if not self._confirm_action(name, input_str):
return "用户拒绝执行此操作"
# 2. 检查参数
if not self._validate_input(name, input_str):
return "参数验证失败"
# 3. 执行
return super()._execute_tool(name, input_str)
def _validate_input(self, name, input_str):
"""验证输入,防止注入"""
# SQL 注入检查
if 'sql' in name.lower():
dangerous = ['DROP', 'DELETE', 'UPDATE', 'INSERT']
if any(kw in input_str.upper() for kw in dangerous):
return False
# 命令注入检查
if 'shell' in name.lower() or 'exec' in name.lower():
dangerous = [';', '|', '&', '`', '$']
if any(c in input_str for c in dangerous):
return False
return True

12.2 监控与日志#

class MonitoredReActAgent(ReActAgent):
"""带监控的 ReAct"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.metrics = []
def run(self, question):
"""带监控的运行"""
import time
start_time = time.time()
result = super().run(question)
# 记录指标
self.metrics.append({
'timestamp': time.time(),
'duration': time.time() - start_time,
'num_steps': len(self.history),
'success': self._is_success(result),
'question_length': len(question),
'result_length': len(result),
})
return result

13. 与现代 Agent 框架的集成#

13.1 LangChain 集成#

from langchain.agents import initialize_agent, AgentType
from langchain.tools import Tool as LangChainTool
# 在 LangChain 中使用 ReAct
agent = initialize_agent(
tools=langchain_tools,
llm=llm,
agent=AgentType.REACT_DOCSTORE,
verbose=True
)
result = agent.run("北京的人口是多少?")

13.2 LlamaIndex 集成#

from llama_index.agent import ReActAgent
from llama_index.llms import OpenAI
# LlamaIndex 的 ReAct Agent
agent = ReActAgent.from_tools(
tools=[search_tool, query_tool],
llm=OpenAI(model="gpt-4"),
verbose=True
)
response = agent.chat("2024 年诺贝尔物理学奖获得者是谁?")

13.3 自研 Agent 框架#

class CustomAgentFramework:
"""自研 Agent 框架"""
def __init__(self, llm, tools):
self.react_agent = ReActAgent(llm, tools)
self.reflection_agent = ReflexionAgent(llm, tools)
def run(self, question, mode='auto'):
"""根据复杂度选择模式"""
if mode == 'auto':
complexity = self._estimate_complexity(question)
if complexity > 0.7:
return self.reflection_agent.run(question)
else:
return self.react_agent.run(question)
elif mode == 'react':
return self.react_agent.run(question)
elif mode == 'reflection':
return self.reflection_agent.run(question)

14. 核心概念总结#

14.1 ReAct 的三大组件#

REACT_COMPONENTS = """
1. Thought (思考):
- 分析当前状态
- 制定下一步策略
- 类型:规划、信息寻求、推理、计算、验证、修正
2. Action (行动):
- 调用外部工具
- 格式:工具名[输入] 或 JSON
- 类型:API 调用、查询、计算、操作
3. Observation (观察):
- 工具返回的结果
- 信息来源:工具执行结果
- 用于下一步的 Thought
"""

14.2 ReAct 的核心循环#

Thought_n → Action_n → Observation_n → Thought_{n+1} → Action_{n+1} → ...
│ │ │
│ │ │
│ ▼ ▼
│ [更新历史] [输出结果]
└─ "我应该做什么?"

14.3 关键设计选择#

设计选择传统 ReAct现代 ReAct
Action 格式字符串解析Function Calling
Prompt 模板手工自动生成
工具描述简短结构化
错误处理完善
上下文管理完整保留总结/截断

15. 实战建议#

15.1 设计 Agent 时的最佳实践#

BEST_PRACTICES = """
1. 工具设计:
- 工具数量适中(5-15 个)
- 每个工具职责单一
- 提供清晰的描述
- 验证所有输入
2. Prompt 设计:
- 清晰的任务描述
- 详细的工具说明
- 完整的格式示例
- 错误处理提示
3. 错误处理:
- 检测循环
- 处理无效 Action
- 容错工具失败
- 设置最大步数
4. 性能优化:
- 缓存重复结果
- 并行独立调用
- 总结历史记录
- 减少冗余 token
5. 安全考虑:
- 验证输入
- 限制敏感操作
- 用户确认机制
- 审计日志
"""

15.2 调试技巧#

DEBUGGING_TIPS = """
1. 启用 verbose 模式: 显示每个 Thought/Action/Observation
2. 记录所有历史: 便于回溯分析
3. 单独测试每个工具: 确认工具正常
4. 使用简单任务测试: 排除 bug
5. 对比不同 LLM: 区分 LLM 和 Agent 框架问题
6. 监控循环: 检测重复模式
"""

15.3 何时不使用 ReAct#

def should_use_react(task):
"""判断是否应该使用 ReAct"""
use_react = True
# 简单的问答不需要
if is_simple_question(task):
use_react = False
# 数学计算可能用其他工具更合适
if is_pure_math(task):
use_react = False # 直接用计算工具
# 需要实时信息才用
if not need_real_time(task) and not need_tools(task):
use_react = False
return use_react

16. 总结与展望#

ReAct 的核心价值#

  1. 统一推理与行动:打破推理模型的封闭性
  2. 可扩展 Agent 系统:通过工具扩展能力边界
  3. 透明可调试:Thought 提供决策透明度
  4. 实用性强:解决真实世界问题

ReAct 的局限与替代方案#

问题替代方案
Token 消耗大ReWOO, Plan-and-Execute
容易循环Reflexion, Plan-and-Execute
上下文膨胀Memory 管理 + RAG
错误传播自适应重试 + 验证
长链效率低多 Agent 协作

未来发展方向#

  1. 更智能的 ReAct:自动选择何时推理、何时行动
  2. 多模态 ReAct:视觉、语音的统一
  3. 协作 ReAct:多个 Agent 协同解决复杂问题
  4. 持久化 ReAct:长期记忆和状态管理
  5. 自我改进的 ReAct:从历史经验学习

学习建议#

  1. 理论:理解 Thought-Action-Observation 循环
  2. 实践:用 LangChain 或自己实现一个简单 Agent
  3. 进阶:研究 Reflexion、Plan-and-Execute 等改进
  4. 应用:将 ReAct 应用到自己的领域
  5. 前沿:关注 LLM Agent 领域的最新研究

ReAct 是 LLM Agent 时代的奠基石。掌握 ReAct 模式是理解现代 Agent 系统(GPTs、Claude Tools 等)的关键。无论技术如何演进,Thought-Action-Observation 的循环思想仍然是 Agent 系统设计的核心范式。

参考资料#

  1. Yao, S., et al. (2022). “ReAct: Synergizing Reasoning and Acting in Language Models.” ICLR 2023.
  2. Wei, J., et al. (2022). “Chain-of-Thought Prompting Elicits Reasoning in Large Language Models.” NeurIPS.
  3. Shinn, N., et al. (2023). “Reflexion: Language Agents with Verbal Reinforcement Learning.” NeurIPS.
  4. Schick, T., et al. (2023). “Toolformer: Language Models Can Teach Themselves to Use Tools.” NeurIPS.
  5. Paranjape, B., et al. (2023). “ART: Automatic multi-step reasoning and tool-use for language models.” arXiv.
  6. Khot, T., et al. (2022). “Decomposed Prompting: A Modular Approach for Solving Complex Tasks.” ICLR.
  7. Press, O., et al. (2022). “Measuring and Narrowing the Compositionality Gap in Language Models.” EMNLP.
  8. Besta, M., et al. (2023). “Graph of Thoughts: Solving Elaborate Problems with Large Language Models.” AAAI.
  9. Chase, H. (2022). “LangChain: Building applications with LLMs through composability.” GitHub.
  10. Liu, J., et al. (2023). “ReWOO: Decoupling Reasoning from Observations for Efficient Augmented Language Models.” arXiv.
  11. Weng, L. (2023). “LLM-powered Autonomous Agents.” Lil’Log Blog.
  12. Wei, J., et al. (2024). “Simple Synthetic Data Reduces Sycophancy in Large Language Models.” arXiv.

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

深入理解 ReAct 模式:让大模型学会推理与行动
https://aiattnstudio.link/posts/react-pattern/
作者
Federico
发布于
2026-07-16
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author

Federico

AI Research Lab

Hello, I'm Federico.

关于实验室 / About
公告

欢迎来到Federico的个人博客

分类
标签
站点统计
57文章
7分类
404标签
1
1. ReAct 的引入
1.1 传统 LLM 的局限
1.2 ReAct 的诞生
1.3 ReAct 的革命性意义
1.4 ReAct 发展简史
2
2. ReAct 的核心思想
2.1 人类认知的类比
2.2 Thought-Action-Observation 循环
2.3 ReAct 的优势
2.3.1 透明性
2.3.2 可验证
2.3.3 可扩展
2.4 ReAct 的数学形式
3
3. ReAct 的核心机制
3.1 Prompt 模板
3.2 Thought 的类型
3.3 Action 的格式
3.4 Observation 的处理
3.5 完成检测
4
4. 工具系统设计
4.1 工具的定义
4.2 工具注册表
4.3 常用工具示例
5
5. 完整 ReAct Agent 实现
5.1 基础实现
5.2 使用 OpenAI Function Calling
6
6. ReAct 的实例应用
6.1 智能客服 Agent
6.2 研究助手 Agent
6.3 旅行规划 Agent
7
7. ReAct 的改进方法
7.1 Reflexion: 自我反思的 ReAct
7.2 ReAct + 计划 (Plan-and-Execute)
7.3 多 Agent 协作
7.4 ReWOO: 减少 token 消耗
8
8. 错误处理与恢复
8.1 常见错误类型
8.2 健壮性增强
8.3 循环检测
9
9. 评估 ReAct Agent
9.1 评估指标
9.2 基准测试
9.3 性能基准结果
10
10. ReAct 的局限与挑战
10.1 主要局限
10.2 与其他模式的对比
10.3 工程挑战
11
11. 性能优化
11.1 减少 Token 消耗
11.2 并行化
11.3 缓存
12
12. 实际部署考虑
12.1 安全考虑
12.2 监控与日志
13
13. 与现代 Agent 框架的集成
13.1 LangChain 集成
13.2 LlamaIndex 集成
13.3 自研 Agent 框架
14
14. 核心概念总结
14.1 ReAct 的三大组件
14.2 ReAct 的核心循环
14.3 关键设计选择
15
15. 实战建议
15.1 设计 Agent 时的最佳实践
15.2 调试技巧
15.3 何时不使用 ReAct
16
16. 总结与展望
ReAct 的核心价值
ReAct 的局限与替代方案
未来发展方向
学习建议
17
参考资料