ReAct(推理 + 行动)范式详解
1. 核心概念
1.1 什么是 ReAct
ReAct(Reason + Act)是一种让大语言模型交替进行推理 和行动的框架,通过"思考-行动-观察"的循环,使模型能够利用外部工具和实时信息来解决问题。
核心思想:将复杂任务分解为一系列的推理步骤和行动步骤,模型在每一步中:
- 思考:分析当前状态,决定下一步需要做什么
- 行动:调用工具获取外部信息或执行操作
- 观察:接收工具返回的结果,更新状态
- 循环:重复上述过程直到任务完成
1.2 ReAct 的本质原理
ReAct 并没有赋予模型真正的行动能力,它的核心在于把"思考"和"行动"都表达为文本,让模型在文本空间中模拟推理和决策过程。
关键洞察:
- 推理(Reasoning):生成自然语言思考,分析问题、制定计划
- 行动(Acting):生成结构化工具调用指令
- 观察(Observation):接收工具执行结果,作为下一步的输入
1.3 ReAct 与 CoT 的关系
| 技术 | 核心能力 | 适用场景 | 工具使用 |
|---|---|---|---|
| CoT | 纯推理(思考) | 数学题、逻辑题、代码生成 | 不需要 |
| ReAct | 推理 + 行动 | 需要查询信息、调用工具的任务 | 必须 |
对比示例:
python
# CoT 场景:数学计算
cot_prompt = """
问题:3个人3天用3桶水,9个人9天用几桶水?
让我一步步思考:
"""
# ReAct 场景:查询天气并给出建议
react_prompt = """
问题:北京明天天气怎么样?我需要穿什么衣服?
可用工具:get_weather(city, date)
请按照以下格式回答:
思考:[分析问题]
行动:[调用工具]
观察:[工具返回结果]
...
最终答案:[综合回答]
"""
2. ReAct 的工作流程
2.1 基础流程
输入问题 → 思考 → 行动 → 观察 → 思考 → 行动 → 观察 → ... → 得出答案
2.2 详细步骤
python
class ReActWorkflow:
"""ReAct 工作流程"""
def __init__(self, llm, tools, max_steps=10):
self.llm = llm # 大语言模型
self.tools = tools # 可用工具列表
self.max_steps = max_steps # 最大步数限制
self.history = [] # 历史记录
def run(self, task):
"""执行 ReAct 流程"""
for step in range(self.max_steps):
# 1. 思考阶段
thought = self._reason(task)
self.history.append({"step": step, "thought": thought})
# 2. 判断是否完成
if self._is_complete(thought):
return self._summarize()
# 3. 行动阶段
action = self._decide_action(thought)
self.history.append({"step": step, "action": action})
# 4. 执行工具
observation = self._execute_action(action)
self.history.append({"step": step, "observation": observation})
# 5. 更新任务状态
task = self._update_task(task, observation)
return "任务未完成,已达到最大步数限制"
3. ReAct Prompt 的结构设计
3.1 四部分组成
| 组成部分 | 作用 | 示例 |
|---|---|---|
| 任务描述 | 描述问题目标和可用工具 | "请查询上海明天的天气" |
| 工具说明 | 告诉模型有哪些工具可用及使用方式 | "get_weather(city, date)" |
| 示例轨迹 | 展示完整的"思考-行动-观察"循环 | 见下方示例 |
| 当前问题 | 需要解决的具体问题 | "北京明天天气怎么样?" |
3.2 完整 Prompt 模板
python
def build_react_prompt(task, tools, examples):
"""构建 ReAct 提示词"""
prompt = """你是一个能够使用工具的智能助手。请按照"思考-行动-观察"的模式解决问题。
可用工具:
"""
# 添加工具说明
for tool in tools:
prompt += f"- {tool['name']}: {tool['description']}\n"
prompt += f" 参数:{tool['parameters']}\n\n"
# 添加示例轨迹
prompt += "示例:\n"
for example in examples:
prompt += f"问题:{example['question']}\n"
for step in example['trajectory']:
prompt += f"思考:{step['thought']}\n"
if 'action' in step:
prompt += f"行动:{step['action']}\n"
if 'observation' in step:
prompt += f"观察:{step['observation']}\n"
prompt += f"答案:{example['answer']}\n\n"
# 添加当前问题
prompt += f"问题:{task}\n"
prompt += "思考:"
return prompt
# 使用示例
tools = [
{
"name": "get_weather",
"description": "获取指定城市指定日期的天气信息",
"parameters": {"city": "城市名称", "date": "日期(格式:YYYY-MM-DD)"}
},
{
"name": "search_flight",
"description": "搜索航班信息",
"parameters": {"from": "出发城市", "to": "到达城市", "date": "日期"}
}
]
examples = [
{
"question": "上海明天天气怎么样?",
"trajectory": [
{"thought": "我需要查询上海明天的天气信息"},
{"action": "get_weather(city='上海', date='2024-01-15')"},
{"observation": "上海明天晴,温度15-22摄氏度,微风"}
],
"answer": "上海明天晴,温度15-22摄氏度,建议穿薄外套。"
}
]
prompt = build_react_prompt("北京明天天气怎么样?我需要穿什么衣服?", tools, examples)
print(prompt)
4. ReAct 的实现示例
4.1 基础 ReAct Agent
python
class ReActAgent:
"""基础 ReAct 智能体"""
def __init__(self, llm, tools):
self.llm = llm
self.tools = tools
self.max_steps = 10
self.format_instructions = """
请按照以下格式输出:
思考:[分析当前情况,决定下一步行动]
行动:[工具名称](参数1=值1, 参数2=值2)
观察:[等待工具返回结果]
如果不需要工具,直接输出:
思考:[分析问题]
答案:[最终回答]
"""
def _parse_action(self, response):
"""解析模型输出中的行动指令"""
import re
pattern = r'行动:(\w+)\((.*)\)'
match = re.search(pattern, response)
if match:
tool_name = match.group(1)
params_str = match.group(2)
# 解析参数
params = {}
for param in params_str.split(','):
if '=' in param:
key, value = param.split('=', 1)
params[key.strip()] = value.strip().strip("'\"")
return {"tool": tool_name, "params": params}
return None
def _execute_tool(self, tool_name, params):
"""执行工具调用"""
if tool_name in self.tools:
return self.tools[tool_name](**params)
return f"未知工具:{tool_name}"
def run(self, task):
"""执行任务"""
prompt = f"""
{self.format_instructions}
可用工具:
{self.tools.keys()}
任务:{task}
思考:
"""
for step in range(self.max_steps):
response = self.llm.generate(prompt)
print(f"步骤{step+1}: {response}")
# 检查是否包含答案
if "答案:" in response:
return response.split("答案:")[-1].strip()
# 解析行动
action = self._parse_action(response)
if action:
observation = self._execute_tool(action["tool"], action["params"])
print(f"观察:{observation}")
# 更新 prompt
prompt += f"{response}\n观察:{observation}\n思考:"
else:
# 没有行动,直接结束
return response
return "任务未完成,已达到最大步数限制"
# 定义工具
def get_weather(city, date):
"""模拟天气查询工具"""
return f"{date} {city}天气晴,温度15-25度"
def search_web(query):
"""模拟网页搜索工具"""
return f"搜索结果:{query} - 相关信息..."
# 创建智能体
tools = {"get_weather": get_weather, "search_web": search_web}
# agent = ReActAgent(my_llm, tools)
# result = agent.run("北京明天天气怎么样?")
4.2 带记忆的 ReAct Agent
python
class ReActAgentWithMemory:
"""带记忆的 ReAct 智能体"""
def __init__(self, llm, tools):
self.llm = llm
self.tools = tools
self.memory = [] # 短期记忆
self.max_steps = 10
def _store_memory(self, content):
"""存储记忆"""
self.memory.append(content)
# 保持记忆在合理范围内
if len(self.memory) > 20:
self.memory = self.memory[-10:]
def run(self, task):
"""执行任务"""
history = "\n".join(self.memory)
prompt = f"""
你是一个带记忆的智能助手。
历史记录:
{history}
当前任务:{task}
可用工具:{self.tools.keys()}
请按照思考-行动-观察的模式解决问题。
"""
for step in range(self.max_steps):
response = self.llm.generate(prompt)
if "答案:" in response:
answer = response.split("答案:")[-1].strip()
self._store_memory(f"任务:{task},答案:{answer}")
return answer
action = self._parse_action(response)
if action:
observation = self._execute_tool(action["tool"], action["params"])
self._store_memory(f"行动:{action['tool']},结果:{observation}")
prompt += f"\n{response}\n观察:{observation}"
return "任务未完成"
5. ReAct 的进阶技术
5.1 Reflexion(反思)
核心思想:在每次行动后进行反思,评估行动效果,调整策略。
python
class ReflexionAgent(ReActAgent):
"""带反思的 ReAct 智能体"""
def __init__(self, llm, tools):
super().__init__(llm, tools)
self.reflection_prompt = """
请反思刚才的行动:
1. 行动是否正确?
2. 是否有更好的选择?
3. 下一步应该怎么做?
"""
def run(self, task):
for step in range(self.max_steps):
# 正常的思考-行动-观察流程
thought = self._reason(task)
action = self._decide_action(thought)
observation = self._execute_action(action)
# 反思阶段
reflection = self.llm.generate(f"""
当前任务:{task}
思考:{thought}
行动:{action}
观察:{observation}
{self.reflection_prompt}
""")
# 根据反思结果调整
if "修正" in reflection or "更好" in reflection:
# 重新规划
task = self._adjust_task(task, reflection)
if self._is_complete(observation):
return self._summarize()
return "任务未完成"
5.2 工具选择优化
核心思想:为每个工具添加使用条件,让模型更好地选择合适的工具。
python
class ToolSelector:
"""工具选择器"""
def __init__(self, tools):
self.tools = tools
self.selection_prompt = """
根据以下任务,选择最合适的工具:
任务:{task}
可用工具:
{tool_descriptions}
请选择一个工具,并说明理由。
"""
def select(self, task):
"""选择工具"""
tool_descriptions = "\n".join([
f"- {name}: {info['description']}(适用:{info['conditions']})"
for name, info in self.tools.items()
])
prompt = self.selection_prompt.format(
task=task,
tool_descriptions=tool_descriptions
)
# 调用 LLM 选择工具
# response = self.llm.generate(prompt)
# return parse_tool_selection(response)
return None
# 使用示例
tools_with_conditions = {
"get_weather": {
"description": "获取天气信息",
"conditions": "查询天气、气温、穿衣建议"
},
"search_web": {
"description": "网页搜索",
"conditions": "查询新闻、知识、最新信息"
},
"calculate": {
"description": "数学计算",
"conditions": "数学题、统计计算"
}
}
# selector = ToolSelector(tools_with_conditions)
# tool = selector.select("北京明天天气怎么样?")
6. ReAct 在不同场景的应用
6.1 信息查询
示例任务:查询 Python 3.11 的新特性
ReAct 流程:
思考:我需要查询 Python 3.11 的新特性,这需要使用搜索工具
行动:search_web(query="Python 3.11 新特性")
观察:Python 3.11 引入了更快的解释器、模式匹配增强、更好的错误信息等
思考:搜索结果已经提供了足够的信息,可以总结回答
答案:Python 3.11 主要新特性包括:...
6.2 数据分析
示例任务:分析销售数据,找出销售额最高的产品
ReAct 流程:
思考:我需要分析销售数据,首先需要获取数据
行动:query_database(sql="SELECT product, SUM(sales) FROM sales GROUP BY product")
观察:产品A: 10000, 产品B: 8000, 产品C: 12000
思考:数据已经获取,可以直接分析得出结论
答案:销售额最高的产品是产品C,销售额为12000。
6.3 代码生成与调试
示例任务:编写一个 Python 函数来计算斐波那契数列,然后测试它
ReAct 流程:
思考:我需要编写一个斐波那契数列函数
行动:code_generator(language="python", task="编写斐波那契数列函数")
观察:def fibonacci(n): ...
思考:代码已生成,需要测试它是否正确
行动:code_executor(code="print(fibonacci(10))")
观察:输出:55
思考:测试结果正确,可以总结
答案:斐波那契数列函数已编写完成,测试通过。
7. ReAct 实践最佳实践
7.1 工具设计原则
- 单一职责:每个工具只做一件事
- 清晰描述:提供详细的工具描述和参数说明
- 返回结构化数据:工具返回结果尽量结构化
- 错误处理:工具应该处理异常情况
7.2 Prompt 设计技巧
python
def advanced_react_prompt(task):
"""高级 ReAct 提示词"""
return f"""
你是一名专业的问题解决专家,能够使用各种工具来获取信息和执行操作。
你的任务是解决以下问题:
{task}
可用工具:
1. search_web(query) - 搜索互联网信息
2. get_weather(city, date) - 获取天气信息
3. calculate(expression) - 数学计算
4. code_executor(code) - 执行代码
工作流程:
1. 思考:分析问题,决定需要什么信息或操作
2. 行动:选择合适的工具并调用
3. 观察:分析工具返回的结果
4. 循环:根据观察结果决定下一步
5. 总结:当获取足够信息后,给出最终答案
注意事项:
- 只在需要时调用工具
- 如果已经有足够信息,直接回答
- 如果工具调用失败,尝试其他方法
- 保持思考过程清晰
开始解决问题:
"""
7.3 错误处理策略
python
class RobustReActAgent(ReActAgent):
"""健壮的 ReAct 智能体"""
def _execute_tool_with_retry(self, tool_name, params, max_retries=3):
"""带重试的工具执行"""
for attempt in range(max_retries):
try:
return self._execute_tool(tool_name, params)
except Exception as e:
print(f"工具调用失败(第{attempt+1}次):{e}")
if attempt == max_retries - 1:
return f"工具调用失败:{str(e)}"
def _handle_tool_error(self, error):
"""处理工具错误"""
recovery_prompt = f"""
工具调用失败:{error}
请分析失败原因,并选择以下方案之一:
1. 重试(使用不同参数)
2. 使用其他工具
3. 基于已有信息回答
4. 告知用户无法完成
"""
# decision = self.llm.generate(recovery_prompt)
# return decision
return "重试"
8. ReAct 与其他范式的结合
8.1 ReAct + RAG
python
class ReActWithRAG:
"""ReAct + RAG 智能体"""
def __init__(self, llm, tools, rag_system):
self.llm = llm
self.tools = tools
self.rag_system = rag_system
def run(self, task):
# 首先检索相关知识
context = self.rag_system.search(task)
if context:
# 如果找到相关知识,先基于知识回答
prompt = f"""
相关知识:{context}
问题:{task}
请根据以上知识回答问题,如果需要更多信息可以调用工具。
"""
response = self.llm.generate(prompt)
# 如果模型表示需要更多信息,则使用 ReAct
if "需要" in response or "查询" in response:
return self._react_flow(task)
else:
return response
else:
# 没有相关知识,直接使用 ReAct
return self._react_flow(task)
8.2 ReAct + Plan-and-Execute
python
class ReActWithPlanning:
"""ReAct + 规划智能体"""
def __init__(self, llm, tools):
self.llm = llm
self.tools = tools
def run(self, task):
# 第一步:制定计划
plan_prompt = f"""
请为以下任务制定详细计划:
任务:{task}
可用工具:{self.tools.keys()}
计划格式:
步骤1:[描述]
步骤2:[描述]
...
"""
plan = self.llm.generate(plan_prompt)
print(f"计划:{plan}")
# 第二步:执行计划(使用 ReAct)
for step in plan.split("\n"):
if step.strip():
result = self._react_step(step.strip())
print(f"步骤结果:{result}")
# 第三步:总结
summary = self.llm.generate(f"""
任务:{task}
计划执行结果:{result}
请总结任务完成情况。
""")
return summary
9. 常见问题与解决方案
Q: ReAct 适合什么场景?
A: ReAct 特别适合需要以下能力的场景:
- 需要实时获取外部信息(如天气、新闻)
- 需要调用工具执行操作(如数据库查询、代码执行)
- 需要多步骤推理的复杂任务
- 需要验证答案正确性的任务
Q: 如何评估 ReAct 智能体的性能?
A: 可以从以下几个方面评估:
- 任务成功率:能否正确完成任务
- 步骤效率:完成任务需要多少步
- 工具使用准确性:是否使用了合适的工具
- 错误恢复能力:遇到错误能否恢复
- 答案质量:最终答案的准确性和完整性
Q: ReAct 有什么局限性?
A:
- Token 消耗大:思考过程会消耗大量 Token
- 执行延迟:每步都需要调用模型和工具
- 工具依赖:需要预先定义好工具集
- 规划能力有限:模型可能无法制定最优计划
Q: 如何在实际项目中应用 ReAct?
A:
- 识别需求:确定哪些任务需要工具调用
- 定义工具:设计和实现工具接口
- 构建 Prompt:设计 ReAct 提示词模板
- 实现循环:编写思考-行动-观察的循环逻辑
- 优化迭代:根据实际效果调整 Prompt 和工具
10. 总结
ReAct 是一种强大的智能体框架,通过"思考-行动-观察"的循环,使大语言模型能够利用外部工具和实时信息来解决复杂问题。
核心要点:
- 推理与行动交替:模型先思考再行动,行动结果作为下一步的输入
- 工具调用能力:通过结构化指令调用外部工具
- 适用场景广泛:信息查询、数据分析、代码生成等
- 可扩展性强:可以与 RAG、规划、反思等技术结合
应用价值:
- 解决需要实时信息的问题
- 完成需要多步骤操作的任务
- 提高答案的准确性和可靠性
- 扩展模型的能力边界
通过掌握 ReAct 范式,可以构建更强大、更实用的 AI 应用。