质量回归检测

9 分钟读完

E9
运维 · 评估与可观测性

质量回归检测:你没法对准确率报警,那就对运行的形状报警。

生产环境没有标签,这意味着每个团队都想要的那个监控——质量掉了就呼我——根本无法按他们设想的方式造出来。更糟的是,能造出来的那个版本很慢:要看清五个百分点的下滑,大约需要一千四百次被打分的运行,而按现实的抽样率,那就是两周。最先动起来的信号不是答案的文本,而是轨迹的几何形状——步数、工具报错率、重试率、运行如何终止——这些统计量不需要标签、不花钱,并且会在一次你没做过的变更之后一小时内偏移。

STEP 1

为什么那个理所当然的监控并不存在。

离线评测回答的是"新版本在我们的套件上是不是更好",那是发布前的问题。它与"此刻正在跑的这个东西还好用吗"不是同一个问题,而后者才是会呼你的那个。有三条结构性事实横在你与一个直接的准确率警报之间:

  • 生产环境里没有基准真值。用户问的东西,没人为它标过答案。你算出来的任何东西,都是另一个模型给出的估计,而它自己也会漂移。
  • 打分是第二套生产系统。对每一次运行都跑一遍 LLM 评判,大致会把你的推理开销翻倍,还多了一个在评判模型被更新时会自己悄悄回退的部件。没人真按 100% 跑,于是人人抽样,而抽样要拿时间来换。
  • 基线越高,统计功效越不留情。你的智能体越好,要证明它变差了就需要越多流量:
# Detect a drop from 90% to 85% success, alpha 0.05, power 0.80
n_per_arm = 700                # ~1,400 scored runs in total

# At 2,000 runs/day:
#   judging 100% of traffic  ->  detectable inside a day, at 2x inference
#   judging 5% of traffic    ->  detectable in about two weeks
#
# Over that same window, the tool-error rate leaves its
# 14-day band within an hour, for free, with no labels.

这一切都不是在反对用评判来做评测——它是确认环节,第 4 步会把它请回来。它论证的是:用评判来做探测器选错了工具。为何这些数字比直觉更糟,见评测方差与统计功效;两者的分工见在线评测与离线评测

STEP 2

最先动起来的是运行的形状。

一个变差了的智能体,几乎总是先干得更卖力,然后才答得更差。检索退化了,于是它多搜三次。工具 schema 变了,于是它重试、改写参数。模型更新让它更谨慎了,于是它问了一句从前会跳过的澄清。这一切在任何一条输出被打分之前就已写在追踪里,而且全部免费,因为你本来就在发跨度。

  • 每次运行的步数,看分布。均值几乎不动,尾部却翻了倍——而失败就在尾部。盯 p50、p90,以及撞上步数上限的运行占比;最后这个数字是本清单上信息量最大的一个。
  • 工具调用报错率,按工具分。聚合起来它什么都藏得住。按工具分,警报本身就点出了坏掉的那个集成。
  • 重试与改写率。同一个工具被用几乎相同的参数连调两次,是智能体在告诉你上一次的结果没法用。
  • 终止原因的构成。完成、放弃、撞步数上限、撞令牌上限、报错、升级给人。这个构成在健康系统里稳定得出奇,而且会在有人投诉之前好几天就开始偏移。
  • 最后一轮时的上下文长度。缓慢的上行漂移意味着检索返回得更多、裁剪得更少,这既是成本信号也是质量信号——长上下文正是指令遵循开始衰减的地方。
  • 拒绝率与澄清提问率。这是现存对"模型被悄悄更新了"最灵敏的探测器,而且完全不需要标签。

用波动带而不是阈值来报警:为每个统计量算一条滚动十四天的分布,当今天落在带外时呼人,并按租户、入口与智能体版本分段。全集群的均值恰恰是那种能让一个坏掉的分段藏住的聚合方式。

STEP 3

再加上不变量:既便宜又不含糊。

轨迹统计灵敏但是软的——它告诉你有东西变了,而不是有东西错了。不变量恰好相反:很少触发,但一旦触发就是一个不需要任何解读的缺陷。每个智能体都有那么几条,而它们是你能交付的最廉价的质量信号。

  • 结构化输出的校验失败。一条无法按其 schema 解析的响应就是 bug,没有别的说法。如果你用了受约束解码,这个数应当恒为零,于是任何非零值都是一次事故。
  • 循环检测。同一个工具、同一组参数,一次运行里出现三遍。它从来不合理、极易检出,而且既是质量事故也是成本事故的先行指标。
  • 引用接地。对任何引用了检索材料的答案,断言被引用的那个块确实在上下文里出现过。这里一旦漂移,说明模型在编造出处,而那比答错更糟。
  • 策略关卡的触发率。如果你的智能体有一道拦截某些动作的关卡,它的触发频率就是一枚行为指纹。一道突然不再触发的关卡,通常意味着智能体不再尝试那个动作,而不是它变安全了。
  • 工具参数的取值分布。一个一直只取四个枚举值之一的参数,如今偶尔出现自由文本,说明上游某处落了一次提示词或 schema 变更。

不变量也是唯一能放进合并前检查的信号,因为它们不需要基线。把它们放进 CI、对着一组固定的运行来跑,它们就从监控变成了关卡——一个进不了生产的回归,是你永远不必去检测的回归。

STEP 4

打分是确认环节,而且要按异常分层抽样。

一旦某条波动带被突破,你需要知道输出质量是否真的动了,而那确实需要一个评判者。常见的错误是把评判当成均匀的背景抽样来跑——那既是购买统计功效最贵的方式,也是最不可能抽中那次失败的方式。

  • 在异常发生的地方抽样。如果撞步数上限的比例翻了倍,就去评判那些撞了上限的运行,而不是从全体里随机切一片。以异常为条件,能把失败的密度提高一个数量级——这正是小样本也能一锤定音的原因。
  • 与上一版本做成对比较,而不是绝对打分。绝对分数会随评判者漂移;而"同一个输入的两个答案孰优"要稳定得多,在同等置信度下所需样本也更少。
  • 把评判者钉住并纳入版本管理。挂在浮动模型别名上的评判者,会在事故当中悄悄重新定义你的指标——那是最糟糕的时刻。把评判者当作任何一个生产依赖来对待,见模型弃用与迁移
  • 连轨迹一起打分,而不只是答案。一次经过三次失败工具调用才拿到正确答案的运行是一次回归,而只看结果的评判会把它判为通过。完整论证见结果评估与轨迹评估
  • 让人留在抽样里。对被评判过的运行保持一小份常设的人工复核,才是你得知评判者本身漂移了的途径。它永远是第一个被砍掉的,也永远是你当初需要的那个。
STEP 5

按计划跑一套金丝雀,因为你的输入也在动。

生产统计把两件事混在了一起:你的系统在变,和你的流量在变。周一步数的一次跳升,可能是一次回归,也可能是新来了一个文档更长的客户。分开它们的唯一办法,是一组固定的输入,按计划打向生产环境——在那里,任何动了的东西都毫无疑问是你的。

  • 二十到五十个有代表性的任务,每小时或每天对着线上栈跑一遍。真实工具、真实索引、真实模型端点。不是带 mock 的离线套件——重点恰恰是抓住那个在你脚下变掉的依赖。
  • 预期非确定性,并为它做设计。相同的请求不会返回相同的文本,所以一套断言精确输出的金丝雀会永久变红,然后被永久忽略。请对第 3 步的不变量做断言,并对第 2 步的统计量做"是否落在带内"的断言。可复现性与非确定性解释了为何这是结构性的,而非一个配置失误。
  • 这是那个"第三方悄悄变了"的探测器。厂商发了一次小版本模型更新、某个 MCP 服务器改了工具描述、某个索引刚跑完重嵌、某家供应商收紧了限流。这些都不会出现在你的部署日志里,而金丝雀是唯一能当天看见它们的仪器。
  • 加入一片对抗性切片。把少量注入尝试与已知恶劣输入长期留在套件里,让安全行为与质量按同样的节奏被监控,而不是等到评审时才看。
STEP 6

把警报接到一个动作上,否则就别发。

一条送达时不带任何决定的质量警报,只会训练人们把它关掉。上面所有东西的价值,都兑现在被呼之后的那二十分钟里,而那需要两样必须在事故之前就建好的能力:把变化归因的能力,以及把它撤销的能力。

  • 每条警报都点名版本。提示词版本、工具 schema 版本、模型 ID、索引版本、检索配置。如果一次回归无法被归因到某次变更,值班者唯一的动作就是猜。发布与版本管理是整页内容的前提。
  • 第一反应是钉回去,不是调试。回滚到上一个已知良好的配置,确认统计量回到带内,之后再诊断。为每一项行为配一个功能开关,能把这件事从一次部署变成一个决定。
  • 想清楚哪些警报值得动熔断开关面向客户的智能体上一次接地不变量被突破,与一次五个百分点的质量下滑,不是同一类事件;在你需要它之前就把这张对应表写下来,并让开关的范围可以只停掉一个分段而不是整个集群。
  • 把闭环接回离线套件。每一次被确认的回归都要变成评测集里的一个用例,否则你下个季度会再检测到同一个失败。正是这套机制,让监控实践得以复利,而不只是不断重复。

本周先上三个数字——撞步数上限的比例、按工具的报错率、终止原因构成——按十四天做波动带,并按版本分段。它们除了你本就在发的追踪之外不花一分钱,比任何评判者都早几个小时动起来,而且能抓住你如今多半是从客户那儿才得知的那些真实回归。用评判来确认,永不用它来探测:一个需要一千四百次带标签运行的指标是一份报告,而报告不是监控。

相关:追踪与可观测性是这里一切数据的来源,智能体可观测性是底层模型,而智能体的事故响应讲的是被呼之后的事。