ReAct:推理与行动交织的 Agent 循环原型
2022 年 10 月,Princeton NLP 和 Google Brain 的研究者在 arXiv 提交了 ReAct(arXiv 2210.03629,后被 ICLR 2023 接收)。论文标题是 Reasoning 和 Acting 的合成词,核心主张只有一句:让语言模型在同一条轨迹里交替生成推理(thought)和动作(action),推理指导动作,动作把外部世界的信息带回推理。
今天所有 coding agent 里那个「调用模型、执行工具、读结果、再推理」的内环,谱系都能追到这篇论文。理解 ReAct 的设计动机和它当年的实验边界,是理解现代 agent loop 的前提。
本文与已有文章的边界
| 已有文章 | 主要讨论 | 与本文的关系 |
|---|---|---|
| Agent 全景指南 | Agent 的必要性、范式演化和高可用落地 | 提供 Agent 范式全景,本文补上循环范式的论文源头 |
| Harness Engineering:长程 Agent 的工程化底座 | 长程 Agent 的工具、状态、验证环境 | Harness 包在循环外面,本文讲循环本身从哪来 |
| 环境可供性:智能的一半是取到正确数据 | Agent 的取数环境和可供性 | ReAct 的失败分析给这个论点提供了 2022 年的实验证据 |
| LLM 搜索成本与搜索精度 | 检索质量对 LLM 的影响 | ReAct 的 Wikipedia API 是最早的「弱检索器 + 强推理」组合之一 |
2022 年的两条平行线
ReAct 出现之前,语言模型有两条互不相交的研究线。
一条是推理线。Chain-of-Thought 让模型在回答前生成中间推理步骤,在算术、常识和符号推理上大幅提分。但 CoT 是封闭系统:全部推理发生在模型内部,接触不到外部世界。模型只能依赖参数里冻结的知识,知识过期就编造,而且一步编造会顺着推理链传播到结论。
另一条是行动线。WebGPT 这类工作让模型在真实环境里生成动作序列(搜索、点击、翻页),但没有显式的推理轨迹去分解目标、跟踪进度、处理意外。模型看见什么做什么,缺少一层「我现在做到哪了、接下来该干什么」的抽象。
ReAct 的假设是这两条线互补:推理帮助模型制定、维护和调整行动计划(reason to act),行动让模型从外部环境获取新信息来支撑推理(act to reason)。
方法:thought 是一种不改变世界的动作
形式上,ReAct 把 agent 的动作空间从环境动作 A 扩充成 A ∪ L,其中 L 是整个语言空间。一条 thought 就是一个取值于 L 的动作,它的特殊之处在于:它不作用于环境、不产生 observation,只把一段推理文本追加进上下文,改变模型后续生成的条件。
flowchart TD
T["Thought:分解目标 / 抽取要点 / 调整计划<br/>只写入上下文,不触碰环境"] --> A["Action:作用于外部环境"]
A --> O["Observation:环境返回的反馈"]
O --> T
论文对两类任务采用了不同的交织密度。知识密集型任务(多跳问答、事实核查)里推理是主角,thought、action、observation 严格交替出现。决策任务(ALFWorld、WebShop)里动作序列很长,thought 只稀疏地出现在关键位置,什么时候思考由模型自己决定。
thought 的用途在轨迹里能看到好几种:分解任务目标制定计划、注入任务相关的常识、从冗长 observation 里抽取要点、跟踪进度维持计划执行、遇到异常时调整方案。
刻意简陋的动作空间
在 HotpotQA 和 FEVER 上,ReAct 的全部工具只有一个 Wikipedia API 的三个动作:
| 动作 | 语义 |
|---|---|
search[entity] |
返回对应词条的前 5 句;词条不存在时返回 5 个相似标题作提示 |
lookup[string] |
在当前词条里模拟 Ctrl+F,返回下一个包含该字符串的句子 |
finish[answer] |
提交答案,结束轨迹 |
这个设计模仿人类和 Wikipedia 的交互方式,检索器故意做得弱。论文的意图是把信息检索的负担压到模型的推理上:检索不到就换个实体再搜,搜出来的内容没用就自己判断该看哪个相似标题。工具越弱,越能看清推理在循环里起的作用。
一条轨迹长什么样
论文里最常被引用的例子:
1 | |
搜索失败、依据提示改搜索词、从 observation 里抽出结论,这些行为在纯 CoT 里不存在,在纯 acting 里没有解释。
冻结的 PaLM-540B 上的结果
所有主实验用冻结的 PaLM-540B 做 few-shot prompting,HotpotQA 用 6 个示例,FEVER 用 3 个,ALFWorld 用 2 个,WebShop 用 1 个。
| 方法 | HotpotQA(EM) | FEVER(accuracy) |
|---|---|---|
| Standard | 28.7 | 57.1 |
| CoT(只推理) | 29.4 | 56.3 |
| Act-only(只行动) | 25.7 | 58.9 |
| ReAct | 27.4 | 60.9 |
| ReAct + CoT 最佳组合 | 35.1 | 64.6 |
| 监督学习 SoTA | 67.5(约 14 万样本) | 89.5(约 9 万样本) |
| 方法 | ALFWorld(成功率) | WebShop(成功率) |
|---|---|---|
| Act-only | 45 | 30.1 |
| ReAct | 71 | 40 |
| 模仿学习基线 | 37(约 10 万样本) | 29.1(约 9 万样本) |
两个值得注意的细节。ReAct 单独用并不总是赢:HotpotQA 上它输给 CoT(27.4 对 29.4),只在 FEVER 上占优。真正的大幅领先出现在决策任务上:ALFWorld 和 WebShop 里,一两个示例的 ReAct 超过了用十万量级样本训练的模仿学习和强化学习基线,成功率绝对提升分别是 34% 和 10%。附录里的 GPT-3(text-davinci-002)实验在这些任务上一致好于 PaLM-540B,HotpotQA 达到 30.8,ALFWorld 达到 78.4,说明方法不绑定单一模型。
把成功和失败拆开看
论文做了一件后来很多 agent 论文不做的事:人工标注 200 条轨迹(ReAct 和 CoT 各取 50 条成功、50 条失败),把成败原因分类。
| 类别 | 定义 | ReAct | CoT |
|---|---|---|---|
| 成功·真阳性 | 推理和事实都正确 | 94% | 86% |
| 成功·假阳性 | 答案碰对了,推理或事实是编的 | 6% | 14% |
| 失败·推理错误 | 推理循环出错,含重复循环跳不出去 | 47% | 16% |
| 失败·搜索无信息 | 检索返回空或无用内容 | 23% | — |
| 失败·幻觉 | 编造事实 | 0% | 56% |
| 失败·标签歧义 | 答案基本正确但不匹配标准答案 | 29% | 28% |
这张表比总分表更有信息量。ReAct 把幻觉从 56% 压到 0%,代价是两种新失败。一种是推理僵化:47% 的失败是推理错误,其中一个反复出现的模式是模型不断重复上一轮的 thought 和 action,跳不出循环,论文推测和 greedy decoding 有关。另一种是被检索器拖累:23% 的失败源于 search 返回了无信息的结果。
换句话说,ReAct 用「把推理锚在外部证据上」消灭了编造,也把模型的上限和检索质量绑在了一起。工具返回的东西没用,循环就卡死。这是「观察面质量决定循环上限」最早的定量证据,和环境可供性一文的论点相互印证。
与 CoT 的组合才是最佳配置
既然 ReAct 事实性强、CoT 推理结构灵活,论文给出了两个互为镜像的组合策略:
- ReAct → CoT-SC:先跑 ReAct,HotpotQA 上 7 步内、FEVER 上 5 步内没有得出答案,就回退到 CoT 自洽投票。
- CoT-SC → ReAct:先跑 21 次采样的 CoT-SC,多数答案得票不足一半(说明模型内部知识不足以自信作答)时,改跑 ReAct。
组合把 HotpotQA 推到 35.1、FEVER 推到 64.6。而且组合方法只用 3 到 5 次采样,就达到了 CoT-SC 用 21 次采样的水平。内部知识和外部检索不是二选一,而是按置信度分流。
微调:学技能还是背事实
Prompting 之外,论文用 bootstrap 方式做了微调:拿 ReAct prompted 的 PaLM-540B 生成 3000 条答案正确的轨迹,微调更小的 PaLM-8B 和 PaLM-62B。
结果的形状比数字更重要:微调后的 8B ReAct 超过了所有 62B 的 prompting 方法,微调后的 62B ReAct 超过了所有 540B 的 prompting 方法。而微调 Standard 和 CoT 的收益明显更差。论文的解释是,微调 Standard 或 CoT 本质上是教模型背诵(可能是幻觉出来的)事实,微调 ReAct 教的是一种可泛化的技能:去哪里获取信息、怎么围绕取回的信息推理。技能比事实迁移得远。
可读、可诊断、可编辑
ReAct 轨迹是人类可读的决策记录。论文用一个 human-in-the-loop 实验展示了这件事的价值:ALFWorld 里一条轨迹因为某步 thought 出现幻觉而失败,人工只把那两条 thought 改掉,agent 随即改变行为,完成了任务。
不用改权重、不用改 prompt 模板,只编辑推理文本就能纠偏。这是后来 agent 系统里人工审阅、轨迹审计、human gate 这类设计的雏形:推理外化成文本之后,人和系统之间多了一个可以介入的界面。
从 ReAct 到现代 agent loop
ReAct 的格式本身早就被淘汰了,但它定义的循环活了下来。
早期 LangChain 的 ReAct agent 就是论文格式的直接工程化:靠文本解析 Thought / Action / Action Input / Observation 字段驱动循环,解析失败是家常便饭。2023 年 6 月 OpenAI 推出 function calling,动作从文本约定变成结构化输出,ReAct 的格式约定被吸收进了 API 层。再往后,现代 coding agent 的 model loop——调用模型、执行工具、结果回填、再推理——就是 thought-action-observation 的工业化版本:thought 变成了模型的 interleaved thinking,observation 变成了 tool result 消息,循环由运行时而不是 prompt 约定来维护。
后续研究也在这个骨架上叠层。Reflexion 给 ReAct 加上自我反思记忆,失败经验以文本形式带进下一轮尝试;SWE-agent 提出 agent-computer interface,专门优化 agent 看到的观察面,直接回应了 ReAct 那 23% 的检索失败。
同样重要的是认清 ReAct 的边界。它只定义了单条轨迹内的循环:一次任务、一个上下文窗口、几个工具。什么时候触发、状态怎么跨会话保存、权限边界在哪、什么证据算完成,这些问题在 ReAct 里不存在,因为 2022 年的实验跑完一条轨迹就结束了。这些循环外围的问题后来长成了独立的工程层,见 Harness Engineering。
参考资料
- ReAct: Synergizing Reasoning and Acting in Language Models(arXiv 2210.03629)
- Google Research Blog: ReAct: Synergizing Reasoning and Acting in Language Models
- ReAct 项目主页与代码
- OpenReview: ReAct(ICLR 2023)
- Reflexion: Language Agents with Verbal Reinforcement Learning(arXiv 2303.11366)
- SWE-agent: Agent-Computer Interfaces Enable Automated Software Engineering(arXiv 2405.15793)
- LangChain Docs: ReAct agent
