首页 > 教程攻略 > ai资讯 >深入Microsoft GraphRAG之索引阶段:原理、测试及如何集成到Neo4j图数据库

深入Microsoft GraphRAG之索引阶段:原理、测试及如何集成到Neo4j图数据库

来源:互联网 时间:2026-08-22 14:13:45

我们已经了解了基于知识图谱的RAG应用原理,之前的文章里也演示过怎么用LangChain或LlamaIndex这类框架构建简易的GraphRAG原型。但话说回来,要把GraphRAG应用真正投入生产,中间还有一大堆优化工作要做。也正因为如此,一些更专业的工具应运而生——微软最近开源的GraphRAG,就迅速成了圈里的焦点。

不少朋友可能已经在微软那篇论文里见过GraphRAG的基本思路了。不过,我们还是打算结合一个实际案例,把GraphRAG的内部原理拆开揉碎了讲清楚,顺带演示一下怎么跟Neo4j图数据库集成——这样一来,灵活性和应用场景都会大不一样。

我们准备分两篇文章来聊,分别侧重索引阶段(Index)和查询阶段(Query)。本篇的内容包括:

  • GraphRAG原理

  • GraphRAG索引构建与源码分析

  • GraphRAG索引集成到Neo4j

GraphRAG原理

Microsoft GraphRAG的源头,是自家那篇论文《From Local to Global: A Graph RAG Approach to Query-Focused Summarization》。论文里说得很清楚,它要解决的,是传统RAG的一个老大难问题:

没法回答那些需要高层语义理解的总结性查询——比如“这些数据集表达了什么主题”。这类任务,学术上叫QFS(Query-Focused Summarization)型任务。

论文里给出的解法是这样的:

先从多个原始文档构建知识图谱(这一步跟之前介绍的Graph RAG差别不大);然后用社区检测算法(比如leiden算法)把知识图谱划分成多个社区/聚簇,再用大模型给这些社区生成自然语言摘要。

等回答QFS类型问题时,先在社区里执行查询拿到中间答案,最后汇总成全局性的答案。

可以把社区理解成

围绕某个主题的一组紧密相关的实体与关系信息

。举个例子,“复仇者联盟与神盾局的复杂关系”这个社区,可能会关联到一大堆超级英雄、组织、事件等实体以及它们之间的关联。

这个过程用下图表示:

图片来自微软论文

这个流程的妙处在于:

它把原始的自然语言文本转化并压缩成图谱,然后又把这些图谱总结回自然语言。说白了,就是从自然语言文本→结构化的知识图谱→自然语言摘要。

由于构建出来的知识图谱已经融合了多个原始文档的实体与关系信息,因此最后基于社区的自然语言摘要,自然也就包含了跨数据源与文档的浓缩信息。这,才是回答QFS问题的底气所在。

Microsoft GraphRAG对这套流程的实现,可以参考论文中的描述:

图片来自微软论文

这里得说明一下,查询阶段(Query Time)相对简单,真正复杂的是索引阶段(Indexing Time)。我们用尽量简洁的方式把处理过程梳理一下:

1. 文本块拆分:

把原始文档拆成多个文本块——这一步跟经典RAG的处理方式一模一样。

2. 实体与关系提取:

借助大模型分析文本块,提取出实体与关系。这一步跟普通的Graph RAG也差不多。

3. 生成实体与关系摘要:

为提取出来的实体与关系生成简单的描述性信息。这就是区别于普通Graph RAG的关键步骤了。后面在Demo里你会看到,这类信息其实是作为属性存放在实体/关系的Graph节点里的。比如“神盾局”这个实体,其中的description属性就是在这一步生成的(后面会演示怎么导入到Neo4j查看):

这种摘要的好处是:可以借助嵌入向量更有效、更准确地对这些实体与关系进行检索——这也就是上图中description_embedding属性的意义所在。

当然,好处背后也有代价。因为需要为大量的实体与关系生成描述信息,所以会触发非常多的LLM调用,这意味着漫长的耗时和昂贵的大模型API开销!我们建议在测试阶段优先用GPT-4o-mini模型。

4. 检测与识别社区:

借助社区检测算法,在Graph里识别出多个社区。

5. 生成社区摘要:

借助大模型给每个社区生成摘要信息,用来了解数据集的全局主题结构和语义。这也是Microsoft GraphRAG的核心价值所在,更是回答QFS问题的关键。我们先看一眼后面Demo中的一个社区及其属性:

GraphRAG索引构建与源码分析

现在我们用一个文档来构建基于MS GraphRAG的Demo应用,重点放在索引阶段。我们准备了一个自然语言描述漫威漫画世界的文本文件用于测试,内容大致如下(全文约2万汉字):

构建GraphRAG索引的过程其实不复杂(详细步骤可以看官方文档):

1.

准备。

用pip安装graphrag库,建议在虚拟环境下操作。

2.

初始化。

这里用msgraphrag作为应用目录:

python -m graphrag.index --init --root ./msgraphrag

初始化完成以后,会在指定的根目录下生成基本的文件与目录结构。重要的包括:

  • input目录:

    用来存放输入的原始文档(txt或者csv)。我们把测试用的txt文件放到这个目录下。

  • .env与settings.yaml配置文件:

    你可以在.env或settings.yaml里修改全部配置项。默认情况下只需要改LLM相关的配置——注意,目前只支持OpenAI或者Azure OpenAI的模型:

  • prompts目录:

    这里存放了自动生成的LLM提示模板文件,一共四个,分别在流程的不同处理阶段使用:
  • entity_extraction:

    用于从自然语言文本中抽取实体与关系。
  • summarize_descriptions:

    用于生成实体与关系的描述性文本。
  • community_report:

    用于生成社区的摘要等报告信息。
  • claim_extraction:

    这是一个可选动作,用来生成一些实体的辅助声明(由GRAPHRAG_CLAIM_EXTRACTION_ENABLED参数控制)。这里先跳过它。

虽然可以直接用初始化时生成的默认提示模板,但强烈建议通过GraphRAG提供的命令来创建

自适应提示模板

GraphRAG会提取输入数据的信息,然后借助大模型分析并生成更有针对性的提示模板。

现在运行下面的命令来创建自适应提示模板(更多参数请参考官方文档):

python -m graphrag.prompt_tune --language Chinese

执行成功后,我们来观察一下prompts目录下新的提示模板文件内容(为了方便理解,这里翻译成中文):

先看用于实体/关系摘要生成的summarize_descriptions提示。

可以看到,新的提示已经结合输入文件的内容进行了“个性化”定制:

再观察用于生成社区摘要的community_report提示

(这里只展示一部分)。可以看到,在生成社区摘要时,会输出一份完整的“报告”,包含标题、解释、发现等信息——这些都有助于更准确地解答QFS问题。

3.

创建索引。

配置和提示模板都准备好以后,就可以开始创建索引了:

python -m graphrag.index --root ./msgraphrag

之后会进入一系列工作流程。当看到如下输出时,说明索引阶段的工作已经完成。

从最后输出的信息里,可以大致了解到它的基本处理过程:从拆分输入文本开始,到提取实体与关系、生成摘要信息、构建内存中的Graph结构、从Graph中识别社区、创建社区报告、创建Graph中的文本块节点和文档节点,等等。当然,除了上面介绍的几个核心步骤,还涉及到大量中间处理细节,比如embedding生成、持久化到存储、不同的算法策略等。如果有兴趣深入了解具体的实现,那还是得去啃GraphRAG的源代码。这里提供几个发现和指南:

  • Microsoft GraphRAG内部借助了DataShaper来实现灵活的工作流与处理动作的“装配”。

    DataShaper

    是微软开源的一个用来

    定义和执行数据处理工作流的库

    。通过定义一个数据处理工作流,你可以对输入的数据(比如Pandas的DataFrame)定义一系列数据操作的

    动作

    (DataShaper里叫

    Verb

    )、

    参数和步骤

    ,执行这个工作流就能完成数据处理。DataShaper里提供了很多开箱即用的Verb,你也可以自定义Verb。多个子工作流还能组合定义成一个更大的工作流。

  • 一种简单的阅读方式:你可以在index/workflows/v1目录下找到基本的工作流定义,比如上面的create_base_extracted_entities;再根据工作流中的步骤(steps)找到对应的verb,然后在index/verbs里找到verb的实现,就能大致了解这个工作流的内部逻辑了。

  • 可以学习代码目录中examples目录下的例子,用GraphRAG的索引引擎来构建自己的数据处理管道——这对理解DataShaper和GraphRAG的内部原理非常有帮助。

  • 值得注意的一点是:Microsoft GraphRAG在索引构建过程中目前并不支持使用图数据库。中间数据主要用Pandas

    DataFrame

    这类结构化类型进行交换;Graph的构建与分析主要借助

    Networkx

    这个图计算库;Graph数据的交换使用

    Graphml

    (一种基于XML的Graph表示);在社区识别时,则借助了

    Graspologic库

    实现的leiden算法。

GraphRAG索引集成到Neo4j

索引构建完成后,默认情况下,GraphRAG会把构建整个知识图谱所需的数据持久化到output目录下,以parquet格式文件存放(

parquet

是一种专门为高效数据存储与分析设计的列式压缩存储文件格式——你可以把它想象成DataFrame的一种持久化格式)。这些文件在查询阶段会被加载到内存及向量数据库,并用于检索:

但parquet是一种底层文件格式,光靠它没法直观地观察上面构建的知识图谱索引的细节。那有没有办法做更直观的可视化、分析和检索呢?

其实parquet文件可以通过pandas库很方便地读取成DataFrame表,所以只要了解了它的结构,就能用Cypher语句把它导入到Neo4j图数据库中,变成节点和关系。

Github上已经有高手完成了这项工作(地址见文章最后):

用他提供的笔记本文件在本地运行,就能成功把上面构建的知识图谱数据全部导入到Neo4j数据库。现在,我们可以通过Neo4j管理台看到完整的可视化知识图谱(部分):

在这个Demo的图谱里,看到的节点包括上面提取的实体(

entity

,又分为不同类型),也包括社区(

community

)、文本块(

chunk

)、原始文档(

document

);而关系则包括

RELATED

(实体之间)、

PART_OF

(chunk与document之间)、

HAS_ENTITY

(chunk与entity之间)、

IN_COMMUNITY

(entity与community之间)。一共产生了690个节点和1793条关系:

有了Neo4j的Cypher语言,你可以查清楚任何你想知道的图谱信息,或者直接点击某个节点查看详情。来看一个社区的信息——比如“蜘蛛侠与反派角色的关系”这个社区的图谱:

这个社区的报告信息(节点属性):

为了更深入地研究GraphRAG生成的数据,还可以用Cypher配合可视化库对知识图谱做进一步分析。比如,通过不同节点的关系数量(Node Degree)来了解节点的重要性:

这里最高的节点度接近30,来看看是哪个节点:

MATCH (n:__Entity__) 
RETURN n.name AS name, count{(n)-[:RELATED]-()} AS degree
ORDER BY degree DESC LIMIT 10

执行结果如下(钢铁侠永远的神?):

除了数据分析,你还可以在此基础上做增强,比如联合导入其他已有的知识图谱数据。当然,更关键的是,你可以在自己的Neo4j图数据库上定义专属于你自己的RAG应用检索与生成器,不再依赖GraphRAG项目自带的Query功能——这带来的灵活性,可不是一星半点。

下一篇,我们将分析Microsoft GraphRAG中Query功能的实现,并探讨如何基于导入的Neo4j库来自定义实现RAG检索器。