论文精读 01|ReAct:把推理、动作与观察编排成闭环
论文档案
| 项目 | 内容 |
|---|---|
| 论文 | ReAct: Synergizing Reasoning and Acting in Language Models |
| 作者 | Shunyu Yao 等 |
| 发表 | ICLR 2023 |
| 原文 | OpenReview / arXiv |
| 项目 | ReAct 项目主页与代码 |
| 本文定位 | Agent Harness 控制循环的起点,而不是完整运行时方案 |
先记住四件事
- ReAct 的核心不是让模型“多想一会儿”,而是把 Thought、Action、Observation 放进同一条可继续的轨迹。
- 推理负责形成和修订计划,动作负责获取外部证据或改变世界,观察把真实结果带回下一轮。
- 它解决的是开环生成问题,没有自动解决权限、隔离、幂等、审计和成功判定。
- 论文最有价值的证据不是某个总分,而是:纯 CoT 容易凭内部先验幻觉,纯 Act 又缺少维护长期意图的工作区。
研究问题:两种半成品怎样拼成闭环
ReAct 出现前,语言模型解决复杂任务常见两条路线。
Chain-of-Thought 路线让模型先生成中间推理,再给最终答案。它对算术和常识推理有效,但整个过程仍封闭在模型上下文里。当模型缺少事实时,一条流畅的推理链也可能只是在放大错误先验。
Action-only 路线让模型直接选择搜索、点击、拿取物体等动作。它可以接触环境,却容易退化成缺少计划的局部反应:不知道已经验证过什么、下一步为何合理,也很难从一次失败观察中调整长期策略。
ReAct 的命题是:推理与行动不应分成两个阶段,而应在时间上交错。抽象成状态机就是:
任务 + 历史
│
▼
Thought: 当前知道什么、缺什么、下一步为何必要
│
▼
Action: 在约束动作空间中执行一步
│
▼
Observation: 环境返回的事实、错误或状态变化
└──────────────────────► 下一轮 Thought这恰好成为后来 Agent Harness 的最小数据面:模型输出决策,运行时执行动作,再把观察归一化回填。
方法拆解
Thought 不是最终解释,而是临时工作记忆
论文把自然语言 reasoning trace 当作一种可读的内部状态。它可用于:
- 把大目标拆成当前子目标;
- 跟踪已经检索到的事实;
- 处理异常,决定重试、换查询或改变计划;
- 判断信息是否足够并结束任务。
这并不意味着 Thought 忠实反映模型内部计算。工程上应把它视为策略生成的中间产物,可用于调试和条件生成,但不能把“模型说自己已经验证”当作真实验收证据。
Action 是受环境定义的协议
在 HotpotQA、FEVER 中,动作是 Search[...]、Lookup[...]、Finish[...] 一类文本命令;在 ALFWorld 中,是文本世界允许的移动、打开、拿取、加热等动作;在 WebShop 中,则是搜索、选择属性和购买等网页操作。
所以 ReAct 并没有规定唯一工具调用格式。它真正要求的是:
模型输出 --解析--> 合法动作 --环境执行--> 可观察结果解析失败、动作越界、工具异常,都应该成为明确 Observation,而不是让模型在看不见的地方失败。
Observation 是外部事实,不是 prompt 装饰
观察的作用是打断模型的自说自话。搜索结果、游戏反馈和页面状态都可能否定上一轮假设。论文中 ReAct 在事实问答上的优势,正来自把外部检索结果引入推理链。
但 Observation 也会制造新问题:它可能过长、重复、无关,甚至包含恶意指令。ReAct 本身没有来源标记与信任分层;现代 harness 必须补上观察裁剪、数据/指令隔离和注入防护。
两类任务使用不同的推理密度
论文没有要求每一步动作前都写长推理:
- 在知识密集型问答里,Thought 较密集,用于组织检索和证据组合;
- 在 ALFWorld、WebShop 这类长轨迹决策里,推理可以稀疏出现,只在制定计划、发现异常或切换子目标时介入。
这给工程实现一个重要启示:不要把“每一步都生成固定长度 Thought”写死。推理频率本身是成本、延迟和性能的控制参数。
实验到底证明了什么
四类任务
| 任务 | 环境特征 | ReAct 要解决的核心矛盾 |
|---|---|---|
| HotpotQA | 多跳 Wikipedia 问答 | 内部推理需要外部证据校正 |
| FEVER | 事实核验 | 结论必须落到可检索证据 |
| ALFWorld | 文本化家居环境 | 长动作序列要维护目标和对象状态 |
| WebShop | 约 118 万商品、自然语言购买指令 | 搜索、属性约束与网页导航要联合进行 |
HotpotQA 使用 6 条人工轨迹作为 few-shot 示例,FEVER 使用 3 条;ALFWorld 按 6 个任务类型各提供 3 条示范轨迹;WebShop 使用 one-shot 轨迹。论文主要模型是 PaLM-540B,因此这里的数字不能脱离模型、prompt 和当时环境直接对照今天的 API。
知识问答:Grounding 与灵活性的交换
在 HotpotQA 与 FEVER 上,ReAct 的优势是事实落地,缺点是可能在检索中卡住。作者对 200 个 HotpotQA 样本做人工错误分析,观察到 CoT 的主要失败类型是事实幻觉;论文报告该类失败约占 CoT 错误的 56%。ReAct 能搜索外部信息,因此幻觉更少,但会被无关或重复文档拖入循环。
结果中常常是 ReAct 与 CoT-SC 的组合最好,而不是单一方法统治所有任务。原因很直接:
- CoT 的闭卷推理更灵活,偶尔能靠先验直接完成;
- ReAct 更可验证,但检索策略和搜索接口成为新瓶颈;
- 两者互补说明“何时调用环境”本身也是策略问题。
ALFWorld:推理对长轨迹很重要
ALFWorld 评测包含 134 个未见环境、6 类家务任务。论文报告最佳 ReAct 试验达到 71% 成功率,最佳纯 Act 试验为 45%,此前 BUTLER 基线为 37%。但 ReAct 不同试验间波动明显,最差一次约 48%。
作者还做了 ReAct-IM 消融:把显式内部推理换成较弱的内隐式形式,成功率从 71% 降到 53%。这支持“语言工作记忆帮助长程决策”,同时也暴露 few-shot 轨迹和采样随机性对结果影响很大。
WebShop:动作闭环带来直接收益
WebShop 含约 118 万商品和 1.2 万条人工指令。ReAct 在论文设置下相对此前最佳方法取得约 10 个百分点的绝对成功率提升。这里的重要信息不是网页 Agent 已经成熟,而是自然语言推理能协调搜索词、商品属性和页面动作。
失败模式比总分更值得学
检索循环
如果查询没有命中关键实体,模型可能只做同义改写,然后反复看到类似结果。Harness 应识别:
- 连续相同或高度相似动作;
- Observation 没有新增实体或证据;
- 同一错误连续出现;
- 预算消耗上升但任务状态不变。
检测后可触发查询改写、切换工具、回滚到 checkpoint 或直接结束,而不是无限继续 ReAct 循环。
上下文膨胀
轨迹越长,历史 Thought 和 Observation 越容易淹没当前状态。论文已经指出复杂动作空间需要更多示例与上下文,而示例本身又挤占任务轨迹空间。现代实现需要把“原始事件日志”和“给模型看的上下文视图”分开:日志完整保存,视图可以裁剪、分页或总结。
动作正确但目标错误
一个动作可能语法合法、执行成功,却把 Agent 带向错误子目标。工具层只能检查类型和权限,任务层还要检查进度与不变量。例如购买任务中,点击成功不代表尺寸、价格和颜色同时满足。
观察不可信
网页文本与检索文档都可能包含 prompt injection。ReAct 将它们直接送回模型,在论文的非对抗设置中合理,在生产系统中却不是安全边界。最少应保留来源、信任级别、内容摘要和产生该观察的动作 ID。
从论文映射到 Harness
| ReAct 概念 | Harness 中更严格的实现 |
|---|---|
| Thought | 可选的策略草稿;默认不作为事实或授权依据 |
| Action | 带版本的结构化命令,先校验再执行 |
| Observation | 有来源、大小限制和敏感级别的执行结果 |
| Trajectory | 追加式事件流,包含因果 ID、时间、成本与状态摘要 |
| Finish | 结束请求;是否成功仍由独立 evaluator 决定 |
| Few-shot trajectory | 可版本化策略资产,需防止泄露答案与过拟合 |
一个可测试的循环可以写成:
while budget.allows_next_step():
view = context_builder.render(task, state, events)
proposal = policy.next_action(view)
action = protocol.validate(proposal)
decision = policy_gate.authorize(action, state)
observation = executor.run(decision.action)
events.append(observation)
state = reducer.apply(state, observation)
if evaluator.is_terminal(state):
break关键差异是 Finish 不直接等于成功,authorize 也不能交给同一个模型自批。
最小复现实验
不要先复刻全部四个基准。用一个确定性小环境就能验证论文机制:
- 设计 20 个必须两次查询才能回答的任务;
- 给模型
search(key)、lookup(id)、finish(answer)三个动作; - 比较一次性回答、Act-only、ReAct 三种策略;
- 固定模型、温度、任务顺序和最大步数;
- 记录任务成功率、动作数、重复动作率、无新增信息步数;
- 人工标注失败是知识缺失、错误计划、工具选择、参数还是停止判断。
随后加入三个 harness 消融:重复动作熔断、观察分页、独立答案验证。这样能区分收益来自“更会推理”,还是来自运行时纠错。
不能从论文推出什么
- 不能证明 Thought 是模型真实、忠实或安全的解释;
- 不能证明增加更多思考总会提升效果;
- 不能证明文本动作优于结构化工具调用;
- 不能证明 ReAct 自带记忆、权限和故障恢复;
- 不能把 2022 年模型上的数字当作今天的模型排行。
ReAct 的历史价值在于给出了一个简洁而可迁移的交互语法。它是 harness 的数据面原型,不是完整 harness。真正落地时,最需要补的恰好是论文没有试图解决的控制面:验证、权限、预算、状态、审计和恢复。