跳到主要内容

Embedding 模型轮换是数据库迁移,而非代码部署

· 阅读需 12 分钟
Tian Pan
Software Engineer

在某个预发布(staging)频道里,一位工程师写道:“将嵌入模型(embedder)升级到 v3,新模型在 MTEB 上的得分提高了 4 分,冒烟测试通过后合并。”两天后,客服工单开始陆陆续续出现,反馈搜索结果感觉“莫名其妙地不对劲”。一周后,检索精度下降了 14 个百分点,余弦相似度分数从 0.85 暴跌至 0.65 左右,而且没人能解释原因——因为这次部署看起来与过去五次模型升级完全一样。这根本不是一次普通的部署。而是一次披着部署外衣的数据库迁移。

嵌入模型轮转是 AI 基础设施中最容易被归类错误的变更类型。它通过与提示词(prompt)微调或生成模型版本更新相同的渠道进入你的系统——配置文件、PR、CI 检查——因此它遵循配置变更的治理流程。但从底层来看,新的嵌入模型并不会产生旧向量的更好版本。它产生的向量完全存在于不同的坐标系中,跨两个流形计算余弦相似度是一个范畴错误(category error)。正确的心理模型不是“升级依赖版本”,而是“在提供读取服务的同时,为一个拥有 5000 万行的表更换主键编码”。

那些将其视为普通部署的团队会在切换过程中发现这一点,通常首先是从用户端发现。而那些将其视为迁移的团队会构建影子索引(shadow index)、运行双重查询、在切换别名前测量一致性,并让旧索引保持一周的热切换状态,以备需要回滚。这两类团队的区别不在于技术复杂程度,而在于是否在第一次提到该问题的冲刺规划(sprint planning)中正确命名了变更类别。

为什么流形无法对齐

每个嵌入模型都定义了一个高维空间,其几何结构反映了模型的训练方式——训练目标、数据组合、分词器(tokenizer)、投影层。两个同样声称将“英语文本嵌入到 1024 维”的模型,其产生的向量不仅仅是同一物理量的不同数值。它们是不同单位、不同拓扑结构空间中的测量值,其中的轴代表不同的含义,而“接近”的概念也由不同的邻居定义。

这就是为什么更换模型并直接用新的查询嵌入去对比旧的存储向量会发生静默失败。请求路径中没有任何报错。向量运算照常运行。数据库返回 k 个结果。但结果在结构上发生了细微的错误:语义上相邻的文档不再排名第一,而与查询共享表面词项(surface tokens)的文档开始超过共享含义的文档。你的余弦得分不会归零——它们会从 0.85 跌落到 0.6 左右的模糊地带,那里所有的东西看起来都差不多,但没有一个是正确的。如果你的可观测性仪表板没有衡量检索质量(大多数仪表板都没有),这种失败是隐形的。

实际后果是:你无法进行原地升级。你无法在保持索引可查询的同时逐步逐向量地迁移,因为任何命中新旧向量混合结果的查询,其返回的结果都是由两个不同相似度函数混合而成的。迁移必然需要完整的重新嵌入(re-embed)加一次性切换。唯一的问题在于你在切换时有多严谨。

迁移方案

直接借鉴数据库模式(schema)迁移的严谨性。这种模式分为四个阶段,跳过任何一个阶段都有其失败模式。

阶段 1:影子索引(Shadow index)。 创建一个新的向量列、集合或命名空间(取决于你的向量数据库),并在后台对整个语料库运行新的嵌入模型,将其写入影子索引。Weaviate 通过集合别名和共存的命名向量支持这一点。Pinecone 和 Qdrant 支持通过你可以起别名的多个索引或集合来实现。Postgres 配合 pgvector 支持通过 CONCURRENTLY 添加第二个 embedding_v2 列。影子索引必须从与实时索引相同的事实源(source of truth)填充,而不是从实时索引本身填充——嵌入是不可逆的,所以你无法将旧向量“翻译”到新空间。你必须在源文本上重新运行嵌入模型。

阶段 2:带有指标一致性的双重读取(Dual-read)。 在切换任何用户流量之前,建立一个离线或影子流量路径,将每个查询发送到新旧两个索引,并记录 Top-k 的重合度。标准做法是使用带有相关性标签的“黄金查询集”(通常几百个查询就足够了),并设定 Top-5 在新旧索引间的重合度目标在 60%–80% 之间。一位发布了完整迁移报告的从业者测量到了 82% 的重合度,并以此作为启动信号。如果重合度低于你的阈值,就是一个危险信号:这意味着要么新模型与旧模型存在显著分歧(在这种情况下,你需要检索评估而非仅仅是基准测试分数来决定这种分歧是否是改进),要么是在重新嵌入过程中,你的分块(chunking)和预处理发生了漂移。无论哪种情况,都不要进行切换。

阶段 3:分阶段切换。 在几天(而非几分钟)内将流量从 5% 提升到 25% 再到 100%。观察点击率、下游回答质量以及任何你信任的产品级检索指标。慢速进行的原因不是因为新索引可能缺少数据,而是因为检索质量的回退不会触发错误警报。它们表现为用户满意度的缓慢下降,只有在积累了足够的会话后你才会注意到。渐进式放量为你提供了统计效能,让你在回退影响到 100% 的流量之前捕获它。

阶段 4:回滚计划,保持热备。 这是最容易为了节省时间而被砍掉的一步,但绝对不应该。旧索引在切换后必须保持在线并可查询至少一周,理想情况下更长。回滚应该是将特性开关从 embedding_v2 切回 embedding 的操作,而不是从备份中恢复。如果你为了节省存储空间已经删除了旧列,那么你就把一个 90 秒的回滚变成了一个耗时数天的全语料库重新嵌入过程——而此时用户正在投诉。影子索引的全部意义在于回滚是无代价的;丢弃旧索引会破坏这一特性。

你未曾预估的运营成本

加载中…
References:Let's stay in touch and Follow me for more thoughts and updates