ReAct
ReAct 是 Reasoning + Acting 的组合,2022 年由姚顺雨(Yao Shunyu)等人提出,发表于 ICLR 2023。它让模型交替进行推理和行动:想一步,做一步,看结果,再继续想。这是最早也最经典的 Agent 循环范式,今天几乎所有支持工具调用的模型,其多轮 tool use 循环本质都是 ReAct 的工程化形态。
动机:两种失败的路线
ReAct 出现之前,让 LLM 干活有两条路线,各有各的死法:
只想不做。 以 Chain-of-Thought 为代表,模型在内部写出一长串推理然后直接给答案。纯推理的问题在于没有外部信息,遇到需要实时数据的问题就开始编。问它今天的股价,它按训练数据里的旧价格一本正经地答。
只做不想。 模型直接输出动作指令调用工具,但没有推理环节。遇到复杂任务,走一步算一步,不会把目标分解成子目标,环境一变就迷失方向。
ReAct 把两者拧到一起。推理轨迹让模型能制定、跟踪和修正行动计划,动作让外部信息进入推理链。外部事实锚定了模型的想象,这就是它减少幻觉的机制。
思考-行动-观察循环
ReAct 的核心是 TAO 循环,三个环节交替运行:
Thought-Action-Observation 循环
- Thought:模型的内部推理,不是给用户看的答案,而是决定下一步做什么的依据。它可以分解问题、提取信息、做常识判断
- Action:真正执行的动作,最常见的是工具调用,比如
Search[科罗拉多造山带] - Observation:工具返回的结果,可能是搜索结果、报错信息,也可能是空结果。它是下一轮 Thought 的事实锚点
循环的终止条件有两个:模型判断信息足够,输出最终答案;或者达到系统设定的最大轮次。
论文里 HotpotQA 的一个例子能看出完整轨迹:
Question: 科罗拉多造山带东部区域延伸到的区域的海拔范围是多少?
Thought 1: 我需要搜索科罗拉多造山带,找到东段延伸的区域,再查海拔范围。
Action 1: Search[科罗拉多造山带]
Observation 1: 科罗拉多造山带是科罗拉多及其周边地区造山运动的一段。
Thought 2: 它没有提到东部地区,我需要查一下东部地区。
Action 2: Lookup[eastern sector]
Observation 2: 东部区域延伸至高平原,称为中原造山带。
Thought 3: 东部区域延伸到高平原,所以我要搜高平原的海拔范围。
Action 3: Search[High Plains (United States)]
Observation 3: 高平原是大平原的一个分区,海拔从 1800 到 7000 英尺。
Action 4: Finish[1800 到 7000 英尺]注意 Observation 2 修正了 Thought 1 的假设(“没有提到东部地区”),这就是外部反馈驱动纠错的机制。模型不会一条路走到黑。
论文实验结果
ReAct 在两类任务上做了评测,都超过了基线:
| 任务类型 | 基准 | 结论 |
|---|---|---|
| 知识密集 | HotpotQA、FEVER | 优于纯 CoT 和 Act-only,幻觉明显减少 |
| 决策任务 | ALFWorld(文本游戏)、WebShop(在线购物) | 优于 Act-only。没有 Thought 的纯行动无法把目标分解成子目标 |
论文还发现,ReAct 和 CoT 不是二选一,最佳做法是结合:模型先用内部知识推理能解决的部分,遇到知识缺口再通过工具获取外部信息。另一个附带收益是可解释性,Thought 链本身就是一份决策日志,每一步为什么这么做都能回看。
和 Function Calling 的关系
这是面试必问的易错点。两者不是一回事:
- Function Calling 是 API 层的能力,解决“模型怎么表达调用意图”:输出结构化工具名和参数
- ReAct 是组织推理和工具调用的流程范式,解决“多步任务怎么推进”:想一步、做一步、看结果
ReAct 可以用 Function Calling 来实现 Action 环节,也可以用其他工具调用机制。现代模型的 tool use 循环,就是 ReAct 在协议层的工程化:把脆弱的文本 Action 行加正则解析,换成了 API 直接吐结构化 JSON。循环结构没变,变的只是 Action 的表达方式。
局限:五个裂缝
裸 ReAct 是纯 Prompt 范式,循环的是一段不断变长的文本,上生产会撞五个问题:
- 上下文越滚越长。 每一圈都把新的 Thought、Action、Observation 拼回上下文,跑 30 步直接撑爆窗口,注意力被稀释,越跑越蠢
- 状态全靠上下文记。 没有独立状态存储,上下文一截断,进度就丢了,模型可能重复执行已做过的步骤
- 容易死循环。 弱模型经常在“再查一次”这种动作里绕不出来
- 终止判断不可靠。 模型说“我做完了”就停,但它可能没做完就宣布完成,也可能做完了还在反复确认
- 不可观测。 一坨文本,排查全靠人肉扒
工程化的解法是把循环本身当系统治理,这就是 Loop Engineering:Observation 先摘要再入上下文、状态独立存储、预算(步数/Token/超时)当一等公民、工具集按阶段收放、终止用“模型信号 + 外部校验 + 硬兜底”多重判断。循环上限一般从 5 步起步,根据线上数据再调。
范式演进
ReAct 之后出现了两个经常和它并列的范式,但很多人没意识到它们不在同一个维度上:
- Plan-and-Execute:先规划后执行。Planner 一次性生成完整步骤清单,Executor 逐项执行,执行中可以重新规划。它和 ReAct 其实是同一个刻度盘的两端,刻度是“在执行前承诺多少”:ReAct 每步重新决策,Plan-and-Execute 一次承诺全局。环境变化快就偏向 ReAct,任务稳定可分解就偏向规划
- Reflexion:跨尝试的反思层。一轮失败后,模型用语言写出反思存入记忆,下一轮带着反思重试。论文作者称之为“语言强化学习”,不更新权重,靠文字自我改进。它不替代 ReAct,而是包在 ReAct 外层。前提是有可验证的成功信号(比如测试通过),没有信号时反思只是往记忆里写故事
成熟的 Agent 通常是组合形态:
生产级 Agent 的范式组合
选型的判断就两句:任务短、路径不确定,裸 ReAct 就够;步骤多、结构可预判,加计划层;产出质量敏感且有硬信号,加反思层。
面试追问
- ReAct 和 CoT 什么区别? CoT 是内部推理增强,不接触外部世界;ReAct 把推理和工具调用交织成循环,用真实观察修正推理。CoT 只会想,ReAct 边想边做
- ReAct 一定比直接回答好吗? 不是。简单任务上 ReAct 只是增加延迟和成本。它的价值在多步探索、需要外部信息的场景
- 写出 Thought 就算 ReAct 吗? 不算。只有 Thought 没有 Action 和 Observation 的闭环,就退化成 CoT。三者缺一不可
- ReAct 和 Plan-and-Execute 怎么选? 它们是同一个刻度盘的两端:每步重新决策还是先承诺全局。环境意外率高偏向 ReAct,任务稳定可分解、延迟敏感偏向 Plan-and-Execute
- ReAct 的死循环怎么防? 最大步数硬上限、重复动作检测、预算触顶优雅退出,终止判断不能全信模型