导学阶段-Reflection 让 Agent 自我修正
本文整理自 CNB 上的开源课程 《Vibe Agent:从零搭建 Coding Agent》。课程讲义、示例代码与练习仓库均在 CNB 上公开,文中示例出自该仓库对应章节。
答案写出来就交给用户,是多数 Agent 的默认做法。Reflection 在这之后加一道工序:让同一个模型换个角色,把自己刚写的东西审一遍,挑出问题就重写。
一个包装层
1 | def run_with_reflection(question, base_agent, review, refine, max_rounds=2): |
base_agent 可以是第 2 章的最小循环、demo_10 的 ReAct、demo_11 的 Plan-and-Solve,甚至一个不调工具的聊天机器人。除三个函数签名之外,Reflection 不碰底层任何东西。课程示例把它包在 Plan-and-Solve 外面,换一个参数就能挪到别的范式上。
默认反思两轮。两轮意味着评审与修订最多各跑两次,轮数上限必须存在,否则模型可能在一版比一版长的修订里循环,token 一路涨上去。课程 demo 默认跑全部 5 个测试任务,与 ReAct、Plan-and-Solve 的横向对比保持同一口径;Reflection 一道题的 token 是其他范式的好几倍,赶时间可以用 --limit 只跑前几个。
评审员需要清单
评审 prompt 的写法决定成败。只说“检查一下有没有问题”,模型几乎一定回 PASS。要给出具体条目:答案是否回答了用户真正问的事、数字和计算是否准确、是否漏掉子问题、是否编造了未经证实的信息。输出也要定格式,VERDICT 与 ISSUES 两个字段,程序才好判断。
1 | import re |
判定看两处:VERDICT 必须是 PASS,ISSUES 段去掉列表符号、空白和句号后必须为空或只写“无”,两处都满足才算通过。不能用子串匹配判断 ISSUES:模型写下“无重大遗漏,但第三天的预算需要补充”时,"无" in issues 会把它当成通过,而它其实提了一个问题。字段解析比猜测自然语言可靠。
修订的 prompt 也不能只丢一句“再改改”。课程实现把用户问题、上一版答案、完整评审意见一起放进去,要求基于意见重写一份,而不是解释或者逐条回应。少了原答案,模型容易从零再写一版,前面没被指出的部分反而可能退步。
举一个具体的修订过程。初稿给出三天行程,评审员指出第二天两个景点相距太远、预算没有落到每天的安排上;修订版按地铁线路重排顺序,并在每天末尾标出花费。整个过程模型没有拿到新信息,改进来自把已有要求重新对齐。
自己审自己的盲区
同一个模型对自己刚写的内容更宽容,第一次评审经常直接 PASS。课程讲义给了一个实用做法:在评审 prompt 里要求它扮演挑剔的高级工程师,必须找出至少 3 个可以改进的地方。强行挑刺会把原本被放过的问题翻出来,修订后的答案通常更完整。
更工业的做法有两个方向。其一是换评审模型,底层用便宜模型干活,审阅时换成能力更强的模型;其二是把测试、静态分析、编译结果接进来,写代码的场景里这比模型自审有效得多。审阅者还有盲区,模型不知道自己不知道的东西,这类错误它看不出来,换个更强的模型也未必能补上。Reflection 能改的是遗漏、结构、表述和明显的算术,改不了没有被提供的事实。
三种范式与代价
| ReAct | Plan-and-Solve | Reflection | |
|---|---|---|---|
| 决策方式 | 走一步看一步 | 先规划再执行 | 起草、审阅、修订 |
| token 消耗 | 步多则多 | 比 ReAct 省 | 两到三倍 |
| 健壮性 | 低,依赖格式解析 | 中,计划错了就废 | 高,多一次自检 |
| 适用任务 | 信息收集、探索 | 流程明确、多步 | 写作、代码、推理 |
| 主要风险 | 模型不守格式 | 计划与现实不符 | 评审员盲区 |
三者不互斥。典型的组合是 Planner 拆任务,每个子任务内部跑 ReAct 做探索,汇总结果,再过一道 Reflection。课程 demo 的观察点是第一次评审给 PASS 还是 NEEDS_REVISION,以及修订版改了哪些地方。跑同一道题,Reflection 的 token 消耗是 Plan-and-Solve 的两到三倍,延迟也跟着涨。
评审与修订各一次调用,成本摆在那里。质量优先、能接受延迟的任务值得加,写报告、改代码、做推理都算。已有确定性校验的环节不必加,编译器和测试比模型更早知道代码能不能跑。另一种常见误用是把 Reflection 当成纠错手段,它只能让答案在已有信息上更完整,模型原本没有的知识不会因为多问一遍就出现。
判断标准可以更具体:任务一旦出错,返工成本是否高于一次评审加一次修订。写文档、改代码这类返工要重读上下文的场景,加一道 Reflection 划算;查个天气、算个加法,评审比干活还贵。
这对搭 Agent 意味着什么
Reflection 把检查这一步从人挪进循环,但它检查的是文本。数字对不对、代码跑不跑、外部状态有没有变,最终仍要由工具和测试回答。评审清单写得越具体,这道工序越有用;清单只写“检查一下”,它只是多花一次钱。
范式解决的是怎么组织循环。循环一旦跑长,第一件失控的事是上下文。下一篇看历史怎么在二十轮里涨到 259 倍。


