[Bug] Disabled Weaviate document vectors are not deleted by segment ID

用户在 Dify 中配置 Weaviate 作为知识库的向量数据库,索引文档中的分段 (segment) 后,禁用或删除该文档时触发。该 Bug 存在于 Dify 主分支 ( main , commit 61b07ab17d ),使用 Docker 自托管部署。

[Bug] Disabled Weaviate document vectors are not deleted by segment ID

[Bug] Disabled Weaviate document vectors are not deleted by segment ID

快速结论:该 Bug 出现在 Dify 使用 Weaviate 作为向量数据库时,禁用或删除文档后,Weaviate 中的向量对象未被删除。优先排查 WeaviateVector._get_uuids() 方法仅使用 page_content 生成 UUID 的逻辑,以及 delete_by_ids() 方法忽略 404 响应的处理。

问题场景

用户在 Dify 中配置 Weaviate 作为知识库的向量数据库,索引文档中的分段 (segment) 后,禁用或删除该文档时触发。该 Bug 存在于 Dify 主分支 (main, commit 61b07ab17d),使用 Docker 自托管部署。

报错原文

[Bug] Disabled Weaviate document vectors are not deleted by segment ID
WeaviateVector._get_uuids() derives object UUIDs only from content
delete_by_ids() treats logical segment IDs as those object UUIDs
Missing-object responses are ignored
Identical segment text can also overwrite another segment because it produces the same object UUID

原因分析

可能原因:这是 Dify Weaviate 向量适配器中的一个已确认但未修复的 Bug。核心问题是 UUID 生成与删除逻辑不一致:

  • UUID 生成错误:WeaviateVector._get_uuids() 方法仅根据 page_content(即分段文本)生成 UUID(使用 uuid5(URL_NAMESPACE, doc.page_content)),而忽略了分段的逻辑 ID(doc_id,一个 UUID4)。
  • 删除逻辑不匹配:Dify 在禁用/删除文档时,调用 delete_by_ids(),并传入分段的 doc_id。但由于 Weaviate 中的对象 UUID 是根据内容生成的,与 doc_id 不匹配,导致 Weaviate 返回 404(对象未找到),而该 404 响应在适配器中被静默忽略(代码位置),因此向量未被删除。
  • 文本内容冲突:由于 UUID 只依赖于文本内容,不同文档中内容相同的分段会产生相同的 UUID,导致向量覆盖,破坏了数据完整性。该问题在 Issue #36137 中已有提及。

注意:现有 PR(#36140、#37068)提出了修复方案,但均未合并到主分支。

环境排查

  • Dify 版本:主分支 main,commit 61b07ab17d(或任何包含此 Bug 的版本)。
  • 向量数据库:Weaviate(需确认具体版本,但 Bug 由代码逻辑引起,与版本关系不大)。
  • 部署方式:Docker 自托管。
  • 相关代码文件:api/providers/vdb/vdb-weaviate/src/dify_vdb_weaviate/weaviate_vector.py,特别是 _get_uuids()delete_by_ids() 方法。

解决步骤

注意:以下步骤基于 Issue 中的分析和未合并的 PR,尚未经过 Dify 官方验证。请在生产环境前充分测试。

  1. 修复 UUID 生成逻辑(参考 PR #36140):修改 _get_uuids() 方法,在生成 UUID 时将 doc_id 纳入计算。例如,将 uuid5(URL_NAMESPACE, doc.page_content) 改为 uuid5(URL_NAMESPACE, f"{doc_id}_{doc.page_content}")。这可以防止不同文档中相同内容的碰撞。
  2. 修复删除逻辑(参考 PR #37068,可优先尝试):修改删除操作,不依赖 UUID 匹配,而是通过 Weaviate 的元数据字段(如 doc_id)进行查询删除。例如,将 delete_by_ids() 改为 delete_by_metadata_field("doc_id", node_id)。这可以确保即使 UUID 生成方式不一致,也能正确删除向量。
  3. 完整重新索引:由于现有对象的 UUID 是根据旧逻辑(仅基于内容)生成的,在应用修复步骤1后,所有已有的 Weaviate 对象将无法与新生成的 UUID 匹配。因此,需要对所有受影响的文档执行完整重新索引。
  4. 监控 404 响应:检查 delete_by_ids() 方法中是否仍存在对 404 响应的静默忽略处理。如果存在,应记录日志或抛出警告,以便在删除不匹配时及时发现。

验证方法

按照 Issue 中的复现步骤验证:

  1. 配置一个使用 Weaviate 的知识库。
  2. 索引一个至少包含一个分段的文档。
  3. 在 Dify 中禁用或删除该文档。
  4. 检查 Weaviate 中对应的集合,确认对象已被删除。可直接查询 Weaviate(例如通过 Weaviate Console 或 API),看看是否有与被删除文档关联的向量残留。
  5. 运行一个不包含活跃文档过滤的检索测试,确保不会返回已禁用/删除文档的向量。

参考来源

langgenius/dify #39174: [Bug] Disabled Weaviate document vectors are not deleted by segment ID

相关 PR(均未合并):

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

celebrityanime
celebrityanime
文章: 13978

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注