正在刊行长文 · Essay
2026-08-13所有内容
随机比特 · Random Bits

Embedding 版本升级后,为什么旧向量不能留在同一个索引里

2026-08-13AI Engineering / Systemsrbits.uk
Embedding 版本升级后,为什么旧向量不能留在同一个索引里

团队把 Embedding 模型从旧版升级到新版。新模型离线召回更好,向量维度也刚好相同,于是工程师只替换查询侧模型,文档索引继续复用。

服务没有报错,余弦相似度照常返回,结果却开始漂移:同义问题找不到,几个无关片段反而长期排在前面。

原因不是数据库损坏,而是查询向量和文档向量来自两个不同的坐标系。维度相同,只说明数组长度一样,不代表每个方向仍表达同一种语义。

向量不能脱离生成它的模型

Embedding 是模型把输入映射到空间中的结果。换模型、换归一化方式,甚至改变同一模型的输入类型配置,都可能重排距离关系。旧空间里的 0.82 与新空间里的 0.82 没有天然可比性。

因此,索引记录不能只有 vector。至少要绑定模型标识、模型版本、维度、距离度量、预处理版本和原始内容版本。查询也必须声明使用哪个向量空间,并且只在同一空间内比较。

同一模型的查询侧和文档侧也未必使用完全相同的入口。有些模型要求明确区分 search_querysearch_document,或者为输入加不同前缀。把文档入口拿来编码查询,数组维度仍然正确,召回质量却会下降。因此版本标识还应包含任务模式,而不只是模型名称。

维度相同不代表坐标系相同

最危险的迁移方式是原地分批覆盖。此时同一索引里一部分文档属于旧空间,一部分属于新空间,查询结果随回填进度持续变化,既难解释也难回滚。

只检查“新向量数量等于文档数量”也不够。回填期间文档可能被更新或删除,后台任务若把旧快照重新写入,会复活已经删除的内容,或用旧文本覆盖新版本的向量。回填写入必须携带内容版本,并且只在目标记录仍是该版本时生效。

最小迁移:双写、回填、切流

更稳妥的做法是蓝绿迁移。先创建新索引;新增或更新的文档同时写入新旧两个空间;后台从原始文本重新生成全部新向量;回填完成后,用固定查询集比较召回、排序和空结果率;达到门槛再切换查询别名,旧索引保留一个回滚窗口。

如果数据库支持命名向量,也可以在同一条记录上并存 embedding_v1embedding_v2,但查询必须显式选择空间,不能把两组向量塞进同一个无版本字段。

切流不宜一次完成。可以先让少量影子流量同时查询新旧空间,只记录差异、不影响用户;再灰度一小部分真实请求,观察空结果、延迟和下游答案质量。若需要回滚,只切回别名或 using 参数,不重新计算任何向量。可逆性来自保留旧空间,而不是相信新模型一定更好。

Embedding 的蓝绿迁移路径

验证不能只看平均 Recall@K。还要检查高频查询、长尾术语、跨语言、短文本、否定表达和权限过滤后的切片。记录新旧 Top-K 的重合率、排序翻转、零结果率和业务点击反馈。只有整体回填完成、增量双写追平、查询侧和文档侧版本一致,才允许切流。

另外必须保存原始内容或可重建的规范化文本。只保存向量等于丢掉迁移源数据;下一次模型升级时,只能从已经压缩过的数字反推文本,这是不可逆的。

清理旧索引前还要确认没有离线任务、缓存键或历史回放继续引用旧版本。删除旧空间是迁移的最后一步,不是切流后的顺手操作。保留期至少覆盖一次完整的业务反馈周期,否则搜索指标在几天后恶化时,团队只剩重新回填这一条昂贵路径。

向量索引不是一袋可以跨模型复用的数字。它是模型、预处理、距离度量和语料版本共同生成的派生工件。

升级 Embedding 时,真正要迁移的不是一个 API 名称,而是一整套坐标系。

作者|随机比特

随机比特公众号二维码
公众号 · 随机比特
从 AI 工具热闹里拆工程真相

写边界、控制面、上下文、成本与安全。