跳到主要内容

与验证器共享盲点的自我修正循环

· 阅读需 10 分钟
Tian Pan
Software Engineer

在智能体复盘中流传的截图每次看起来都一模一样。一段长长的追踪记录。一个单一的任务。十二次迭代。智能体生成了草稿,进行了评估,发现了一个小瑕疵,生成了修订版,进行了评估,发现了一个略有不同的微小瑕疵,接着又生成了另一个修订版。验证器返回的分数一直徘徊在 0.78 到 0.84 之间。它从未跨越门槛。智能体从未上报异常。三小时后,任务因超时而终止,产生了一笔足以支付一名高级工程师四分之一日薪的 Token 账单。

团队将其称为“自我修正”问题,因为架构图上就是这么标注的。实际的失败是结构性的。验证器其实就是换了一个提示词的生成器。收敛准则是模型自己的意见。重试预算是隐式的,受限于智能体的超时时间,而不是由智能体本身推理决定的。这三个失败孤立来看都不像是 Bug,这正是团队会将其上线的原因。

验证器看到的正是生成器看到的

当智能体的输出以某种可恢复的方式出错时,第一本能是让模型检查自己的工作。当该检查通过了一个有缺陷的答案时,第二本能是让模型检查那个检查。这种反身验证的堆叠感觉应该会收敛到某种真相上。但通常并非如此。

一项关于 LLM 自我修正的 2025 年基准测试衡量了当同一个模型既负责生成又负责批判时会发生什么。在 14 个模型中,模型未能发现其自身输出中相同错误的平均比例为 64.5% —— 而这些错误如果是出现在用户的输入中,模型本来是能发现的。这种失败不是随机的,而是系统性的。模型在生成时的失败模式与其在评估时的失败模式完美契合,因为两者都源于模型对“好”的定义的同一底层分布。

这就是为什么自我修正循环会自信地迭代出一个错误答案。第 2 到第 10 次迭代并没有增加信息。它们只是润色了散文,收紧了结构,对生成器本就不确定的主张进行套期保值,而让核心的承重错误保持原样。验证器永远看不见它,因为验证器就是产生它的同一个电路。

将自我修正分解为“置信能力”(在受到质疑时捍卫正确答案)和“批判能力”(将错误答案转化为正确答案)在这里很有用。大多数生产环境中的循环都针对前者进行微调,并假设后者是免费附赠的。事实并非如此。增加迭代次数会提高预期校准误差 (Expected Calibration Error) —— 模型随着迭代变得越来越自信,而不是越来越正确。

因精疲力竭而收敛并非真正的收敛

当一个循环因为分数停止波动而“收敛”时,运行该循环的团队应该询问分数衡量的是什么。如果分数是验证器对答案质量的信心,且验证器与生成器共享盲区,那么稳定的分数既可能意味着“答案变正确了”,也可能意味着“模型用尽了表达其不确定性的方式”。在循环内部,无法区分这两种状态。

陷入这种状态的智能体生产追踪记录具有鲜明的特征。同一个工具被以稍微改写后的相同参数重复调用。分数在成功门槛下方的窄幅区间内震荡。Token 成本线性攀升。推理步骤通过同义词替换不断重复。延迟增加。状态没有改变。智能体在工作,但这种工作并无产出。一个运行 10 个周期的 Reflexion 架构循环所消耗的 Token 可能是单次线性传递的 50 倍,而且超过第二轮后的边际价值非常小,以至于那些仔细监测的团队经常发现第 3 到 10 轮纯粹是成本浪费。

导致成本高昂的原因是大多数智能体继承的预算结构。由于完整的对话历史会被重新输入到下一个提示词中,每次迭代都会重新计费。一个 20 步的循环最终消耗的 Token 超过简单的单步估算的 10 倍。账单随深度呈平方级增长。一个长时间“几乎收敛”的循环比一个快速失败的循环成本更高。

“让它再试一次”是一个预算炸弹

给智能体重试余地的直觉是合理的。大多数单次 (One-shot) LLM 调用在处理难题时的准确率在 60-70% 左右。迭代填补了通往企业级可靠性的空白。错误在于将“迭代是好事”等同于“越多迭代越好”。收益曲线会迅速放平,而成本曲线则不会。

在那些白白耗费预算的循环中,有几种模式反复出现:

  • 没有绑定的重试策略。 智能体不断重试,直到被其他因素停止 —— 超时、Token 上限或外部监控。智能体本身没有“放弃”的概念。没有内部信号表明这次尝试毫无进展。
  • 没有工具和参数的去重。 智能体用相同的输入调用相同的函数,得到相同的输出,并再次对相同的输出进行推理。每一次传递都增加了延迟和成本,但都没有增加信息。
  • 由循环控制的收敛准则。 智能体试图跨越的门槛是由决定其是否达标的同一个模型设定的。智能体既当学生又当老师,任何低于门槛的分数都被视为重试的许可。
  • 没有陈旧性检查 (Staleness Check)。 智能体没有注意到它最近三次尝试看起来一模一样。没有在第 N 次和第 N-2 次迭代之间进行比较,以检测循环是否已不再改变状态。

这些问题中的每一个都可以单独修复。但通常在设计阶段都不会被修复,因为它们预防的失败模式 —— 在单个任务上烧掉五位数的 Token 账单 —— 只会在事故中浮现,而大多数团队会将事故归因于“智能体卡住了”,而不是归因于允许它卡住的架构。

有界自我修正的纪律

能在生产负载下保持稳定的模式包含三个要素。这些要素并不新颖,只是经常被忽略。

Agent 无法延展的重试预算。 自我修正迭代的最大次数固定在编排层,而不是由 Agent 自身协商决定。两到三轮是一个合理的默认值。研究一致表明,自我修正带来的 75% 的改进发生在头两次迭代中;其余的则是一种“税收”。当预算耗尽时,循环退出——不是进入“换个提示词再试一次”,而是进入下文描述的升级路径。

异构验证器。 评估输出的模型不应与生成器共享相同的盲点。最廉价的做法是使用不同的模型家族——Claude 生成,GPT 或 Gemini 评判,反之亦然。更严谨的版本是针对不同目标进行训练或微调的专用验证器:过程奖励模型(PRM)、实际运行输出的代码执行沙箱、或者非验证器编写的单元测试。多 Agent 验证框架进一步扩展了这一点,结合了多个验证器,这些验证器的个体盲点相关性足够低,从而使它们的共同判断具有意义。重点是验证器必须在认识论上独立于生成器。如果不是,它就不是验证器,而是信心放大器。

预算耗尽时的明确移交。 循环的失败情况不是“抛出异常并崩溃”,而是“生成一个升级 Payload(负载),人类可以在无需重新推导 Agent 状态的情况下对其进行处理”。该 Payload 包括原始任务、每一次尝试的输出、每一个评分、验证器提出的异议,以及 Agent 对自己无法收敛的原因总结。移交发生在预算耗尽的那一刻,而不是在 Agent 沉默一小时之后。升级是设计的一项功能,而不是设计的灾难性终结。

在账单寄达前检测循环

在事后分析阶段之前就能在生产环境中捕捉到自我修正循环的团队,通常会监测三种信号。这些信号都不新鲜,但在大多数 Agent 仪表板中都见不到。

在单个 Trace 中具有高度文本相似性的重复 Span 是一个强信号。两个连续的 Agent 步骤,如果其输出的嵌入余弦相似度(Embedding Cosine Similarity)达到 90% 以上,且其间的工具调用没有状态变化,这几乎总是表明循环已不再取得进展。对这种模式设置一个简单的警报,就可以在 Trace 运行超时之前捕获大多数情况。

每个 Trace 的 Token 成本是一个滞后但可靠的信号。成本达到该任务类型中位数 10 倍的 Trace,要么是在解决一个异常困难的实例,要么是陷入了循环。按任务类型对 Trace 进行分组并标记成本离群值,可以将账单本身转化为检测器。看起来很昂贵的 Trace 就是需要人工介入查看的。

验证器评分轨迹是最直接的信号,但也是最难解释的。单调爬升至阈值的评分正在收敛。在狭窄范围内波动的评分则不然。模式识别很简单;问题在于编排器是否观察了轨迹,还是仅仅看最终是否达到了阈值。大多数编排器都不看。

循环的真正用途

更深层的问题是自我修正到底要完成什么。如果目标是“把错误的答案改对”,那么只有当验证器能察觉到错误时,循环才有效——而这正是生成器的盲点明确排除的情况。如果目标是“让边缘答案变得更好”,那么两轮就足够了,剩下的都是演戏。如果目标是“增加 Agent 对发布代码的信心”,那么循环正在做的正是其架构所说的:在不增加证据的情况下放大信心。这些都不是坏目标。它们只是需要不同的机制,而“让 Agent 验证并重试”仅是其中一种目标的机制。

以高置信度收敛于错误答案的 Agent 正是在做其设计所奖励它做的事情。修复方法不是更好的提示词或更智能的模型。它需要一个不共享生成器失败模式的外部验证器、一个由编排器而非循环自身意见决定的重试预算,以及一条将人工升级视为正常终止状态而非紧急情况的移交路径。同时具备这三点的团队将不再发生自我修正事故。只具备其中两点的团队仍会遇到同样事故的缩小版,只是发生得稍晚一点,成本稍高一点。

永远运行下去的循环并没有损坏。它的损坏程度恰恰等于模型的盲点程度,昂贵程度恰恰等于预算允许的程度,置信度恰恰等于验证器想要的程度。架构选择了这一切。

References:Let's stay in touch and Follow me for more thoughts and updates