这次升级看起来就像是白捡的便宜。供应商发布了一个更新的模型,它在每一项公开基准测试中的得分都更高,每个 token 的成本更低,且生成 token 的速度更快。你在一个配置文件里修改了模型字符串,运行了评估套件,看着 340 个测试用例全部变绿,然后在周二下午发布上线。到了周四,客服工单不断增加,却没人能指出到底是哪一个测试失败了。
这是应用层 LLM 开发中最令人困惑的失效模式,因为它违反了其他所有软件与你达成的契约:如果测试通过,行为就保持一致。在这里,该契约失效了。模型升级不是对一个你可控接口的库进行版本更新。它是一次对概率函数的无声、大规模更替,而你的评估套件只检查了你想到要写下来的那一小部分行为。
真正带来伤害的退化往往存在于你从未编码定义过的行为中——语气、冗余度、格式习惯,以及模型如何处理请求中模糊的中间地带。这些恰恰是你的用户所依赖的东西,也恰恰是 pass/fail 断言无法察觉的东西。
为什么“基准测试得分提升”是最危险的绿色信号
基准测试衡量的是综合能力。你的产品依赖的是分布中特定点上的特定行为切片,而这两者之间的关联非常微弱。一个模型可能在研究生级别的数学上表现更好,但同时变得更爱唠叨、更容易推诿,或者更倾向于用 Markdown 围栏包裹 JSON 载荷——而在此期间,基准测试的分数会一直上升。
令人不安的事实是,输出分布 就是 LLM 功能的 API 表面。你消费的不是权重;你消费的是权重发射出的 token。当供应商更改权重、分词器(tokenizer)或推理栈优化时,这种分布会发生偏移,且偏移的维度是任何排行榜都无法追踪的。从业者调查的结果往往大同小异:绝大多数生产环境中的 LLM 功能在模型更改后的头几个月内会出现可衡量的行为偏移,而从偏移开始到收到第一个用户投诉之间的时间差通常在两周或更长。
两周是一个关键数字。这意味着反馈回路(告诉你某些东西坏了)的速度比导致故障的发布要慢。你的断言显示正常,是因为它们问错了问题,而正确的问题一直在生产环境中被错误地回答着——且表现糟糕。
那些能通过所有断言的退化
命名那些悄悄潜入的具体退化类型会有所帮助,因为每一种类型都需要不同的检测策略。
- 分布偏移 (Distributional drift):模型平均来看仍然正确,但其回答的“形态”发生了变化。回复变长了 30%,或者中等置信度的措辞从“这是”变成了“这可能是”。没有单个输出是错误的,因此不会触发断言,但整体体验下降了。
- 风格偏移 (Stylistic drift):语气、正式程度和格式习惯发生了变化。旧模型返回精简的列表项;新模型写段落。如果你的 UI 是针对旧形态调整的,那么现在的布局看起来就坏了,尽管内容本身没问题。
- 拒绝边界偏移 (Refusal-boundary drift):新模型的安全校准发生了移动。它现在拒绝处理旧模型可以处理的请求,或者在以前能干脆利落回答的问题上变得含糊其辞。除非你针对那个精确的提示词 (prompt) 有评估用例,否则你只能从愤怒的用户那里得知这一消息。
- 格式严格度偏移 (Format-strictness drift):JSON 模式变得更严格或更宽松了。原本能可靠省略代码围栏的模型,现在有一半的时间会带上它,而那些假设 JSON 干净的下游解析器开始在以前从未卡过的输入上报错。
- 长尾边缘用例 (Long-tail edge cases):那些你从未编写过测试的行为,因为你从未想象过它们。生产环境的流量具有任何精心挑选的数据集都无法捕捉的长尾效应,而新模型由于先验知识的不同,往往最先在这些长尾部分表现出差异。
请注意这些情况的共同点:在单元测试的理解范围内,它们都不是“错误答案”。它们是行为的偏移,从未出现在你的显式契约中,因为在它们发生变动之前,你根本不知道自己依赖于它们。你的评估套件是你凭想象力预见到的故障快照。从定义上讲,危险的退化往往是你没有预见到的那些。
为什么评估套件本身无法解决这个问题
发生此类事故后的直觉是增加更多用例。你因为冗余度退化而吃过亏,所以你写了一个“回复必须在 400 token 以内”的检查。这没什么不好,但这是在打一场过时的战争。下一次升级会使你仍未想到要编码定义的维度发生退化,然后你会在事后补上 那个 用例,永远比事故慢一步。
更深层次的问题在于,黄金数据集 (golden dataset) 是一个固定的、低基数的产物,却试图代表高基数、处于偏移中的现实。几百个手动挑选的用例无法代表数百万次真实对话的形态,尤其无法代表长尾部分——而这恰恰是新模型先验最容易产生分歧的地方。离线评估是必要的——它们能捕捉到你 可以 预见的退化,而且每次变更时运行的成本很低——但将评估套件全绿视为发布的“门槛”则是错误的。全绿的评估套件意味着“我已知的故障都没有恶化”。它对那些我尚未遇到的故障只字未提。
因此,解决方案不是一个更好的黄金数据集,而是第二道防线:在真实用户依赖候选模型之前,先用 真实流量 对其进行衡量。
用实时对照捕捉问题,而不是更大的测试集
真正有效的模式是像对待数据库迁移一样严谨地对待模型升级:固定评估(Pinned Eval)、影子部署(Shadow)、金丝雀发布(Canary),并在每个阶段都保留真实的回滚路径。核心逻辑是,在根据同一组实时输入对比新旧模型的表现之前,绝不让新模型的行为触达用户。
将旧模型固定为实时对照。 你能做的最有价值的一件事就是保持前一个模型版本的运行并将其固定。它是你的基准。任何关于新模型更好或更差的断言都是关于 增量(Delta) 的断言,而你无法针对一个不断变动的参考物来衡量增量。在发布的那一刻就固定到一个带有日期戳的快照,这样当下次升级到来时,你对比的是一个已知的量,而不是模糊的记忆。
在真实流量上对候选模型进行影子部署。 在实时请求中并行运行新模型,但不向任何人展示其输出。现在,你拥有了针对用户产生的实际分布(包括长尾场景)的成对输出——旧的和新的。对比(Diff)它们。它们产生分歧的地方就是你的回归面,这会暴露任何断言都覆盖不到的维度:长度增量、拒绝率增量、格式增量、语调转变。这一步将“基准测试分数提高了”转化为“这里有 200 个真实的请求,新模型的表现有明显差异,并按差异程度排序”。
对增量进行评分,但不要深陷其中。 你无法阅读每一组影子部署的成对输出。抽样几个百分点进行人工抽查——权重偏向长尾场景以及两个模型分歧最大的案例,而不是简单地对容易的中间部分进行均匀采样。对于其余部分,运行 LLM-as-judge,不问“新答案是否正确”,而问“行为是否发生了变化,以及朝哪个方向变化”。在低成本衡量维度(如响应长度、拒绝率、JSON 解析成功率、延迟)上的统计漂移指标,能提供在人类察觉之前就触发的持续信号。
通过评估门禁的回滚机制进行金丝雀发布。 只有在影子部署看起来没问题之后,你才将一小部分实时流量(1% 到 5%)真正路由到新模型。将回滚机制与滚动通过率以及相同的漂移指标挂钩,这样影子部署漏掉的回归问题在触达所有用户之前,就会触发自动回滚。金丝雀发布是你的最后一道防线,而不是你的第一项测试。
这到底需要多少成本,以及为什么值得
这一切都不是免费的。影子部署会使你镜像的那部分流量的推理成本翻倍。维护一个固定的对照组意味着在原本只想运行一个模型的地方运行两个。构建对比和判别流水线是真正的工程任务,而不是一个配置选项。团队之所以跳过它,是因为“快乐路径”——修改字符串、运行评估、发布——在大多数情况下是有效的,而失败在发生之前往往是不可见的。
但请权衡一下当你跳过这些步骤时实际选择的替代方案:将一次无声的行为变动发布到生产环境,并让你的用户替你运行回归测试,忍受两周的检测滞后期,以及一个接一个的愤怒工单。影子部署基础设施的成本是一个固定的、可预算的支出项。而无声回归的成本是一个你无法控制的变量,是以无法挽回的信任作为代价的。
让这一切变得可行的认知重构是:停止将模型升级视为一种改进,而将其视为 一种在你衡量的维度上恰好趋向正向的行为变化。改进不需要金丝雀发布,但行为变化需要。一旦版本更新与任何其他生产环境的行为变化处于相同的变更管理轨道——分阶段、影子部署、金丝雀发布、可回滚——绿色评估套件就会回归它本应有的角色:一个有用的底线,而不是发布的大门。
下一个模型会比这一个更好。它也会在基准测试未衡量、你的测试未检查的方面表现得有所不同。那些能够从容升级的团队,是那些预先假设了这一点,并构建了实时对照,以便在用户感知到差异之前先看到差异的团队。
会员专享
余下内容仅对会员开放。
会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。
- —完整文章,包含未公开存档的部分
- —可落地的工作框架,附带权衡与决策依据
- —新文章抢先看,先于公开发布
随时取消 · 一次订阅,畅读全部