GraphRAG通过构建知识图而非向量堆来处理多跳关系查询,相比传统RAG能回答"A如何与C相关"这类复杂问题。
普通 RAG 会把文档切成若干 chunk,生成 embedding,并在查询时返回向量与问题最接近的少量 chunk。这种方式很适合“查找一个事实”,却完全应付不了“A 与 C 有什么关系?”——因为答案并不存在于任何单独的 chunk 中。它分散在多个 chunk 里,而其中任何一个与问题的相似度都不够高。GraphRAG(Microsoft Research,2024)解决了这个问题:它检索的是知识图谱,而不是一堆文本。下面来看看它是如何工作的。
最近邻检索并不理解“连接”。当你提出一个多跳问题时,每一跳的信息都位于不同的 chunk 中;而那个负责连接 A 与 C 的桥梁 chunk,可能几乎没有与查询相同的词,因此永远不会被检索出来。
这些串联信息根本不在索引的表达能力之内——你能拿到的,只会是那些本身就与问题相似的段落,而一条关系链并不像任何一句你能输入的问题。
在处理任何查询之前,GraphRAG 会额外执行一次索引流程。LLM 读取每一个 chunk,并提取 (实体)–[关系]→(实体) 三元组——将人物、组织、模型等表示为节点,将它们之间的关系表示为边——然后把同一事物的重复提及合并成一个节点。
这种合并正是关键所在:同一个实体即使出现在十份文档中,也会被归并为一个拥有十条边的节点,从而建立起跨文档的连接,而这是扁平 RAG 永远不具备的能力。实体提取只需在建立索引时支付一次成本,而不是每次查询都重新执行。
可以这样理解它的输出:每个 chunk 都会生成类似 (GraphRAG)–[introduced by]→(Microsoft) 和 (Microsoft)–[builds]→(Azure) 的记录。十个分别提到 Microsoft 的 chunk 不再是十条彼此孤立的事实——它们会汇聚到同一个 Microsoft 节点上。于是,GraphRAG 与 Azure 之间突然出现了一条路径,尽管从未有任何一句原文直接写出这层关系。
现在,“A 与 C 有什么关系?”这类问题会转化为一次图遍历。从种子实体出发,沿着边逐步行走,找出连接路径 A→B→C——即使没有任何一个 chunk 曾经同时提到 A 和 C。
答案不是从某个碰巧命中的 chunk 中提取出来的,而是根据路径上的关系重新构建的。这就是“local”查询模式,也是知识图谱真正发挥价值的地方:它可以完成五跳推理,而扁平检索从结构上就不可能把这些信息组装起来。
对于“所有这些内容的主要主题是什么?”这样的宏观问题,单纯遍历图同样不够。因此,索引器会把连接紧密的节点聚类成若干社区,并让 LLM 为每个社区编写一段简短摘要。
随后,“global”查询会对这些社区摘要执行 map-reduce,生成面向整个语料库的答案。固定大小的 chunk 检索无法做到这一点,因为答案关注的是全部内容的整体结构,而不是某个单独段落——根本不存在一个可以与问题“接近”的 chunk。
代价在于成本和新鲜度:GraphRAG 需要预先调用 LLM,对图谱执行提取、合并和摘要;扁平 RAG 则只需生成 embedding 并存储。当文档发生变化时,GraphRAG 的重新索引也更加繁重。
作为回报,它能回答扁平 RAG 最不擅长的两类问题——多跳关系和全局综合——同时仍然可以处理简单的局部查询。与其说 GraphRAG 是 vector RAG 的替代品,不如说它是在后者之上增加关联能力的一层。许多系统会同时保留两者,并根据问题类型进行路由:简单查询继续使用扁平检索,需要串联线索或理解全局的问题则交给知识图谱。
扁平 RAG 检索的是与问题相似的段落。GraphRAG 检索的是问题所提及事物之间的关系。
这就是两者最核心的区别。也正因如此,在演示中,一个五跳答案可以沿着图谱路径逐步亮起;而面对完全相同的语料库,扁平 RAG 只能返回最近的 chunk,并对其中没有包含的部分束手无策。
观看系统如何根据六份文档构建图谱,然后运行一次五跳查询,点亮一条扁平 RAG 无法看到的路径:
https://dev48v.infy.uk/ai/days/day52-graphrag.html
如需采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。