模型迁移指南:如何在不破坏生产环境的情况下更换基础模型
每一个运行基于 LLM 的功能超过六个月的团队都曾面临过同样的时刻:更出色的模型发布了,当前的供应商涨价了,或者你依赖的模型收到了 90 天后停用的通知。你需要更换正在运行的生产系统底层的基座模型。大多数团队将其视为一次配置更改 —— 更新模型 ID,重新运行评估测试集,然后发布。接着,他们会花费接下来的两周时间来处理评估从未捕捉到的回归问题。
模型迁移问题与传统的软件升级有着本质的不同。当你更换数据库版本时,查询语义是被保留的。当你更换基座模型时,一切都会改变:输出分布会偏移,边缘案例的行为会分歧,而那些学会了依赖特定模型特性的下游系统会默默崩溃。这些故障模式是分布式的,而非二进制的,这意味着它们隐藏在评估测试集覆盖率最低的长尾部分。
这里有一份考虑了这些现实情况的迁移指南 —— 从在用户发现之前捕捉行为漂移的影子测试期,到防止向量索引一夜之间失效的嵌入兼容层,再到在故障模式难以察觉时真正奏效的回滚策略。
为什么“只运行评估测试集”是必要但不充分的
标准的模型迁移方法大致是这样的:将你的评估测试集指向新模型,对比评分,如果数字看起来不错,就发布。这种方法能捕捉到大约 60-70% 的现实世界回归。剩下的 30-40% 隐藏在你的评估测试集从未设计去检查的地方。
核心问题是分布不匹配。你的评估测试集是某人想到并包含在内的输入样本集。生产流量是混乱的长尾分布,包含了没人预料到的输入。模型更换可能在评估集上得分完全相同,但在真实流量的尾部产生细微差别的输出 —— 不同的 JSON 格式约定、改变的拒绝边界、改变的置信度校准,或者导致下游解析器和用户预期失效的语气转变。
评估测试集经常遗漏的三类特定故障:
- 格式漂移:新模型在旧模型返回原始 JSON 时,将 JSON 包装在 Markdown 代码块中。你的解析器能处理两者,但额外的 Token 会消耗掉高流量端点的延迟预算。
- 拒绝边界偏移:新模型拒绝了 3% 旧模型可以处理的查询,或者 —— 更糟糕的是 —— 处理了旧模型正确拒绝的查询。由于评估集没有包含足够的边界案例,这两个方向都不会在评估中表现为准确率回归。
- 校准变化:新模型对不确定的答案表现出更高的置信度。依赖置信度阈值的下游系统开始做出不同的路由决策,从而产生级联效应,导致原本无关的功能出现看似 Bug 的行为变化。
评估是你的起飞前检查清单。它们告诉你新模型是否具备进入生产环境的可能性。它们不会告诉你生产环境是否已经为新模型做好了准备。
影子测试期:在真实流量上并行运行模型
当你在实际的生产流量上进行测试时,评估性能与生产行为之间的差距就会缩小。影子测试 —— 将实时请求同时路由给当前模型和候选模型,但仅将当前模型的响应提供给用户 —— 能让你真实地了解新模型在真实输入分布下的表现。
架构:在应用层而非负载均衡器层实现流量复制。你需要捕获影响模型行为的完整请求上下文(包括对话历史、系统提示词和工具定义),而不仅仅是原始的 HTTP 负载。影子模型接收相同的输入,其输出被记录用于对比,但绝不会展示给用户。
持续时间:运行影子测试至少一个完整的业务周期。如果你的产品有周波动模式(周末流量较轻,周一早晨较重),单日的影子测试会错过伴随不同使用场景而来的输入分布偏移。对于大多数 B2B 应用,两周是捕捉到足够长尾流量并产生意义的最短时间。
影子测试期间衡量什么:
- 语义等效率:尽管表层存在差异,但响应对在语义上等效的比例是多少?这是你的主要健康指标。使用 LLM 裁判配合特定的评分标准,而不是字符串相似度。
- 差异分析:对于模型产生分歧的案例,对差异进行分类。新模型是更好、更差,还是仅仅不同?“不同”并非没有代价 —— 它意味着需要重新培养用户预期并更新下游集成。
- 延迟分布:对比 P50、P95 和 P99 延迟。一个在 P50 处快 20% 但在 P99 处慢 40% 的模型会改善仪表盘数据,但会降低最复杂查询的用户体验。
- Token 经济效益:衡量生产流量中的实际 Token 使用量。产生更简洁输出的模型可以节省成本;而在回答之前生成更长思维链推理的模型,其成本可能高于每 Token 单价差异所暗示的水平。
- 错误率和拒绝率:分别跟踪拒绝、格式错误输出和超时率。高流量端点上 0.5% 的拒绝率增加意味着每天有数百次失败的用户交互。
成本考量:在测试期间,影子测试会使你的 LLM API 成本翻倍。为此进行明确的预算编制。如果 100% 流量的成本过高,可以进行采样 —— 但要按请求类型分层采样,而不是随机采样。随机采样会使稀少但重要的请求模式代表性不足。
嵌入向量兼容性:那个被所有人遗忘的迁移环节
当你的模型切换涉及嵌入模型(Embedding Model)时——或者当供应商在版本更新中悄悄更新了嵌入模型权重时——你数据库中的每个向量都会在无声无息中与新查询变得不兼容。旧的嵌入向量和新的查询向量存在于不同的几何空间中。它们之间的余弦相似度分数变得毫无意义,但仍然会返回看似合理的数值,因此这种故障是隐形的:检索质量在没有任何错误信号的情况下下降。
双索引策略是生产环境嵌入向量迁移最安全路径:
- 为新嵌入向量添加并行列。在现有列旁边添加新列。并发构建新索引,以确保生产环境的读取不受干扰。
- 异步批量重新嵌入语料库。以 50-100 个文档为一组进行批量处理,并设置速率限制以保持在 API 配额内。跟踪进度,以便在任务中途失败时可以恢复。
- 在切换前验证重合度。针对两个索引运行你最常见的查询,并测量 top-K 结果的重合度。如果 top-10 结果中有 80% 以上的重合,说明新模型保留了你的检索语义。如果低于 70%,请调查新模型是真的更好,还是仅仅表现不同。
- 通过特性标志(Feature-flag)进行切换。使用单个环境变量控制由哪个索引响应生产查询。这让你可以实现即时回滚——无需重新部署,无需重新索引。
- 稳定后再清理。只有在度过稳定期(至少一周)后,才删除旧列并重命名新索引。在此之前,保持两个索引都是热切换状态。
适配器捷径:如果全面重新索引不切实际(语料库超过 1 亿个向量或重新嵌入成本过高),可以使用轻量级的线性变换将新的查询嵌入映射到旧的向量空间中。关于漂移适配器(Drift-adapters)的研究表明,这可以在完全避免重新索引的同时,保留 90-95% 的检索质量。权衡之处在于永久性的技术债务:你携带了一个兼容性补丁(Shim),未来的每一次迁移都必须考虑到它。
对一切进行版本控制:在每个向量旁边存储嵌入模型的版本。在查询时,确保查询嵌入是由与存储向量相同的模型版本生成的。这听起来显而易见,但最常见的嵌入迁移 Bug 就是查询模型与文档嵌入模型不匹配,这会导致检索质量下降——而不是直接崩溃。
真正奏效的回滚策略
LLM 系统中的模型回滚比看起来要难,因为故障信号通常是延迟且模糊的。如果用户得到的回答稍差,他们不会提交 Bug 报告——他们只会对你的产品减少一点信任。等到退化体现在聚合指标中时,它可能已经影响用户好几天了。
在开始迁移之前设计你的回滚方案:
- 在整个迁移期间保持旧模型端点处于“热”状态。“热”意味着它正在积极处理影子流量,而不仅仅是理论上可用。冷启动的 LLM 端点与热端点具有不同的延迟特性,而在压力下进行回滚时,回滚延迟至关重要。
- 预先定义回滚触发条件。在迁移开始前确定特定指标的特定阈值,而不是在事故发生的紧急关头才去决定。例如:拒绝率超过基准值 0.5% 以上、p99 延迟超过基准值 30% 以上、语义等效性降至 90% 以下。
- 自动化回滚机制。使用特性标志将流量导回旧模型,通过单个 API 调用或配置更改即可切换。如果你的回滚需要重新部署,那么对于在第三天凌晨 2 点发现的细微回退情况来说,它的响应速度太慢了。
- 考虑状态污染。如果新模型一直在向对话历史、知识库或其他持久化存储写入数据,回滚模型并不 会回滚这些状态。预先决定是否需要对受污染的会话进行特殊处理。
分阶段发布作为全面切换的替代方案:与其一次性切换 100% 的流量,不如循序渐进地引导——5%,然后 25%,接着 50%,最后 100%——在每个阶段都设置稳定期和指标审查。这限制了爆炸半径,并能让你尽早获得关于真实用户影响的信号。代价是迁移周期变长,以及同时维护两个模型的运维复杂性。
提示词兼容层
基础模型对同一个提示词(Prompt)的响应并不完全相同。针对 GPT-4 优化的提示词在 Claude 上会产生不同的结果,而为 Claude 3 调整的提示词在 Claude 4 上的表现可能不尽如人意。模型迁移必然要求提示词迁移。
在开始之前审计你的提示词库存。每一个系统提示词、少样本(Few-shot)示例集和输出格式指令都需要针对新模型进行审查。最需要关注的是那些具有特定输出格式要求的提示词——例如 JSON Schema、结构化提取模板和工具调用(Tool-use)指令。
运行提示词级别的 A/B 测试。在影子流量期间,针对每个主要的提示词,比较旧模型上的旧提示词与新模型上的适配提示词的输出。这可以隔离性能回退是由模型变化还是提示词变化引起的。
常见的提示词适配模式:
- 指令特异性:较新的模型通常需要较少的显式格式指令,但需要更明确的约束陈述。如果你旧的提示词花了 200 个 Token 解释 JSON 格式化,新模型可能只需要 50 个 Token,但可能需要在边界条件上花费 100 个 Token。
- 少样本示例数量:模型升级通常会减少所需的少样本示例数量。尝试使用更少的示例进行测试——这不仅是为了节省 Token,还因为在能力更强的模型上,不必要的示例可能会因过度约束输出空间而降低输出质量。
- 系统提示词重构:不同的模型对系统提示词内部指令顺序的敏感度不同。在旧模型上作为提示词中间部分的指令,在新模型上可能需要作为结尾指令。
实践中的迁移时间线
对于一个拥有相当流量的生产系统,一个现实的模型迁移计划通常如下:
第 1 周:准备工作。审计 Prompt 库,搭建双模型基础设施,定义回滚触发条件和成功指标,如果适用,开始对 Embedding 进行重新索引。
第 2-3 周:阴影期 (Shadow Period)。在生产流量上同时运行两个模型。每日分析两个模型输出的差异。根据发现的问题调整 Prompt。修复格式不兼容的问题。
第 4 周:分阶段发布。将 5% 的生产流量路由到新模型。监控真实的业务指标——不仅是模型质量指标,还包括任务完成率和会话时长等产品指标。
第 5 周:逐步扩量。将比例提升至 25%,然后是 50%。每次提升后包含 48 小时的稳定观察期。
第 6 周:完全切换与稳定。将 100% 的流量切换到新模型。将旧模型保持在一周的预热状态。监控“延迟回归”现象(即前几天指标良好,但随着新模型遇到更罕见的输入模式,指标开始下降)。
第 7 周 :清理工作。停用旧模型的端点。删除旧的 Embedding 索引。更新文档和操作手册 (Runbooks)。
对于一个名义上的配置变更来说,六到七周似乎很慢。但跳过这些步骤的团队往往最终会在凌晨 2 点进行紧急回滚——如果考虑到事故响应、根因分析和信任修复,所耗费的时间反而更长。
这对你的架构意味着什么
模型迁移真正的教训在于架构层面:你的系统在构建时就应该假设模型是会变化的。如果更换模型需要修改几十个文件、更新硬编码的模型名称、在没有双索引能力的情况下重新索引,或者必须重新部署才能回滚,那么你的架构就与特定模型过度耦合了。每当行业格局发生变化,你都将为此付出代价。
请将模型抽象在接口之后。对你的 Embedding 进行版本控制。为模型路由设置特性开关 (Feature-flag)。一次性构建好阴影测试基础设施并保持其可用。这些并不是针对迁移的专项投入,而是确保你的 LLM 系统在生态演进速度超过团队反应能力时,依然保持可维护性的运营基石。
你今天运行的模型不会是六个月后运行的那个。请据此进行构建。
- https://www.codeant.ai/blogs/llm-shadow-traffic-ab-testing
- https://dev.to/humzakt/zero-downtime-embedding-migration-switching-from-text-embedding-004-to-text-embedding-3-large-in-1292
- https://arxiv.org/html/2603.03111v1
- https://byaiteam.com/blog/2025/12/30/llm-model-drift-detect-prevent-and-mitigate-failures/
- https://wallaroo.ai/ai-production-experiments-the-art-of-a-b-testing-and-shadow-deployments/
- https://medium.com/data-science-collective/different-embedding-models-different-spaces-the-hidden-cost-of-model-upgrades-899db24ad233
- https://sparkco.ai/blog/mastering-embedding-versioning-best-practices-future-trends
- https://insightfinder.com/blog/hidden-cost-llm-drift-detection/
