GraphRAG实战:知识图谱增强检索的工程落地

3 阅读1分钟

传统 RAG 的检索是「局部的」——它找到最相关的文本块,但看不见块与块之间的关系。GraphRAG 通过引入知识图谱,让检索可以沿着实体关系游走,回答传统 RAG 回答不了的「多跳推理」问题。本文从原理到工程实践,带你完整落地 GraphRAG。

一、传统 RAG 的局限性

假设你的知识库包含以下三段文档:

  • 文档A:「张伟是字节跳动的AI研究院院长」
  • 文档B:「字节跳动在2023年发布了豆包大模型」
  • 文档C:「豆包大模型在代码生成任务上超过了GPT-4」

问题:「张伟领导的团队开发的大模型在代码任务上的表现如何?」

传统 RAG 的问题:

  • 向量检索可能只召回文档A(最相关于「张伟」),或文档C(最相关于「代码表现」)
  • 无法将三段文档的信息链接起来进行多跳推理
  • 答案需要:张伟 → 字节跳动 → 豆包大模型 → 代码性能

这就是知识图谱的用武之地。

二、GraphRAG 核心架构

GraphRAG(由 Microsoft 2024年提出并开源)的工作流分为两个阶段:

2.1 索引阶段(离线)

原始文档
    ↓ 文本分块
文本块
    ↓ LLM抽取实体与关系
知识图谱(实体节点 + 关系边)
    ↓ 图社区检测
社区层级(Leiden算法)
    ↓ LLM生成社区摘要
社区摘要向量化
    ↓ 存入向量数据库
图索引 + 向量索引

2.2 查询阶段(在线)

Global Search(全局搜索)

  • 适用于需要概览整个知识库的问题(「这个知识库主要讲了什么?」)
  • 利用社区摘要层级,从高层向下检索
  • 生成 map-reduce 风格的答案

Local Search(局部搜索)

  • 适用于针对特定实体的问题(「张伟负责哪些项目?」)
  • 先找到相关实体,再通过图关系扩展上下文
  • 结合向量检索和图遍历

三、Microsoft GraphRAG 快速上手

3.1 安装

pip install graphrag

3.2 初始化项目

mkdir kg-project && cd kg-project
python -m graphrag.index --init --root .

这会生成以下目录结构:

kg-project/
├── .env                    # API Key 配置
├── settings.yaml           # 核心配置
└── input/                  # 放你的文档

3.3 配置

.env 文件:

GRAPHRAG_API_KEY=your-openai-api-key

settings.yaml 关键配置:

llm:
  api_key: ${GRAPHRAG_API_KEY}
  type: openai_chat
  model: gpt-4o-mini        # 抽取用 mini 降成本
  max_tokens: 4000

embeddings:
  async_mode: threaded
  llm:
    api_key: ${GRAPHRAG_API_KEY}
    type: openai_embedding
    model: text-embedding-3-small

chunks:
  size: 1200
  overlap: 100

entity_extraction:
  max_gleanings: 1          # 最大抽取轮数
  
community_reports:
  max_length: 2000          # 社区摘要最大长度

local_search:
  text_unit_prop: 0.5       # 文本块占上下文比例
  community_prop: 0.1       # 社区摘要占比
  conversation_history_max_turns: 5

3.4 建立索引

# 将文档放入 input/ 目录后
python -m graphrag.index --root .

索引完成后,会生成 output/ 目录包含:

  • entities.parquet:所有抽取的实体
  • relationships.parquet:实体间关系
  • communities.parquet:社区划分结果
  • community_reports.parquet:社区摘要

3.5 查询

# 全局查询
python -m graphrag.query \
  --root . \
  --method global \
  "这些文档的主要主题是什么?"

# 局部查询
python -m graphrag.query \
  --root . \
  --method local \
  "张伟领导的团队开发了哪些AI产品?"

四、自定义 GraphRAG 系统

如果你需要更灵活的控制,可以使用 LlamaIndex 的 PropertyGraphIndex 自建 GraphRAG:

from llama_index.core import SimpleDirectoryReader, PropertyGraphIndex
from llama_index.core.indices.property_graph import (
    ImplicitPathExtractor,
    SimpleLLMPathExtractor,
)
from llama_index.llms.openai import OpenAI
from llama_index.embeddings.openai import OpenAIEmbedding

# 加载文档
documents = SimpleDirectoryReader("./data").load_data()

# 配置实体抽取
llm = OpenAI(model="gpt-4o-mini", temperature=0)
embed_model = OpenAIEmbedding(model="text-embedding-3-small")

# 构建知识图谱索引
index = PropertyGraphIndex.from_documents(
    documents,
    kg_extractors=[
        # 隐式路径:基于共现关系
        ImplicitPathExtractor(),
        # 显式路径:LLM抽取三元组
        SimpleLLMPathExtractor(
            llm=llm,
            max_paths_per_chunk=10,
            num_workers=4,
        ),
    ],
    embed_model=embed_model,
    show_progress=True,
)

# 持久化
index.storage_context.persist("./graph_storage")

4.1 自定义实体类型

from llama_index.core.indices.property_graph import SchemaLLMPathExtractor
from typing import Literal

# 定义领域特定的实体类型
entities = Literal["人物", "组织", "产品", "技术", "地点"]
relations = Literal["领导", "开发", "隶属于", "使用", "发布"]

# 定义合法的三元组模式
schema = {
    "人物": {"领导": ["组织"], "开发": ["产品", "技术"]},
    "组织": {"发布": ["产品"], "使用": ["技术"]},
    "产品": {"隶属于": ["组织"]},
}

extractor = SchemaLLMPathExtractor(
    llm=llm,
    possible_entities=entities,
    possible_relations=relations,
    kg_validation_schema=schema,
    strict=True,  # 严格模式,只提取符合 schema 的三元组
)

4.2 混合检索(图 + 向量)

from llama_index.core.query_engine import RetrieverQueryEngine
from llama_index.core.retrievers import VectorContextRetriever, LLMSynonymRetriever

# 图检索器(基于实体关系扩展)
graph_retriever = index.as_retriever(
    include_text=True,          # 包含原始文本
    similarity_top_k=5,         # 向量相似度 top-5
)

# 同义词扩展检索
synonym_retriever = LLMSynonymRetriever(
    index.property_graph_store,
    llm=llm,
    include_text=False,
)

# 组合检索
from llama_index.core.retrievers import PGRetriever

hybrid_retriever = PGRetriever(
    sub_retrievers=[graph_retriever, synonym_retriever]
)

# 构建查询引擎
query_engine = RetrieverQueryEngine.from_args(
    retriever=hybrid_retriever,
    llm=llm,
)

# 查询
response = query_engine.query(
    "张伟领导的团队开发的大模型在代码任务上表现如何?"
)
print(response)

五、知识图谱可视化

建立知识图谱后,可视化是理解和调试的重要工具:

import networkx as nx
import matplotlib.pyplot as plt
from pyvis.network import Network

def visualize_kg(relationships_df, output_html="kg_viz.html"):
    """使用 pyvis 生成交互式知识图谱可视化"""
    net = Network(
        height="750px", width="100%",
        bgcolor="#222222", font_color="white",
        notebook=False
    )
    
    # 添加节点和边
    entities_added = set()
    for _, row in relationships_df.iterrows():
        src = row['source']
        tgt = row['target']
        rel = row['description']
        
        if src not in entities_added:
            net.add_node(src, label=src, color="#4EA0AE")
            entities_added.add(src)
        
        if tgt not in entities_added:
            net.add_node(tgt, label=tgt, color="#FF6B6B")
            entities_added.add(tgt)
        
        net.add_edge(src, tgt, title=rel, label=rel[:20])
    
    # 物理布局配置
    net.set_options("""
    {
      "physics": {
        "forceAtlas2Based": {
          "springLength": 100,
          "springConstant": 0.08
        },
        "solver": "forceAtlas2Based"
      }
    }
    """)
    
    net.save_graph(output_html)
    print(f"知识图谱已保存: {output_html}")

六、GraphRAG vs 传统 RAG:何时选哪个?

场景传统 RAGGraphRAG
单文档问答✅ 够用❌ 杀鸡用牛刀
多文档综合⚠️ 有限✅ 擅长
多跳推理❌ 难以处理✅ 天然适合
关系查询❌ 不支持✅ 核心优势
索引成本高(需大量 LLM 调用)
更新频率可增量更新全量重建成本高
实时数据适合不适合(静态知识库)

黄金法则

  • 知识库内实体关系丰富、问题需要多跳推理 → GraphRAG
  • 知识库以陈述性事实为主、问题相对独立 → 传统 RAG
  • 两者结合(Hybrid)→ 用传统 RAG 做快速召回,用 GraphRAG 做深度推理

GraphRAG 代表了 RAG 技术演进的重要方向。随着工具链成熟和成本下降,预计 2026-2027 年它将成为企业级知识库系统的标准配置。现在掌握它,是抢占技术先机的正确时机。