跳到主要内容

AI 功能标记:LLM 驱动功能的渐进式发布

· 阅读需 12 分钟
Tian Pan
Software Engineer

大多数团队通过惨痛的教训发现,发布一项新的 LLM 功能与发布一个新的 UI 按钮完全不同。一个在离线评估中表现出色的 Prompt 变更发布到生产环境后,可能会悄无声息地导致 30% 用户的体验质量下降——而你的仪表盘却全程显示 HTTP 200。等你察觉时,成千上万的用户已经遭遇了糟糕的体验,而你却没有快速恢复到正常状态的路径。

防止传统软件故障的渐进式发布工具包——特性标志(feature flags)、金丝雀发布(canary releases)、A/B 测试——同样适用于 LLM 驱动的功能。但其机制差异之大,以至于直接复制粘贴现有的部署手册会让你陷入麻烦。非确定性、语义质量指标以及 LLM 变更的多层性质(模型、Prompt、参数、检索策略)都制造了团队通常会低估的棘手问题。

你实际发布的是什么

团队常犯的第一个错误是将 “Prompt 变更” 视为一个单一的原子化操作。在实践中,一个 LLM 功能变更几乎总是一个组合包:

  • 模型版本:从一个供应商模型切换到另一个,或在同一供应商系列中升级。
  • 系统提示词(System prompt)或指令:关于模型应如何响应的行为规范。
  • Prompt 模板:用户输入在发送给模型之前是如何被格式化的。
  • 采样参数:Temperature、top-p、max tokens —— 控制输出分布的数值。
  • 检索配置:对于基于 RAG 的功能,查询哪些知识源以及如何对其进行排名。
  • 输出解析逻辑:如何从原始模型响应中提取结构化输出。

这些层中的每一层都可以独立设置标志、测试和回滚。最严谨的团队会分别为每一层设置版本,并逐一部署变更。在实践中,迫于发布压力,这些层往往会一起变动——只要你有一套机制能在出现性能回退(regression)时隔离出是哪一层导致的问题,这样做也无妨。

为什么标准的 A/B 测试会失效

传统的 A/B 测试假设在输入相同的情况下,实验组 A 和实验组 B 会产生确定性的输出。你衡量结果,运行 t 检验,然后宣布胜出者。LLM 输出在每一个层面上都违背了这一假设。

即使将 Temperature 设置为零,LLM 的输出也并非完全可复现。GPU 集群上的浮点运算执行顺序取决于负载;混合专家(MoE)模型会将 Token 路由到不同的专家子集。相同的 Prompt 在不同次调用中可能会产生显著不同的响应。这意味着你的 “对照组” 不是一个固定的基准,而是一个分布。

这有两个实际影响:

统计效能(Statistical power)要求提高。 你的结果指标的方差比确定性功能要高。运行一小时或仅有几百次交互的测试会得出充满噪声的结果。严谨进行 LLM A/B 测试的团队,对于隐式指标(任务完成度、参与度)通常会针对每个变体收集成百上千次的交互,而对于显式反馈信号(点赞/点踩评分),由于响应率较低,需要的样本量则更多。

语义质量需要专门的评估基础设施。 传统指标如错误率、延迟和点击率是必要的,但还不够。一个以幻觉率增加 10% 为代价换取更快响应的模型,在你的性能仪表盘上看起来会非常出色。你需要将 LLM-as-a-judge 评估作为测量流水线的一部分运行——即评估事实准确性、响应相关性和格式合规性的自动化准则——并将其集成到特性标志评估中,而不是作为一个单独的离线步骤。

三层指标栈

稳健的 LLM 特性实验会同时在三个层面进行测量:

计算指标 是最简单的:首 Token 时间(TTFT)、总延迟、每次响应的 Token 数、单次请求成本。这些是完全确定性的,可以直接集成到标准监控中。

确定性行为指标 需要稍多一些设置:格式合规性(响应是否符合预期的 JSON schema?)、长度是否在范围内、工具调用(tool call)成功率、拒绝率。这些可以通过简单的启发式方法而不是另一个 LLM 来评估。

语义质量指标 是最难的:相对于标准答案(ground truth)的响应准确性、与用户实际意图的相关性、幻觉率、多轮对话的连贯性。这些需要基于 LLM 的评估或人工标注,两者的在大规模运行时都较慢且昂贵。

团队常陷入的失败模式是只测量第一层——因为这很容易——然后在全面发布后才发现,新版本的模型虽然在技术指标上更快,但在语义上表现更差。延迟方面的优势换来的是用户能立即察觉到的质量损失。

提示词管理:版本化难题

你存储和版本化提示词变体的方式决定了你实验的安全性。存在三种常见的模式,其风险状况各不相同:

硬编码常量配合布尔标志 是最简单的方法:代码的不同分支包含不同的提示词文本,由特性标志(feature flag)选择运行哪个分支。这与代码审查和版本控制相集成,但它将提示词的更改与代码部署耦合在一起。更改提示词需要重新部署,这降低了迭代速度。

字符串类型的特性标志 直接在标志配置中存储提示词文本。这实现了无需部署即可更新提示词,听起来很有吸引力,直到你意识到你完全绕过了同行评审、测试和回滚审计追踪。标志值中的一个拼写错误会演变成一场生产事故,且没有代码差异(diff)来展示发生了什么变化。

带有版本 ID 的提示词平台 是推荐的模式。提示词存在于专用系统(如 PromptLayer、Langfuse 或自研存储)中,具有不可变的流水号记录。特性标志存储的是版本 ID,而不是提示词文本。标志控制哪个版本处于激活状态;提示词平台提供实际内容。你获得了无需部署的迭代速度,同时不会牺牲审计追踪或同行评审,而且回滚只是切换标志,而不是重新部署代码。

分组一致性:隐藏 Bug 的根源

跨会话运行的 LLM 功能有一个容易被忽视的一致性要求:在变体 A 上开始对话的用户,在该交互的持续时间内应继续体验变体 A。

如果你的标志评估是无状态的——即每次请求都重新查询标志——那么当你推送标志更新时,用户可能会在对话中途经历模型切换。对于聊天机器人和多轮对话智能体(agent)来说,这会产生明显的逻辑不连贯:模型的行为、语气和能力在轮次之间发生了变化。用户会体验到产品出故障了。

解决方法是 粘性分配 (sticky assignment):在会话开始时将标志解析为某个变体,存储该分配结果(存储在会话、用户配置文件或专门的实验存储中),并在该会话后续的所有请求中使用存储的分配。新会话会获取当前的标志状态;现有会话则被隔离,直到它们自然结束。

同样的原则也适用于多步智能体工作流。如果一个智能体在 5 分钟内执行了 10 次工具调用,你肯定不希望标志更改在工作流中途传播。应在任务创建时解析变体分配,而不是在每个步骤中解析。

AI 功能的分阶段发布

LLM 功能变更的一个实用分阶段序列:

阶段 1 —— 内部阴影流量 (Internal shadow traffic):将生产环境请求的副本路由到新变体,但不向用户展示结果。离线比较输出。这能在任何用户接触之前捕获明显的质量退化——如格式破坏、高拒绝率、常见查询类型的幻觉等。

阶段 2 —— 金丝雀发布 (5% 的流量):将新变体暴露给一小部分用户。在此阶段,你主要关注计算和确定性指标:延迟、错误率、格式合规性。让金丝雀发布运行足够长的时间,以捕获负载下的延迟峰值和真实查询分布中的边缘情况。

阶段 3 —— A/B 测试 (50/50 分流):运行完整的统计实验。收集足够的交互数据,以使你的语义质量指标达到显著性。设置最小实验持续时间——不少于一个工作日,通常为一周——以捕捉代表性的流量模式,包括周末行为和使用高峰。

阶段 4 —— 全量发布或回滚:根据 A/B 测试结果,要么推广到 100%,要么回退到之前的版本。如果选择推广,请保留旧变体以便在无需代码部署的情况下快速回滚。

在每个阶段,定义自动回滚触发器:如果错误率超过 X%,或者 LLM 评委 (LLM judge) 评估得分降至 Y% 以下,则自动回滚并传呼值班人员。人工评审速度太慢,无法在质量退化影响大量用户群之前及时捕获。

静默降级:无人监控的失败模式

LLM 生产环境中最棘手的失败模式是响应表面上看是正确的,但实际上是错误的。你的监控显示 HTTP 200。延迟正常。用户没有立即投诉——响应看起来合乎逻辑,只是不准确。一周后你发现,自从你部署模型升级以来,特定类别的查询一直在返回幻觉数据。

发生这种情况是因为 LLM 质量无法从基础设施指标中观察到。标准的 APM 工具只能告诉你请求是否完成,而不能告诉你完成的内容是否正确。

捕捉静默降级需要三件事:

  • 持续的 LLM 即评委 (LLM-as-judge) 评估,针对抽样的生产流量运行,而不仅仅是针对你的评估测试集。你的离线评估集代表了你构建它时的分布情况;而生产流量是会发生偏移的。
  • 主题和查询分类,按查询类别细分质量指标。模型可能总体得分很高,但在特定的查询类型上表现退化——通常是那些在你的评估集中没有得到充分体现的长尾或复杂查询。
  • 趋势监控,而不仅仅是阈值告警。质量指标比目标低 2% 也许可以接受;但如果一个指标连续三周每周下降 2% 就不行了。基于趋势的告警能在渐进式退化跨越绝对阈值之前将其捕获。

回滚作为一等公民功能

当检测到性能退化时,回滚的路径至关重要。在传统软件中,回滚意味着撤销一次提交并重新部署。而通过功能标志 (Feature Flags),回滚只需几秒钟的开关切换即可生效,无需运行流水线。

这改变了你对实验激进程度的权衡逻辑。如果回滚代价高昂(需要重新部署、协调、在非工作时间加班),团队就会变得保守——他们会堆积变更,减少实验次数,并避免在周五触碰生产环境。当回滚是瞬时完成时,你可以行动得更快。

快速回滚的前提条件包括:

  • 之前的变体仍然可用且处于热启动状态(而非冷启动)
  • 标志状态的更改能够在没有缓存延迟的情况下传播
  • 依赖的服务(检索索引、提示词模板、解析逻辑)已进行版本化,以匹配标志变体
  • 运维手册 (Runbook) 准确记录了需要切换哪些标志以及切换顺序

最后一点是团队最容易出错的地方。涉及多个组件的 LLM 变更需要跨多个标志进行协同回滚。如果你同时升级了模型和系统提示词,那么仅回滚模型标志而不回滚提示词标志,产生的状态可能比两者都不回滚还要糟糕。在发布前就记录好你的回滚序列,而不是在事故发生后才开始。

综合实践

实际的切入点并不是一套完整的渐进式交付基础设施,而是一个经过良好埋点的实验。选择一个你计划发布的特定 LLM 变更,进行 50/50 的流量切分,自动衡量计算指标和确定性指标,并添加一个语义质量信号(即使它只是显式的用户反馈)。运行一周。这种在发布前先进行衡量的纪律,将揭示你对自己系统认知中的盲点。

在此基础上,随着你发现特定部署中实际会出现故障的点,再逐步添加自动回滚触发器、粘性会话分配和 LLM 评判员 (LLM-judge) 评估。做得好的团队并非在第一天就部署了一套完美的系统,而是在实际实验的过程中增量地构建基础设施。这是判断你的衡量指标是否真正与用户体验相关的唯一方法。

另一种选择是大多数团队起步时采用的方法:发布变更,观察几天的指标,然后祈祷。在出事之前,这种方法一直有效。

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