← 返回 Agent 技术总览
🧠 推理框架系列

ReAct / Agent 推理框架:从 CoT 到 ReAct 到 Tree-of-Thought

CoT · ReAct · ReAct-Step · ToT · GoT · 实际 Prompt 格式 · 对比测评 · 框架选择指南

💭
一、CoT 思维链——Agent 推理的起点

所有 Agent 推理框架的共同祖先是 Chain-of-Thought(思维链)。Wei et al. 2022 年发现:让模型在给出答案前先写出推理过程,准确率大幅提升。这个发现开启了「让 LLM 慢思考」的研究方向。

1. Standard CoT vs Zero-Shot CoT

Standard CoT(Few-Shot)
示例:
Q: 小明有 3 个苹果,又买了 2 袋苹果,每袋 4 个,共几个?
A: 先算购买量:2袋×4=8个。再加原有:3+8=11个。答:11个。

新问题:
Q: 小红有 5 个橙子,买了 3 袋...
需要提供示例,但效果最好
Zero-Shot CoT
Prompt 末尾只加一句话:

「Q: 小明有 3 个苹果...
Let's think step by step.

模型就会自动展开推理过程
不需要示例,适合快速部署

2. CoT 的局限性(为什么需要 ReAct)

  • 无法获取实时信息:CoT 只在 LLM 的参数知识范围内推理,不能搜索、不能查数据库
  • 事实性错误无法自纠:推理链里如果某步用了错误的知识,后续步骤会在错误基础上继续推
  • 单次输出:只能生成文字,不能执行代码、调用 API 等行动

ReAct 的诞生就是为了解决这三个问题——让推理(Reasoning)和行动(Acting)交替进行。

二、ReAct 框架——推理与行动的闭环

ReAct(Yao et al., 2022)把 LLM 的工作方式从「一次性输出」变成「推理 → 行动 → 观察」的循环,每次行动的结果成为下次推理的输入。

1. ReAct 的三个原语

💭
Thought(思考)
LLM 内部的推理过程,对用户可见(增加可解释性)。
「我现在需要搜索 X,因为...」
🔧
Action(行动)
调用工具或输出结果。格式化为可解析的结构(工具名 + 参数)。
search("关键词")
👀
Observation(观察)
工具执行结果,作为新的上下文追加到对话中。
「搜索结果:...」

2. ReAct vs 普通 CoT 的核心区别

图1:CoT vs ReAct 数据流对比
CoT(单次推理) 用户问题 + 推理指令 LLM 一次性推理 (无法获取外部信息) 最终答案(可能有幻觉) ReAct(循环推理+行动) 用户问题 Thought Action Observation 循环 Finish ✓
📝
三、ReAct Prompt 完整格式(可直接用)

一个生产可用的 ReAct System Prompt 包含:工具列表、输出格式规范、终止条件。

1. System Prompt 模板

## System Prompt

你是一个智能助手,可以使用以下工具完成任务:

## 可用工具
- search(query: str): 搜索互联网,返回相关信息片段
- calculator(expr: str): 计算数学表达式,如 "2 * 3.14 * 5"
- finish(answer: str): 当任务完成时调用,输出最终答案

## 输出格式
每次只输出以下格式之一:

Thought: [你的推理过程,说明为什么要做下一步]
Action: [工具名]([参数])

或者当观察到结果后继续:

Thought: [基于 Observation 的分析]
Action: [下一步动作]

## 重要规则
- 每次只输出一个 Thought + 一个 Action,不要一次性规划所有步骤
- Action 之后等待 Observation,不要自己编造 Observation
- 信息足够时立刻调用 finish()

2. 完整对话示例(带 Observation 注入)

User: 2024 年奥运会游泳冠军是谁?他打破了哪些记录?

Thought: 这是关于 2024 年巴黎奥运会的实时信息,我的训练数据可能不完整,需要搜索。
Action: search("2024 巴黎奥运会 游泳 冠军 世界纪录")

Observation: [搜索结果] 潘展乐在 100 米自由泳以 46.40 秒打破世界纪录夺金...

Thought: 已获得主要冠军信息,但想确认是否有更多记录被打破,再查一次。
Action: search("2024 奥运会 游泳 世界纪录 全部")

Observation: [搜索结果] 本届共打破 2 项世界纪录:潘展乐 100m 自由泳 46.40s...

Thought: 信息已足够,可以回答。
Action: finish("2024 巴黎奥运会,潘展乐在 100 米自由泳以 46.40 秒打破世界纪录夺冠。本届共打破 2 项游泳世界纪录。")

3. Observation 注入方式

当 LLM 输出 Action: search("xxx") 后,你的代码需要:① 解析出工具名和参数;② 执行工具调用;③ 把结果以 Observation: ... 的形式追加到对话历史;④ 再次调用 LLM。

# 核心循环(伪代码)
while not finished:
  response = llm.generate(messages)
  thought, action = parse_react_output(response)
  
  if action.tool == "finish":
    return action.args # 任务完成
  
  result = execute_tool(action.tool, action.args)
  messages.append({"role": "tool", "content": f"Observation: {result}"})
  steps += 1
  if steps > max_steps: break # 防止无限循环
🔀
四、ReAct 变体

1. Reflexion(带记忆的 ReAct)

在 ReAct 基础上加入「失败反思」:任务失败 → LLM 写一段反思(「哪里错了?为什么?」)→ 反思存入持久记忆 → 下次重试时先读取历史反思。相当于给 Agent 加了「从错误中学习」的能力。

Reflexion 新增的 Prompt 片段:
## 历史反思记录(每次失败后自动追加)
[尝试1失败] 反思:我直接搜索了太宽泛的关键词,下次应该先明确搜索范围再细化。
[尝试2失败] 反思:我错误地把百分比当绝对数值用了。

2. Plan-and-Execute(计划再执行)

标准 ReAct 是「边想边做」,步骤顺序不固定。Plan-and-Execute 把它分成两阶段:

① Planner LLM
生成完整步骤计划
② Executor LLM
逐步执行,遇到意外可回到①

优点:步骤可检查、可人工审核;缺点:初始计划可能不准确,灵活性不如标准 ReAct。

3. LATS(Language Agent Tree Search)

把 ReAct 和 Monte Carlo Tree Search(MCTS)结合:在每个 Action 决策点,采样多个候选 Action,用 Value Model 评估哪条路最有希望,类似 AlphaGo 的搜索策略。效果最好但计算成本极高,适合离线任务。

4. Structured ReAct(强制格式)

利用 LLM 的 JSON/结构化输出能力,强制 Action 输出为 JSON:

// 替代自由文本 Action,用结构化 JSON
{
  "thought": "需要搜索 2024 年奥运会游泳结果",
  "action": {
    "tool": "search",
    "parameters": {"query": "2024 Olympics swimming results"}
  }
}

优点:解析稳定,不会因为 LLM 输出格式不规范而报错;缺点:token 消耗更多。

🌳
五、Tree-of-Thought(ToT)

ToT(Yao et al., 2023)把单条推理链扩展成树形结构:在每个推理步骤,生成多个候选续写,用 Value Model 评估每条分支的前景,选最优的继续搜索

1. ToT 的四个组件

组件作用实现方式
Thought Decomposer把问题分解成适合逐步探索的格式Prompt 工程,让 LLM 输出「下一步可能性」
Thought Generator在当前节点生成 k 个候选续写采样 k 次(temperature > 0)或让 LLM 生成 k 个选项
State Evaluator对每个候选节点打分(有希望/没希望)Value Prompt 让 LLM 评分,或启发式规则
Search Algorithm决定如何遍历树BFS(广度优先)或 DFS(深度优先)

2. ToT 适合什么任务

✅ 适合
  • 数学证明(多种证明路径)
  • 代码规划(哪种架构方案)
  • 创意写作(探索不同风格/情节走向)
  • 谜题/游戏(24 点游戏、填字)
❌ 不适合
  • 需要工具调用的任务(用 ReAct)
  • 简单问答(CoT 就够了)
  • 实时性要求高(ToT 比 ReAct 慢 5~20 倍)
  • 预算有限的生产环境
🕸️
六、Graph-of-Thought(GoT)——更进一步

GoT(Besta et al., 2023)把 ToT 的树形结构进一步扩展成有向无环图(DAG)。树中每个节点只有一个父节点,而图中多个分支可以汇聚——允许把多条推理路径的结果聚合合并,再继续推理。

CoT
一条链
ToT
树(分支不聚合)
GoT
图(分支可以聚合)

GoT 目前主要在研究阶段,生产落地案例少。对于大多数工程场景,ReAct 仍然是最实用的选择

📊
七、框架对比与选型指南
框架复杂度速度精度工具调用推荐使用场景
CoT⭐⭐⭐⭐⭐⭐⭐⭐推理题、分析型任务
ReAct⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐需要工具的多步骤任务(首选)
Reflexion⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐允许重试的任务(代码、搜索)
Plan-Execute⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐步骤可预期、需要人工审核的任务
ToT⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐❌/有限探索性问题、离线批量任务
GoT⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐❌/有限研究场景,暂不推荐生产
选型建议:
1. 先试 CoT,如果准确率够就不需要更复杂的框架
2. 需要工具(搜索、代码、API)→ 用 ReAct
3. 任务允许多次重试,且有明确的失败信号 → 加 Reflexion
4. 任务需要探索多种方案且时间充裕 → 考虑 ToT
5. 对延迟敏感的生产环境 → 永远优先用最简单够用的框架
⚙️
八、工程实现要点

1. 防止无限循环

ReAct 循环没有自然终止条件,必须设置:

  • 最大步骤数(通常 10~20 步):超过则强制停止并返回当前最优结果
  • 最大 token 预算:超过上下文窗口限制时截断早期对话历史
  • 重复检测:连续两步 Action 完全相同时中断(Agent 卡住了)

2. 上下文窗口管理

ReAct 每次循环都在往对话历史里追加内容,步骤多了会超出 token 限制。解决方案:

  • 对 Observation 做摘要压缩(长搜索结果 → 只保留最相关的段落)
  • 只保留最近 N 步的完整历史,早期步骤只保留摘要

3. 解析 Action 的鲁棒性

LLM 的输出不总是严格按照格式。工程上需要处理:

  • Action 里的工具名拼错 → 模糊匹配或提示 LLM 重试
  • JSON 格式不合法 → 用 JSON 修复库(如 json_repair
  • 没有 Action 只有 Thought → 判断是否已经是 finish 意图