增量嵌入更新

增量嵌入更新

💡 原文英文,约6500词,阅读约需24分钟。
📝

内容提要

本文介绍如何让 Qdrant 文档搜索的向量与原始 Markdown 内容保持同步,核心是增量更新:为每个文本块生成确定性 ID 和内容指纹,同步时仅重新嵌入真正变化的文本,位置变动则复用已有向量,并删除源中已不存在的块。

🔎

延伸解读

增量更新的核心机制

文章通过为每个文本块生成确定性ID和内容指纹(如SHA-256),实现向量与原始Markdown的同步。同步时,仅重新嵌入内容真正变化的块;若文本位置变动但内容相同,则复用已有向量;同时删除源中已不存在的块。这种方法避免了全量重新嵌入的开销,适用于分块确定且枚举源成本低的场景。

集合元数据作为安全护栏

文章建议在集合元数据中记录嵌入模型和预处理管道版本。每次同步前检查这些元数据,若与当前管道不一致,则触发全量重新嵌入到新集合。这防止了不同模型或不同预处理方式产生的向量混合,避免检索质量下降且难以排查的问题。

同步流程的四种状态处理

同步时,每个传入块根据ID和内容指纹与集合比较,分为四种状态:未变化(跳过)、内容变化(重新嵌入并更新)、地址变化(复用向量并创建新点)、新增(嵌入并插入)。最后删除集合中不在传入列表的点。这种分类处理确保了高效且准确的同步。

生产环境优化建议

文章指出,示例中为便于理解,对每个未知块单独进行哈希查找。在生产环境中,应批量执行哈希查找和点更新,以减少网络往返和提升性能。此外,可考虑在同步前创建快照作为安全网,确认无误后再删除。

❓

Q&A

为什么需要增量嵌入更新?

因为向量是原始数据的转换,当原始数据(如 Markdown 文档)变化时,向量不会自动更新。如果不主动更新,文档搜索会基于已不存在的文本的嵌入进行,导致搜索结果过时。增量嵌入更新可以检测文本变化并同步向量,确保搜索始终反映最新内容。

增量嵌入更新具体会执行哪些操作?

每次运行会:保持未更改的块不变;重新嵌入内容变化的文本;当文本位置变化时复用已有向量;添加新文本;删除源中已不存在的文本。

如何为文档块生成确定性ID和内容指纹?

确定性ID通过将URL、锚点和块编号组合(如 url + "#" + anchor + "::" + chunk_num)转换为UUID生成,确保相同位置总是产生相同ID。内容指纹是文本的SHA-256哈希,任何字符变化都会改变指纹,用于判断内容是否相同。

当文档块的位置发生变化但内容不变时,如何处理?

通过内容指纹过滤查找是否已存在相同文本的向量。如果找到,则复用该向量创建新点,并保留原点的 last_updated 时间戳,避免重新嵌入,节省计算成本。

如何确保集合中的向量与嵌入模型和预处理流程一致?

在集合元数据中保存嵌入模型名称和管道版本。每次运行前检查这些元数据是否与当前配置匹配,如果不匹配则触发全量重新嵌入到新集合,防止不同模型或预处理产生的向量混合导致检索质量下降。

同步过程中如何判断一个块是新增、修改还是删除?

通过比较传入块的ID和内容指纹与集合中存储的对应值:ID存在且指纹相同则为未更改;ID存在但指纹不同则为内容修改;ID不存在但指纹在其他ID下存在则为位置变化;ID不存在且指纹也不存在则为新增;集合中存在但传入列表中缺失的ID则为删除。

🏷️

标签

➡️

继续阅读