实体感知RAG——UnWeaver,不建知识图谱,VectorRAG加一层实体索引就能打赢GraphRAG
最近在整理 RAG 相关的资料,一直绕不开一个老问题:VectorRAG 简单但检索太糙,GraphRAG 精细但重得离谱,到底该选哪个?
直到看到三星 AI 中心华沙团队(Samsung Labs)的一篇论文,标题就很有意思——《UnWeaving the knots of GraphRAG -- turns out VectorRAG is almost enough》,大意是"解开 GraphRAG 的结,原来 VectorRAG 就差不多够了"。他们提出的 UnWeaver 给了第三种答案:不建图,只拆实体。
因此,这篇就来把 UnWeaver 的思路捋一遍,顺便聊聊它的实验数据该怎么看。
一、RAG 的两难:VectorRAG 太糙,GraphRAG 太重
1. VectorRAG:一个 chunk 一个向量,信息被稀释
我们都知道,VectorRAG 的套路是把文档切成固定长度的 chunk,每个 chunk 做一次向量嵌入,查询时按相似度召回。
问题在于,一个 chunk 里往往混着好几个主题、好几个实体。比如一段产品手册,前半段讲蓝牙配对,后半段讲电池保养,最后压成一个向量,两边的信息都被对方稀释了。
这会带来两个后果:
- 召回的 chunk 里夹带大量和问题无关的内容,噪声大,容易引发幻觉;
- 多跳问答吃力。答案需要的信息散在好几个 chunk 里,单靠向量相似度很难一次都捞回来。
2. GraphRAG:效果不一定好,成本一定高
GraphRAG 走了另一个极端:把文本拆成"实体-关系-实体"三元组,建一张完整的知识图谱,再通过图遍历、子图匹配来检索。
思路没毛病,但落地门槛很高。索引阶段要做实体识别、关系抽取、实体链接、社区发现、集群摘要等一长串步骤;检索阶段没法复用成熟的 ANN 向量搜索,得定制图查询,甚至上图数据库。
更扎心的是,投入这么大,效果却不一定对得上。后面的实验数据会看到,GraphRAG 在几个基准上连最基础的 VectorRAG 都没打过。
那么问题就来了:能不能只拿 GraphRAG 的好处(实体级的细粒度表示),而不要它的图结构和高昂成本?
二、UnWeaver 是什么
论文摘要里有一句话点出了核心:
UnWeaver disentangles the contents of the documents into entities.
简单的说,UnWeaver 不在 chunk 层面检索,而是先把文档内容拆解(disentangle)成一个个实体,一个实体可以出现在多个 chunk 里;查询时先找实体,再通过实体把原始 chunk 找回来。
这样做有两个好处:检索的粒度细到了实体级别,而最终喂给 LLM 的仍然是原文 chunk,没有经过摘要改写,对原文是忠实的。
它和 GraphRAG 最大的区别是:只抽实体,不建模实体之间的关系。没有图,自然也就没有图遍历。
三、两阶段架构
UnWeaver 分为离线索引和在线查询两个阶段,整体上是在现有 VectorRAG 技术栈上"多加一步"。
1. 离线索引:拆实体,再聚合
原始文档
└─ 文档分块(固定长度 chunk,和普通 VectorRAG 一样)
└─ 实体提取(LLM 从每个 chunk 中提取实体及其在该 chunk 里的描述)
└─ 实体聚合(同名实体归为一类,拼接它在各个 chunk 中的描述)
└─ 双索引构建
├─ 实体向量库(对聚合后的实体描述做嵌入)
└─ 实体-chunk 映射矩阵(二进制矩阵,记录每个实体出现在哪些 chunk)
可以看到,前面的分块和普通 VectorRAG 完全一致,多出来的是后面三步。
这里有两个细节值得说一下。
第一,实体提取只看单个 chunk,没有跨 chunk 的依赖。这意味着这一步可以完全并行,也不用像 GraphRAG 那样做复杂的实体链接、关系抽取。
第二,实体聚合是整个方案的精髓。同一个实体的信息可能散落在几十个 chunk 里,每个 chunk 只讲了它的一个侧面。把这些描述拼起来再做嵌入,相当于给这个实体画了一张完整的画像,核心信息被放大,无关噪声被过滤,这个向量自然比"混了一堆主题的 chunk 向量"要准得多。
还是拿产品手册举例。"蓝牙模块"这个实体可能在第 3、17、42 个 chunk 里分别讲了配对、功耗、故障排查。聚合之后,"蓝牙模块"的向量就只代表蓝牙模块本身,不会再被电池保养之类的内容干扰。
2. 在线查询:零图操作
用户查询
└─ 向量嵌入 → 在实体向量库中做 Top-K 检索(找到最相关的实体)
└─ 通过实体-chunk 映射矩阵,拿到这些实体关联的 chunk
└─ 投票机制筛选出 Top-N chunk
└─ 把 chunk 作为上下文 → LLM 生成答案
全程没有任何图遍历、子图匹配,只比纯 VectorRAG 多了一步"实体 → chunk"的映射。
投票这一步可以这样理解:Top-K 个实体各自指向若干 chunk,被越多相关实体同时指向的 chunk,越可能是答案所在。下面是我按这个思路写的一段示意代码,帮助理解映射矩阵和投票是怎么配合的:
import numpy as np
# 实体-chunk 映射矩阵:行是实体,列是 chunk,1 表示该实体出现在该 chunk 中
# 这里假设 4 个实体、6 个 chunk
entity_chunk = np.array([
[1, 0, 1, 0, 0, 1], # 实体0:蓝牙模块
[0, 1, 1, 0, 0, 0], # 实体1:配对模式
[0, 0, 1, 1, 0, 1], # 实体2:指示灯
[0, 0, 0, 0, 1, 0], # 实体3:电池
])
def retrieve_chunks(top_k_entities: list[int], top_n: int) -> list[int]:
# 取出命中实体对应的行,按列求和,得到每个 chunk 的票数
votes = entity_chunk[top_k_entities].sum(axis=0)
# 按票数从高到低排序,取前 N 个 chunk
ranked = np.argsort(-votes)
return [int(i) for i in ranked[:top_n] if votes[i] > 0]
# 假设查询"蓝牙配对时指示灯怎么闪",在实体向量库里命中了实体 0、1、2
print(retrieve_chunks([0, 1, 2], top_n=2)) # [2, 5]
可以看到,chunk 2 同时被三个实体指向,票数最高,排在第一位;chunk 5 被"蓝牙模块"和"指示灯"指向,排第二;而只和"电池"相关的 chunk 4 根本不会被召回。
注意:这段代码只是用来说明思路的示意,论文中投票的具体打分规则(是否按实体相似度加权等)请以原论文和官方开源实现为准。
这个映射矩阵还顺带带来一个好处:可解释性。我们能明确知道是哪几个实体召回了哪些 chunk,而纯 VectorRAG 只能告诉你"这两个向量的余弦相似度是 0.83"。在金融、法律、医疗这类对合规要求高的场景,这一点本身就很有价值。
四、实验数据怎么看
论文在 RAGBench 的三个数据集(COVID-QA、eManual、Tech-QA)上,对比了 UnWeaver、VectorRAG、RAPTOR 和 GraphRAG:
| 数据集 | 方法 | 事实正确性 FC(μ↑) | 索引 LLM Tokens(k) | 查询 LLM Tokens(k) |
|---|---|---|---|---|
| COVID-QA | UnWeaver | 0.3823 | 1466 | 994 |
| VectorRAG | 0.3790 | - | 922 | |
| RAPTOR | 0.3643 | 770 | 2649 | |
| GraphRAG | 0.3092 | 25882 | 7051 | |
| eManual | UnWeaver | 0.4811 | 98 | 940 |
| VectorRAG | 0.4793 | - | 343 | |
| RAPTOR | 0.4466 | 57 | 1177 | |
| GraphRAG | 0.3424 | 1428 | 3266 | |
| Tech-QA | UnWeaver | 0.3135 | 3747 | 2384 |
| VectorRAG | 0.3218 | - | 2354 | |
| GraphRAG | 0.2847 | 49270 | 5944 |
先说一下 FC 这个指标。FC 衡量的是答案里的声明有多少能被检索到的上下文支撑,即 被上下文支持的声明数 / 答案总声明数。值越高,说明 LLM 越是"照着资料回答",而不是靠自己的参数知识瞎编。
这张表我看下来有几点体会。
第一,GraphRAG 在三个数据集上都输给了 VectorRAG。这其实是论文标题想说的事:VectorRAG 已经差不多够了,花大力气建图并没有换来对等的回报。
第二,UnWeaver 相比 VectorRAG 的提升其实很小。COVID-QA 上是 0.3823 对 0.3790,eManual 上是 0.4811 对 0.4793,Tech-QA 上甚至还略输一点。所以网上一些"吊打""碾压"的说法要打个折扣,它打赢的是 GraphRAG,和 VectorRAG 基本是同一水平。
第三,和 GraphRAG 比,索引成本是断崖式下降。按表里的数字算,GraphRAG 的索引 Token 消耗是 UnWeaver 的 13~18 倍(Tech-QA 约 13 倍,eManual 约 15 倍,COVID-QA 约 18 倍)。查询阶段 GraphRAG 也要高出好几倍。
第四,查询成本并不是"零代价"。COVID-QA 和 Tech-QA 上,UnWeaver 的查询 Token 和 VectorRAG 几乎一样;但 eManual 上是 940k 对 343k,接近 3 倍。召回的上下文更完整,喂给 LLM 的东西自然也更多,这一点要心里有数。
五、为什么不建图也行
UnWeaver 这篇论文最有意思的地方,不在于它本身有多强,而在于它戳破了一个认知:GraphRAG 真正有用的是"实体级的信息拆解",而不是"图结构"本身。
UnWeaver 没有定义任何实体关系,没有做任何图遍历,只是把实体从 chunk 里拆出来、把跨 chunk 的描述聚合起来,就拿到了细粒度、低噪声、天然聚合多处信息这几个好处。由本例不难发现,图在大多数 QA 场景里更像是一层昂贵的包装。
从工程角度看,这个方案也很友好。向量库、Embedding 模型、ANN 检索都是现成的,离线索引多跑一个实体提取和聚合,再维护一个映射矩阵就行,不需要引入图数据库这种新组件。
六、我的一些顾虑
当然,它也不是银弹。结合论文的实验设置,我想到几个落地前需要考虑的点:
- 语言覆盖:RAGBench 是英文数据集,中文场景下"同名实体归为一类"这一步会不会更难(同一个东西多种叫法、简称、中英混用),需要自己验证;
- 上游依赖:整个方案建立在 LLM 实体提取的质量上,提取错了、漏了,错误会直接传到索引层;
- 增量更新:实体聚合是全局的,文档频繁变动时,某个实体的聚合描述和向量要跟着重算,这部分成本需要单独评估。
所以我的看法是:如果现在用的是 VectorRAG,效果还过得去,UnWeaver 是一个低成本、值得试一试的增强方向;如果正打算上 GraphRAG,不妨先拿 UnWeaver 这种"只拆实体"的方案做个对照,很可能就够了。
总结
- VectorRAG 的问题是 chunk 粒度太粗,向量被无关内容稀释;GraphRAG 粒度够细,但工程复杂、成本极高,效果还不一定好;
- UnWeaver 的核心是不建图,只拆实体:单 chunk 提取实体 → 跨 chunk 聚合描述 → 实体向量库 + 实体-chunk 映射矩阵;
- 查询时先检索实体,再通过映射矩阵投票选出 chunk,全程零图操作,结果可解释;
- 实验上 UnWeaver 和 VectorRAG 基本持平,明显优于 GraphRAG,索引 Token 只有 GraphRAG 的十几分之一;
- GraphRAG 的价值在实体拆解,不在图结构本身。
相关资料
论文:UnWeaving the knots of GraphRAG -- turns out VectorRAG is almost enough(Samsung Labs,arXiv:2603.29875)
开源实现:SamsungLabs/UnWeaver