1. 为什么你的 RAG 总是在"胡说八道"?
2024/2025 年,RAG(检索增强生成)已经成为了企业落地大模型的标配。我们把文档切片(Chunking),存入向量数据库(Vector DB),然后用余弦相似度(Cosine Similarity)去匹配。
一切看起来很美,直到你遇到这种问题:
用户提问: "对比一下 A 项目和 B 项目在 2023 年的营收策略有什么不同?"
如果你的文档里,A 项目的策略在第 10 页,B 项目的策略在第 50 页。
● 传统 Vector RAG 的表现: 它可能检索到了 A 的片段,也检索到了 B 的片段,但它无法理解两者之间的关联。更糟糕的是,如果文档中没有显式包含"A 和 B 的对比"这句话,向量检索很可能找不全信息,导致大模型开始"幻觉"或者回答"由于缺乏信息,我无法回答"。
痛点在于:向量检索擅长"语义相似",但极度缺乏"结构化逻辑"和"全局视野"。
这时候,GraphRAG(基于知识图谱的 RAG) 就该登场了。
2. 什么是 GraphRAG?
简单来说,GraphRAG = 知识图谱 (Knowledge Graph) + 向量检索 (Vector Search) + LLM。
微软研究院在最近的论文中大力推崇这种模式。它的核心思想是:不仅要把文本存成向量,还要把文本中的"实体(Entity)"和"关系(Relation)"提取出来,存成一张网。
举个栗子 🌰
原文:"马斯克是 SpaceX 的 CEO,SpaceX 计划在 2030 年登陆火星。"
● Vector RAG 看到的是:一堆关于马斯克、SpaceX、火星的数字向量。
● GraphRAG 看到的是结构化数据:
-
(马斯克) --[担任]--> (CEO) --[所属公司]--> (SpaceX) -
(SpaceX) --[计划]--> (登陆火星) --[时间]--> (2030)
当你问"谁计划在 2030 年去火星?"时,GraphRAG 可以顺着图谱的边(Edge)精准找到答案,哪怕这两个词在原文中距离很远。
3. GraphRAG vs Vector RAG:全方位对比
| 维度 | Vector RAG (传统) | GraphRAG (进阶) |
|---|---|---|
| 核心原理 | 文本切片 + 向量相似度 | 实体关系抽取 + 图遍历 |
| 擅长场景 | 简单的事实问答(What) | 复杂推理、多跳查询(How/Why) |
| 上下文能力 | 碎片化,容易丢失全局信息 | 结构化,能连接跨文档的知识 |
| 幻觉率 | 较高(找不到就瞎编) | 较低(基于确定的关系回答) |
| 构建成本 | 低(切分存入即可) | 高(需要抽取实体、构建图谱) |
4. 实战:用 Python + LangChain 实现一个迷你 GraphRAG
光说不练假把式。下面我们用 Python 快速搭建一个 GraphRAG 的雏形。
4.1 技术栈准备
● LangChain: 编排框架
● OpenAI (GPT-4o/GPT-3.5): 用于实体抽取和生成
● Neo4j: 图数据库(推荐使用 Neo4j AuraDB 的免费云实例,省去本地安装麻烦)
4.2 环境安装
bash
pip install langchain langchain-community langchain-openai neo4j
4.3 核心代码实现
第一步:连接图数据库
首先,我们需要连接到 Neo4j。
python
import os
from langchain_community.graphs import Neo4jGraph
# 配置你的 API Key 和数据库连接
os.environ["OPENAI_API_KEY"] = "sk-..."
os.environ["NEO4J_URI"] = "bolt://localhost:7687"
os.environ["NEO4J_USERNAME"] = "neo4j"
os.environ["NEO4J_PASSWORD"] = "password"
# 初始化图对象
graph = Neo4jGraph()
第二步:将文本转化为图谱(核心魔法)
这是 GraphRAG 最关键的一步。我们需要用 LLM 自动从非结构化文本中提取实体和关系。LangChain 提供了 LLMGraphTransformer 来做这件事。
python
from langchain_experimental.graph_transformers import LLMGraphTransformer
from langchain_openai import ChatOpenAI
from langchain_core.documents import Document
# 准备一段测试文本(模拟企业文档)
text = """
埃隆·马斯克是特斯拉和SpaceX的首席执行官。
特斯拉总部位于得克萨斯州,主要生产电动汽车。
SpaceX专注于航天技术,并计划殖民火星。
"""
documents = [Document(page_content=text)]
# 初始化 LLM 和 图转换器
llm = ChatOpenAI(temperature=0, model="gpt-4o") # 建议用强模型做抽取
llm_transformer = LLMGraphTransformer(llm=llm)
# 提取图数据
graph_documents = llm_transformer.convert_to_graph_documents(documents)
# 打印看看提取了什么
print(f"提取到的节点: {graph_documents[0].nodes}")
print(f"提取到的关系: {graph_documents[0].relationships}")
# 存入 Neo4j 数据库
graph.add_graph_documents(graph_documents)
运行后,你的 Neo4j 数据库里就会自动生成 (马斯克)-[CEO]->(特斯拉) 这样的节点关系图。
第三步:基于图谱进行检索问答
现在数据已经在图里了,我们使用 GraphCypherQAChain,它会自动将自然语言转换成 Cypher 查询语句(类似 SQL)。
python
from langchain.chains import GraphCypherQAChain
chain = GraphCypherQAChain.from_llm(
graph=graph,
llm=llm,
verbose=True, # 开启 verbose 可以看到生成的 Cypher 语句
allow_dangerous_requests=True
)
query = "特斯拉和SpaceX有什么共同点?"
response = chain.invoke(query)
print(f"AI 回答: {response['result']}")
4.4 效果分析
当你运行上述代码时,LangChain 会在后台生成类似这样的 Cypher 查询:
cypher
MATCH (p:Person)-[:CEO]->(c:Company) WHERE p.id = '埃隆·马斯克' RETURN c.id
AI 会通过图谱发现,这两个实体都指向同一个 Person 节点(马斯克),从而精准回答:"它们都由埃隆·马斯克担任首席执行官。"
如果是传统的 Vector Search,可能只会分别检索到两段话,然后由 LLM 费力地去拼凑答案,很容易遗漏。
5. 进阶思路:Graph + Vector 混合检索
在生产环境中,单纯用图检索也有局限(比如对模糊概念的匹配能力弱)。最佳实践是"混合检索":
-
非结构化查询:先用 Vector Search 找到相关的文档块。
-
结构化扩展:以 Vector 检索到的实体为起点,在 Knowledge Graph 中向外跳跃 1-2 层,获取关联信息。
-
上下文融合:将"向量检索的文本" + "图谱检索的关系"一起喂给 LLM。
微软的 GraphRAG 库正是采用了这种类似"社区检测(Community Detection)"的高级算法,对图谱进行聚类摘要,从而实现对海量信息的宏观理解。
6. 总结
RAG 的下半场,拼的不是谁的向量库大,而是谁的数据更"懂"逻辑。
GraphRAG 虽然在构建初期会增加一些成本(抽取实体耗费 Token,图数据库维护),但它带来的准确率提升和复杂推理能力,对于金融、医疗、法律等对严谨性要求极高的领域,是不可或缺的。
动手试试吧!哪怕只是把你的个人笔记变成一张知识图谱,那种上帝视角的感觉,绝对会让你上瘾。