GraphRAG 索引数据流解析:默认配置下文档如何一步步转化为 GraphRAG 知识模型
GraphRAG 索引引擎是一套基于 LLM 的流水线,其核心任务是把非结构化文本加工成结构化、可供检索的知识产物。本文围绕 GraphRAG 项目中的《Indexing Dataflow》文档(见 docs/index/default_dataflow.md)展开,逐阶段讲解默认配置工作流如何把输入文档转化为 GraphRAG Knowledge Model(知识模型),并结合仓库源码、默认参数与测试用例补齐各阶段的实现细节。读完本文,你将理解知识模型中各产物(TextUnit、Entity、Community 等)的确切来源,掌握每个阶段对应的 workflow 与可调配置项,从而能够根据自己的语料与算力情况合理裁剪或调优整条索引流水线。
一、GraphRAG 知识模型:索引产物的统一规格
GraphRAG 的索引引擎(默认配置模式)产出的所有数据都对齐到一个被称作 GraphRAG Knowledge Model 的知识模型上。该模型是对底层存储技术的抽象,为下游搜索模块提供了统一的访问接口。其数据定义集中存放在 data_model 目录 中。
知识模型定义了以下实体类型,其中标注的字段即默认情况下会做文本嵌入(text-embedding)的字段:
| 知识模型类型 | 含义 | 默认嵌入字段 | 来源说明 |
|---|---|---|---|
Document |
系统输入文档,可以是 CSV 中的每一行,也可以是独立的 .txt 文件 | 标题/文本(非默认嵌入主体) | 输入读取阶段加载 |
TextUnit |
待分析文本块,即切分后的 chunk | text |
Phase 1 切分得到 |
Entity |
从 TextUnit 中抽取出的实体,如人物、地点、事件或你自定义的实体模型 | title_description(标题与描述拼接) |
Phase 3 LLM 抽取 |
Relationship |
两个实体之间的关系 | —(通常由实体间接参与) | Phase 3 LLM 抽取 |
Covariate |
抽取出的声明(claim)信息,含对实体的、可能带时间边界的事实性陈述 | — | Phase 3(可选) |
Community |
基于实体与关系图做层次社区检测后形成的聚类结构 | — | Phase 4 |
Community Report |
对每个社区内容生成的总结报告,供人类阅读与下游检索使用 | full_content |
Phase 5 |
在仓库中,这些数据模型的类型定义(例如 entity.py、relationship.py、community.py、community_report.py、covariate.py、text_unit.py、document.py)及最终的输出表列定义(见 schemas.py)都是索引产物是否符合规范的判定依据。
二、默认配置工作流全景
默认配置(Default Configuration Mode)是 GraphRAG 开箱即用、配置成本最低的运行方式,通过 graphrag init 初始化后编辑 settings.yaml 即可控制细节(见 docs/config/overview.md、docs/config/init.md、docs/config/yaml.md)。
下面这张图展示了文档从输入到知识模型产物的六大阶段全貌:
---
title: Dataflow Overview
---
flowchart TB
subgraph phase1[Phase 1: Compose TextUnits]
documents[Documents] --> chunk[Chunk]
chunk --> textUnits[Text Units]
end
subgraph phase2[Phase 2: Document Processing]
documents --> link_to_text_units[Link to TextUnits]
textUnits --> link_to_text_units
link_to_text_units --> document_outputs[Documents Table]
end
subgraph phase3[Phase 3 Graph Extraction]
textUnits --> graph_extract[Entity & Relationship Extraction]
graph_extract --> graph_summarize[Entity & Relationship Summarization]
graph_summarize --> claim_extraction[Claim Extraction]
claim_extraction --> graph_outputs[Graph Tables]
end
subgraph phase4[Phase 4: Graph Augmentation]
graph_outputs --> community_detect[Community Detection]
community_detect --> community_outputs[Communities Table]
end
subgraph phase5[Phase 5: Community Summarization]
community_outputs --> summarized_communities[Community Summarization]
summarized_communities --> community_report_outputs[Community Reports Table]
end
subgraph phase6[Phase 6: Text Embeddings]
textUnits --> text_embed[Text Embedding]
graph_outputs --> description_embed[Description Embedding]
community_report_outputs --> content_embed[Content Embedding]
end
2.1 六大阶段与 workflow 的对应关系
这六大阶段并非松散概念,而是映射到 workflows/factory.py 中注册的标准流水线。从源码可见,IndexingMethod.Standard 对应的完整 workflow 序列为:
"load_input_documents",
"create_base_text_units",
"create_final_documents",
"extract_graph",
"finalize_graph",
"extract_covariates",
"create_communities",
"create_final_text_units",
"create_community_reports",
"generate_text_embeddings",
对应关系可以整理为下表,方便后续按需裁剪或定位某个阶段的实现:
| 数据流阶段 | 对应 workflow | 输入 | 输出/产物 |
|---|---|---|---|
| Phase 1 切分 TextUnits | create_base_text_units |
Documents | text_units 表 |
| Phase 2 文档处理 | create_final_documents |
Documents + TextUnits | documents 表(与 text_unit 关联) |
| Phase 3 图抽取 | extract_graph → finalize_graph → extract_covariates |
TextUnits | entities、relationships、covariates 表 |
| Phase 4 图增强 | create_communities |
finalize 后的关系图 | communities 表 |
| Phase 5 社区总结 | create_community_reports |
communities 表 | community_reports 表 |
| Phase 6 文本嵌入 | generate_text_embeddings |
text_units、entities、community_reports | 向量库中的 embedding 写入 |
注:若使用 Fast 索引方法(
IndexingMethod.Fast,对应 factory.py 中_fast_workflows),实体与关系抽取将改用 NLP 方式(extract_graph_nlp)以节省 LLM 资源,且流程中不包含extract_covariates,即声明/claims 抽取始终被跳过;同时还会执行prune_graph对图做裁剪。
下面分阶段深入每个处理环节。
三、Phase 1:组合 TextUnits(文本切块)
第一阶段将输入文档转换为 TextUnit。TextUnit 是图抽取技术所使用的最小文本分析单位;同时,后续抽取出的知识项(Entity/Relationship/Covariate)都会引用其所属的 TextUnit,从而保留回溯到原始源文本的血缘关系(provenance)。
---
title: Documents into Text Chunks
---
flowchart LR
doc1[Document 1] --> tu1[TextUnit 1]
doc1 --> tu2[TextUnit 2]
doc2[Document 2] --> tu3[TextUnit 3]
doc2 --> tu4[TextUnit 4]
3.1 切块参数(默认值)
切块大小以 token 计数,默认 1200 tokens,可通过 chunking 配置段调整。chunk 越大,图抽取的保真度越低、回溯引用文本的语义价值越小,但整体处理速度会显著加快;反之则质量更高但更慢、更耗 LLM。
在 config/defaults.py 的 ChunkingDefaults 中可以看到全部默认值:
| 配置项 | 默认值 | 说明 |
|---|---|---|
chunking.type |
tokens |
切块策略,默认按 token 切分 |
chunking.size |
1200 |
每块目标 token 数 |
chunking.overlap |
100 |
相邻块重叠的 token 数,用于保持上下文连续性 |
chunking.encoding_model |
o200k_base |
用于计数的 tokenizer 编码模型 |
chunking.prepend_metadata |
None |
可选的元数据字段列表,嵌入到每个 chunk 文本之前 |
3.2 源码层面的实现细节
create_base_text_units workflow 的实现位于 workflows/create_base_text_units.py。其关键逻辑值得注意:
- 流式读写:
create_base_text_units逐行(row-by-row)异步读取 documents 表并写入 text_units 表,避免一次性将全量数据载入内存,适合超大语料; - 每块一行数据:每个 chunk 生成一行
{id, document_id, text, n_tokens}; - ID 由内容哈希生成:
row["id"] = gen_sha512_hash(row, ["text"]),即 TextUnit 的 ID 是文本内容的 SHA-512 哈希,天然支持幂等与去重(同一文本不会产生重复 TextUnit),相关实现见 utils/hashing.py; - 可选元数据前缀:配置
chunking.prepend_metadata时,会调用graphrag_chunking.transformers.add_metadata把文档元数据以.换行分隔符形式拼到 chunk 文本前,使每个 chunk 自包含来源信息。
切块真正依赖的通用组件在独立的 graphrag-chunking 包(packages/graphrag-chunking),其中 create_chunker(config.chunking, tokenizer.encode, tokenizer.decode) 依据 chunking.type 返回 token/sentence 等不同策略的 chunker。仓库在 tests/verbs/test_create_base_text_units.py 中有相应端到端校验。
四、Phase 2:文档处理(Documents 表)
第二阶段为知识模型创建 Documents 表。Final documents 本身并不直接参与 GraphRAG 的检索计算,但这一步把每篇文档与其切分出的 TextUnits 关联起来,为下游自有应用提供文档维度的溯源能力。
---
title: Document Processing
---
flowchart LR
aug[Augment] --> dp[Link to TextUnits] --> dg[Documents Table]
4.1 Link to TextUnits
该步骤把每一篇文档关联到 Phase 1 生成的 TextUnits(多对多关系:一篇文档对应多个 TextUnit,一个 TextUnit 也反过来标记其文档归属),使我们可以回答"哪些文档涉及哪些文本块"以及反向问题。对应 workflow 为 create_final_documents。
4.2 Documents Table
经过以上处理,Documents 表被写入知识模型存储。默认配置下,索引输出会落盘为 Parquet 表(默认输出目录为 output,见 docs/index/overview.md),例如示例语料产出的 [documents.parquet](https://gitcode.com/GitHub_Trending/gr/graphrag/blob/7bb23cc7f32f47cf618a1ae9cca39a6695f434ae/docs/examples_notebooks/inputs/operation dulce/documents.parquet?utm_source=gitcode_repo_files)。
五、Phase 3:图抽取(Entities / Relationships / Claims)
第三阶段针对每个 TextUnit 进行分析,抽取图原语:Entities(实体)、Relationships(关系)与 Claims(声明)。其中实体与关系在 extract_graph workflow 中一次性完成抽取,claims 则由 extract_covariates workflow 单独完成。
---
title: Graph Extraction
---
flowchart LR
tu[TextUnit] --> ge[Graph Extraction] --> gs[Graph Summarization]
tu --> ce[Claim Extraction]
5.1 实体与关系抽取
图抽取的第一步是逐个 TextUnit 调用 LLM,从原始文本中提取实体与关系。该步骤的输出是"每个 TextUnit 一张子图",其中:
- entities 包含
title(标题)、type(类型)和description(描述); - relationships 包含
source(源实体)、target(目标实体)和description(描述)。
各子图随后被合并:任何 title 与 type 相同的实体会被合并,其多个 description 聚合成描述数组;同理,任何 source 与 target 相同的关系也会合并描述数组。
extract_graph workflow 的实现在 workflows/extract_graph.py,其核心调用链为:
- 通过
DataReader(context.output_table_provider).text_units()读取 Phase 1 产出的 text_units 表; - 用
create_completion(...)构造抽取 LLM(使用config.extract_graph.completion_model_id指定模型,并使用独立的缓存命名空间extract_graph); - 调用
extract_graph操作(见 operations/extract_graph)执行逐 TextUnit 的实体关系抽取; - 若
config.snapshots.raw_graph开启,还会把抽取后、总结前的原始表另存为raw_entities/raw_relationships,便于排查提示词效果。
抽取默认参数(见 config/defaults.py 中 ExtractGraphDefaults):
| 配置项 | 默认值 | 说明 |
|---|---|---|
extract_graph.entity_types |
["organization", "person", "geo", "event"] |
关注的实体类型白名单,提示 LLM 只抽取这些类型 |
extract_graph.max_gleanings |
1 |
对抽取结果的"追问"(gleaning)轮数,用于补漏 |
extract_graph.completion_model_id |
default_completion_model |
使用的 completion 模型 |
值得注意:如果某次抽取没有检测到任何实体或关系,extract_graph.py 会直接抛出
ValueError并中止流水线(如"Graph Extraction failed. No entities detected during extraction."),这是防呆设计,避免把空图继续往下游传递。
5.2 实体与关系总结
得到实体关系图后,每个实体/关系都携带一长串 description。随后流水线让 LLM 把每个 description 数组压缩成单个实体/关系各一条的简洁描述,以保留所有 description 中彼此不同的信息。总结后的实体与关系即拥有唯一、精炼的描述文本。
总结步骤使用独立的模型配置与缓存命名空间:
- 模型由
config.summarize_descriptions.completion_model_id指定,缓存名为summarize_descriptions(见extract_graph.py中的create_completion与context.cache.child(...)调用); - 参数默认值(
SummarizeDescriptionsDefaults):max_length = 500(总结文本最大长度)、max_input_tokens = 4000(喂给总结 LLM 的单条输入上限); - 调用
summarize_descriptions操作(operations/summarize_descriptions)后,实体按title、关系按(source, target)左连接回填总结文本。
5.3 Claims / Covariates 抽取(可选)
最后,作为一条独立 workflow(extract_covariates),系统从源 TextUnits 中抽取 claims。Claim 是带有状态评估和时间边界的事实性陈述,最终导出为主产物 Covariates。
需要特别注意的是:claim 抽取默认关闭。原因在于 claim 抽取通常需要先做提示词调优(prompt tuning)才有实用价值。源码依据见 config/defaults.py 中 ExtractClaimsDefaults:
| 配置项 | 默认值 | 说明 |
|---|---|---|
extract_claims.enabled |
False |
总开关,置 True 才执行 claims 抽取 |
extract_claims.description |
Any claims or facts that could be relevant to information discovery. |
向 LLM 描述"什么是需要抽取的 claim" |
extract_claims.max_gleanings |
1 |
追问轮数 |
extract_claims.model_instance_name |
extract_claims |
LLM 缓存命名空间 |
从源码结构看(
_fast_workflows中不含extract_covariates),Fast 模式会无条件跳过 claim 抽取;此外IndexingMethod.Fast对应的_fast_workflows也印证了原文档关于 FastGraphRAG 采用 NLP 抽取的表述(其使用extract_graph_nlp而非extract_graph)。
六、Phase 4:图增强(社区检测)
现在已拥有一张可用的实体关系图。为了使下游能够理解图的组织结构,我们希望对实体做层次社区检测(community detection),给出不同粒度的图聚类视图。
---
title: Graph Augmentation
---
flowchart LR
cd[Leiden Hierarchical Community Detection] --> ag[Graph Tables]
6.1 Community Detection:层次化 Leiden 算法
该步骤使用 Hierarchical Leiden 算法对图做递归社区聚类,直到社区规模达到阈值为止。这样既保留了图的社区结构认知,又提供了一种在不同粒度层级上导航与总结图的方式(顶层社区≈全局结构,底层社区≈局部簇)。
相关配置与默认值(ClusterGraphDefaults):
| 配置项 | 默认值 | 说明 |
|---|---|---|
cluster_graph.max_cluster_size |
10 |
递归聚类停止的社区规模阈值 |
cluster_graph.use_lcc |
True |
是否只保留最大连通分量(largest connected component)后再聚类 |
cluster_graph.seed |
0xDEADBEEF |
随机种子,保证聚类结果可复现 |
实现细节可在 operations/cluster_graph.py 中看到:它先把关系边归一化为无向对并去重,use_lcc 为真时用 stable_lcc 取最大连通子图,再把带权重边列表交给 graphrag.graphs.hierarchical_leiden.hierarchical_leiden(hierarchical_leiden.py)计算多层划分,最终输出 (level, community, parent, nodes) 形式的聚类结构,并建立每层 node → cluster 及 cluster → parent_cluster 的层级映射。
create_communities workflow(workflows/create_communities.py)在此基础上做数据装配:为每个社区聚合 entity_ids、社区内(source 与 target 同属一个社区的)relationship_ids 与 text_unit_ids,补上 id、human_readable_id、title、parent、children、size、period 等列,形成满足 COMMUNITIES_FINAL_COLUMNS 约束的 communities 表。
6.2 Graph Tables
图增强完成后,最终 Entities、Relationships 与 Communities 表被导出。
- 在进入社区检测前,
finalize_graphworkflow 会先对实体关系图做收尾(见 workflows/finalize_graph.py):流式读取关系表构建去重无向边上的节点度数映射(degree_map),再分别调用finalize_entities/finalize_relationships操作(finalize_entities.py、finalize_relationships.py)逐行富化并写出实体与关系最终表; - 若开启
snapshots.graphml,还会把关系图导出为 GraphML 快照文件(snapshot_graphml),供 Gephi 等可视化工具直接打开——这是社区、报告的人工质检/探索的重要辅助手段; - 其中 entities 表需要给实体计算并写入
degree,这也是索引输出的标准字段。
七、Phase 5:社区总结(Community Reports)
在获得实体关系图与社区层级之后,接下来基于 communities 数据为每个社区生成报告。报告的粒度决定了其视角:若某社区是顶层社区,报告描述的就是整张图;若是低层社区,报告则描述局部簇。
---
title: Community Summarization
---
flowchart LR
sc[Generate Community Reports] --> ss[Summarize Community Reports] --> co[Community Reports Table]
7.1 Generate Community Reports
这一步让 LLM 对每个社区生成总结,目的是理解社区内部的独有信息,并提供"高层概览或局部深挖"两种粒度下的图理解。报告内容包括 执行摘要(executive overview),并引用社区子结构中的关键实体、关系与 claims。
对应实现为 create_community_reports workflow(workflows/create_community_reports.py),其底层社区报告总结操作位于 operations/summarize_communities(依据报告内容来源又分为 create_community_reports 与 Fast 模式使用的 create_community_reports_text,分别基于图内容与纯文本总结,见 factory.py 的 workflow 注册)。
7.2 Summarize Community Reports
每份 community report 还会再做一次 LLM 压缩总结,得到适合速读/速用的短版本(short-hand use)。随后进入记账收尾(bookkeeping)工作:生成 community_report ID、关联 community、记录 full_content(长版,用于向量化)与 summary(短版)等。
社区报告相关默认参数(CommunityReportDefaults):
| 配置项 | 默认值 | 说明 |
|---|---|---|
community_reports.max_length |
2000 |
报告生成的最大 token 长度 |
community_reports.max_input_length |
8000 |
送入报告生成 LLM 的输入上下文上限 |
community_reports.completion_model_id |
default_completion_model |
报告生成所用模型 |
community_reports.model_instance_name |
community_reporting |
LLM 缓存命名空间 |
7.3 Community Reports Table
以上全部完成后,导出最终 Community Reports 表。报告中既包含可读文本(供 global search 等下游基于 LLM 的总结式检索使用),也包含其关联社区与实体清单,是整个知识模型中价值密度最高的产物之一。
八、Phase 6:文本嵌入(Text Embeddings)
对于所有需要下游向量检索的产物,流水线在最后一步生成文本嵌入(text embedding),并直接写入配置的向量库。默认会嵌入三类内容:实体描述、TextUnit 文本、社区报告全文。
---
title: Text Embedding Workflows
---
flowchart LR
textUnits[Text Units] --> text_embed[Text Embedding]
graph_outputs[Graph Tables] --> description_embed[Description Embedding]
community_report_outputs[Community Reports] --> content_embed[Content Embedding]
8.1 三类默认嵌入及其源字段
generate_text_embeddings workflow(workflows/generate_text_embeddings.py)内部维护了一张字段映射表 EMBEDDING_FIELDS,决定"读哪张表、嵌入哪个列":
| 嵌入名称 | 源表 | 被嵌入列 | 备注 |
|---|---|---|---|
text_unit_text |
text_units | text |
TextUnit 全文 |
entity_description |
entities | title_description |
由 transform_entity_row_for_embedding 把标题与描述拼接成嵌入输入 |
community_full_content |
community_reports | full_content |
社区报告长版全文 |
默认开启这三类嵌入(相关默认值集中定义在 config/embeddings.py,并作为 embed_text.names 的默认值被 config/defaults.py 引用)。用户可增删 embed_text.names 以决定要生成哪些向量。
8.2 嵌入执行的实现细节
从源码可以看出该阶段的工程化要点:
- 每个字段独立创建向量库实例:
create_vector_store(config.vector_store, config.vector_store.index_schema[field_name]),schema 中描述了各字段的索引结构; - 真正执行批量嵌入的是
embed_text操作(operations/embed_text),批大小由embed_text.batch_size(默认 16)与embed_text.batch_max_tokens(默认 8191)控制; - 若
snapshots.embeddings开启,还会同时把向量以embeddings.{field_name}命名的快照表写出; - 若某字段对应源表不存在(例如关闭了 claims 而没有报告时嵌入源缺失),workflow 会打印 warning 并跳过该字段而非中断流水线。
向量库类型由 vector_store.type 指定,默认是 LanceDB(db_uri 默认 output/lancedb,见 VectorStoreDefaults)。仓库提供了 lancedb、Azure AI Search、CosmosDB 等实现,分布在独立的 graphrag-vectors 包(packages/graphrag-vectors)。索引侧的真实产物示例可参考示例语料下的向量文件(如 [embeddings.community_full_content.parquet](https://gitcode.com/GitHub_Trending/gr/graphrag/blob/7bb23cc7f32f47cf618a1ae9cca39a6695f434ae/docs/examples_notebooks/inputs/operation dulce/embeddings.community_full_content.parquet?utm_source=gitcode_repo_files) 与 lancedb/ 目录)。
九、索引产物落地形态与验证
默认配置下整条流水线跑完后,落地的典型 Parquet 产物与知识模型一一对应。以仓库示例语料(docs/examples_notebooks/inputs/operation dulce/)为例可以看到:documents.parquet、text_units.parquet、entities.parquet、relationships.parquet、covariates.parquet、communities.parquet、community_reports.parquet,外加可选的 embedding 快照与 lancedb/ 向量目录。
值得注意的是原文档对六阶段的划分与源码 workflow 顺序存在一处细节差异:文档将社区检测放在"Graph Tables 导出"之前,而真实流水线中 finalize_graph(生成最终实体/关系表)先于 create_communities 执行,随后才有 create_final_text_units 等步骤——理解这条真实执行顺序有助于你在裁剪自定义流水线时(通过 workflows 配置覆写默认列表)不遗漏前置依赖。
对每个阶段的正确性,仓库还提供了大量端到端测试可作为行为参考,例如:
- tests/verbs/test_create_base_text_units.py
- tests/verbs/test_extract_graph.py
- tests/verbs/test_create_communities.py
- tests/verbs/test_create_community_reports.py
- tests/verbs/test_generate_text_embeddings.py
这些测试与本文描述的六个阶段一一印证,是深入理解每个 workflow 输入输出契约的最佳阅读起点。
十、进一步阅读
- 索引引擎的整体架构与 workflow 编排:见 docs/index/architecture.md,其中还介绍了 LLM 缓存层与工厂模式(Providers & Factories),帮助你理解为何各阶段都有独立缓存命名空间;
- 配置详解与
settings.yaml写法:docs/config/overview.md、docs/config/yaml.md; - 快速上手的初始化与运行方式:docs/config/init.md;
- 默认值全集与 dataclass 定义:packages/graphrag/graphrag/config/defaults.py;
- 标准/快速/增量索引流水线注册:packages/graphrag/graphrag/index/workflows/factory.py。
掌握了本文的六大阶段脉络,再结合源码逐步定位每个 workflow 的输入输出,你就拥有了按需裁剪、调优乃至自定义 GraphRAG 索引流水线的完整地图。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00