为什么选择 ReAct,而不是纯 Chain 或 Tool Use?

一、三种范式对比

维度 纯 Chain(思维链) 纯 Tool Use(工具调用) ReAct(推理+行动)
核心流程 一次性推理到底 调用工具 → 拿结果 → 继续调用 思考 → 行动 → 观察 → 再思考 循环
有无反馈闭环 ❌ 无 ⚠️ 隐式(工具结果可直接用,但不显式推理) ✅ 显式推理 + 观察整合
可解释性 中等(有推理步骤,但静态) 低(只见工具调用链) (每一步思考都可见)
错误恢复能力 ❌ 一步错,全盘错 ⚠️ 工具失败可重试,但缺乏反思 ✅ 观察失败后可重新推理
动态调整 ❌ 路径固定 ⚠️ 工具链可微调 ✅ 根据观察结果改变策略

二、逐一对比如下

2.1 纯 Chain:线性推理的局限

纯 Chain(Chain of Thought)是一次性规划好推理路径,然后按顺序执行。

复制代码
输入问题
  │
  ▼
Step 1: 推理 → Step 2: 推理 → Step 3: 推理 → ... → 输出答案

问题

  • 不能与外部交互------无法查资料、调 API、读文件
  • 幻觉无法纠正------推理中产生错误信息,没有外部信息源来校验
  • 路径僵化------如果第三步推理需要第一步的实际结果,纯 Chain 做不到

例子:用户问"今天北京天气怎么样?"

纯 Chain ReAct
直接编一个天气(幻觉) Thought: 需要查实时天气 → Action: 调用天气 API → Observation: 晴,25°C → Thought: 可以回答了 → Answer

2.2 纯 Tool Use:有手无脑

纯 Tool Use 是让模型直接调用工具,不要求显式的推理过程。

复制代码
Function Call → Result → Function Call → Result → ... → Output

问题

  • 缺乏反思环节------工具返回了意料之外的结果,模型可能机械地继续而不是调整思路
  • 可解释性差------用户/开发者看到的是工具调用历史,而不是"为什么这样调"
  • 复杂推理能力弱------多步任务需要"调用哪个工具 → 结果说明什么 → 下一步该做什么"的推理链,纯调用缺乏中间的 reasoning trace

对比示例:用户问"帮我查一下腾讯今天的股价,如果涨幅超过 3% 就发微信通知我"

纯 Tool Use ReAct
get_stock("0700.HK") → 结果 Thought: 先查股价
send_wechat(...) → 结果 Action : get_stock("0700.HK")
(直接发通知,可能不判断涨幅) Observation: 涨了 4.2%
Thought: 涨幅 4.2% > 3%,需要通知
Action : send_wechat("涨幅 4.2%")
Observation: 发送成功
Answer: 已通知

三、ReAct 的核心优势

3.1 反馈闭环

Thought思考Action行动Observation观察

每一步行动都有观察结果,观察结果驱动下一步的思考。这是一个感知-行动闭环

3.2 错误自愈

复制代码
Thought: 我需要查订单 #12345 的状态
Action: query_order(order_id=12345)
Observation: 订单不存在

Thought: 可能 ID 记错了,让我先搜索用户名 "张三" 的订单
Action: search_orders(user_name="张三")
Observation: 找到 3 个订单,[#12346, #12347, #12348]

Thought: 最近的一条是 #12346,查询它
Action: query_order(order_id=12346)
Observation: 状态 = 已发货

Answer: 您最近的订单 #12346 已发货

如果第一步出错就停止,这就是纯 Chain/Tool Use 的问题。ReAct 通过 Thought → Observation → 重新 Thought 实现了主动纠错。

3.3 可解释性与调试友好

层级 能看到什么
用户视角 模型每一步在想什么,为什么调这个工具
开发者视角 推理路径是否合理,Prompt 是否产生了偏差
安全审计 完整的决策链,可追溯每一步逻辑

3.4 动态任务分解

ReAct 可以根据当前观察动态决定下一步,而非提前规划死。

复制代码
复杂问题: "帮我分析这份财报,挑出营收增长最快的三个业务线"
        ↓
Thought: 先提取财报 → Action: read_file → Observation: 200页PDF
        ↓
Thought: 太长了,先看目录 → Action: get_toc → Observation: 5个业务线
        ↓
Thought: 逐个提取营收数据 → Action: extract_revenue → ...
        ↓
(根据每步结果,动态决定下一个要处理的业务线)

四、ReAct 的实现范式

复制代码
class ReActAgent:
    """最简 ReAct 循环"""
    
    def __init__(self, llm, tools: dict):
        self.llm = llm
        self.tools = tools  # {"search": func, "calc": func, ...}
        self.history = []
    
    def run(self, question: str, max_steps: int = 10) -> str:
        prompt = self._build_prompt(question)
        
        for _ in range(max_steps):
            response = self.llm(prompt)
            
            # 解析 Thought / Action / Observation
            parsed = self._parse(response)
            
            if parsed["type"] == "answer":
                return parsed["content"]
            
            if parsed["type"] == "action":
                # 执行工具
                tool = self.tools.get(parsed["action"])
                result = tool(parsed["input"]) 
                obs = f"Observation: {result}"
                self.history.append(f"{response}\n{obs}")
                prompt = self._build_prompt(question, self.history)
    
    def _parse(self, response: str) -> dict:
        """从 LLM 输出中解析 Thought / Action / Final Answer"""
        # 匹配 Thought: ... \n Action: tool_name[input]
        # 或 Final Answer: ...
        ...

    def _build_prompt(self, question: str, history=None) -> str:
        return f"""Answer the following question. You may use these tools:
{tools_desc}

Use this format:
Thought: your reasoning
Action: tool_name[input]
Observation: tool result
... (repeat)
Final Answer: your answer

Question: {question}
History: {history or ''}
"""

Prompt 模板决定了 ReAct 的结构:

复制代码
You have access to the following tools:
- search[query]: 搜索互联网
- calculator[expression]: 数学计算

Use the following format:
Thought: 你当前的推理
Action: 要调用的工具
Action Input: 工具参数
Observation: 工具返回的结果
... (这个 Thought/Action/Observation 循环可重复)
Final Answer: 最终给用户的回答

Question: {user_question}

五、ReAct 也有局限

局限 说明 缓解方案
Token 消耗高 每次 Thought + Action + Observation 都占上下文 对历史做摘要压缩
死循环风险 反复进入同一条 Reasoning 路径 设置 max_steps 上限 + 重复检测
推理质量依赖 Prompt 设计 Prompt 写得不好,模型可能跳步骤或格式错误 结构化输出(JSON Mode)+ Few-shot 示例
延迟高 每步都要 LLM 推理 + 工具调用 + 再 LLM 推理 允许并行 action(ReWOO 等变体)

六、决策矩阵:什么时候该用哪种范式

场景 推荐范式 原因
简单问答、无需外部信息 纯 Chain / 直接生成 不需要工具,ReAct 反而浪费 token
单步工具调用(查一次天气) 纯 Tool Use / Function Calling 无需反思循环
多步推理 + 工具 + 需纠错 ReAct 需要观察 → 重新推理的闭环
确定性工作流(固定步骤) 纯 Chain + Tool Use 路径已定,不需要动态调整
开放域复杂问题 ReAct 无法预知所需步骤和工具

七、总结

纯 Chain = 有脑无手 (只能想,不能做) 纯 Tool Use = 有手无脑 (能做,但不会反思) ReAct = 脑手协同(边想边做,做完了想,想清楚再做)

ReAct 的核心价值在于 Thought → Action → Observation → Thought 的闭环 ,这正是人类解决复杂问题的方式:尝试、观察、调整、再尝试。对于 AI Agent 需要动态决策的场景,这个闭环是不可替代的决策引擎。