来源:互联网 更新时间:2026-08-17 14:30
这几天,微软开源了GraphRAG——一个基于知识图谱构建的检索增强生成系统,迅速在技术圈里引起了不小的讨论。坦白说,这个框架关注了挺久,趁着热度认真啃了啃源码。这篇文章,就当作是一份阅读笔记,记录下对GraphRAG系统架构、关键概念和核心工作流的理解。
(本次分析的代码对应commit id为a22003c302bf4ffeefec76a09533acaf114ae7bb,更新于2024年7月5日。)
在深入代码之前,有必要先搞清楚GraphRAG要解决的问题。论文里一针见血地指出了常规RAG的致命短板:
“然而,RAG在面对针对整个文本语料库的全局性问题时,比如‘这个数据集的核心主题是什么?’,就显得力不从心了。因为这本质上是一个聚焦于查询的总结性任务,而不是一个明确的检索任务。”
简单说,传统RAG玩不转这种高层次的概括性问题。GraphRAG的解决方案也很清晰,论文里给出了具体思路:用社区检测算法,把整个知识图谱拆解成一个个模块化的社区,然后让大模型自下而上地为每个社区生成摘要。最后,再通过一种“map-reduce”的方式,让每个社区并行回答查询,最终汇总成一个全局性的答案。

和大多数RAG系统类似,GraphRAG的整个流水线也分为索引和查询两个阶段。索引阶段,用LLM来提取实体、关系和协变量等结构化信息,构建知识图谱。然后利用社区检测技术进行切分,再让LLM做摘要。到了查询阶段,就可以针对具体问题,把相关社区的摘要汇总起来,生成一个全局性的答案。
官方文档写得很清楚了,但要理解实现细节,还得看源码。项目的整体结构长这样:
. ├── cache ├── config ├── emit ├── graph │ ├── embedding │ ├── extractors │ │ ├── claims │ │ ├── community_reports │ │ ├── graph │ │ └── summarize │ ├── utils │ └── visualization ├── input ├── llm ├── progress ├── reporting ├── storage ├── text_splitting ├── utils ├── verbs │ ├── covariates │ │ └── extract_covariates │ │ └── strategies │ │ └── graph_intelligence │ ├── entities │ │ ├── extraction │ │ │ └── strategies │ │ │ └── graph_intelligence │ │ └── summarize │ │ └── strategies │ │ └── graph_intelligence │ ├── graph │ │ ├── clustering │ │ │ └── strategies │ │ ├── embed │ │ │ └── strategies │ │ ├── layout │ │ │ └── methods │ │ ├── merge │ │ └── report │ │ └── strategies │ │ └── graph_intelligence │ ├── overrides │ └── text │ ├── chunk │ │ └── strategies │ ├── embed │ │ └── strategies │ ├── replace │ └── translate │ └── strategies └── workflows └── v1
这里面隐藏了大量值得深挖的细节,接下来会结合具体代码来展开。
程序运行时,控制台会打印出完整的workflow列表,这是理解整个索引流水线的关键入口:
⠹ GraphRAG Indexer ├── Loading Input (InputFileType.text) - 1 files loaded (0 filtered) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00 0:00:00 ├── create_base_text_units ├── create_base_extracted_entities ├── create_summarized_entities ├── create_base_entity_graph ├── create_final_entities ├── create_final_nodes ├── create_final_communities ├── join_text_units_to_entity_ids ├── create_final_relationships ├── join_text_units_to_relationship_ids ├── create_final_community_reports ├── create_final_text_units ├── create_base_documents └── create_final_documents All workflows completed successfully.
索引阶段是整个项目的核心,流程也最为复杂。启动索引的命令很简单:
python -m graphrag.index --init --root ./ragtest python -m graphrag.index --root ./ragtest

实际调用的是`graphrag/index/__main__.py`的主函数,通过argparse解析参数后,会转调`graphrag/index/cli.py`里的`index_cli`函数。
简单梳理一下调用链路(上图灰色标记的是核心函数):
cli.py::index_cli()函数首先处理用户输入,比如检查是否需要初始化目录(`--init`),这一逻辑由`cli.py::index_cli()`执行,主要看配置文件、prompt模板、.env文件等是否存在,不存在就创建。限于篇幅,这里只讨论默认配置的运行流程。理清逻辑后,可以自行修改配置。
result = PipelineConfig( root_dir=settings.root_dir, input=_get_pipeline_input_config(settings), reporting=_get_reporting_config(settings), storage=_get_storage_config(settings), cache=_get_cache_config(settings), workflows=[ *_document_workflows(settings, embedded_fields), *_text_unit_workflows(settings, covariates_enabled, embedded_fields), *_graph_workflows(settings, embedded_fields), *_community_workflows(settings, covariates_enabled, embedded_fields), *(_covariate_workflows(settings) if covariates_enabled else []), ], )
这段代码的意图很清楚:根据不同的功能,生成完整的workflow序列。需要注意的是,这里并不考虑workflow之间的依赖关系,只是单纯地根据`workflows/v1`目录下的模板,生成一系列workflow。
`run.py::run_pipeline()`才是真正的执行者,其核心逻辑包含两部分:
workflows/load.py::create_workflow():利用现有模板创建不同的工作流。graphlib::topological_sort():根据workflow间的依赖关系,计算DAG的拓扑排序。到目前为止,我们其实还没真正触及索引阶段的业务逻辑,只是理清了GraphRAG内置的这套pipeline编排系统。现在以一个具体的workflow——index/workflows/v1/create_final_entities.py——为例,看看它到底是怎么运作的。
examples/single_verb,应该就能明白。从功能上看,它有点像Prefect。create_final_entities.py。翻看源码可以发现,它依赖于workflow:create_base_extracted_entities,同时定义了cluster_graph、embed_graph等操作。其中,cluster_graph采用了leiden策略,具体代码在index/verbs/graph/clustering/cluster_graph.py中:from datashaper import TableContainer, VerbCallbacks, VerbInput, progress_iterable, verb @verb(name="cluster_graph") def cluster_graph( input: VerbInput, callbacks: VerbCallbacks, strategy: dict[str, Any], column: str, to: str, level_to: str | None = None, **_kwargs, ) -> TableContainer:
可以看到,这里的`leiden`算法其实来自另一个图算法库`graspologic`。
artifacts/stats.json文件,就能整理出完整的索引流水线。官方文档也给出了非常详细的说明,不过依据源码提取出来的pipeline似乎还是有些差异,有兴趣的朋友可以留言探讨。查询阶段的pipeline相对简单一些。执行查询的命令如下:
# Global search python -m graphrag.query --root ./ragtest --method global "What are the top themes in this story?" # Local search python -m graphrag.query --root ./ragtest --method local "Who is Scrooge, and what are his main relationships?"
这里有Global/Local两种搜索模式。生成函数调用关系图后,整体结构会更加清晰。

graphrag/query/__main__.py中的主函数会根据参数不同,分别路由到cli::run_local_search()或cli::run_global_search()。
cli::run_global_search()主要调用factories.py::get_global_search_engine(),返回一个GlobalSearch类的实例。这个类与LocalSearch类似,都是基于工厂模式创建的。其核心方法是structured_search/global_search/search.py::GlobalSearch.asearch(),它采用了map-reduce策略:先让大模型为每个社区的摘要并行生成答案,然后汇总所有答案,形成最终结果。作者在相关的prompts里给出了非常详细的说明。
也正是因为这种map-reduce机制,Global Search对token的消耗量相当大。
与全局搜索类似,cli::run_local_search()主要调用factories.py::get_local_search_engine(),返回一个LocalSearch类的实例。这里的asearch()方法相对简单,直接根据上下文给出回复。这种模式更接近常规的RAG语义检索策略,token消耗也更少。
与Global Search不同,Local模式综合了nodes、community_reports、text_units、relationships、entities、covariates等多种源数据。官方文档对此有详细说明,这里就不再赘述了。
综合来看,微软这次推出的GraphRAG框架确实干货满满,值得花些时间去仔细研读和思考。
腾讯ima怎么把微信内容一键导入知识库?
黄金价格不断创新高!黄金稳定币XAU、PAXG市值达11亿美元
CC币价格预测(2026-2035):Canton币今日价格走势+长期价格预测
新浪互联网热点小时报丨2026年07月26日16时_今日实时互联网热点速递
腾讯ima怎么创建共享知识库?
2026鸣潮账号交易安全指南:五大交易平台对比与风险避坑分析
今日比特币暴涨分析:Metaplanet的比特币BTC投资推动股价上涨17%
新浪机器学习热点小时报丨2026年07月25日18时_今日实时机器学习热点速递
新浪人工智能热点小时报丨2026年07月30日18时_今日实时人工智能热点速递
比特币(BTC)核心周期指标复刻历史走势 价格或跌破5.8万美元关键支撑位
蚂蚁庄园今日答案7月21日(今日已更新) 蚂蚁庄园今天正确答案是什么呢
Celestia价格预测2026-2032:TIA币能否引领山寨币上涨行情?历史价格回顾
2026年三角洲行动账号交易指南:5大交易平台对比与安全选购建议
Windy卫星云图怎么看?云层变化识别技巧
TRUMP价格走势与WEPE预售进展解析
kimi提示词专家使用方法新手指南
抖音怎么取消申请退货退款?抖音上取消退货怎么操作
WorkBuddy登录后怎么查看积分?
一加手机如何设置三指长按屏幕局部截图
短剧《仙人跳获透视,古玩玉器我全拿捏》剧情介绍
手机号码测吉凶
本站所有软件,都由网友上传,如有侵犯你的版权,请发邮件haolingcc@hotmail.com 联系删除。 版权所有 Copyright@2012-2013 haoling.cc