Cached document embeddings shift to the wrong inputs after an invalid vector is skipped

该问题通常出现在 Dify 自托管环境中批量生成文档嵌入(缓存嵌入)时:当某个输入的向量无效(归一化后为 NaN)而被跳过,缩短后的有效向量列表会错位压缩,导致后续有效向量与错误的输入(文本哈希或文件 ID)配对并写入缓存。排查重点是 CacheEmbedding 中跳过无效向量后“有效向量与原批次

快速结论:该问题通常出现在 Dify 自托管环境中批量生成文档嵌入(缓存嵌入)时:当某个输入的向量无效(归一化后为 NaN)而被跳过,缩短后的有效向量列表会错位压缩,导致后续有效向量与错误的输入(文本哈希或文件 ID)配对并写入缓存。排查重点是 CacheEmbedding 中跳过无效向量后“有效向量与原批次索引 zip”这一段的索引对齐逻辑。

适用环境:Dify 自托管(Self Hosted, Source),版本为 main 分支提交 09054169c42100b8ff5ebc1163636220fa7162bc;问题同时影响 embed_documents() 和 embed_multimodal_documents()。Issue 未提供操作系统、Python、CUDA、显卡等环境信息,也未指明具体嵌入供应商版本。

最快修复方案:暂无确认的一步修复方案。Issue 中已明确说明修复方向(让每个成功归一化的向量保留其原始批次索引,只将无效向量所在槽位留为 None),并称已在 #45569 中修复,但讨论链未提供该 PR 的合并状态与可核对的补丁细节。

注意事项:跳过无效向量的校验逻辑本身并非缺陷来源,直接回退该保护会让 NaN/全零向量重新进入缓存。修复涉及写入磁盘的 Embedding 行,已经错位写入的缓存不会因代码修复而自动纠正,可能需要重建受影响文档的嵌入;此点 Issue 未直接验证。

问题场景

在 Dify 自托管源码部署中,批量文档索引会调用 CacheEmbedding.embed_documents()(多模态路径为 embed_multimodal_documents()),一次传入两个或以上未缓存输入。当嵌入供应商对较早的某个输入返回无效向量(归一化结果为 NaN,例如 Ollama 偶尔返回全零向量),且随后的输入返回有效向量时,触发该问题。

报错原文

Cached document embeddings shift to the wrong inputs after an invalid vector is skipped

原因分析

已确认的机制:无效向量会从 embedding_queue_embeddings 中被移除,随后这个变短的列表仍与原 embedding_queue_indices 做 zip。于是紧随其后的有效向量被放进无效输入的位置,并以错误的文本哈希或文件 ID 持久化,而它原本的输入槽位保持为 None。结果是文档与向量之间的对齐在无任何报错的情况下被破坏,供应商只需在一次批量索引中返回一个全零或 NaN 向量即可触发,之后可能降低检索效果。

该问题由 #11840 加入的跳过保护逻辑暴露出来;触发条件最初来自 #11827 报告的 Ollama 供应商偶发全零嵌入。

环境排查

  • 确认 Dify 源码版本是否为 main 提交 09054169c42100b8ff5ebc1163636220fa7162bc(Issue 报告的复现基线)。
  • 确认是否运行自托管源码部署,而非云端版本。
  • 确认嵌入供应商是否曾出现全零或 NaN 向量(Issue 中 Ollama 有此类报告,其他供应商未提及)。
  • 确认使用路径是纯文本 embed_documents() 还是多模态 embed_multimodal_documents(),两者行为一致。
  • Issue 未提供 Python、PyTorch、CUDA、显卡或依赖版本信息,这里不做推断。

解决步骤

  1. 在批量嵌入返回后、写入缓存或持久化 Embedding 行之前,不要对 embedding_queue_embeddings 直接压缩删除无效向量;为无效向量在其原索引处保留占位(例如 None),使其与 embedding_queue_indices 保持一一对应。
  2. 仅对成功归一化的向量做持久化,并确保每个有效向量使用其原始批次索引对应的文本哈希或文件 ID。
  3. 保留原有行为:无效向量仍记录日志,其槽位仍为 None,不进入缓存。
  4. 同时检查文本嵌入与多模态嵌入两条路径,确认两边都做了上述对齐修正。
  5. 可优先尝试核对 Issue 提到的 #45569 修复是否已包含对齐修正并应用到当前部署;若已错位持久化历史嵌入,评估重建受影响文档的嵌入。

验证方法

参考 Issue 的复现思路:用 SQLite 与 mock 供应商构造“较早输入返回 NaN 向量、较晚输入返回有效向量”的两个及以上未缓存输入,分别覆盖 embed_documents() 和 embed_multimodal_documents()。检查返回列表与持久化的 Embedding 行:无效输入槽位应为 None,后续有效向量应落在自己的原始索引上,而不是无效输入的槽位。修复前该用例表现为有效向量错位,修复后应对齐正确。

参考来源

langgenius/dify #41476

GamsGo AI

AI 工具推荐

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

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

了解 GamsGo AI

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

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 33435

发表回复

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