我知道 ReAct 这个概念很久了。但真正理解它,是在我发现我的 Hermes 每天都在跑几百个 ReAct 循环,而我竟然没意识到需要为它设计约束的时候。
几个月前,我搭了一个内容生产流水线:研究 Agent → 写作 Agent → 审计 Agent → 发布 Agent。每个 Agent 内部本质上就是一个 ReAct 循环——思考要做什么,调用工具,观察结果,继续思考。
一开始一切正常。研究 Agent 调用 web_search,回来信息,写作 Agent 写初稿,审计 Agent 检查质量。直到有一天,某个 Agent 在一个简单问题上循环了 12 轮——反复调用工具、返回结果、觉得不够、再调用——最终一条消息消耗了 8 万 Token。成本是正常执行的 6 倍。
我当时的第一反应是"模型出 bug 了"。后来才意识到问题出在我自己身上:我让模型自由决定"什么时候该停下",但没有给它足够的约束条件。
这就是 ReAct 的核心问题:它给你灵活性,但灵活性一定要代价。这篇从我的实际教训出发,讲讲 ReAct 到底是什么,以及什么时候该用它的哪种变体。
ReAct 不是 OpenAI 发明的,不是 LangChain 的功能,不是某个框架的特性。它是 2022 年 Shunyu Yao 等人提出的一篇论文的核心观点:Reasoning + Acting(推理 + 行动)。
论文的核心发现很简单:让语言模型先想一步(我该做什么),再做一步(调用工具或查资料),看到结果后再想下一步——效果远好于让模型直接回答。
这个发现后来成了所有 Agent 系统的理论根基。LangGraph 的 StateGraph、CrewAI 的多 Agent 协作、OpenAI 的 Function Calling——底层都在做同一件事:Thought → Action → Observation 的循环。
ReAct 是最基础的模式。实际工程中根据任务复杂度有三种变体,它们的成本结构和适用场景完全不同。
工作方式: 不预先计划,每一步都基于当前观察做出决策。每一步消耗一次 LLM 调用,每次调用都要把之前所有轮次的上下文重新传进去。
成本特征: 假设一轮对话消耗 1K Token 输入 + 0.5K Token 输出,5 轮循环的总消耗大约是 (1+0.5) + (2.5+0.5) + (4+0.5) = 9K Token——不是 5 倍,是接近 10 倍。因为每轮都要把历史上下文重新传给模型。
适合: 简单任务(2-3 步能完成),或者任务步骤无法预先确定的场景。
我的教训: 没有设置最大步数的 ReAct 循环,是我那次 8 万 Token 事故的直接原因。现在所有 Agent 都默认加上了 max_steps=5 和 token_budget=10000。
工作方式: 模型先输出一份完整的执行计划,然后按计划一步步执行,不中途调整。
成本特征: 只有一次计划成本 + N 次执行成本。执行轮次没有传递历史开销——因为计划已经包含了所有上下文。在我的测试中,同样 5 步任务,Plan-then-Execute 比 ReAct 节省约 40% 的 Token。
适合: 步骤明确的流程——批量数据处理、定时报告生成、格式固定的操作流程。
但有一个坑: 计划一旦出错,无法在执行中纠正。我试过让 Agent 先计划再执行一个三步骤的数据清洗流程——它在第一步就偏离了计划,但因为模式是"按计划执行",它不会停下来重新评估,一路错到底。
工作方式: 初始计划和执行交替进行——执行一段后根据观察结果重新评估和调整计划。
成本特征: 介于前面两者之间。每 N 步做一次计划调整,比 ReAct 节省约 20-30% 的 Token,比 Plan-then-Execute 多 15-20%。
适合: 复杂的多步骤任务——故障排查、多源数据整合、需要反复验证的流程。
以下是我在自己的系统里跑出来的实际数据:
| 维度 | ReAct | Plan-then-Execute | RePlan |
|---|---|---|---|
| 5 步任务 Token 消耗 | ~9K | ~5.5K | ~7K |
| 相对成本 | 基准 100% | ~60% | ~78% |
| 面对意外 | ✅ 灵活应对 | ❌ 一路错到底 | ⚠️ 可调整 |
| 实现复杂度 | 低 | 低 | 中 |
| 最佳场景 | 2-3 步简单任务 | 步骤明确的任务 | 复杂多步骤任务 |
我现在的选型规则:
Claude 说它有 200K 上下文,实际可用的大约 60K。GPT-4o 说它有 128K,实际可用的大约 30K。模型在长上下文中有一个"两头高中间低"的注意力衰减模式——最开头的内容和最近的内容效果最好,中间部分容易被稀释。
这意味着:一个 10 轮 ReAct 循环,第 3 轮获取的信息在第 8 轮可能已经被模型"遗忘"了——不是真的忘了,是注意力被后面轮次的内容稀释了。
对策: 每 N 轮做一次上下文摘要,把关键信息从原始对话历史中提取出来放到上下文的前面位置。这在我的 Harness 上下文管理方法里称为"优先级保留"——不是平均对待所有内容,而是标记哪些内容不能丢。
ReAct 的另一个隐蔽问题:工具返回错误结果时,模型通常不会主动承认它不确定。它假装理解,然后基于错误信息继续推理。一个 API 返回了空值,模型不会说"工具返回了空值,我不确定",而是说"未找到相关信息,结论是 X"。
这个问题的可怕之处不在于"一次出错",而在于错误会沿着 ReAct 链传播和放大——一步错,后面基于错误结论的所有推理都是错的。
对策: 在验证闭环中增加"结果合理性检查"——不是说工具返回了什么就信什么,而是对关键结果做二次校验。比如返回的数据量级是否在合理范围内、关键字段是否为空等。
固定成本的系统容易预算,ReAct 的成本取决于模型"想了多少步"。同样的任务,今天可能 3 步完成,明天因为模型版本变化走了 6 步。我的监控数据显示:相同 Skill 在不同日期的 Token 消耗波动幅度可以达到 2-3 倍。
对策: 设置硬性预算上限;对超预算的执行自动降级(比如从 GPT-4 降到 3.5 重新执行);把执行数据接入自进化引擎,发现异常模式时自动调整约束。
ReAct 是所有 Agent 系统的底层循环。它不是一个框架选择——你用的是哪个框架,底层都是 ReAct。但三种变体(ReAct / Plan-then-Execute / RePlan)的成本和可靠性差异巨大,选错了可能让你的成本翻倍而可靠性减半。
我的建议: 默认用 ReAct + 最大步数限制。当你的任务可以预先确定步骤时,切换到 Plan-then-Execute。只有当任务足够复杂且不确定时,才上 RePlan。不要为了拥抱新概念,去选择自己当前不需要的复杂度。
💬 评论