第 14 章 · Reflection 反思

一封发出去才发现写错的催款邮件

那个做跨境的卖家,最近让 Agent 帮他给拖欠货款的海外分销商写催款邮件。Agent 写得很漂亮:措辞得体、语气不卑不亢、还附上了账单编号。他扫了一眼觉得挺好,直接群发了。

结果第二天收到三封回信,都在问同一件事:邮件里写的应付金额,把上个月已经付清的那笔也算进去了。Agent 用的是“截至目前的累计订单额”,却忘了减掉已回款——它给出了一个看起来完全合理、实则算错了的答案,而且自己毫不知情。

人做完一件重要的事,会下意识回头核一遍:“这个数对吗?有没有漏?”这个“回头看”的动作,Agent 天生是缺的——它生成完就交差,不会自己停下来质疑。要补上这一课,靠的就是 Reflection(反思)

反思是什么:给 Agent 装一个“回头看”的循环

Reflection 的核心,是在“生成结果”之后、“交付结果”之前,插入一个自我评估—修正(self-reflection)的循环:

  1. 产出(generate):Agent 先给出一个初步结果。
  2. 评估(evaluate/critique):让 Agent 批判性地审视这个结果——哪里可能错?符合要求吗?有没有漏项?
  3. 修正(revise):根据评估意见,改进结果。
  4. 重复:直到评估通过,或达到预设的次数上限。

放到催款邮件那个场景,理想的轨迹应该是:

产出   → 起草邮件,应付金额填 ¥86,400
评估   → 审一遍:金额是"累计"还是"未结"?账单口径对不对?
       → 发现问题:用了累计额,没扣掉已回款 ¥40,000
修正   → 改成未结金额 ¥46,400,附上已收款明细
评估   → 再审:金额对、口径清楚、语气得体
交付   → 通过,发出

那次翻车,缺的正是中间“评估”这一环。

为什么有效:生成者和批评者是两种心态

反思能起作用,背后有一个很关键的洞察:“生成”和“评判”是两种不同的心态(生成者 vs 批评者)。

  • 处在“生成者(generator)”心态时,模型一门心思往前推,顺着自己的思路把答案铺完——它在乎的是“把话说圆”。
  • 切换到“批评者(critic)”心态时,模型的任务变成“挑刺”——它在乎的是“哪里站不住脚”。

同一个模型,换个心态去看同一份输出,常常能发现它在生成时视而不见的问题。这就像自己写的文章自己校对总看不出错别字,但让你“假装是审稿人”逐句挑毛病,就能揪出来。反思,本质上就是强制模型做一次视角切换

由此引出两种常见做法:

  • 自我反思:同一个 Agent 先做、再以批评者身份自我审视、再改。轻量,一个 Agent 搞定。
  • 双角色反思:一个 Agent 专职生成、另一个专职挑错,结果在两者间往返。这已经踏进了多 Agent 的门槛(Part 5 会展开),但视角分离更彻底、更不容易“自己护着自己”。

学术界把这类思路提炼成了几个经典范式,比如 Reflexion(把评估反馈作为“经验”存下来指导下一次尝试)和 Self-Refine(同一模型自我反馈、自我改进的迭代)。名字不用记死,记住它们共同的主张就够了:让模型评判并改进自己的输出,能显著提升质量。

最好的反思,往往来自真实反馈

这里要泼一盆冷水:让模型“自己评判自己”并不总靠谱——它可能一边写错、一边还夸自己写得对。所以在 pi 里,最有效的反思常常不是靠额外的 LLM 调用,而是靠真实反馈

一个编码 Agent 的循环里,反思是天然内建的:

Action      → 写一段计算未结货款的代码
Observation → 运行单元测试,失败:已回款那笔没扣
Thought     → 我看看错在哪……哦,漏了 payments 表的关联
Action      → 修改代码
Observation → 测试全绿

这里“运行测试”就是评估、“看报错再改”就是修正——整个反思循环没多花一次模型的“自我批评”调用,却比任何自我批评都可靠,因为测试结果是客观的,模型骗不了它。同理,类型检查、编译报错、接口返回的错误码、甚至给催款邮件跑一遍“金额=累计-已回款”的校验脚本,都是廉价又硬核的反馈来源。

一句话原则:能用真实反馈,就别用模型自评;实在没有客观信号时,才退而求其次让模型当批评者。

用 pi 实现:把评估插进生命周期

如果确实需要一个显式的“自我批评”步骤,pi 的扩展机制(第 8 章)让你能在关键生命周期点插入一个评估回合。比如在给出最终答案之前拦一道:

// 概念示意:交付前强制过一次"批评者"审查
export default function reflectionExtension(pi) {
  pi.on("beforeFinalAnswer", async (draft, ctx) => {
    // 让模型切换到"严格审阅者"视角,专门挑错
    const critique = await ctx.ask(
      `你是一名严格的审阅者,只负责挑错,不负责夸奖。
       检查下面这份草稿是否有事实错误、计算错误或遗漏要求:\n${draft}`
    );
    if (critique.hasIssues) {
      // 有问题:带着反馈打回,让主循环重做一轮
      return { revise: true, feedback: critique.issues };
    }
    // 没问题:放行
  });
}

beforeFinalAnswer 是一个生命周期点,我们在这里插入一次批判性检查,有问题就带着 feedback 打回重做。注意这里刻意把提示写成“只挑错、不夸奖”——就是为了把模型硬推进批评者心态,避免它敷衍地说一句“看起来不错”。

反思不是越多越好:给它装刹车

反思很像第 3 章讲的循环,同样有“停不下来”的风险。每多一轮反思,就多一份成本和延迟;无限反思还可能让 Agent 陷入“改来改去、越改越差”的纠结。所以必须设护栏:

  • 限次数:最多反思 N 次(通常 1–3 次就够,边际收益递减很快)。
  • 优先便宜反馈:能用测试/类型检查判定的,就别多花一次 LLM 调用。
  • 明确停止条件:不是“感觉差不多了”,而是可判定的信号——测试全绿、检查项全过、评估无 issue。

动手看看

打开 pi 的编码 Agent,故意让它写一段有 bug 的小函数,同时给它一个会失败的测试。观察它的循环:它会不会在看到测试失败后,自己回头改代码、再跑一次?这就是最朴素、也最实用的反思——你没写任何“反思”代码,反思却发生了。

再做个对照实验:把测试拿掉,只让它“自己检查一遍代码有没有问题”。对比两种方式发现问题的准确率,你会更直观地体会到“真实反馈 > 模型自评”这句话的分量。

实战中的几个坑

坑一:模型自评“睁眼说瞎话”。

  • 现象:让它自查,它信誓旦旦说“没问题”,结果错的照样错。
  • 原因:还处在生成者心态,护着自己的输出;或评估提示太温和。
  • 对策:优先用测试/类型等真实反馈;必须自评时,把提示写成“只挑错不夸奖”,强制切到批评者视角。

坑二:反思停不下来,改来改去。

  • 现象:一轮轮反思,答案反复横跳,成本飙升还不收敛。
  • 原因:没设次数上限,或停止条件是主观的“差不多了”。
  • 对策:限最多 N 次,用可判定的客观信号(测试全绿)作为停止条件。

坑三:反思成本盖过收益。

  • 现象:给每个小问题都套上评估回合,token 翻倍,效果没明显变好。
  • 原因:对简单任务也无脑上反思。
  • 对策:只对高价值、易出错的任务(金额、代码、对外文案)开反思;简单问答别套。

坑四:批评者和生成者是同一份上下文,挑不出刺。

  • 现象:自我反思时,模型顺着原来的思路“确认”了错误答案。
  • 原因:评估和生成共享上下文,思维定式带过去了。
  • 对策:用双角色反思,让评估方在相对独立的上下文里看结果;或把待评估内容“洗”成干净输入再交给批评者。

对比:其他框架

Reflexion / Self-Refine 这类范式落地时,各框架大多用“再跑一轮评估”或“双角色”来实现:

框架反思怎么做特点
LangGraph把反思画成显式循环:generate → reflect → revise,用条件边判断“是否再改”循环边界一目了然,最可控
CrewAI常用“执行者 + 审阅者”双角色,输出在两者间往返贴近团队协作心智
PydanticAI无内建反思循环,但 schema 校验是天然的“廉价反馈”,不合规就重试结构化输出即免费反思
Agno用 Team 的生成者 + 评审者角色实现,框架不强制灵活,需自己搭
pi优先靠真实反馈(测试、报错),也可用扩展在 beforeFinalAnswer 插入显式自评廉价反馈优先,显式自评可选

共性是“生成”与“评判”分离、循环直至达标;差别在于——是花一次模型回合去评判,还是尽量用测试/类型这类真实反馈把评判“外包”给客观世界,省钱又靠谱。

小结

  1. Reflection = 给 Agent 加一个自我评估—修正循环:在交付前插入“评估”一环,堵住“错了却不自知”。
  2. 有效的关键是生成者 vs 批评者的视角切换——同一模型换个心态挑刺,能发现生成时的盲点。
  3. 真实反馈优于模型自评:测试、类型检查、报错这类客观信号,比让模型夸自己可靠得多、也便宜得多。
  4. pi 里编码循环天然含反思;需要显式自评时,用扩展在 beforeFinalAnswer 等生命周期点插入批评者回合。
  5. 反思要装刹车:限次数、优先便宜反馈、用可判定的客观信号作停止条件——反思不是越多越好。

规划给方向、反思纠错,还有一种不靠外部反馈、单凭“想清楚”就能让单个 Agent 变准的基础技巧——下一章的 Chain-of-Thought 思维链