知识图谱 RAG:用图结构增强检索与推理
检索增强生成(Retrieval-Augmented Generation,简称 RAG)通过把外部知识检索进上下文来缓解大模型的幻觉、知识过期与不可追溯问题。但在面对需要跨文档串联信息的复杂问题时,仅靠向量相似度检索往往力不从心。知识图谱 RAG 把实体与关系显式组织成图,让检索从「找片段」升级为「沿关系游走」,从而更好地支撑多跳推理,并给出可追溯的证据链。
本文先说明朴素 RAG 的短板,再介绍知识图谱基础、图谱 RAG 的整体流程、微软 GraphRAG 这一代表方案,最后对比向量 RAG 的取舍并梳理开源生态。
为什么朴素 RAG 在多跳问答上吃力
朴素 RAG 的检索环节通常是这样的:把文档切分为若干文本块,用嵌入模型转成向量存入向量库;用户提问时,取语义最相近的若干块喂给大模型。这种方式在「单跳」事实型问题(例如「A 是谁」)上表现不错,但遇到多跳问题时会暴露三个弱点。
第一,语义近邻不等于逻辑相连。多跳问题的答案分散在多个文档中,关键实体之间靠关系而非字面相似度相连。向量检索容易召回表面相似却无关的文本块,漏掉真正有用的那一跳。
第二,缺乏全局视角。朴素 RAG 一次只看若干个局部片段,难以回答「数据集中反复出现的核心主题是什么」这类全局归纳问题,因为这本质上是一个对整个语料做摘要的任务。
第三,推理过程不可追溯。即使模型勉强拼出答案,也难以说明「是依据哪几条关系推出的」,可解释性与审计性较弱。
知识图谱 RAG 的核心思路,正是用图结构弥补上述缺口:把实体、关系、属性建为图,让检索沿边扩展,并让生成阶段能够引用明确的证据路径。
知识图谱基础(实体、关系、子图)
知识图谱由三类要素构成。
- 实体(Entity):现实世界中的对象,例如「公司」「人物」「药物」「疾病」。在图中表现为节点。
- 关系(Relation):实体之间的有向关联,例如「研发」「任职于」「治疗」。在图中表现为带类型的边。
- 属性(Attribute):实体或关系的附属信息,例如「成立年份」「剂量」。
把这些要素组织起来后,一个三元组(头实体,关系,尾实体)便成了一条基本事实,例如(阿司匹林,治疗,头痛)。多条三元组相连,就构成一张图。
在此基础上,子图(Subgraph)是图检索的关键单元:它是围绕若干中心实体、沿关系扩展出来的一片局部图。相比孤立的文本块,子图天然携带了实体之间的结构信息,更适合作为多跳问答的上下文。
(阿司匹林) -[治疗]-> (头痛)
|
[成分]
|
(水杨酸)
上图展示了一个极简子图:阿司匹林通过「治疗」关系连到头痛,通过「成分」关系连到水杨酸。当问题涉及「阿司匹林相关成分能缓解哪些症状」时,沿这两条边即可完成两跳推理。
图谱 RAG 流程(抽取、建图、检索、生成)
知识图谱 RAG 通常分为四个阶段:抽取、建图、检索、生成。
抽取
从原始文档中抽取实体与关系。传统做法依赖命名实体识别与关系抽取模型,当前更常见的做法是用大模型按指定 schema 直接产出结构化三元组。
extract_prompt = """从下面的文本中抽取实体与关系,输出 JSON 列表,
每个元素形如 {"head": 头实体, "relation": 关系, "tail": 尾实体}。
只输出可验证的事实,不要编造。
文本:
{text}
"""
def extract_triples(text, llm):
resp = llm.chat(extract_prompt.format(text=text))
return parse_json_list(resp)
抽取质量直接决定图谱上限,因此需要约束 schema、做去重与实体消歧(把指代同一对象的「苹果公司」「Apple」归并)。
建图
把三元组写入图存储,得到可查询的知识图谱。生产环境多用图数据库(如 Neo4j),原型阶段可用 NetworkX 等内存图库。建图阶段通常还会做社区划分,把联系紧密的实体聚成簇,为后续的全局摘要做准备。
检索
检索不再只取向量近邻,而是结合多种策略:
- 实体链接:先识别问题中的实体,定位图节点。
- 子图扩展:沿关系游走出 k 跳邻居,得到相关子图。
- 向量辅助:对节点描述做语义检索,补足图谱未覆盖的内容。
- 社区摘要召回:在全局问题上,直接调用预先生成的社区摘要。
生成
把检索到的子图与原文片段整理为上下文,连同问题一起交给大模型生成答案,并在答案中标注所依据的三元组或关系路径,提升可解释性。
代表方案:微软 GraphRAG
微软提出的 GraphRAG(见论文 From Local to Global: A Graph RAG Approach to Query-Focused Summarization,arXiv:2404.16130)是图谱 RAG 的代表性实现,其开源仓库位于 github.com/microsoft/graphrag。
它的核心流程分为两步建图与两类查询。
第一步,用大模型从源文档中抽取实体知识图谱,得到节点与边。第二步,对图中联系紧密的实体群做社区划分(借助 Leiden 等图聚类算法),并为每个社区预生成一份社区摘要。
查询时分为两种模式:
- 局部搜索(Local Search):针对具体实体,把相关子图与原文片段结合回答,适合「某实体的细节」类问题。
- 全局搜索(Global Search):针对整个语料的全局问题,让每个社区摘要各自生成部分回答,再汇总成最终答案,适合「数据集的主题是什么」这类归纳式问题。
论文在约一百万 token 规模的语料上验证:相较于传统 RAG,GraphRAG 在回答的完备性与多样性上均有显著提升,尤其在全局意义上理解问题上优势明显。
与向量 RAG 的对比与取舍
两者并非互相取代,而是互补。下面给出取舍参考。
| 维度 | 向量 RAG | 知识图谱 RAG |
|---|---|---|
| 多跳推理 | 较弱,靠片段相似度 | 较强,可沿关系游走 |
| 全局归纳问题 | 不擅长 | 擅长(社区摘要) |
| 可解释性 | 弱,难以追溯 | 强,可给出证据路径 |
| 构建成本 | 低,切块加嵌入即可 | 高,需抽取、建图、消歧 |
| 维护成本 | 较低 | 较高,图谱需持续更新 |
| 适用数据 | 非结构化文本为主 | 实体关系明确、需串联的数据 |
实践中的常见策略是混合架构:用向量 RAG 兜底开放域召回,用知识图谱 RAG 承担多跳与全局问题,并把图谱证据作为答案的引用来源。
开源生态(Neo4j、NetworkX)
图谱 RAG 的落地依赖成熟的图工具链。
- Neo4j:主流的图数据库,提供 Cypher 查询语言与图算法库,支持实体链接、子图查询与社区检测,是生产级图谱 RAG 的常用底座。其官方站点(neo4j.com)也提供 GraphRAG 相关教程与白皮书。
- NetworkX:Python 生态中的轻量图分析库,适合在原型阶段做抽取、建图与社区划分,无需部署数据库。
- 微软 GraphRAG:前文提及的端到端框架,封装了抽取、建图、社区摘要与两类查询。
- LangChain / LlamaIndex:提供了图检索器与向量检索器的集成接口,便于把图谱 RAG 接入既有 RAG 管线。
一个用 NetworkX 做子图扩展的示例:
import networkx as nx
G = nx.DiGraph()
G.add_edge("阿司匹林", "头痛", relation="治疗")
G.add_edge("阿司匹林", "水杨酸", relation="成分")
# 取两跳邻居作为相关子图
sub = nx.ego_graph(G, "阿司匹林", radius=2)
print(list(sub.edges(data=True)))
小结
朴素 RAG 在单跳事实检索上简单有效,却难以应对需要跨文档串联的多跳问题与全局归纳问题。知识图谱 RAG 用实体、关系、子图把知识结构化,使检索可以沿关系游走、生成可以引用明确证据,从而提升多跳推理能力与可解释性。微软 GraphRAG 通过「建图加社区摘要」的两段式设计,在局部与全局两类查询上均有优势。落地时应结合向量 RAG 做混合检索,并依据数据特征在 Neo4j、NetworkX 等工具间权衡成本与规模。
参考与延伸阅读
- Edge D., Trinh H., Cheng N. 等。From Local to Global: A Graph RAG Approach to Query-Focused Summarization。arXiv:2404.16130(2024)。https://arxiv.org/abs/2404.16130
- Microsoft。GraphRAG 开源仓库。https://github.com/microsoft/graphrag
- Gao Y., Xiong Y., Gao X. 等。Retrieval-Augmented Generation for Large Language Models: A Survey。arXiv:2312.10997(2023)。https://arxiv.org/abs/2312.10997
- Neo4j。图数据库与 GraphRAG 官方资料。https://neo4j.com