传统 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:何时选哪个?
| 场景 | 传统 RAG | GraphRAG |
|---|---|---|
| 单文档问答 | ✅ 够用 | ❌ 杀鸡用牛刀 |
| 多文档综合 | ⚠️ 有限 | ✅ 擅长 |
| 多跳推理 | ❌ 难以处理 | ✅ 天然适合 |
| 关系查询 | ❌ 不支持 | ✅ 核心优势 |
| 索引成本 | 低 | 高(需大量 LLM 调用) |
| 更新频率 | 可增量更新 | 全量重建成本高 |
| 实时数据 | 适合 | 不适合(静态知识库) |
黄金法则:
- 知识库内实体关系丰富、问题需要多跳推理 → GraphRAG
- 知识库以陈述性事实为主、问题相对独立 → 传统 RAG
- 两者结合(Hybrid)→ 用传统 RAG 做快速召回,用 GraphRAG 做深度推理
GraphRAG 代表了 RAG 技术演进的重要方向。随着工具链成熟和成本下降,预计 2026-2027 年它将成为企业级知识库系统的标准配置。现在掌握它,是抢占技术先机的正确时机。