论文:《ReAct: Synergizing Reasoning and Acting in Language Models》
链接:https://arxiv.org/pdf/2210.03629
背景:
经过适当提示的大型语言模型(LLMs)已经展现出进行推理步骤以推导出算术、常识和符号推理任务中问题的答案的涌现能力,但“思维链”推理是一个静态的黑盒,因为模型使用其内部表示来生成思考,并且没有与外部世界建立联系,这限制了其反应式推理或更新知识的能力。这可能导致事实幻觉和推理过程中的错误传播等问题。
目标:以协同的方式将推理和行动结合起来进行一般任务解决 。
人类智能的核心在于推理与行动的紧密结合。例如做饭时,人们会根据当前状态调整计划、搜索外部信息、反思并修正行为。这种“边想边做”的机制在 LLM 中尚未被充分建模。
提出一种统一的框架 ReAct,使 LLM 能交错生成推理轨迹和动作,实现“边推理边行动”,提升任务解决能力、可解释性和鲁棒性。
ReAct,一种结合推理和行动的通用范式,用于解决各种语言推理和决策任务(图1)。ReAct以交错的方式提示大型语言模型生成与任务相关的语言推理轨迹和行动,这允许模型进行动态推理,以创建、维护和调整行动的高级计划(为行动而推理),同时还可以与外部环境(例如Wikipedia)交互,以将额外信息纳入推理(为推理而行动)。
大型语言模型(LLMs)在推理(reasoning)和行动(acting)方面表现出强大能力,但现有研究通常将两者割裂开来:
推理:如 Chain-of-Thought (CoT) 提示,仅依赖模型内部知识进行静态推理,容易幻觉(hallucination)和错误传播。
行动:如 WebGPT、SayCan 等,通过语言模型生成动作与环境交互,但缺乏高层抽象推理和工作记忆支持。
1.提示词工程
CoT(Chain of Thought,思维链)---- prompt engineering
标准CoT:
# 伪代码示例 def chain_of_thought(prompt):# 1. 在提示中加入推理步骤要求enhanced_prompt = f"""请按步骤推理: 问题:{prompt} 让我们一步步思考:""" # 2. 模型生成包含推理步骤的回复response = model.generate(enhanced_prompt)# 3. 提取最终答案answer = extract_final_answer(response)return answer
Few-shot CoT(少样本示例COT):
给模型提供几个(通常是2-5个)带有完整推理步骤的示例,让模型学会模仿这种“一步一步思考”的方式来解决新问题。
# 使用示例演示推理过程 few_shot_examples = """ Q: 小明有5个苹果,吃了2个,又买了3个,现在有几个? A: 小明原来有5个苹果,吃了2个后剩下5-2=3个。然后买了3个,现在有3+3=6个。所以答案是6。Q: 如果一本书30元,打8折后多少钱? A: 原价30元,8折就是乘以0.8。30 × 0.8 = 24元。所以答案是24元。 """
关键技术点:
-
步骤分解:将复杂问题分解为多个推理步骤
-
中间结果:明确展示每一步的计算或推理过程
-
自然语言格式:用自然语言描述推理过程
2.执行策略/范式/思维模式
1)ReAct(Reasoning + Acting)
-
思想:边想边做,即时决策
-
过程:思考→行动→观察→再思考(循环)
实现推理和执行的交错进行,伪代码如下:
class ReActAgent:def __init__(self, model, tools):self.model = modelself.tools = tools # 可用工具集(搜索、计算器、API等)def run(self, question):context = f"问题:{question}\n"max_steps = 5for step in range(max_steps):# 1. 思考下一步thought = self._think(context)# 2. 决定行动(如果需要)action = self._decide_action(thought)if action.type == "FINISH":return action.answerelif action.type == "TOOL":# 3. 执行工具调用observation = self._use_tool(action.tool, action.params)# 4. 观察结果并继续context += f"观察:{observation}\n"def _think(self, context):prompt = f"""{context} 现在我需要思考下一步该做什么。我应该:""" return self.model.generate(prompt)
差异对比
| 方面 | CoT | ReAct |
|---|---|---|
| 核心 | 纯推理链 | 推理+行动交互 |
| 外部交互 | 无 | 支持工具调用 |
| 错误处理 | 内部修正 | 通过观察结果调整 |
| 结构 | 线性推理 | 循环决策 |
| 适用场景 | 纯推理问题 | 需要外部信息的任务 |
2)混合ReAct/CoT实现
def react_with_cot(agent, question):# 初始推理步骤(CoT风格)initial_reasoning = agent.think(f"分析问题:{question}")# ReAct循环while not task_complete:# 1. 推理当前状态(CoT)thought = agent.think(f""" 当前状态:{current_state} 需要解决:{sub_problem} 我的推理:""") # 2. 决定行动action = agent.decide_action(thought)if action == "USE_TOOL":result = agent.use_tool()# 3. 基于结果的进一步推理(CoT)reflection = agent.think(f""" 工具返回:{result} 这意味着:""")
工程实现:
CoT优化:
- 使用few-shot示例指导推理格式
- 明确要求"逐步思考"
- 加入自我验证步骤
ReAct优化:
- 限制最大循环次数防止死循环
- 设计清晰的工具描述
- 实现回退和错误处理机制
混合策略:
- 复杂任务先用CoT分解
- 需要外部信息时切到ReAct
- 关键步骤加入反思和验证
性能考量:
-
CoT:增加token消耗,但提升准确率
-
ReAct:需要多次模型调用,延迟较高
-
缓存策略:缓存常用推理结果
-
并行处理:并行工具调用优化
langChain agent实现:
from langchain.agents import initialize_agent, Tool from langchain.agents import AgentType# 定义工具 tools = [Tool(name="Search", func=search_tool, description="搜索信息"),Tool(name="Calculator", func=calculator, description="数学计算") ]# 创建ReAct代理 agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,verbose=True )
3)Plan-and-Execute(计划与执行)
-
思想:先规划,再执行
-
过程:总体规划→分解任务→顺序执行
伪代码:
问题:北京今天天气如何?我想知道是否适合户外运动【规划阶段】 计划: 1. 获取北京今日天气数据 2. 获取户外运动适宜条件标准 3. 对比天气数据与运动条件 4. 给出建议【执行阶段】 → 执行步骤1:调用天气API → 结果:25°C,晴朗,PM2.5=30 → 执行步骤2:查询运动适宜条件 → 结果:适宜温度20-28°C,PM2.5<50 → 执行步骤3:对比 → 结果:符合条件 → 执行步骤4:生成建议def plan_and_execute(problem):# 第一阶段:制定计划plan = model.generate(f""" 制定解决这个问题的计划: 问题:{problem}请输出分步骤的计划:""") # 第二阶段:按计划执行steps = parse_plan(plan)results = []for step in steps:# 专注于当前步骤result = execute_step(step, previous_results=results)results.append(result)# 第三阶段:整合结果final_answer = synthesize_results(results)return final_answer
| 维度 | ReAct | Plan-and-Execute |
|---|---|---|
| 决策时机 | 即时决策,动态调整 | 预先规划,按计划执行 |
| 灵活性 | 高,可根据反馈实时调整 | 较低,需重新规划 |
| 复杂度 | 更适合开放性问题 | 更适合结构化任务 |
| 资源消耗 | 可能多次工具调用 | 工具调用更有计划性 |
| 错误处理 | 内嵌在循环中 | 需要额外错误处理机制 |
| 透明度 | 思考过程可见 | 计划阶段清晰可见 |
| 适用场景 | 探索性任务、动态环境 | 复杂多步任务、有明确步骤 |
langchain中plan-and-execute实现:
from langchain_experimental.plan_and_execute import (PlanAndExecute, load_agent_executor,load_chat_planner )# 1. 规划器 planner = load_chat_planner(llm)# 2. 执行器 executor = load_agent_executor(llm, tools, verbose=True)# 3. 组合 agent = PlanAndExecute(planner=planner,executor=executor,max_iterations=3 )# 运行 - 先规划再执行 result = agent.run("帮我写一份关于AI发展的市场报告")
系统架构
论文解析:https://blog.csdn.net/bylander/article/details/152733528