跳到主要内容

GraphRAG — 架构与原理

30 秒导读: GraphRAG 是微软研究院开源的一套"知识图增强 RAG"数据管道。它先用 LLM 把你的私有文档读成一张"谁和谁有什么关系"的知识图,再把图切成一层层"社区"并为每个社区写一份摘要报告;查询时既能像普通 RAG 那样精确捞局部细节,也能靠社区报告回答"这批文档整体在讲什么"这类全局问题——后者恰恰是传统向量 RAG 的死角。


1. 这是什么(零基础也能懂)

一句话定义

GraphRAG = 索引期用 LLM 把一堆文本抽成知识图并预生成分层摘要 + 查询期在图和摘要上做检索问答的一整套流水线。

它解决的那个具体痛点

先说传统 RAG(向量检索 RAG)怎么工作,再说它卡在哪:

  • 传统 RAG:把文档切块 → 每块算 embedding → 提问时用问题的 embedding 找最相似的几块 → 把这几块塞给 LLM 作答。
  • 它擅长的:局部事实类问题("X 的电话是多少""合同第 3 条写了啥")——答案就落在某几块里,捞出来即可。
  • 它答不了的:全局主题类问题。比如"这 1000 篇报告里反复出现的 5 个主题是什么?"——答案不在任何单独一块里,而是散落在全体文档里、需要归纳。向量检索只会捞回"和问题字面最像"的几块,归纳不出全局。

GraphRAG 补的就是这后半块:它在索引时就先把全体文档归纳成"社区报告",于是全局问题变成"读一遍这些预先写好的摘要再汇总"。

给谁用

  • 有一批私有的、叙事性强的语料(调研报告、案卷、访谈、公司知识库),想问既有细节又有全局的问题的人。
  • ⚠ 官方明确提醒:索引很烧钱(要对每块文本反复调 LLM),建议先拿小数据试(README.md)。

用起来什么样

它是一个命令行工具 graphragpackages/graphrag/graphrag/cli/main.py,基于 typer,命令见 @app.command):

# 1. 在某目录初始化配置和默认 prompt
graphrag init --root ./ragtest
# 2. 把 ./ragtest/input 里的文档索引成图(这一步烧钱、耗时)
graphrag index --root ./ragtest
# 3. 提问——global 适合全局主题,local 适合具体实体
graphrag query --root ./ragtest --method global "这些文档的主要主题是什么?"
graphrag query --root ./ragtest --method local "关于 Martin Smith 都说了什么?"

索引跑完,./ragtest/output/ 下会多出一批 parquet 表:entities(实体)、relationships(关系)、communities(社区)、community_reports(社区报告)、text_units(文本块)等——各表的列见 packages/graphrag/graphrag/data_model/schemas.py(ENTITIES_FINAL_COLUMNS 等)。查询就是在这些表上跑。

一句话直觉

把传统 RAG 想成"给文档建了个全文搜索框";GraphRAG 则是先请一个分析师把整摞文档读一遍,画出人物关系图、并按主题分章写好综述,之后你既能查关系图里的某个人,也能直接读某一章综述——不用每次提问都从零归纳。

本节到此不碰任何底层代码。你只需记住:GraphRAG 干两件事——把文本变成图+分层摘要(索引),再在其上问答(查询)。


2. 顶层全景(它大概怎么转)

两个阶段一张图

怎么读这张图:上半是索引期(离线、烧钱、跑一次),把原始文档一路加工成图和社区报告;下半是查询期(在线),四种搜索模式各自从不同的产物里取料回答。

┌──────────────────────── 索引期 (build_index) ────────────────────────┐
原始文档 ──▶│ ①切块 ②LLM抽图 ③定稿+算度数 ④Leiden聚类 ⑤LLM写社区报告 │
(.txt │ text_units ─▶ entities ─▶ 补 degree ─▶ communities ─▶ community_ │
.csv…) │ relationships (分层) reports │
│ ⑥文本向量化 embeddings│
└──────────────────────────────┬──────────────────────────────────────┘
│ 产物: 一组 parquet 表 + 向量库
┌───────────────────────────────┴──────────────────────── 查询期 (query) ┐
│ global : 读所有社区报告 → map 每批打分 → reduce 汇总 (答全局主题) │
│ local : 问题→向量找种子实体→取其邻居/关系/原文块 → 单次作答 (答具体实体) │
│ drift : 先用社区报告"定调"→在图上迭代提追问、逐步下钻 (兼顾全局+局部) │
│ basic : 纯文本块向量检索,退化成传统 RAG (最省钱的兜底) │
└──────────────────────────────────────────────────────────────────────┘

部件一句话职责

部件干什么在哪
索引 API组装并驱动索引流水线packages/graphrag/graphrag/api/index.py(build_index)
流水线工厂把"方法名"翻译成一串 workflowpackages/graphrag/graphrag/index/workflows/factory.py(PipelineFactory)
workflow 集每个索引步骤一个文件packages/graphrag/graphrag/index/workflows/*.py
图抽取算子调 LLM 从文本抽实体/关系packages/graphrag/graphrag/index/operations/extract_graph/graph_extractor.py(GraphExtractor)
聚类算子分层 Leiden 把图切成社区packages/graphrag/graphrag/index/operations/cluster_graph.py(cluster_graph)
社区摘要算子自底向上给每个社区写报告packages/graphrag/graphrag/index/operations/summarize_communities/summarize_communities.py
查询 API四种搜索的对外入口packages/graphrag/graphrag/api/query.py
四种 Search各模式的检索+作答编排packages/graphrag/graphrag/query/structured_search/*
数据模型实体/关系/社区/报告等类型 + 表列定义packages/graphrag/graphrag/data_model/

主线走一遍(不进代码)

  1. 切块。 文档按 token 数切成 text_unitscreate_base_text_units)。
  2. 抽图。 对每个块调 LLM,抽出实体和关系,再把同名实体/同一对关系的多条描述用 LLM 合并成一段(extract_graph)。
  3. 定稿图。 遍历关系算出每个实体的"度数"(连了多少条边)并写回(finalize_graph)。
  4. 聚类。 用分层 Leiden 把实体图切成一层层社区,父社区含若干子社区(create_communities)。
  5. 写报告。 自底向上:先给叶子社区喂它的实体/关系原料让 LLM 写摘要,上层社区太大放不下时就改用下层报告当原料(create_community_reports)。
  6. 向量化。 把实体描述、文本块等算成 embedding 存进向量库,供查询期语义检索(generate_text_embeddings)。
  7. 查询。 用户选 global / local / drift / basic 之一,各自从上面产物取料,交给 LLM 作答。

目标:看懂"大盘"就够进各章了。


3. 该读哪一章(阅读地图)

本项目较大,拆成五章,建议顺序如下:

  1. 01-indexing-pipeline.md —— 先看索引流水线怎么被工厂组装、9 个 workflow 怎么串起来、数据在表之间怎么流。这是全局骨架。
  2. 02-graph-extraction.md —— 再钻"从文本到实体/关系"这一最核心的抽取步:gleaning 多轮补抽、描述合并、以及不花 LLM 的 NLP 快速路径。
  3. 03-communities-and-reports.md —— 然后看图怎么被 Leiden 切成分层社区、社区报告怎么自底向上滚动生成。这是 GraphRAG 区别于普通 RAG 的关键资产。
  4. 04-query-search.md —— 有了产物,看四种查询各自怎么检索和作答,尤其是 global 的 map-reduce 和 drift 的图上迭代。
  5. 05-architecture-internals.md —— 最后是工程内幕:monorepo 分包、流水线运行时与状态、存储/缓存抽象、增量更新,以及一张总代码地图。

只想快速判断相关性的 agent:读完本 index.md 的 §1–§2 即可决定下钻哪章;每章开头都有"这章讲什么"。


4. 横向对比(放在 rag-context 货架里看)

GraphRAG 在"RAG / 上下文工程"这一区里,取的是一条重索引、换全局能力的路线:

维度传统向量 RAGGraphRAG
索引成本低(只算 embedding)(每块文本要多次调 LLM 抽图、合并、写报告)
擅长的问题局部事实检索局部 + 全局主题归纳
核心资产向量索引知识图 + 分层社区报告
查询成本一次检索一次生成global 要 map-reduce 多次调用;local 接近传统 RAG

一句话取舍:GraphRAG 用昂贵的一次性索引,换来了向量 RAG 拿不到的"全局归纳"能力;如果你的问题都是局部事实类,它的 basic 模式其实就退化回了传统 RAG,未必值得那份索引钱。

更细的原理和取舍在各分章里展开。