跳到主要内容

第 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_graphpackages/graphrag/graphrag/index/operations/cluster_graph.py)的处理链:

  1. 归一化 + 去重边:把每条边的 (source,target) 排序成无向对、去掉反向重复(_compute_leiden_communitieslo/hi + drop_duplicates)。
  2. 可选取最大连通块use_lcc 为真时只保留最大连通子图(stable_lcc),丢掉零散孤岛。
  3. 跑分层 Leidenhierarchical_leiden(edge_list, max_cluster_size, random_seed)packages/graphrag/graphrag/graphs/hierarchical_leiden.py),受 max_cluster_size 约束——一个社区太大就继续往下切一层,这正是"分层"的来源。
  4. 整理成 (level, cluster, parent, nodes) 四元组返回。

create_communitiespackages/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",让聚类结果在同输入下可复现——对"想每次跑出一样的图"很关键。


3.3 社区报告:自底向上滚动生成(最妙的一步)

有了社区树,就要给每个社区写一份摘要报告。天真做法是"把社区里所有实体+关系描述喂给 LLM",但上层大社区的原料会远超上下文窗口。GraphRAG 的解法是自底向上、逐层滚动

最底层社区 (叶子):原料 = 自己的实体 + 关系 + (可选)claims 描述
│ LLM 各写一份报告

上一层社区:原料够小就同上;
原料太大(超 max_input_length)就【改用其子社区已写好的报告】当输入
│ LLM 写报告

... 一直滚到 level 0,每个社区都有一份报告

主循环在 summarize_communitiespackages/graphrag/graphrag/index/operations/summarize_communities/summarize_communities.py):它按 get_levels 从底层到高层遍历,对每层用 level_context_builder(即 build_level_context)拼这一层每个社区的上下文——关键就在这里:当某社区的"本地上下文"(自己的实体/边)放不下时,build_level_context 会用下层已生成的报告替代,从而把信息"压缩着往上带"。

# 示意,非源码。对应 summarize_communities 的分层循环骨架
for level in levels: # 从底层往上
level_context = build_level_context(
pd.DataFrame(reports), # 已经写好的下层报告
community_hierarchy_df=...,
local_context_df=local_contexts, # 每个社区的"本地"实体/边上下文
level=level, max_context_tokens=max_input_length)
local_reports = await derive_from_rows(level_context, run_generate, ...) # 并发写报告
reports.extend(local_reports) # 累积,供更上层复用

为什么这样最省又不丢信息(精华): 底层报告已经把"一小撮实体讲了什么"浓缩好了;上层直接拿下层报告当积木,就不必把成千上万条原始描述再塞一次——用"报告的报告"逼近"全体原料的摘要",既不爆上下文、又保留了层级信息。这也正是 global search 能"读几百份报告答全局"的前提。


3.4 一份社区报告长什么样

单个社区的报告由 CommunityReportsExtractorpackages/graphrag/graphrag/index/operations/summarize_communities/community_reports_extractor.py)用 JSON 模式生成,结构化字段(CommunityReportResponse):

字段含义
title这个社区的主题名
summary一段总摘要
findings若干"发现",每条含 summary + explanation(详述 + 依据)
rating该社区"重要性/影响力"评分(浮点)
rating_explanation评分理由

_get_text_output 会把这些拼成一份 Markdown 全文(full_content),既存结构化 JSON 也存拼好的文本,两种形态查询期都用得上。最后 finalize_community_reports 把报告接回社区元信息,产出 community_reports 表(列见 COMMUNITY_REPORTS_FINAL_COLUMNS:含 summary, full_content, rating, findings, full_content_json, size 等)。

那个 rating(重要性评分)不是摆设:global search 排序、动态社区选择都会用它当"这个社区值不值得读"的信号(见第 04 章)。


3.5 代码地图

主题文件路径符号名
聚类算子(去重/LCC/Leiden)packages/graphrag/graphrag/index/operations/cluster_graph.pycluster_graph,_compute_leiden_communities
分层 Leiden 实现packages/graphrag/graphrag/graphs/hierarchical_leiden.pyhierarchical_leiden
最大连通块packages/graphrag/graphrag/graphs/stable_lcc.pystable_lcc
建社区表packages/graphrag/graphrag/index/workflows/create_communities.pycreate_communities
社区报告 workflowpackages/graphrag/graphrag/index/workflows/create_community_reports.pycreate_community_reports
自底向上滚动摘要packages/graphrag/graphrag/index/operations/summarize_communities/summarize_communities.pysummarize_communities
分层上下文(报告代原料).../summarize_communities/graph_context/context_builder.pybuild_level_context,build_local_context
单份报告生成(JSON 结构).../summarize_communities/community_reports_extractor.pyCommunityReportsExtractor,CommunityReportResponse
社区/报告列定义packages/graphrag/graphrag/data_model/schemas.pyCOMMUNITIES_FINAL_COLUMNS,COMMUNITY_REPORTS_FINAL_COLUMNS