数据截至 (上游 commit 03c7a3d2b2eb)
第 3 章 · 社区与社区报告:图的分层归纳
这章讲什么: GraphRAG 区别于普通 RAG 的核心资产,是把知识图切成一层层"社区"、再给每个社区预先写好一份摘要报告。本章讲 Leiden 分层聚类怎么把图切成树状社区(
create_communities),以及社区报告怎么自底向上滚动生成(create_community_reports)。
3.1 为什么要"社区"
回到最初那个痛点:全局问题("这批文档整体在讲什么")的答案不在任何单个文本块里。GraphRAG 的解法是:既然实体图上"联系紧密的一撮实体"往往对应一个主题,那就把图切成一撮一撮(社区),每撮写一份摘要——全局问题就变成"读这些摘要再汇总"。
"联系紧密的一撮节点"在图论里叫社区检测。GraphRAG 用的是 Leiden 算法(一种社区检测算法,能把图划分成模块度高的簇),而且用 它的分层版本,得到一棵社区树。
3.2 分层 Leiden:把图切成一棵社区树
怎么读这张图:level 0 是最粗的大社区,往下每层把大社区再切成更小的子社区,形成父子树;每个实体在每一层都属于某个社区。
level 0: [ 社区 C0 ........................... ] (整张图/最大连通块粗分)
│ 细分
level 1: [ C0-a ] [ C0-b ] [ C0-c ] ... (每个再切小)
│
level 2: [C0-a-1][C0-a-2] ... (继续切,直到够小)
聚类入口 cluster_graph(packages/graphrag/graphrag/index/operations/cluster_graph.py)的处理链:
- 归一化 + 去重边:把每条边的 (source,target) 排序成无向对、去掉反向重复(
_compute_leiden_communities里lo/hi+drop_duplicates)。 - 可选取最大连通块:
use_lcc为真时只保留最大连通子图(stable_lcc),丢掉零散孤岛。 - 跑分层 Leiden:
hierarchical_leiden(edge_list, max_cluster_size, random_seed)(packages/graphrag/graphrag/graphs/hierarchical_leiden.py),受max_cluster_size约束——一个社区太大就继续往下切一层,这正是"分层"的来源。 - 整理成 (level, cluster, parent, nodes) 四元组返回。
create_communities(packages/graphrag/graphrag/index/workflows/create_communities.py)拿到聚类结果后,做几件"填表"的事:给每个社区聚合它的 entity_ids;只聚合社区内部的边(source 和 target 同属一个社区,见 intra = with_both[community_x == community_y])当 relationship_ids;用 parent/children 把树的双向指针建好。产物是 communities 表(列见 data_model/schemas.py(COMMUNITIES_FINAL_COLUMNS))。
可复现性:
seed会透传给 Leiden(random_seed=seed),配上stable_lcc的"stable",让聚类结果在同输入下可复现——对"想每次跑出一样的图"很关键。