循环原语:ReAct、五个构件、以及什么时候停
推理和行动交错着来,比只推理不行动强 34 个百分点。但循环真正难的不是转起来,是停下来——而停不下来的账单是按轮数乘上去的。
上一篇画了四层栈的地图。这一篇进到循环内部。
ReAct:推理、行动、观察、重复
这个原语的出处是 2022 年那篇 ReAct(副标题 Synergizing Reasoning and Acting in Language Models)。
它的主意很简单:让模型交错地产出「推理痕迹」和「具体动作」,而不是只做其中一样。
两边互相帮忙:
- 推理帮行动 —— 推理痕迹让模型能归纳、追踪、更新行动计划,还能处理异常
- 行动帮推理 —— 动作让它接触外部世界(知识库、环境),把新信息取回来
这个组合解掉的是纯思维链的老毛病:只推理不行动的模型会一路幻觉下去,而且错误会沿着推理链传播 —— 因为它没有任何机会去核对现实。
数字上:在两个交互式决策基准(ALFWorld 和 WebShop)上,ReAct 比模仿学习和强化学习方法的成功率分别高出 34 和 10 个百分点,而它只用了一两个上下文示例。
「观察」这一步是这个原语的重心。 没有它,模型只是在自己脑子里推演;有了它,每一轮都被现实校正一次。
每个 agent 循环的五个构件
ReAct 是内核。而一个能自己转起来的循环,一圈里要做五件事。少一件,圈要么转不起来,要么原地打转。
| 构件 | 干什么 | 少了会怎样 |
|---|---|---|
| 发现 | 自己找出这一轮该干什么 | 你每天早上还得告诉它干什么 |
| 交接 | 把任务交给干活的 agent,彼此隔离 | 几个 agent 改同一个目录,撞成一团 |
| 验证 | 换一个 agent 来说「不行」 | 它自己夸自己,一轮轮往下滑 |
| 持久化 | 把状态写到对话之外 | 每天早上都从同一个地方重新开始 |
| 调度 | 让它一轮接一轮转下去 | 那只是「跑过一次」,不是循环 |
发现这一格决定了整个循环的天花板。 如果它捞上来的活本身没价值,后面四格做得再漂亮也是在为一件没意义的事服务。
这五格里最容易被偷工减料、也最不能省的是验证。它是那个「能说不行」的东西 —— 一个没有真正检查的循环,只是一个对着自己点头的 agent。这一点在多份材料里被反复证明:被改的对象和验证的对象必须分开。
停止条件:循环真正难的地方
「循环」这个词容易让人以为难点在转起来。真正难的是停下来。
停止条件有三类,成本完全不同:
一、固定轮数。 最简单,也最钝。跑三轮就停 —— 但三轮可能没干完,也可能第一轮就该停了。
二、模型自己说完成了。 最危险。它会说完成的,几乎总是说。让干活的那个来判断干完没有,是让它给自己判卷。
三、独立的判据。 交给一个新的、没参与干活的模型或者一段确定性的检查去判断条件成立没有。
Claude Code 把第三类做成了一个原语 /goal:给一个条件,让它跑到条件成立为止。
/goal all tests in test/auth pass and the lint step is clean关键在于每一轮之后,是一个小而快的新模型去检查条件成不成立 —— 不成立就再跑一轮,而不是把控制权交回来。完成与否由一个新模型判定,不是由干活的那个判定。
这是银行业里几十年的双人复核原则(maker-checker):录入大额转账的人和复核的人必须是两个人。搬到 agent 上就是 —— 写代码的和判断写完没有的,不能是同一个。
顺带澄清一个容易混的地方:/goal(跑到条件成立)和 /loop(按间隔重跑)不是一回事。后者只是定时重复,它不判断任何东西。
循环经济学:为什么停不下来这么贵
单次运行跑飞了,代价是一次调用。循环跑飞了,代价要乘以轮数 —— 而且是在你睡觉的时候乘。
三笔账值得在动手之前就算:
一、派生的帮手会翻倍。 一个循环分出两个子 agent,每个子 agent 又可能重试三次 —— 一轮的实际调用数是你写下的那个数的好几倍。
二、重试是复利。 一个卡住的 bug 配上「失败就重试」,能空转整整一夜。它不会报警,因为从系统的角度看它一直在正常工作。
三、上下文越长越贵。 循环把自己的产出喂回去,于是每轮的输入都比上一轮长。成本不是线性的,是随轮数累加的。
第一条我自己量到过一个具体的数。我那套东西接执行引擎跑一条四步的用例,日志显示每次请求 prompt 都在 9000 token 上下,而其中 6144 已经命中前缀缓存 —— 也就是说贵的不是文本,是每一步都要重新编码一张截图。一条四步的用例十六分钟。把这个数乘进「几十轮」,循环经济学就不是一句空话了。
所以那篇实践笔记给的建议很直接:在第一次让它无人值守跑之前,就把硬上限设好 —— 单次运行预算、每日预算、最大重试次数。
这些数字主要不是为了省钱,是断路器。 它们把一个开放式的风险变成一个有界的风险。一个没有上限的循环,等于把花钱的权力交给了自己的 bug。
边界与代价
ReAct 那 34 个百分点是 2022 年、在特定基准上的数。 今天的模型基线早就不同了,别拿它去论证「现在用 ReAct 还能涨这么多」。它证明的是方向:让模型有机会观察现实,比让它闷头推理强。
五个构件不是每个循环都要全上。 一个只在你眼前跑几轮的小循环,不需要持久化和调度。全上是过度工程;而少了验证那一格,任何规模都不该上线。
停止条件用独立模型判,也有它的代价。 每轮多一次调用,而且那个判官本身也会错。它换来的是「判官至少没有被写代码的过程说服过」—— 这是结构上的独立,不是能力上的更强。
下一篇
这一篇讲的是循环内部的骨架。下一篇往下挖一层,看单次运行本身是怎么被武装起来的:
harness 的解剖(骨架、错误处理、护栏)、上下文腐烂为什么会让 agent 跑着跑着忘了自己在干嘛,以及那个整个循环转动所依赖的铰链 —— 验证。