在不破坏生产环境的情况下发布 AI 功能:LLM 的阴影模式、灰度发布和 A/B 测试
一个团队在周二下午将 GPT-4o 换成了一个更新的模型。到周四,支持工单增加了 30%,但没人能说清原因 —— 新模型的回答稍短,拒绝了一些旧模型能处理的边缘情况请求,并且日期格式化的方式不同,导致下游解析器崩溃。团队选择了回滚。两个迭代周期的工作付诸东流。
这种故事不断上演。问题不在于新模型更差 —— 它在大多数方面可能表现得更好。问题在于团队发布的流程与发布 bug 修复程序完全相同:合并、部署、观察。这对代码有效,但对 LLM 则行不通。
LLM 的发布结合了软件部署中最困难的部分:你无法通过单元测试来建立信心,故障模式是弥散的(表现为糟糕的输出而非崩溃),并且在你的指标捕捉到问题之前,用户就已经感受到了质量下降。答案是借鉴成熟基础设施团队发布高风险变更的方法 —— 渐进式发布 —— 但要针对 LLM 系统的特定属性进行调整。
为 什么发布 LLM 不同于发布代码
在深入研究技术之前,有必要明确是什么让 LLM 部署不同于常规软件部署。
非确定性是不可约的。 即使将 temperature 设置为 0 并采用贪婪采样(greedy sampling),LLM API 在实践中也不是确定性的。研究记录了在输入完全相同的情况下,多次运行的准确率差异可达 15%。根本原因是 GPU 浮点运算:操作并非严格结合,并行序列处理期间的批处理大小(batch size)可变性会在推理时引入不同的舍入误差。这意味着你无法编写一个单元测试来提供关于模型变更的可靠信号 —— 同一个查询在多次运行中可能产生显著不同的输出。
微小的变化具有巨大的爆炸半径。 提示词的微调、微调数据的更新或模型版本的升级,其改变行为的方式与基准测试所捕捉到的内容截然不同。一个在 MMLU 上得分更高的新模型,在处理模糊的客户问题时可能表现不同,产生的输出可能更长从而破坏 UI 组件,或者拒绝前一个模型接受的某类请求。这些退化是真实的,但直到你拥有真实流量时才会显现。
反馈是延迟的。 与 500 错误不同,糟糕的 LLM 输出可能在数小时或数天后才会通过用户投诉、下游管道故障或支持工单浮出水面。这种延迟信号意味着你需要一种在不让用户面临风险的情况下运行新版本的方法,同时收集足够的数据来做出决策。
成本是变量,而非常量。 更换模型会改变你的 token 成本。一个质量提升 20% 的新模型,单次调用成本可能是原来的 3 倍。渐进式发布让你可以从小规模开始发现新模型的成本概况,以免它超出你的整体预算。
影子模式:在无风险的情况下验证真实流量
影子模式是任何重大 LLM 变更的最低风险起点。核心思路很简单:将生产环境的请求同时复制给当前模型(服务用户)和候选模型(不服务用户)。记录两者的输出,进行对比,并根据你的观察做出晋升决定。
典型实现是将所有生产流量照常路由到当前模型,同时由一个后台进程将相同的请求发送给候选模型。候选模型的响应绝不会展示给用户 —— 它们会被送往日志系统进行评估。
关键部分是评估层。没有它,影子模式只会给你留下一堆日志。你真正需要的是自动化对比:一个 LLM 评审员(LLM judge),根据与你的用例相关的标准(事实准确性、语气、任务完成度、格式合规性)评估这两个响应,对比 token 数量和成本,以及在现实并发负载下的延迟测量。
一种行之有效的模式是在部署任何内容之前,对历史生产请求运行影子模式代理。将上周的流量在候选模型中回放,并让评审员将输出与当前模型产生的输出进行对比。这能让你在触及生产基础设施之前,快速了解可能出现退化的领域。
影子模式也有实际成本。你同时运行两个模型,这在评估期间大约会使你的推理支出翻倍。将影子请求与基准响应关联起来的复杂性也增加了运维开销。影子模式是处理重大变更(模型升级、重大提示词结构调整、新的工具 schema )的正确工具,而非针对细微的提示词调整。
金丝雀发布:真实用户,小范围暴露
一旦影子模式让你确信候选模型没有明显的逻辑错误,金丝雀发布就会将风险转移到小规模的真实用户身上。
模式如下:将一小部分流量 —— 从 1% 开始,对于高风险应用甚至低至 0.1% —— 路由到候选模型,而其余流量保留在基准模型上。监控这两个群组的所有指标。如果指标保持在可接受的范围内,逐渐增加金丝雀的流量份额:1% → 5% → 20% → 50% → 100%。如果出现任何问题,爆炸半径是有限的,且回滚只需更改一次配置。
关键的基础设施要求是一致的用户分配。一个在某次请求中命中金丝雀的用户,在同一会话的后续请求中也应命中金丝雀。将每个单独的请求随机分配给金丝雀或基准模型会产生不连贯的用户体验 —— 用户在同一个对话中会看到不同的回复风格、格式和行为。
对于 LLM 工作负载,你在金丝雀发布期间跟踪的指标不同于典型的服务发布:
- 延迟百分位数 (p50, p95, p99) —— 而不仅仅是平均值,因为 LLM 的延迟分布高度偏斜
- 单次请求成本 —— token 数量随模型版本而变化,在 100% 流量时出现的成本意外是非常昂贵的
- 错误和拒绝率 —— 新模型可能会拒绝更多类别的请求,这可能是也可能不是你想要的
- 输出长度分布 —— 模式坍缩(极短的输出)或失控的冗长都表明出现了问题
- 用户反馈信号 —— 点踩、重新生成请求和会话放弃,以群组转化率进行衡量
对于生产环境的金丝雀发布,自动回滚不是可选项。设置明确的阈值 —— 如果 p99 延迟增加超过 40%,如果拒绝率跳升超过 5%,如果单次请求成本增量超过预算 —— 让金丝雀控制器将 100% 的流量路由回基准模型,而无需人类在凌晨 2 点介入。
A/B 测试:衡量真正重要的指标
金丝雀部署告诉你新模型是否可以安全部署。A/B 测试则告诉你它是否更好。这是两个不同的问题,混淆它们会导致发布的技术上稳定但却让用户体验变差的变更。
LLM A/B 测试的挑战在于 LLM 的质量无法简化为单一指标。一个模型可能在事实性问题上更准确,更啰嗦,速度更快,但同时在针对你特定用户群的语气上表现更差。你需要知道哪些维度对你的产品至关重要,并且需要直接衡量它们。
隐性信号是最可靠的先行指标。重新生成请求(用户要求模型重试)、响应后立即放弃会话以及后续的澄清问题都表明响应未满足用户需求。这些信号是实时可用的,不需要显式的评价基础设施。
显性信号(点赞/点踩,星级评分)拥有高质量的数据,但覆盖率较低 —— 通常只有 2-5% 的响应会获得评分。它们可用作合理性检查(sanity check)和捕捉严重的回归,但对于细致的比较来说是不够的。
自动化评估填补了这一 空白。使用 LLM 裁判大规模地根据你的标准评估响应,可以提供人工评分无法比拟的覆盖率。关键在于裁判的标准需要根据你的用户实际关注点进行校准,而不是根据你认为合理的标准。
LLM A/B 测试特有的统计挑战非常显著。非确定性会增加质量指标的方差,这意味着你需要比传统 A/B 测试更大的样本量才能达到统计显著性。根据经验,如果你目标是 5% 的最小可检测效应(MDE),且具有 80% 的统计功效(power)和 95% 的置信度(confidence),请计划每个组别准备数万个会话 —— 如果你的质量指标噪声特别大,则需要更多。延迟反馈(在请求数小时后才到达的质量信号)延长了最短测试时间,且容易导致采样不足。
一个有帮助的模式:在进行统计分析之前,先按请求类型进行预分层。新模型可能在事实问答方面表现更好,但在创意任务方面表现较差。将两者聚合在一起会掩盖这两个信号。请根据对你的用例至关重要的请求类别对分析进行细分。
特性标志:上述所有内容的控制平面
影子模式、金丝雀部署和 A/B 测试都有一个共同的控制平面需求:你需要一种方法,在不部署代码的情况下动态地将请求路由到不同的模型版本或提示词变体。
特性标志(Feature flags)是常规答案,但 LLM 引入了典型标志实现无法很好处理的复杂性。
会话状态化(Conversation statefulness)。 改变哪个模型处理请求的标志对于无状态查询来说没问题。但对于多 轮对话来说,这是一个严重的问题,因为当你决定更改模型分配时,用户正处于上下文中间。在对话中途更换模型会导致突兀的风格转变和上下文丢失 —— 新模型不知道前一个模型说了什么。对话式 AI 的标志评估应该锁定在会话级别,而不是请求级别。
成本作为部署变量。 通过标志启用能力更强(且更昂贵)的模型是一项具有预算影响的基础设施变更。控制模型路由的标志需要与成本监控集成,并具有基于支出率(而不仅仅是质量或延迟)的自动熔断开关(kill switches)。
随时间漂移。 传统的特性标志控制的代码路径除非你修改它们,否则不会改变。即使你不触动标志,模型行为也会随着时间推移而漂移 —— 供应商会更新模型权重,行为模式会随微调数据而变化,拒绝模式也会演变。今天指向 "gpt-4o-latest" 的标志在三个月后指向的不再是相同的行为。如果你的标志对模型版本的定义比较宽泛,你实际上是在引入隐性滚动更新,从而绕过了你所有精心设计的金丝雀和 A/B 基础设施。
在标志中尽可能固定模型版本。gpt-4o-2024-11-20 是一个稳定的标志目标。gpt-4o-latest 则不是。
实践中的发布序列
将这些技术整合到一个连贯的发布流程中:
首先是影子阶段。 在任何生产环境暴露之前,在重放的历史流量上运行候选版本,并使用自动化裁判对输出进行评分。根据回归指标设定准入门槛:如果裁判对候选版本的评分低于基准线且超过了你的可接受阈值,请停止并迭代。
1% 的金丝雀。 影子模式通过后,将一小部分真实流量路由到候选版本。监测所有基础设施和质量指标至少 24-48 小时。这里的目标是捕捉影子模式遗漏的回归 —— 真实用户分布总是与历史流量在微妙之处有所不同。
渐进式放量。 在每个步骤(1% → 5% → 20% → 50% → 100%)中,停留足够的时间以积累主要质量指标的统计学意义数据。自动化放量过程,以便在突破阈值时暂停并报警。
大规模 A/B 测试。 在完全推广之前,当处于 50/50 拆分阶段时运行完整的 A/B 比较。这是你收集用户偏好和任务完成数据的时候,这些数据会告诉你该变更是否为净收益(net positive),而不仅仅是净安全(net safe)。
熔断开关始终可用。 在一分钟内将 100% 的流量路由回基准线的能力是必不可少的。这不应该需要代码部署或提交工单。一个配置更改或单个开关就应该足够了。
这实际上需要什么
上述技术听起来很简单,但它们对基础设施有真正的先决条件,而大多数团队都低估了这一点。
你需要一个请求路由层,它能够按可配置的比例拆分流量,在会话中一致地分配用户,并能动态更改路由而无需重启。你现有的 API 网关可能可以处理这些,但它需要连接到一个并非原始设计一部分的评估和监控系统。
你需要一个近乎实时运行的自动化评估流水线。没有自动化评估的影子模式(Shadow mode)只是昂贵的日志记录。评判器(Judge)需要根据你的具体用例进行校准,这需要在构建和验证评判标准方面进行初始投资。
你需要针对正确的指标进行埋点。标准的 APM 工具为你提供延迟和错误率。LLM 特有的指标——单次请求成本、输出长度分布、拒绝率、重新生成率——需要在你的应用程序代码和评估流水线中进行显式埋点。
做得好的团队会将 LLM 的发布视为与生产基础设施变更同等严谨的事情。而那些吃亏的团队则认为模型更换就像依赖升级一样:风险低、易于撤销、适合在周五下午发布。
你所封装的底层模型比以往任何时候都更加强大。发布流程也需要与之匹配。
- https://medium.com/@singhrajni/why-should-you-deploy-your-ml-model-in-shadow-mode-68f0064170a6
- https://www.qwak.com/post/shadow-deployment-vs-canary-release-of-machine-learning-models
- https://www.zenml.io/blog/what-1200-production-deployments-reveal-about-llmops-in-2025
- https://www.codeant.ai/blogs/llm-shadow-traffic-ab-testing
- https://thinkingmachines.ai/blog/defeating-nondeterminism-in-llm-inference/
- https://arxiv.org/html/2408.04667v5
- https://medium.com/@komalbaparmar007/llm-canary-prompting-in-production-shadow-tests-drift-alarms-and-safe-rollouts-7bdbd0e5f9d0
- https://portkey.ai/blog/canary-testing-for-llm-apps/
- https://blog.devcycle.com/using-feature-flags-to-build-a-better-ai/
- https://lotuslabs.medium.com/a-b-testing-for-llms-measuring-ai-impact-using-business-metrics-173b4c00cff0
- https://www.llama.com/docs/deployment/a-b-testing/
- https://deepchecks.com/llm-production-challenges-prompt-update-incidents/
