GraphRAG 检索增强+图模型
往期的NaiveRAG基本都是显式检索,而GraphRAG通过知识图谱增强了总结能力。
1 引入
RAG的向量查询可以如下归纳:


- 索引阶段:文档先进行分块(可以划分成统一大小的512token块,也可以根据语义按句子划分,如spaCy),然后通过某种Embedding方式(普通的Embedding Layer、又或者是BERT类型的Transformer Encoder)转化成嵌入向量,创建某种便于索引的数据结构(普通的哈希表、K-D树、局部敏感哈希等)。
- 检索阶段:这里有很多种检索策略,传统的的包括SQL查询、关键词匹配,流行的方法则是结合元数据过滤的相似度查询等。
- 生成阶段:检索到的数据会进行排序(最近邻搜索),然后结合用户的输入,送进LLM生成答案并打分,最后选择打分最高的输出。
通常意义上,RAG的作用是从外部知识源中检索相关信息,使LLM能够回答有关私有或以前未见过的文档集合的问题。对于显式的检索任务,RAG表现优异;但是对于例如“数据集中主要的主题是什么?”这类问题,由于这是一个全局性问题,一般的RAG通常表现不佳。
因此,RAG应该分成两种:一种是具备查询向量功能的RAG,另一种是具备查询摘要能力的RAG。
GraphRAG属于后者,使用LLM在两个阶段构建基于图的文本索引:首先从源文档中提取实体知识图谱,然后使用社区检测方法为所有密切相关的实体群体预生成社区总结。
2 流程管道

面向领域的总结指的是根据特定的领域的要求,使用适应该领域的提示词和方法,从文档中提取和生成高度相关且有意义的总结信息。协变量指的是协因变量变的量,在这里指的是实体节点或关系边相关联的额外属性,属于包含在摘要中的信息。
在编程中,协变体现了子类的扩展性,允许子类型替换父类型,通常用于返回类型(A=B,G(A)=G(B));逆变体现了子类的继承性,允许父类型替换子类型,通常用于参数类型(A=B,G(B)=G(A))。
2.1 Source Documents → Text Chunks
一个基本的设计决策是确定从源文档提取的输入文本应以何种粒度分割为文本块以便处理。在接下来的步骤中,每个文本块将传递给一组LLM提示,用于提取图索引的各种元素。
这一步输入原文档,输出文本块。
2.2 Text Chunks → Element Instances
基本要求是识别并提取每个源文本块中的图节点和边的实例。作者使用一个多部分的LLM提示,首先识别文本中的所有实体,包括它们的名称、类型和描述,然后识别所有明确相关实体之间的关系,包括源实体和目标实体及其关系的描述。这两类元素实例都输出为一个包含分隔元组的列表。
这一步输入文本块,输出图节点和边的实例列表。
2.3 Element Instances → Element Summaries
对前一步列表中每个图元素(如实体节点、关系边和协变量)创建独立而有意义的摘要。接下来的RAG检索到的文档信息实际上就用这个摘要替代原本信息。
这一步输入实例列表,输出每个实例元素的摘要。
2.4 Element Summaries → Graph Communities
在前一步中创建的索引可以建模为一个同质无向加权图,其中实体节点通过关系边连接,边的权重表示检测到的关系实例的归一化计数。给定这样的图,可以使用各种社区检测算法将图划分为社区,这些社区中的节点彼此之间的连接比与图中其他节点的连接更强。作者使用Leiden算法,因为它能够高效地恢复大规模图的层次社区结构。这个层次结构的每个级别都提供了一个社区划分,以互斥且全面覆盖的方式覆盖图的所有节点,从而实现分而治之的全局总结。
Leiden算法流程
- 初始分配
- 将每个节点分配到一个独立的社区,每个节点自成一个社区。
- 局部节点移动
- 对每个节点,尝试将其移入相邻节点所属的社区,条件是这种移动会提升质量函数。
- 重复上述过程,直到没有节点可以被移动以进一步提升质量函数。
- 精细化
- 将原有社区划分中的每个社区内部再分为多个连通部分。
- 合并这些连通部分,以获得更细粒度的社区划分。
- 聚合社区
- 将每个社区视为一个元节点,构建一个新的网络:
- 元节点之间的边权重等于其对应社区之间所有边的权重总和。
- 自环的权重表示社区内部的连接强度。
- 重复迭代
- 在新的网络上,重复步骤2到4,直到没有进一步改进质量函数的可能。
- 每次迭代都会减少网络的规模,生成一个更高层级的社区网络。
- 收敛与输出
- 当进一步的社区划分不再提升质量函数时,算法终止。
- 输出最终的社区结构。

这一步输入的是基于前一步创建的同质无向加权图,输出社区划分后的结构图。
2.5 Graph Communities → Community Summaries
下一步是为Leiden层次结构中的每个社区创建类似报告的摘要,这种方法设计用于扩展到非常大的数据集。这些摘要本身就有独立的价值,可以用于理解数据集的整体结构和语义,甚至可以在没有具体问题的情况下,用于解析语料库。例如,用户可以浏览某一层级的社区摘要以寻找感兴趣的主题,然后跟随链接查看更低层级的报告,以获取每个子主题的详细信息。然而,这里我们专注于它们作为基于图的索引的一部分,用于回答全局查询的实用性。
社区摘要的生成方式如下:
-
叶节点层级社区(如C3层级):叶节点层级社区的元素摘要(节点、边、协变量)按照优先级依次添加到LLM上下文窗口中,直到达到token限制。优先级如下:对于每个社区边缘,根据源节点和目标节点的综合度(即总体重要性)递减排序,依次添加源节点、目标节点、关联协变量和边缘本身的描述。
-
高层级社区(如C0层级):如果所有元素摘要都能在上下文窗口的token限制内,则按照叶节点层级社区的方式处理并总结社区内的所有元素摘要。否则,按照元素摘要token数量递减顺序对子社区进行排序,并迭代地用子社区摘要(较短)替换其关联的元素摘要(较长),直到符合上下文窗口的限制。
这一步输入的是社区结构图,输出各个层级的社区摘要。
2.6 Community Summaries → Community Answers → Global Answer
以上步骤以图结构事先存储,实际用户查询时只需要查询合适的(C0,C1,C2,C3层级)节点和关系,以及社区摘要。
步骤是随机打乱并分块前一步的社区摘要(同一个社区摘要被放进不同块中);使用LLM为每个加上用户输入的块生成中间答案,给出帮助评分;按评分排序中间答案,选取最高评分答案作为全局答案。
这一步输入的是用户提问和社区摘要,输出全局答案。
3 评价标准
作者使用LLM评估器进行的对头比较指标如下:
- 全面性(Comprehensiveness):答案在多大程度上提供了足够的细节来覆盖问题的所有方面和细节?
- 多样性(Diversity):答案在提供不同观点和见解方面有多丰富和多样?
- 赋能性(Empowerment):答案在多大程度上帮助读者理解主题并做出明智的判断?
- 直接性(Directness):答案在多大程度上具体而清晰地回答了问题?
实验结果如下(数字代表横行胜过纵列的百分比):

这里的TS指的是2.6节打乱分块用的不是社区摘要,而是源文本;SS指的是NaiveRAG。
需要注意的是,尽管如QFS的总结性问题使用GraphRAG摘要查询效果远远胜过NaiveRAG,但是面对针对性查询仍然是NaiveRAG的向量查询更好。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!