登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  科技周边 >  人工智能

Embedding 模型更换后向量库为什么必须重建索引

来源:17golang原创

时间:2026-09-08 17:50:03 259浏览 收藏

Embedding 模型一换,向量库通常不能继续沿用原索引。原因不只是向量维度可能变化:模型的语义空间、池化方式、归一化策略、输入提示词和切片规则都可能变化。旧文档向量与新查询向量即使都是 768 维,也不代表每个坐标表达同一种语义。正确做法是给新模型建立独立版本,重新编码文档、重建 ANN 索引,再通过别名切换。

要点速览
  • 先比较模型契约:模型 ID、版本、维度、归一化、提示词和距离度量。
  • 文档向量、查询向量和索引必须属于同一个 embedding_version,不能只检查维度。
  • 用固定查询集验收新索引,切换时保留旧索引和回滚指针。

先比较模型契约而不是只看向量维度

向量检索的前提是“比较双方在同一个空间里有意义”。Hugging Face 将 feature extraction 描述为把文本转成向量,Sentence Transformers 也把相似文本放在更接近的向量空间中。这个空间由模型及其使用方式共同决定,不是由一个整数维度决定。

迁移前先把下面这些字段写进索引元数据。模型仓库或 revision 变了、归一化开关变了、query/passage 前缀变了,都应当按新空间处理。

契约字段要核对什么不一致时的处理
模型身份模型 ID、revision、运行后端通常重新编码
向量形状维度、数据类型、是否截断维度不同必须新索引
语义处理池化、归一化、query/passage 提示词按不兼容迁移处理
检索定义cosine、内积或 L2,以及切片规则重建索引并重新验收
Embedding 模型更换后旧文档向量与新查询向量分属不同向量空间的关系图
图1:模型切换后,即使维度数字相同,旧文档向量与新查询向量也不应直接放进同一比较空间。

把旧空间和新空间彻底分开

不要把新向量追加到旧集合,也不要让服务端用新模型生成查询向量后去搜索旧索引。最简单的隔离方式是把版本写进集合名、命名空间和元数据,例如 docs_embedding_v1docs_embedding_v2,并让查询服务根据同一个版本加载模型和索引。

一个最小的编码约束可以写成下面这样。示例只展示契约绑定,不依赖具体向量数据库;真正落库时还要把 embedding_version、文档 ID 和切片版本一起写入记录。

from sentence_transformers import SentenceTransformer

# 模型、归一化和版本必须作为一组契约保存
MODEL_ID = "BAAI/bge-small-en-v1.5"
EMBEDDING_VERSION = "v2"
model = SentenceTransformer(MODEL_ID)

def encode_passages(texts: list[str]) -> list[list[float]]:
    # 文档和查询必须使用同一套归一化约定
    return model.encode(
        texts,
        normalize_embeddings=True,
        convert_to_numpy=False,
    ).tolist()

records = [
    {"doc_id": "faq-001", "embedding_version": EMBEDDING_VERSION, "text": "..."}
]
vectors = encode_passages([item["text"] for item in records])
# 写入 docs_embedding_v2;不要混入 v1 的向量
for item, vector in zip(records, vectors):
    save_vector(collection="docs_embedding_v2", metadata=item, vector=vector)

如果只是换了 ANN 索引实现,但模型输出、归一化、距离度量和切片内容完全不变,可以从旧向量重建索引;如果换了 Embedding 模型或输入处理链,就必须重新编码原始文本。

回填文档并用固定查询集验收

先冻结一小组真实查询和人工确认的相关文档,作为迁移基线。回填时从原始文档或切片表读取文本,而不是把旧向量再转换成新向量。新索引至少要比较 Recall@K、命中率、空结果比例和 P95 延迟;只看“接口返回 200”无法判断检索质量。

生产迁移可以采用双写:新文档进入系统时同时写入 v1 和 v2,历史数据由后台任务分批回填。回填任务要可重试,记录最后成功的文档 ID 或游标,并让失败记录可单独补偿。不要在回填未完成时把 v2 宣布为唯一索引。

用别名切换并保留可回滚入口

新索引构建完成后,先让离线查询集和一小部分灰度请求读取 v2。确认召回、回答引用和延迟达到目标,再把 retrieval_current 这样的读取别名切到 v2。旧索引至少保留一个回滚窗口,回滚只需要把别名指回 v1,并让查询模型同步切回 v1。

Embedding 向量库迁移中双写回填、版本索引、离线查询集与检索别名的关系图
图2:新索引通过独立版本和读取别名接入,旧索引保留为可回滚目标。

上线前可以按这份清单复核:原始文本是否全部回填;查询模型与文档模型是否同版本;归一化和距离度量是否一致;别名切换是否原子;旧索引是否仍可读;监控是否能区分 v1、v2 的命中率和延迟。这里最容易漏掉的是查询侧:只重建文档索引,却忘记把查询编码器一起切换,结果仍然是跨空间比较。

常见问题

新旧模型输出维度相同,还需要重建吗?

通常需要。维度相同只说明张量形状兼容,不说明坐标语义、归一化和相似度分布兼容;除非你能证明模型和完整输入契约没有变化。

只更换向量数据库,是否必须重新生成 Embedding?

不一定。若向量值、距离定义和切片完全不变,可以直接用旧向量重建新 ANN 索引;迁移前仍要用固定查询集验证结果。

能否边回填边让用户搜索新索引?

可以做灰度,但要明确覆盖范围并保留 v1 回退。未回填的文档会造成召回缺口,所以不要在全量完成和质量验收前全量切换。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>