数据截至 (上游 commit 03c7a3d2b2eb)
第 1 章 · 索引流水线:文档怎么一步步变成图
这章讲什么: GraphRAG 的索引不是一个大函数,而是一串有名字的小步骤(workflow)顺序跑。本章讲这串步骤怎么被"工厂"按方法名组装、数据怎么在一堆表之间流、以及第一步"切块"的细节。抽图、聚类、写报告这三大步各有专章(02/03)。
1.1 一句话:索引 = 一串 workflow 顺序执行
打开 packages/graphrag/graphrag/api/index.py 的 build_index,会发现它自己几乎不干活,只做三件事:
- 按"方法"造出一条流水线:
PipelineFactory.create_pipeline(config, method)。 - 把流水线交给
run_pipeline去驱动。 - 收集每步的结果
PipelineRunResult,回调通知开始/结束/出错。
所以理解索引 = 理解"有哪些 workflow、按什么顺序、各读写哪张表"。
1.2 工厂:把"方法名"翻译成一串步骤名
PipelineFactory(packages/graphrag/graphrag/index/workflows/factory.py)是个纯注册表:
workflows: dict[str, WorkflowFunction]—— 步骤名 → 该步骤的函数。pipelines: dict[str, list[str]]—— 方法名 → 步骤名的有序列表。
create_pipeline 的逻辑很直白:优先用配置里显式给的 config.workflows,否则按方法名查表,然后把"名字列表"映射成"函数列表"打包成 Pipeline:
# 示意,非源码。对应 factory.py create_pipeline
workflows = config.workflows or cls.pipelines.get(method, []) # 名字列表
return Pipeline([(name, cls.workflows[name]) for name in workflows]) # 名字→函数
四种内置方法跑哪一串
文件底部用 register_pipeline 注册了四条线(IndexingMethod 枚举见 config/enums.py)。它们共享大部分步骤,差别只在"抽图那一段"和"是否带增量更新尾巴":
| 方法 | 抽图方式 | 是否增量 | 适用 |
|---|---|---|---|
standard | LLM 抽图(extract_graph) | 否 | 质量优先、可承担 LLM 成本 |
fast | NLP 名词短语抽图(extract_graph_nlp + prune_graph) | 否 | 省钱/省时,质量略降 |
standard-update | LLM 抽图 | 是(尾部加 *_update_workflows) | 已索引过、来了新文档 |
fast-update | NLP 抽图 | 是 | 同上但走快速路径 |
standard 方法展开后的完整步骤序列(_standard_workflows,前面再拼一个 load_input_documents):
load_input_documents 读入原始文档
└▶ create_base_text_units 切块 → text_units 表
└▶ create_final_documents 定稿 documents 表
└▶ extract_graph LLM 抽实体/关系 (第 02 章)
└▶ finalize_graph 算度数、定稿 entities/relationships
└▶ extract_covariates (可选) 抽"断言/协变量"claims
└▶ create_communities Leiden 聚类 → communities (第 03 章)
└▶ create_final_text_units 把实体/关系 id 回填进 text_units
└▶ create_community_reports LLM 写社区报告 (第 03 章)
└▶ generate_text_embeddings 文本向量化 → 向量库
fast 只是把 extract_graph 换成 extract_graph_nlp + prune_graph,并用 create_community_reports_text(基于文本块而非图)写报告。