跳到主要内容

模型弃用就绪:在 90 天倒计时之前审计你的行为依赖

· 阅读需 10 分钟
Tian Pan
Software Engineer

当 Anthropic 去年废弃一个 Claude 模型时,一家公司察觉到了——但这仅仅是因为下游解析器在生产环境中开始报错。罪魁祸首?新模型偶尔会将其 JSON 响应包裹在 Markdown 代码块中。旧模型从不这样做。没人记录过这一假设,也没人对此进行过测试。修复只花了一个下午;诊断却花了三天。

这种模式——无声的行为依赖在生产环境中“震耳欲聋”地崩盘——是模型迁移中典型的失败模式。你更新了模型 ID,跑了一个简单的冒烟测试(sanity check),然后发布。六周后,一些细微的问题出现了。你的 JSON 解析失败率提高了 0.6%。边缘情况下的拒绝率翻了一番。你的结构化提取漏掉了一个以前能可靠填充的字段。差异不在代码中——而在模型的行为中,而你从未为此编写过契约(contract)。

随着主要供应商现在的废弃周期缩短至 60–180 天,且模型发布的速度在加快,这已不再是一个理论上的担忧。这是一个周期性的运营挑战。以下是如何提前应对的方法。

“行为依赖”到底意味着什么

显性依赖很简单:你调用 gpt-4-turbo,然后换成 gpt-4o。搞定。隐性依赖才是问题所在。

考虑一下,除了模型回答问题的能力之外,生产系统实际上还依赖什么:

输出格式的一致性。你的解析代码假设没有 Markdown 包裹的 JSON。或者它假设模型在摘要中总是返回恰好两句话。或者它期望结构化提取中有一个特定的键名。这些假设很少被写下来;它们只是你一直在使用的模型所表现出来的特性。

拒绝行为。Claude 3 Opus 拒绝某些类别请求的比例与 Claude 3.5 Sonnet 不同。Llama 3.1 拒绝了 83% 的对抗性请求;GPT-4o 拒绝了约 4%。如果你的应用程序依赖模型优雅地处理用户输入中的边缘情况,拒绝阈值的差异可能会悄无声息地破坏用户流程。

幻觉率。不同模型的幻觉率差异巨大——而在利基科学、法律和医学话题上差距最大。在一个模型上能可靠结合上下文生成的答案,在另一个模型上可能就不行了。

模棱两可的语言模式(Hedging patterns)。GPT-4 大约有 3.3% 的答案含糊其辞;Claude 2 约为 2%。如果你在下游解析自然语言输出中的置信度信号,这些对冲短语(hedge phrases)的分布就很重要。

推理令牌的暴露。一些模型会在输出中暴露它们的思维链(chain-of-thought)推理;而另一些则不会。监测或记录推理痕迹的应用程序在这一点发生变化时会悄然失效。

这些行为都没有被模型供应商作为保证写入文档。它们是被观察到的行为——而这正是你的系统真正依赖的东西。

指纹识别测试套件

行为审计的目标不是测试新模型是否“更好”。它是为了回答一个更狭窄的问题:在对你的特定系统至关重要的方面,新模型的行为是否保持一致?

从构建一个“黄金数据集”开始:从过去 6–12 个月的真实生产流量中提取 50–200 个代表性的输入输出对。包括:

  • 代表你最常见用例的正向路径(Happy-path)示例
  • 以前出现过失败或意外行为的边缘案例
  • 探测格式合规性(JSON schema、字段存在性、输出长度)的示例
  • 以前触发过拒绝或对冲(hedging)的输入

在当前模型和候选模型上运行此数据集。从四个维度对输出进行评分:

格式合规性。输出是否符合预期的 schema?使用 JSON 校验器,而不是肉眼观察。对于下游代码以编程方式解析的任何字段,合规性必须达到 99% 以上。

语义准确性。在已知标准答案(ground truth)的情况下,新模型是否产生了正确答案?“LLM-as-judge”在这里非常有效——使用最强模型根据评分标准对候选输出进行评分。

行为指纹。新模型拒绝、对冲或未能完成任务的频率是多少?当你没有要求时,它将其输出包裹在 Markdown 中的频率是多少?跟踪这些行为的比例,而不仅仅是单个实例。

边缘案例处理。当你发送对抗性输入、格式错误的请求或无关的主题提示时会发生什么?新模型处理这些方式的差异可能会影响你的下游错误处理。

像 Promptfoo 这样的工具使这变得切实可行。你在 YAML 中定义测试用例和评分标准,并行地在多个模型端点运行它们,并获得差异对比。你可以将其接入 CI 流水线,这样任何模型版本的提升都会自动运行回归测试套件。

如果你已经在使用 LangChain,LangSmith 提供了类似的功能——它记录所有交互,并可以在每个拉取请求(pull request)上运行评估套件,在行为回归到达生产环境之前将其发现。

区分“必须修复”与“可接受的偏差”

并非所有模型间的行为差异都需要在切换前进行处理。关键的区别在于:这种差异是会导致系统故障,还是属于可接受范围内的噪声。

修复前禁止迁移:

解析失败就是解析失败。如果新模型生成的 JSON 导致你的代码无法反序列化——哪怕只有 0.5% 的概率——在上线前也必须修复它。这同样适用于任何会触发应用程序异常的输出格式变化。这些问题是二元的:要么能用,要么不能用。

超过阈值的功能退化(Functional regression)也是一个阻碍因素。如果新模型在核心任务上的准确率相对于基准下降了 10% 以上,那就不是偏差,而是退化。在开始迁移之前,请明确定义这个阈值,这样在时间紧迫的切换过程中,你就能依据数据而非主观印象做出决定。

安全和合规行为需要根据具体情况进行评估。如果你的应用程序运行在受监管的领域,你需要验证新模型的拒绝行为(Refusal behavior)和输出特性是否仍符合你的合规要求。这很难完全自动化,需要人工审查边缘案例(Edge cases)。

接受并监控:

在合理范围内的语气和风格变化几乎总是可以接受的。如果新模型稍微简洁一些,或者措辞稍有不同,通常没问题。在生产环境中监控一周,但不要因此阻碍迁移。

如果延迟(Latency)和成本的权衡在你的 SLA 范围内,则是可以接受的。如果成本有所降低,增加 30ms 的延迟通常是可以接受的。请明确决定这种权衡,而不是将所有差异都视为问题。

如果你有下游验证机制,幻觉率(Hallucination rate)在窄幅区间内的波动(例如从 1.5% 到 2.5%)通常是可以接受的。如果你没有下游验证,那才是需要修复的问题——而不一定是模型本身。

迁移操作指南 (Runbook)

在切换前两周,针对候选模型运行完整的回归测试套件,并记录每一个差异。对于每个行为偏差,做出明确的决定:修复、接受或监控。在继续进行之前,完成所有“必须修复”的项目。

在切换当天,不要一次性切换 100% 的流量。在前两个小时内,将 5% 的请求路由到新模型,并每 15 分钟监控一次质量指标——错误率、格式符合度、延迟。如果其中任何指标退化超过了你的阈值,立即回滚。回滚能力应该是通过更改单个配置来实现,而不是重新部署。

在迁移开始前明确定义回滚标准。一组有效的标准包括:错误率增加超过 5%、格式符合度低于阈值,或者在生产环境中观察到任何解析失败。具体的阈值并不如提前定义它们重要,这样你就不会在压力之下做出主观判断。

在 24–48 小时内逐渐将流量增加到 100%。关注生产指标,而不仅仅是测试结果。行为退化往往出现在真实用户的输入分布上,而这些分布可能并未被你的测试集完全捕获。

大多数团队都会忽略的最后一步:即使迁移顺利,也要进行事后分析(Postmortem)。记录你发现了哪些行为差异,哪些需要修复,以及你的系统对哪些差异比预期更敏感。这将使下一次迁移变得更快。

构建超越单一模型的架构基础设施

那些能够顺利应对模型弃用的团队,其深刻教训在于他们不再将每次迁移视为一次性事件。相反,他们构建了让迁移成为常态的基础设施。

这在实践中意味着几件事。将你的模型调用放在抽象层之后,这样更改底层模型 ID 只需修改一行配置,而不是进行代码重构。将“黄金数据集”(Golden dataset)维护为一等工程资产——每当你在生产环境中捕获到一个有趣的边缘案例时,就将其添加到数据集中,像对待测试套件一样对待它。在 CI 中运行行为评估,以便在代码审查阶段就发现退化,而不是在生产环境中。

这也意味着要现实地看待模型生命周期。主要提供商每年都会发布多个重要的模型版本。你今天使用的模型在被弃用前的预期生产寿命约为 12–18 个月。从一开始就将迁移就绪性(Migration readiness)构建到你的架构中,比将每次迁移都视为紧急情况要划算得多。

那些在模型弃用面前挣扎的团队,往往是那些深度依赖于特定模型版本的隐式行为保证,却从未记录这些假设或对其进行系统测试的团队。而那些能够平滑处理迁移的团队,则尽早构建了评估基础设施,并像对待 API 合约一样对待行为合约——即明确、可验证且带有自动化检查。

90 天倒计时是最后期限。在收到邮件通知之前,就应该建立起你的审计基础设施。

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