← 返回 关于

你的 RAG 做错了

2026-05-15 · 原文链接

有一种新方法可以:

而且它不需要改动你的检索算法、重排器或嵌入模型。它修复的是更上游、几乎没人检查的东西。

每条 RAG 管线一开始都有同一个假设:一段文本 chunk 是适合嵌入的知识单元。

这个假设几乎从未被审视。

而它正是大多数检索失败的源头;人们却总想在下游修补这些失败。

为什么 Chunk 是糟糕的单元

一段文本 chunk 是结构中性的容器。它不知道:

由于 chunk 没有观点边界,切分器会在 token 数用尽的地方直接切断。

于是你可能检索到半张表、一个没有论证的结论,或一句被剥离上下文后才显得成立的主张。模型无法知道缺了什么。

版本问题同样严重。

大多数企业语料库中,同一份文档会以十几个几乎相同的版本散落在 SharePoint、Confluence 和 Git 里。

Top-K 检索会返回同一段落的五个副本,当前版本和废弃版本混在一起。LLM 会把它们融合成一个自信但错误的答案。

由于 chunk 本身也不携带元数据,数据内部没有地方绑定访问控制。

角色过滤器、版本状态、权限级别:所有这些最终都会变成外挂在 orchestrator 上的逻辑,与它本应治理的内容相脱节。

LangChain、LlamaIndex 和 Haystack 都位于这一切之上。它们只是从你放进向量库的内容里编排检索。

大多数技术栈在文档解析器和向量库之间什么都没有。

三个问题正是在这个空隙里叠加起来的。

更好的单元:问答包

chunk 之所以失败,是因为它在结构上不可知。修复方式,是让知识单元在结构上显式。

不要嵌入一段散文窗口,而是嵌入一个主张:一个问题、它经过验证的答案,以及作为类型化 schema 的治理字段。

每个单元只放一个事实,不多放。

你的查询本来就是问题。当索引存储的是问题的答案时,匹配就变成结构性的,而不只是语义性的。

你不再期待正确段落刚好浮到顶部。你是在把一个问题直接匹配到它的答案。

Blockify 是 Iternal Technologies 的一个预处理层,它把这种结构实现为 IdeaBlock:一个问题、经过验证的答案,以及权限级别、版本状态、来源等类型化治理字段,全都放在同一个对象上。

它映射的是用户实际查询 RAG 系统的方式:以问题形式查询。

关键洞见是:当你嵌入的是问答包,而不是文本窗口时,你的 embedding 表示的是一个单一的原子主张,而不是一段恰好包含它的叙事。

这会在向量几何上产生可衡量的后果。

在 Blockify 基于 17 份文档、298 页内容的内部基准中,从查询到最佳匹配 block 的平均余弦距离,IdeaBlocks 为 0.1585,朴素 chunks 为 0.3624。

这意味着检索距离降低了 2.29 倍。

反直觉发现:数据更少,准确率更高

大多数人会以为缩小语料库会损害检索。

语义蒸馏中的实际情况不是这样。

在 Blockify 的内部基准中,管线从源文档生成了 2,042 个原始 IdeaBlocks。

在 3 到 5 轮、80% 到 85% 相似度阈值的迭代去重之后:

冗余副本之所以伤害而不是帮助,是因为同一段落的十五个近似副本,会在 embedding 空间的同一区域制造十五个相互竞争的向量。

检索会把概率质量分散到它们身上,拉低规范版本的匹配分数。把它们折叠成一个规范 block,信号就会变得更清晰。

你的向量索引不是一块要尽量塞满的硬盘。它是一个检索表面,冗余会劣化它。

管线:从文档到 IdeaBlocks

修复方式,是在任何内容进入向量库之前,先运行一条预处理管线。

Blockify 的处理分为七个阶段。每个阶段都有明确的输入和输出,因此故障可以被定位,也可以复现。

阶段 1:界定范围

在解析任何文档之前,你先定义索引层级:组织 > 业务单元 > 产品 > 角色。

这会决定哪些 block 被标记到哪个访问层级,也会影响后续去重的方式。

阶段 2:摄取

文档可以以 DOCX、PDF、PPT、PNG/JPG、Markdown 或 HTML 形式进入。

解析器将内容交给 LLM 层,运行微调过的 LLaMA 3 / QWEN 3.5 / Gemma4(以及其他自定义基础模型变体),把原始 chunks 转换成草稿 IdeaBlocks:一个关键问题、一个两到三句话的经过验证的答案,以及类型化治理字段。

输入大小限制在 1,000 到 4,000 个字符之间,实际中点约为 2,000。

阶段 3:切分与抽取

上下文感知切分意味着,LLM 会把 chunks 转换成草稿 IdeaBlocks,而不是只按 token 数切断。每个 chunk 的输出是一组问答对,而不是一段文本窗口。

阶段 4:语义去重

这一步清理的是检索表面。

Blocks 会以 80% 到 85% 的余弦相似度阈值聚类,并迭代三到五轮。

近似重复项会通过第二个专门调优的 LLM 合并成单一规范 block。该管线针对 GPU 优化,但也可以通过 Intel Xeon 优化版本在额外 CPU 容量上运行。

最终得到的数据集中,索引中的每个向量都代表一个不同主张,而不是十五个几乎相同、争夺同一检索位置的副本之一。

阶段 5:自动标注

每个 block 都会获得类型化元数据:权限级别(PUBLIC、INTERNAL、CONFIDENTIAL、SECRET)、版本状态(Current、Deprecated、Draft、Approved)、产品线、出口管制标记和数据隐私标签。这些由管线应用,而不是由文档作者手动添加。

阶段 6:人工验证

一个包含 2,000 到 3,000 个 IdeaBlocks 的产品语料库,会分给 5 到 10 位 SME,每人每季度花 1 到 2 小时验证自己负责的部分。验证对象是附有来源引用的结构化主张,而不是原始文档。

阶段 7:导出

经过验证的 blocks 会通过 API 推送到向量数据库,或导出为 JSON-L。支持的向量存储包括 Azure AI Search、Pinecone、Milvus、Vertex Matching Engine。支持的 embedding 模型包括 OpenAI、Bedrock、Mistral、Jina 和开源模型。

无论使用哪种组合,这条管线都位于文档解析器和向量库之间。

应用层会发生什么变化

你嵌入的单元决定了应用层能做什么。

架构并不改变你的查询方式。它改变的是你能对答案信任到什么程度。

底层原则

chunk 原本只是解析便利,后来却变成了检索假设。

它没有观点边界、版本上下文或访问状态。多年来,检索技术栈一直在修补这种错配:重排器、混合搜索、阈值调优、提示工程。

但所有这些都位于真正问题的下游。

修复方式不是更好的检索算法,而是更好的单元。

RAG 技术栈开始在解析和向量化之间长出一层蒸馏层,就像 Web 技术栈曾在源站和浏览器之间长出 CDN 层一样。

你可以用聚类、基于 LLM 的摘要和 schema 约束自己构建它。也可以使用像 Blockify 这样为此专门设计的工具。

无论哪种方式,把 chunk 当作单元这一假设才是 bug;在数据层修复它,比调整检索本身更划算。

它是开源的!

在这里自己试试 →

感谢阅读!

如果你觉得有启发,欢迎转发给你的网络。

找到我 → @akshay_pachaar ✔️

获取更多关于 LLM、AI Agents 和机器学习的洞见与教程。