讨论 RAG 升级的时候,GraphRAG 大概率排在候选名单第一行。我也认真评估过它:搭了实验、测了基线、算了一本实现账,最后把它挡在了检索管线外面——并且给这个“不用”预先写好了复开条件。这篇不复盘代码,复盘的是一次“不立项”决策是怎么做出来的。
1. GraphRAG 强在哪:把多跳变成沿边走
先把它到底解决什么问题说清楚,不然“上不上”就是站队。
向量检索的本质,是拿问题文本和文档块算语义相似度。它擅长回答“问题里提到的概念,答案里也提到”的问题。但它有个结构性盲区:多跳问题——答案需要的那个关键实体,根本不在问题文本里。
举个我评测集里的合成例子。这道题相关的语料就两个文档(真实评测集当然更大,这里只展示跟这道题有关的部分):
文档 A《星辰科技·供应商合作档案》 ——片段 A-12: “……星辰科技的国内仓配物流由顺丰速运承接,双方自 2024 年起保持合作,合作范围覆盖仓储与干线运输……”
文档 B《顺丰速运企业介绍》 ——片段 B-03: “……顺丰速运由王卫创立,目前由王卫担任董事长,服务网络覆盖全国……”
现在问: “星辰科技的快递公司老板是谁?”
注意这个问题里没有“顺丰”,也没有“王卫”。而答案要拼两条证据:A-12 告诉你星辰科技的快递公司是顺丰,B-03 告诉你顺丰的老板是王卫。两个片段各自只和问题“一半相关” ——A-12 有快递公司但没有老板,B-03 有老板但通篇没有星辰科技。夹在中间的“顺丰”,就是连接两段证据的桥:先从星辰科技走到顺丰,再从顺丰走到王卫。
桥实体不在问题里,这就是多跳的本质。这道题的 gold 也由此定义:两个片段都拿回来才算对,只拿回一个就是失败——这个定义是后面全部评测设计的基础。
GraphRAG 的思路是把这个“跳”显式化,分两步:离线阶段用 LLM 对文档做实体关系抽取,把语料组织成一张图;检索阶段不再只做一次相似度匹配,而是沿着图的边走——从星辰科技走到顺丰,再从顺丰走到王卫。
三种取回方式放在一起看:
| 方式 | 怎么拿到“顺丰老板” | 依赖什么 |
|---|---|---|
| 向量一次召回 | 拿问题直接搜——搜不到,桥不在问题里 | 语义相似度 |
| 查询分解 | 拆成两个子查询:先查“A 的快递公司”,再把查到的“顺丰”拼进第二个子查询 | 问题可拆解 |
| 图遍历 | 从 A 沿边走到顺丰,再沿边走到老板 | 离线建好的图 |
注意第二行:图不是唯一的走桥方式。查询分解也能走桥,只是把“沿边走”换成了“拆两步问” 。这个伏笔在第四节兑现。
2. 它看起来就是为我设计的
诚实地说,评估开始之前,我是想上 GraphRAG 的。理由看起来都很硬:
- 我的 RAG 管线里确实存在跨文档多跳场景——证据散在多个文档,回答一个问题要跨越它们;
- 检索质量的焦虑是真实的,谁都想在管线里加一层“看起来更强”的东西;
- 顺带地,“用了 GraphRAG”对项目叙事也好看。
诱惑是真实的。所以我给自己立了一条顺序,后来证明它是整个评估里最重要的决定:评估一个检索升级,第一件事不是搭它,是测基线。
逻辑很简单:GraphRAG 的全部收益,建立在一个前提上——“基线在多跳场景拿不回桥”。这个前提是可以直接检验的。先检验它,再决定要不要为图付钱。
3. 先手棋:基线在多跳场景到底缺不缺东西
3.1 基线怎么走桥
我的基线管线是多路召回加融合排序;对复合问题,前面还有一层查询分解。拿上一节那道题走一遍:子查询一,“星辰科技的快递公司是哪家”——和片段 A-12 高度相关,命中;从结果里抽出“顺丰”这个实体,拼进子查询二:“顺丰速运的创始人是谁”——和片段 B-03 高度相关,命中。两次普通的检索,接力走完一条两跳的链。跨文档靠子查询接力,不靠图。
也就是说,第一节表格里的第二行,我的基线是有的。那问题就变成一个纯粹的实验问题:这条接力路径,在我的场景里走得通吗?
3.2 评测集怎么建
要回答“走得通吗”,光靠手感不行,得有一把尺。我的评测集是这么建的:
- 合成语料。语料是自己造的,不是网上扒的——好处是场景完全可控:想让某道题考跨文档跳接,就把证据故意拆进两个文档——第一节那道题就是这么造出来的;每个片段有编号(A-12、B-03),标准答案精确锚定到具体片段。
- 按失败模式分层。整个评测集不是一锅烩,而是按“会怎么失败”分层:常规检索、跨文档多跳、权限、拒答……各自独立成层。GraphRAG 要评估的,只是其中“跨文档多跳”这一层——评估什么技术,就只看它声称能救的那一层,其他层的分数和这个决策无关。
- 每条带 gold。每道题标注三样:标准答案落在哪个片段、关键事实是什么、系统的预期行为是什么。没有 gold 的评测集只是感觉,不是证据。
- 构建脚本校验 + 冻结。校验防手滑——gold 声称答案在 3 号片段,构建脚本就去 3 号片段里验关键事实,验不过直接构建失败;冻结防漂移——评测集任何一个字节变了,前后两次的指标就不可比。尺子本身必须是静止的。
- 两类指标。一类管“有没有”:该拿回的证据,拿没拿回到头部;一类管“全不全”:该拿回的,是不是都拿回来了。“有没有”看排序能力,“全不全”看召回能力——后面的验尸会用到这个区分。
3.3 为什么这个顺序不能反
如果基线在多跳层已经饱和,GraphRAG 的增量空间在数学上就是零——它再强,也强不过“已经拿全了”。如果基线有缺口,那也要先看清楚缺口是什么,才知道图是不是对的药。
先测基线,不是保守,是把“要不要上新技术”从信仰问题变成测量问题。
4. 结果:桥走通了,缺的不是图
结论先行:基线在跨文档层把该拿的全拿回来了——像 A-12 和 B-03 这样的 gold 片段,全部出现在头部命中位置;查询分解的接力路径确实把桥走通了。偶发的召回不全,逐条验尸之后,没有一条的根因是“缺一条关系边”——缺口在排序,不在图的结构。
也就是说:GraphRAG 要解决的“拿不回桥”,我的基线没有这个问题。基线已经把靶场清空了,GraphRAG 连证明自己的机会都没有。
这里有一个很值得记住的推理形状:如果顺序反过来——先搭图、再评测——我会看到什么?指标没变差。然后呢?然后就是最危险的滑坡:“图至少没坏处,留着吧”。为它付出永久的抽取、维护、一致性成本,换一句“没坏处”。 “没坏处”和“该上”之间,隔着一整个决策流程。
5. 就算有增量,还有一本实现账
假设基线真的有缺口、GraphRAG 真能补上,上不上之前还有一本账要算——这些和评测无关,是工程成本:
- 图的构建与新鲜度:实体关系抽取靠 LLM,文档一更新就要重抽;图会漂移,新旧一致性要自己管;
- 索引的存活:图索引放内存,重启就丢,冷启动要重建——文档越多,重建窗口越长;
- 规模天花板:文档规模上去之后,抽取成本和内存占用增长得比检索收益快,这条曲线不可忽略;
- 双写一致性:文档库和图是两个真相源,同步策略又是一个要设计的子系统。
这些不是 GraphRAG 的缺陷,是所有“离线预计算型”方案的共同代价。为一种还不需要的能力,先付一笔永久账单——这才是热门技术最常见的真实价格。
公允起见也要说另一面:有些场景图确实是该上的——基线连子查询都拆不出来的模糊关系跳接、跨海量实体的聚合统计、多关系推理链。判断标准始终是同一个:先有证据说明基线缺,再谈上不上。
6. 不立项,但带着复开条件
决策:不立项。
但这句话不完整,完整版是:不立项,且带复开条件。 复开条件有两条,缺一不可:
- 破线:给“有没有”这个指标预设一条报警线,持续跌破——线的具体数值取决于你的基线水位和重建成本,数值本身不重要,重要的是它必须预先写下来,而不是事后挑一个;
- 验尸:跌破之后逐条确认,缺口类型确实是实体关系跳接——而不是排序退化,不是切片边界,不是语料结构变了。
为什么是两条?只看线:可能只是语料变难了,错怪管线;只验尸:没有报警时机,根本发现不了。线负责“什么时候去看”,验尸负责“看到了是不是它”。
这套东西的本质是:把“不立项”从一个终审判决,改造成一个带监控的搁置。决策错了会自己报警——这比“当时判断对不对”重要得多,因为后者只有天知道,前者是可以设计的。
7. 数字去哪了
细心的话你会发现,这篇没有出现任何具体指标值和样本量。这是刻意的。
那些数值绑定着我的语料分布、切片策略和管线参数,搬到你的环境里不可复现,也不可迁移——引用别人的指标数字,是评测类文章里最容易产生虚假安全感的事。可迁移的只有决策结构本身:分层评测集怎么建、gold 怎么锚、为什么先测基线、复开条件为什么是双门。
所以这篇留给你的是一套可以照着做的流程,不是一组可以引用的结论。真要照着做,你会在你自己的语料上得到你自己的数字——那个数字才是有资格做决策的数字。
8. 收尾
评估到最后,GraphRAG 在我的管线里输给了一个很朴素的实验结论:基线把桥走通了。
下次有人(可能就是未来的我)在会上喊“我们上 GraphRAG 吧”,可以先问一句: “基线在多跳场景上,到底缺什么?” 答得上来,图才值得建;答不上来,先去把尺子造出来。