跳到主要内容

“什么发生了变化”查询是你的索引无法回答的 RAG 问题

· 阅读需 12 分钟
Tian Pan
Software Engineer

一个用户问你的助手,“这季度我们的退款政策有什么变化?”系统返回了一个当前退款政策的、格式良好的自信总结。用户点点头,关闭聊天,并根据一个与他们提出的问题完全无关的信息采取行动。你的评测套件(eval suite)没有捕捉到这一点。你的忠实度指标(faithfulness metric)没有标记它。检索看起来很完美——它返回了高度相关的分块(chunks)。合成看起来也很完美——它引用了它使用的每个分块。唯一的问题是,问题是关于 变化 的,而你的索引没有变化的概念。

这是向量相似度检索无法通过调优修复的失败模式。同一文档的两个版本具有几乎相同的嵌入(embeddings)——这就是好的嵌入所 的,它们将语义等效的文本折叠到同一个邻域中。因此,当你问“什么改了”时,检索器返回其中一个版本,LLM 总结该版本,而答案在沉默中成为了“什么都没变”的幻觉。用户无法察觉。你的评测集可能也无法察觉,因为你的评测集是围绕“什么是 X”的问题构建的,而不是“现在 X 有什么不同”。

问题的规模比缺失一个功能要大。增量查询(Delta queries)——“什么改了”、“Q3 与 Q2 有什么不同”、“自我上次查看以来有什么新内容”、“事故发生后我们是否更新了 SLA”——在任何基于不断演进的文档的生产环境 RAG 系统中,都占据了实际流量的很大一部分。工程团队发布版本说明(release notes)。法律团队比较合同版本。客户成功团队需要知道本月更新了哪些政策。这些查询都无法通过围绕“寻找最相似的分块”构建的索引得到很好的服务。它们需要一个知道什么在前、什么在后,以及在两个不同时间点看到的同一个分块是什么的索引。

为什么向量相似度无法检测变化

那些打破初次构建者直觉的假设是,认为“更多的检索”最终会覆盖两个版本。事实并非如此。一个经过良好调优的嵌入模型会将“退款窗口为 30 天”和“退款窗口为 14 天”映射到非常接近的向量——它们共享大部分 Token,共享相同的句法模式,共享相同的领域。余弦相似度将它们放在嵌入空间中相邻的位置。对于没有指定时间的查询,检索器没有维度去偏好其中一个。它随机选择一个并提供服务。下游的 LLM 只有一份文档可读,而该文档讲述了一个关于退款的连贯故事,它生成的答案也是连贯的,但却是错误的。

这是一个结构性限制,而不是调优问题。你无法通过提高 k 值、降低 k 值、更换嵌入模型、添加重排序器(re-ranker)或重写提示词来修复它。这些干预措施都无法教会检索器“该文档上季度的版本”和“该文档本季度的版本”之间的区别。两个版本都占据相同的语义邻域。两个版本看起来都像是对表面层查询的好答案。检索器正在完成它被设计要做的任务——而那项任务不包括时间。

VersionRAG 于 2025 年末发表,并对此进行了直接测量。在针对演进中的技术文档的版本敏感问题的基准测试中,普通 RAG 的准确率仅为 58% 到 64%——对于二元问题来说仅略高于随机水平。准确率上限并不是调优差距。它是同样的结构性上限:系统无法可靠地将关于“截至目前的文档”的问题与关于“文档如何变化”的问题区分开来。一个显式地将文档演进建模为分层图的版本感知变体,在同样的基准测试中达到了 90% 的准确率,且索引 Token 减少了 97%。这种提升来自架构,而不是来自更好的嵌入器。

没人察觉的幻觉

内容幻觉——LLM 捏造了一个与来源相矛盾的事实——会被忠实度检查捕捉到。每一个现代 RAG 评测框架都会根据检索到的上下文对输出进行评分,并标记上下文不支持的说法。这是标准的幻觉防御手段,而且很有效。

增量幻觉(Delta hallucinations)则完全避开了这种防御。LLM 对给定的上下文是忠实的。上下文是文档的当前版本。该版本的总结是准确的。幻觉存在于 用户提问 的层面,而不是 文档内容 的层面——当问题是“告诉我 X 是如何变化的”时,模型回答了“告诉我关于 X 的信息”。忠实度指标将其评分为完全通过,因为该指标旨在将说法与检索到的分块进行比较,而不是将答案的框架与问题的框架进行比较。

检测这一点需要不同类别的评测——一种包含带有标准答案差异(ground-truth diffs)的增量查询,并根据答案是否产生了对比而非描述来进行评分。大多数团队的评测套件中都没有这一类别。他们有“事实性”查询、“总结性”查询,也许还有“多跳”查询。他们没有将“增量”查询作为一类核心维度。因此,这种失败模式永远不会出现在仪表盘上,永远不会消耗错误预算,并在沉默中发布到生产环境。直到有客户因为根据助手自信提供的过时信息做出了决定而投诉时,才会被察觉。

了解变更的索引是什么样的

解决这一问题的架构包含四个组件,而 RAG 默认入门套件中缺少其中的每一个。

首先是一个时序索引,它保留带有差异元数据的版本化文档。当文档更新时,你不会丢弃旧的嵌入(Embedding)——而是保留它,为其标记版本号和有效期窗口,并存储每个分块(Chunk)的内容寻址哈希,以便系统知道哪些分块实际上发生了变化。LiveVectorLake 的设计对此使用了语义分块上的 SHA-256;实际效果是,对“一个段落的微小编辑”会保留所有其他分块的嵌入,仅对真正变动的那一个进行重新索引。这不仅仅是存储层面的整洁——它是差异查询(Delta queries)所需的基础底层。

其次是一个查询意图分类器,它将差异查询路由到专门的差异检索流水线。对于“发生了什么变化”这类问题,普通的相似性搜索是错误的默认选择。分类器——可以是一个小模型,甚至是查询模板上的正则表达式——检测意图标记,如“什么变了”、“X 与 Y 有何不同”、“……有什么新内容”、“自上季度以来”,并将这些查询路由到不同的检索路径,获取相关文档的“修改前”和“修改后”版本,而不仅仅是一个相似的分块。VersionRAG 明确描述了这一路由层;省略该架构的方案往往停留在 58% 的性能水平。

第三是保留跨版本分块身份的分块策略。当你对新版本文档重新分块时,需要一种方法来表示“版本 2 中的这个分块对应版本 1 中的那个分块”。如果没有这一点,即使你检索到两个版本,大语言模型(LLM)也无法对齐它们——它会得到两块看起来无关的文本,且没有对比的框架。解决方法是结构化分块(按章节标题、条款编号、段落锚点),而不是纯粹基于长度的分块,并配合一个在分块内容编辑后仍保持稳定的分块标识符。

第四是专为对比而非总结设计的合成提示词。默认的 RAG 提示词——“根据这些分块回答问题”——对于差异查询是错误的。差异查询的正确提示词会给模型提供标记好的“修改前”和“修改后”版本,并要求其生成结构化差异(Structured diff):添加了什么,删除了什么,哪些是在不改变意思的情况下重新表述的,哪些是在实质内容上发生了变化。这是一个不同的生成任务,具有不同的输出模式,将其视为默认总结提示词的变体只会产生模糊的内容。

你可能遗漏的评估维度

差异查询评估是具体的。你构建一个版本化文档语料库——发布日志是一个简单的起点,但合同、政策、技术规范和配置文件也都适用。对于每一对版本,你编写一小组带有命名实际变更的真值(Ground-truth)差异的差异查询。然后你从两方面进行评分:系统是否检索到了正确的版本“对”,以及合成结果是否生成了提及实际变更的对比,且没有捏造未发生的变更。

差异合成的评分标准必须惩罚标准忠实度(Faithfulness)指标无法捕捉的三种失败模式。第一种是“静默当前版本”回答——系统像回答内容问题一样总结了最新版本。第二种是“静默过期版本”回答——系统总结了之前的版本,通常是因为旧版本的嵌入在查询中得分略高。第三种是“捏造变更”回答——系统虚构了差异中并不包含的版本差异,这通常是因为当提示词将问题框架设定为“什么变了”时,LLM 默认会生成对比结构。

对现有的 RAG 系统运行这种评估可能会让人感到不安。其得分会远低于其他评估维度。但这正是重点所在。你的“什么是 X”的性能与“X 发生了什么变化”的性能之间的差距,就是你的用户已经在承受的体验鸿沟。

更宏大的模式:相似性检索只是其中一种模式

差异查询是一个更深层问题的最显性案例:向量相似性检索是更丰富的检索问题空间中的一种模式,而大多数生产环境中的 RAG 系统都受困于仅在那一种模式下运行。其他模式同样真实存在并能回答常见问题:

  • 趋势查询(Trend queries)——“过去两年我们的定价是如何演变的”——需要按时间顺序排序的检索,而不是按相似性排名的检索。
  • 反事实查询(Counterfactual queries)——“如果我们在这个案例中使用旧政策会发生什么”——需要能够根据假设条件拉取文档非当前版本的检索。
  • 对比查询(Comparative queries)——“我们的 SLA 与行业标准有何不同”——需要从两个不同的语料库中拉取并对齐的检索,而不是将它们混在一起的检索。
  • 溯源查询(Provenance queries)——“这个数字最初出现在文档的什么地方”——需要遍历文档历史的检索,而不是按当前相关性排名的检索。

这些问题的形式都与差异查询问题相同。默认的相似性排名检索器会返回自信、格式良好、看起来似是而非的答案,但却会以忠实度指标无法捕捉的特定类别方式失败。除非你为其构建一个评估切片,否则这些失败模式都是不可见的。

本周行动指南

如果你正在运行一个处理动态文档的 RAG 系统——几乎所有的业务 RAG 系统都是如此——那么在本周进行任何架构调整之前,你可以先做一次快速评估。采样你的生产流量,按意图对查询进行分类,并统计其中“增量型(delta-shaped)”查询所占的比例。如果这一比例具有实际意义,请构建一个小的增量评估切片,并在你当前的系统上运行它。然后,请直面结果,不要有任何回避。

能够交付下一代实用 RAG 产品的团队,是那些将检索视为一个具有多种模式的问题空间的团队,而不是将其仅仅视为包装了重排序器的相似度搜索。如果团队继续将“寻找最接近的文本块”作为通用原语,那么其系统的隐性失败率将随着底层文档的变化速率而同步增长。在文档不断变化的业务场景中,这种速率就是助手在回答用户实际提出的问题时的出错率。

References:Let's stay in touch and Follow me for more thoughts and updates