RAGFlow v0.16.0 深度技术解析

知识图谱核心技术
全链路解析

从实体抽取到图检索融合,深入剖析 RAGFlow GraphRAG 模块的每一步技术实现细节, 揭示向量 RAG 与图 RAG 双引擎协同的架构奥秘

5
核心模块
2
抽取模式
N-hop
多跳推理
P(E|Q)
概率评分

GraphRAG 模块概述

GraphRAG 是 RAGFlow 的知识图谱增强检索模块,通过构建实体-关系图谱来增强传统 RAG 的检索能力,实现从隐式语义匹配到显式关系推理的跃迁

图谱构建
基于 LLM 从文档中抽取实体与关系,使用 NetworkX 构建知识图谱,支持增量合并与 PageRank 计算
实体消解
两阶段实体归一化策略:编辑距离初筛 + LLM 精判,合并指代同一实体的不同表述,v0.16 起可手动关闭
社区发现
基于 Leiden 层级社区检测算法,自动发现实体聚类,生成社区摘要报告,增强全局理解能力
图谱检索
KGSearch 多路径检索:关键词实体搜索、向量相似度召回、N-hop 邻居探索、社区报告检索
双引擎融合
向量检索器 (Dealer) 与图检索器 (KGSearch) 并行工作,图结果优先插入,实现跨模态互补增强
灵活配置
实体归一化可选、社区报告可选、Light/General 模式切换,在效果与成本之间灵活 Trade-off

GraphRAG vs 传统 RAG 对比

特性维度 传统 RAG GraphRAG
数据结构文本块 (Chunks)文本块 + 知识图谱
检索方式向量相似度向量 + 图遍历
关系理解隐式(上下文窗口)显式(实体关系三元组)
多跳推理 困难 支持
全局理解 强(社区摘要)
实体消歧 不支持 可选
Token 开销较高(可配置优化)

目录结构与核心概念

GraphRAG 模块位于 ragflow/rag/graphrag/ 目录下,采用分层模块化设计

目录结构

graphrag/
├── __init__.py
├── utils.py              # 工具函数 (graph_merge, set_graph, get_graph)
├── search.py             # KGSearch 图谱检索器
├── entity_resolution.py    # 实体消解器
├── entity_resolution_prompt.py# 消解提示词
├── query_analyze_prompt.py  # 查询分析提示词
├── general/              # 通用图谱提取
│   ├── index.py           # run_graphrag 主流程
│   ├── graph_extractor.py  # GraphExtractor 提取器
│   ├── graph_prompt.py     # 微软 GraphRAG 提示词
│   ├── community_reports_extractor.py
│   ├── leiden.py          # Leiden 社区发现
│   └── mind_map_extractor.py
└── light/                # 轻量级图谱
    ├── graph_extractor.py
    └── graph_prompt.py     # LightRAG 提示词

处理流程总览

1
文档分块
获取文档 chunks,准备输入文本块
2
实体关系提取
LLM 驱动,General 多轮 Gleaning / Light 单轮快速提取
3
子图生成与合并
NetworkX 构建子图 → graph_merge() 合并至全局图 → 更新 PageRank
4
实体消解 可选
编辑距离初筛 + LLM 精判,合并重复实体节点
5
社区发现与摘要 可选
Leiden 层级社区检测 → 社区报告生成 → 向量索引

核心数据结构

实体 (Entity)
name str 实体名称
type str Person/Org/Event...
description str 实体描述
attributes dict 扩展属性
关系 (Relation)
source str 源实体
target str 目标实体
type str 关系类型
description str 关系描述
weight float 关系权重
社区 (Community)
entities list 实体集合
level int 层级深度
report str 摘要报告

图谱构建主流程

run_graphrag() 是整个知识图谱构建的入口函数,编排了从文档分块到社区报告的完整流水线

graphrag/general/index.py
核心入口
async def run_graphrag(
    row: dict,
    language,
    with_resolution: bool,   # 是否启用实体消解
    with_community: bool,   # 是否启用社区发现
    chat_model,
    embedding_model,
    callback,
):
    # Step 1: 获取文档分块
    chunks = []
    for d in settings.retrievaler.chunk_list(doc_id, tenant_id, [kb_id]):
        chunks.append(d["content_with_weight"])

    # Step 2: 生成子图(根据 method 选择提取器)
    subgraph = await generate_subgraph(
        LightKGExt if method != "general" else GeneralKGExt,
        tenant_id, kb_id, doc_id, chunks,
        language, entity_types, chat_model, embedding_model,
    )

    # Step 3: 合并子图到全局知识图谱
    new_graph = await merge_subgraph(
        tenant_id, kb_id, doc_id, subgraph, embedding_model,
    )

    # Step 4: 实体消解(可选)
    if with_resolution:
        await resolve_entities(new_graph, subgraph_nodes, ...)

    # Step 5: 社区发现与报告(可选)
    if with_community:
        await extract_community(new_graph, tenant_id, kb_id, ...)

图谱合并策略 — graph_merge()

节点合并
当节点已存在时,将新节点的描述信息叠加至原有节点描述中,保留完整语义信息。同时重新计算所有节点的 PageRank 分数,确保全局图权重分布的准确性。
关系合并
当关系(边)已存在时,将新关系的描述信息、权重和关键词叠加至原有关系。关系权重随多次出现而累积增强,反映实体间关联的置信度。
v0.16 关键变更
旧版: 每个文档 → 独立知识图谱   →   新版: 每个知识库 → 统一知识图谱
单文档的 Graph 实体动态更新到知识库级图谱中,删除文档时同步移除对应实体,实现增量式图谱演化

实体与关系抽取

知识图谱构建的基础环节,通过精心设计的 Prompt 和 Few-Shot 机制,利用 LLM 完成实体和关系的结构化抽取

General 模式 — 微软 GraphRAG Prompt

  • 采用微软 GraphRAG 标准提示词,实体描述更详细完整
  • 支持多轮提取 (Gleaning):首轮提取后,LLM 继续追问"是否还有遗漏的实体",进行补充提取
  • max_gleanings 参数控制追加轮次(默认 1 轮)
  • Token 消耗较高,适合知识密集型场景
  • 支持实体消解和社区发现完整流程
graphrag/general/graph_extractor.py
class GraphExtractor(Extractor):
    def __init__(self, llm_invoker, language="English",
             entity_types=None, max_gleanings=1):
        self.max_gleanings = max_gleanings

    async def _process_single_content(self, chunk):
        # 第1轮: 标准提取
        result = await self._invoke_llm(prompt)
        # 第2~N轮: Gleaning 追加提取
        for i in range(self.max_gleanings):
            glean_result = await self._invoke_llm(glean_prompt)
            result += glean_result

Light 模式 — LightRAG Prompt

  • 采用 LightRAG 简化提示词,Token 消耗显著降低
  • 单轮提取,无 Gleaning 追加,速度更快
  • 适合大规模文档的快速图谱构建
  • 抽取效果与大模型能力和数据特征相关,建议对比测试
  • 适合快速原型验证和成本敏感场景
graphrag/light/graph_extractor.py
class GraphExtractor(Extractor):
    """轻量级图谱提取器 — 单轮快速提取"""
    def __init__(self, llm_invoker, language="English",
             entity_types=None):
        # 无 max_gleanings 参数
        # 使用简化的 LightRAG 提示词
        pass
graphrag/general/graph_prompt.py
General Prompt
GRAPH_EXTRACTION_PROMPT = """
-Goal-
Given a text document, identify all entities and relationships.

-Steps-
1. Identify entities: entity_name, entity_type, entity_description
2. Identify relationships: source_entity, target_entity,
   relationship_description, relationship_strength
3. Return output in {language}
4. When finished, output {completion_delimiter}

Entity_types: {entity_types}
Text: {input_text}
Output:
"""
Few-Shot 机制
Prompt 中嵌入示例输出格式,引导 LLM 按照固定分隔符输出实体和关系,便于后续基于分隔符的结构化解析
结果解析
_entities_and_relations() 方法基于预定义分隔符对 LLM 输出进行切分,提取结构化的实体名称、类型、描述及关系信息

实体类型设计

通用实体类型
Person 人物 Organization 组织 Location 地点 Event 事件 Product 产品 Technology 技术 Concept 概念
领域特定类型(医疗示例)
Disease 疾病 Symptom 症状 Drug 药物 Treatment 治疗 BodyPart 部位

实体消解

合并指代同一实体的不同表述,消除图谱中的冗余节点,是提升检索准确性的关键环节

实体消解示例
"苹果公司" ←→ "Apple Inc." ←→ "苹果"
三个不同表述指向同一实体,消解后合并为单一节点,保留所有描述信息

两阶段消解策略

阶段一:编辑距离初筛

使用 editdistance 库计算实体名称间的编辑距离,快速筛选出可能需要合并的候选实体对。

目的:减少候选对数量,避免将大量实体对送入 LLM 判断,显著降低 Token 消耗。

这一步是纯工程手段,速度快、零 Token 开销。

def _find_candidates(self, entities):
    """基于编辑距离找出候选合并对"""
    candidates = []
    for e1, e2 in combinations(entities, 2):
        if editdistance.eval(e1, e2) < threshold:
            candidates.append((e1, e2))
    return candidates
阶段二:LLM 精判合并

将初筛后的候选实体对送入 LLM,由大模型判断两个实体是否确实指代同一事物。

LLM 能理解语义层面的等价关系(如缩写、别名、多语言表述),远超字符串匹配的能力。

这是 Token 消耗的主要来源,也是 v0.16 提供手动关闭选项的原因。

async def _should_merge(self, ent1, ent2) -> bool:
    """使用 LLM 判断是否合并"""
    prompt = ENTITY_RESOLUTION_PROMPT.format(
        entity1=ent1, entity2=ent2
    )
    result = await self.llm.invoke(prompt)
    return result == "YES"
graphrag/entity_resolution.py
核心类
class EntityResolution:
    """实体消解器"""

    def __init__(self, llm, resolution_prompt=ENTITY_RESOLUTION_PROMPT):
        self.llm = llm

    async def resolve(self, entities: list[dict], graph: nx.Graph):
        # 1. 按类型分组
        grouped = group_by_type(entities)
        # 2. 对每个类型组进行消解
        for entity_type, group in grouped.items():
            candidates = self._find_candidates(group)
            for e1, e2 in candidates:
                if await self._should_merge(e1, e2):
                    merge_nodes(graph, e1, e2)
        # 3. 返回更新后的图
        return graph

社区发现与摘要

基于 Leiden 层级社区检测算法自动发现实体聚类,生成社区摘要报告,增强全局理解能力

Leiden 算法

Leiden 算法通过模块度优化生成高质量的社区划分,相比 Louvain 算法解决了"连接不良社区"的问题。

RAGFlow 使用 graspologic 库的 hierarchical_leiden 实现,支持多层级社区划分。

每个层级产生不同粒度的社区聚类,上层更粗粒度,下层更细粒度。

graphrag/general/leiden.py
def _compute_leiden_communities(
    graph: nx.Graph,
    max_cluster_size: int,
    use_lcc: bool = True,
    seed=0xDEADBEEF,
) -> dict[int, dict[str, int]]:
    if use_lcc:
        graph = stable_largest_connected_component(graph)
    # 多层级社区划分
    community_mapping = hierarchical_leiden(
        graph, max_cluster_size=max_cluster_size,
        random_seed=seed
    )
    results = {}
    for partition in community_mapping:
        level = partition.level
        results.setdefault(level, {})
        results[level][partition.node] = partition.cluster
    return results

社区摘要生成

CommunityReportsExtractor

为每个社区生成摘要报告,基于社区内实体和关系的描述信息,通过 LLM 生成能够代表社区核心内容的文本。

社区摘要的核心价值:提升社区召回的准确性。当用户查询涉及全局性问题时,社区摘要能提供宏观视角的回答。

v0.16 起社区报告生成变为可选,因为该步骤完全依赖 LLM,是 Token 消耗的重要来源之一。

community_reports_extractor.py
class CommunityReportsExtractor:
    def __init__(self, llm, max_tokens=4096):
        self.llm = llm

    async def extract_reports(self, graph, communities, level=0):
        reports = []
        for community_id, entities in communities.items():
            # 收集社区内实体和关系
            context = build_context(graph, entities)
            # LLM 生成摘要
            report = await self.llm.invoke(prompt)
            reports.append(report)
        return reports
社区发现流程
知识图谱 → 最大连通分量层级 Leiden 划分多粒度社区社区摘要报告
每个层级的社区包含不同粒度的实体聚类,上层社区更宏观,下层社区更精细,支持多尺度知识理解

图谱检索 — KGSearch

KGSearch 是知识图谱检索的核心类,实现了从查询分析到多路径检索再到概率评分的完整检索链路

1
查询重写 — query_rewrite()
使用 LLM 分析用户问题,提取相关的实体关键词实体类型,为后续图检索提供种子
2
关键词实体向量搜索
通过提取的实体类型在知识图谱中做 PageRank 计算(随机游走),得到 PageRank 值前 N 的实体及其描述
3
实体向量相似度召回
通过查询中提取的实体进行向量相似度召回,获取相似实体及其描述,以及 N-hop 的实体关系
4
关系向量搜索
通过原始问题用向量相似度召回实体关系及其描述,直接定位问题相关的关系三元组
5
N-hop 邻居探索
从种子实体出发,进行 N 跳扩展,收集邻居节点和边,实现相似度衰减的多跳关系推理
6
概率评分排序
对实体和关系进行排序,排序理论支撑贝叶斯公式
7
社区检索
用相关实体召回 Top 1 社区摘要,提供全局视角的上下文信息
核心评分公式 — 贝叶斯概率排序
P(E|Q) = P(E) × P(Q|E) = PageRank × Similarity
P(E) — 实体/关系的先验重要性(PageRank 值,基于图结构随机游走计算)
P(Q|E) — 给定实体/关系时查询的似然度(向量相似度,基于 Embedding 计算)
两者相乘得到后验概率,既考虑了实体在图中的全局重要性,又考虑了与查询的语义相关性
graphrag/search.py
核心检索类
class KGSearch(Dealer):
    """知识图谱检索器"""

    def query_rewrite(self, llm, question, idxnms, kb_ids):
        """查询重写:提取关键词和实体类型"""
        prompt = QUERY_ANALYZE_PROMPT.format(question=question)
        result = llm.invoke(prompt)
        return type_keywords, entities_from_query

    def retrieval(self, question, tenant_ids, kb_ids,
              emb_mdl, llm,
              ent_topn=6, rel_topn=6, comm_topn=1,
              ent_sim_threshold=0.3):
        # 1. 查询重写
        type_keywords, entities = self.query_rewrite(...)
        # 2. 检索相关实体 (PageRank + 向量)
        entities = self._search_entities(...)
        # 3. 检索相关关系
        relations = self._search_relations(...)
        # 4. N-hop 扩展
        extended = self.extend_by_n_hop(entities, graph, n_hop=2)
        # 5. 社区检索
        communities = self._community_retrival_(...)
        return entities, relations, communities, token_count

N-hop 多跳遍历

graphrag/search.py — extend_by_n_hop
def extend_by_n_hop(self, seed_entities, graph, n_hop=2):
    """从种子实体出发,进行 N 跳扩展"""
    visited = set(seed_entities.keys())
    current_hop = set(seed_entities.keys())
    for hop in range(n_hop):
        next_hop = set()
        for node in current_hop:
            for neighbor in graph.neighbors(node):
                if neighbor not in visited:
                    next_hop.add(neighbor)
                    visited.add(neighbor)
        # 相似度随跳数衰减
        decay_factor = 1.0 / (hop + 2)
        current_hop = next_hop
    return extended_entities

RAG + GraphRAG 融合机制

向量检索器与图检索器并行工作,通过跨模态融合策略实现互补增强,图结果优先展示确保关键实体关系信息不被淹没

向量检索器 (Dealer)

  • 全文搜索 (BM25/关键词)
  • 向量语义搜索 (Embedding)
  • 加权融合: 5% 文本 + 95% 向量
  • 可选 Rerank 重排序
  • TOC 引导检索
  • 父子块检索
并行执行

图检索器 (KGSearch)

  • 查询重写 (LLM 实体提取)
  • PageRank 实体排序
  • 向量相似度实体召回
  • N-hop 邻居探索
  • 关系向量搜索
  • 社区报告检索

跨模态融合结果

图检索结果前置插入到向量检索结果的位置 0,确保知识图谱的结构化关系信息优先展示
向量检索提供语义匹配,图检索提供结构化关系推理,两者互补增强

检索融合实现
融合逻辑
# 向量检索
ranks = settings.retrievaler.retrieval(
    question, embd_mdl, kb.tenant_id, [kb_id],
    page=1, page_size=top,
    similarity_threshold=similarity_threshold,
    vector_similarity_weight=0.3,
    top=top,
)

# 可选开启知识图谱检索
if use_kg:
    ck = settings.kg_retrievaler.retrieval(
        question, [tenant_id], [kb_id],
        emb_mdl, LLMBundle(kb.tenant_id, LLMType.CHAT)
    )
    # 图检索结果插入最前面,知识图谱优先展示
    if ck["content_with_weight"]:
        ranks["chunks"].insert(0, ck)

融合配置参数

use_kg
是否启用知识图谱检索,关闭后仅使用向量检索
vector_similarity_weight
关键词与向量搜索的权重比例(默认 0.3)
similarity_threshold
最小相似度阈值,低于此值的结果被过滤
rerank_id
重排序模型 ID,可选启用 Rerank 进一步优化排序
top_n
返回结果数量,控制最终检索的 chunk 数量
ent_topn / rel_topn / comm_topn
实体/关系/社区的返回数量(默认 6/6/1)

数据库引擎融合差异

数据库引擎向量检索融合方式特点
Elasticsearch Boost-based fusion 基于提升因子的融合,将向量分数转换为 Boost 值
Infinity Atan 标准化融合 使用 Arctan 函数标准化分数后融合,更平滑

配置建议与最佳实践

根据不同场景需求,在效果与成本之间做出最优权衡

场景 抽取模式 实体消解 社区报告 推荐理由
快速原型 Light 最低成本快速验证
生产环境 General 完整功能,最佳效果
大规模文档 Light 平衡速度和质量
知识密集型 General 多跳推理 + 全局理解

性能优化策略

并发提取
多个文本块的实体关系提取可并发执行,通过 max_concurrent 参数控制并发度,显著提升构建速度
批量索引
实体和关系的向量索引采用批量写入策略,batch_size 可配置,减少数据库写入次数
LLM 缓存
对相同 Prompt 的 LLM 调用结果进行缓存,避免重复请求,降低 Token 消耗和延迟
v0.16 核心设计哲学
效果 ← 可配置权衡 → 成本
实体归一化可选 · 社区报告可选 · Light/General 模式切换 · 检索参数可调
每一个高 Token 消耗环节都提供开关,让用户在知识图谱质量和成本之间自主决策

关键注意事项

文档解析质量
知识图谱构建前务必检查文档解析质量。OCR 误识别会导致关键术语错误,使后续实体关系全部断裂。建议先导出解析后的纯文本预览确认。
模型选择影响
不同 LLM 对同一段文字可能给出不同标签体系。可视化审查工具不是锦上添花,而是必经环节。建议根据领域特点选择合适的模型。
实体类型设计
选择具有实际业务价值的实体类型至关重要,这直接影响知识图谱的准确性。通用类型适合起步,领域特定类型提升精度。
可视化审查
自动构建的知识图谱通常无法达到数据可视化的完美要求,主要作为辅助召回存在。可视化审查工具帮助发现和修正错误连接。