看起来相关和真正相关是两回事。
RAG是当前的标准
截至2024年,RAG是企业使用LLM最常见的方式。
检索增强生成。 搜索外部文档,塞入上下文,让模型基于此回答。
RAG有效。 它让LLM可以引用从未训练过的内部文档。 它让LLM反映最新的信息。 它显著减少了幻觉。
没有RAG,企业对LLM的采用会慢得多。 RAG是一项值得尊重的技术。
但RAG有根本性的局限。 这些局限不是通过构建更好的RAG来解决的。 它们源于RAG本身的前提。
RAG的工作原理
RAG的核心是三个步骤。
第一步:将文档分割成块。 PDF、wiki、内部文档按固定大小(通常200–500个token)切分。
第二步:将每个块转换成嵌入向量。 一个数百到数千维的实数向量。 文本的"含义"被映射到向量空间中的一个点。
第三步:当查询到来时,找到相似的向量。 查询也被转换为向量。 cosine相似度最高的前5–20个块被选中并插入上下文。
简单而优雅。 而这里隐藏着三个根本性问题。
问题一:相似不等于相关
嵌入相似度衡量的是"两段文本是否在相似的上下文中使用了相似的词"。
这不是相关性。
举例。
查询:“苹果公司2024年第三季度的营收是多少?”
嵌入搜索可能返回的块:
- “苹果公司2024年第三季度营收为949亿美元。"——相关
- “苹果公司2023年第三季度营收为818亿美元。"——相似但时间段不同
- “三星电子2024年第三季度营收为79万亿韩元。"——相似但公司不同
- “一个苹果派大约有296千卡。"——关键词重叠
嵌入相似度无法区分这四者。 在向量空间中,“苹果营收"聚集在一个区域。 无论是2023还是2024,苹果还是三星—— 向量距离无法可靠地区分它们。
加一个重排器能改善。 但重排器同样是阅读和判断自然语言文本, 所以根本性的歧义问题依然存在。
基于语义结构的搜索则不同。 如果"苹果公司"这个实体有唯一标识符, 它永远不会和"苹果"这种水果混淆。 如果"2024年第三季度"是一个时间字段, 它与"2023年第三季度"被机械地区分开。
不需要计算相似度。 匹配还是不匹配?是或否。
问题二:块不是意义的单位
再看RAG的第一步。 “将文档分割成块。”
那个"分割"就是问题所在。
当你把文档分割成500个token的单位时, 意义在中间被切断。 一个段落横跨两个块。 论证的前提和结论被分开了。
“李舜臣在鸣梁海战中以12艘船迎战133艘"在块A中, “学者们对这些数字存在争议"在块B中。 如果查询只检索到块A, 可信度信息在进入上下文时已经丢失了。
把块做大?它们消耗更多窗口。 把块做小?更多上下文被切断。 加重叠?你在重复内容上浪费窗口。
无论怎么调整,根本问题不变。 按token数分割自然语言文本, 就等于按token数分割意义。 意义有其固有的大小, 用不相关的单位去切分它,就会出问题。
在结构化表示中,意义的单位是显式的。 一个谓述就是一条边。 边不会被分割。 搜索在边的层级上操作。 不存在在意义中间切断的问题。
问题三:检索结果的质量无从得知
RAG返回了5个块。 在把这5个放入上下文之前,有几个问题要问。
这条信息的来源是什么? 参考日期是什么? 确定性有多高? 这5个之间是否相互矛盾?
在自然语言块中,这些事情无法得知。
来源可能在块中某处以自然语言的形式被提及,也可能没有。 时间参考可能在文档的某个地方,也可能在分块时被丢失了。 可信度在自然语言中没有结构化的槽位,所以几乎总是缺失的。 矛盾检查需要阅读所有5个块并对它们进行推理。
最终,你不得不把质量判断委托给LLM。 你用RAG来降低LLM调用成本, 但你又调用LLM来验证RAG结果。
在结构化表示中,来源、时间和可信度是字段。 “排除没有来源的陈述"是一行查询。 “排除2023年之前的信息"是一个字段比较。 “排除可信度低于0.5的"是一个数值比较。 不需要LLM调用。
RAG的根本前提
这三个问题的根源是一件事。
RAG以自然语言搜索自然语言。
文档是自然语言。 块是自然语言。 嵌入是自然语言的统计近似。 搜索结果是自然语言。 进入上下文的是自然语言。
自然语言的歧义渗透了整个管道。
搜索不准确,因为你以歧义的形式搜索歧义的内容。 上下文丢失,因为你以与意义无关的大小分割歧义的内容。 验证不可能,因为你无法从歧义的内容中提取质量信息。
大多数改进RAG的尝试都在这个前提内运作。
用更好的嵌入模型。——统计近似更精细了,仅此而已。 用更好的分块策略。——切分位置改善了,仅此而已。 加重排器。——再多读一遍自然语言,仅此而已。 用混合搜索。——混合了关键词和相似度,仅此而已。
所有这些都有效。 所有这些都停留在自然语言的框架内。 没有一个是根本性的。
根本替代方案的条件
要超越RAG的局限,前提必须改变。 不是以自然语言搜索自然语言, 而是以结构化方式搜索结构化表示。
这个替代方案必须满足三个条件。
用匹配而不是相似度搜索。 不是找"看起来相似的东西”, 而是找"匹配的东西”。 标识符是否匹配?是否在时间范围内? 是或否。不是概率。
意义的单位就是搜索的单位。 不是按token数分割, 而是按谓述存储、按谓述搜索。 不存在在意义中间切断的问题。
元数据嵌入在结构中。 不需要调用LLM来判断搜索结果的质量。 来源、时间和可信度是字段, 所以机械过滤是可能的。
当这三个条件满足时, 搜索从"猜测可能的候选” 转变为"确认匹配的内容”。
RAG是一种过渡技术
这不是贬低RAG。
RAG是在一个只有自然语言的世界里最好的答案。 当文档是自然语言,知识以自然语言存储, 而LLM是处理自然语言的工具时, 用自然语言搜索自然语言是显而易见的选择。
而且RAG确实有效。 有RAG的LLM远比没有RAG的准确。 这是事实。
但如果"一个只有自然语言的世界"这个前提改变了, RAG的定位也随之改变。
如果结构化表示存在, RAG变成了"接受自然语言输入并搜索结构化存储"的前端。 自然语言 -> 结构化查询 -> 结构化搜索 -> 结构化结果 -> 上下文。
RAG不会消失。 它的后端改变了。 从嵌入相似度搜索到基于语义结构的搜索。
总结
RAG是当前上下文工程的标准。 它有三个根本性的局限。
- 相似 ≠ 相关。 嵌入相似度不保证相关性。“看起来相似"和"确实相关"是不同的。
- 块 ≠ 意义。 按token数分割会在意义中间切断。前提和结论被分离。可信度信息丢失。
- 质量判断不可能。 检索到的块的来源、时间和可信度无法被机械地确定。判断它们需要LLM调用。
三个问题的根源是一件事。 以自然语言搜索自然语言。
根本替代方案是改变前提。 匹配,而不是相似度。 谓述,而不是token块。 嵌入式元数据,而不是外部判断。
RAG是一种过渡技术。 它是在一个只有自然语言的世界里最好的答案。 当那个前提改变时,RAG的后端也随之改变。