Appearance
课 3 · Graph RAG 融合与适用场景
本课目标
把图检索和向量检索融合到完整 RAG 流程里,理解 Graph RAG 解决什么问题、不解决什么问题。
关键理解:Graph RAG 不是向量 RAG 的升级替代,而是专门针对关系推理场景的补充。
Graph RAG 的定位
RAG 演进
基础 RAG向量检索
→
混合 RAG向量 + BM25
→
Graph RAG+ 实体关系图谱
每一步都是在原有基础上加能力,不是替代。
融合检索流程
typescript
// packages/rag-core/src/retrieval/full-pipeline.ts
import { hybridSearch } from './hybrid-search'
import { graphSearch } from '../graph/graph-search'
import { rerankWithLLM } from './rerank'
interface RetrievalContext {
chunks: Array<{ id: string; content: string; fileName: string }>
graphFacts: string[] // 图谱检索到的结构化事实
}
export async function retrieveWithGraph(query: string): Promise<RetrievalContext> {
// 1. 混合检索(向量 + 关键词)
const chunks = await hybridSearch(query, 10)
// 2. 图检索(实体关系)
const graphRelations = await graphSearch(query)
// 把图检索结果转成自然语言片段
const graphFacts = graphRelations.map(
(r) => `${r.entity.name} -[${r.relType}]-> ${r.related.name}: ${r.related.description ?? ''}`
)
// 3. 对 chunks 做 Rerank(图检索结果不参与 Rerank,直接放入上下文)
const rerankedChunks = await rerankWithLLM(query, chunks, 5)
return {
chunks: rerankedChunks,
graphFacts,
}
}在 Agent 生成答案时,把图谱事实和文档片段一起放入上下文:
typescript
// apps/api/src/services/agent.ts
const { chunks, graphFacts } = await retrieveWithGraph(message)
const context = [
graphFacts.length > 0
? `【知识图谱关系】\n${graphFacts.join('\n')}`
: '',
chunks.map((c, i) => `[${i + 1}] ${c.fileName}\n${c.content}`).join('\n\n'),
].filter(Boolean).join('\n\n---\n\n')Graph RAG 适用场景
适合:
| 场景 | 例子 |
|---|---|
| 多跳关系查询 | "A 的合作伙伴是哪些?他们各自的产品是什么?" |
| 关系推理 | "谁参与开发了同时用到 X 和 Y 技术的项目?" |
| 实体聚合 | "列出所有和 OpenAI 有合作关系的机构" |
| 路径解释 | "解释 A 和 B 之间的关联路径" |
不适合:
| 场景 | 原因 |
|---|---|
| 语义相似查询 | "哪些文档讲到类似的做法?"→ 向量检索更好 |
| 长文档理解 | 图谱只记录实体关系,不记录上下文细节 |
| 动态数据 | 图谱需要维护,频繁变化的数据维护成本高 |
| 小知识库(< 100 文档) | 引入 Neo4j 的成本超过收益,向量检索已足够 |
路由决策
不是所有问题都需要图检索,加一个路由判断:
typescript
// packages/rag-core/src/retrieval/router.ts
async function shouldUseGraphSearch(query: string): Promise<boolean> {
// 简单规则:包含关系词就用图检索
const relationKeywords = [
'关系', '相关', '合作', '开发者', '属于', '哪些', '列出', '谁参与',
'和.*有.*关', '如何关联',
]
return relationKeywords.some((kw) => new RegExp(kw).test(query))
}
export async function smartRetrieve(query: string) {
const useGraph = await shouldUseGraphSearch(query)
if (useGraph) {
return retrieveWithGraph(query)
} else {
const chunks = await hybridSearch(query, 5)
return { chunks, graphFacts: [] }
}
}Graph RAG 的实际限制
面试时能说出限制比只夸优点更有价值:
- 抽取质量依赖 LLM:LLM 抽取的实体和关系会有误差,影响图谱质量
- 维护成本:文档更新时,图谱也要同步更新,有额外的维护负担
- 冷启动:知识库较小时图谱稀疏,关系推理效果不明显
- Embedding 已覆盖大多数场景:大多数知识库问答用混合检索就够了,Graph RAG 是锦上添花
Agentic RAG 和 Graph RAG 的关系
面试常问这两者的区别:
| Agentic RAG | Graph RAG | |
|---|---|---|
| 核心思路 | Agent 主动决定检索策略(Query Rewrite、多轮检索、Self-check) | 用图结构表示知识,支持关系推理 |
| 解决问题 | 复杂问题的多步检索 | 实体关系的路径推理 |
| 可以组合 | ✅ Agentic RAG + Graph RAG 是完整方案 | ✅ |
两者不互斥,生产环境往往同时用:Agent 决定"用什么检索策略",Graph RAG 是其中一种检索选项。
本节产物
packages/rag-core/src/retrieval/
full-pipeline.ts # 融合检索:混合检索 + 图检索 + Rerank
router.ts # 是否使用图检索的路由判断面试追问
Graph RAG 适合什么场景?
适合需要多跳关系推理的场景:实体之间的关联路径、聚合查询("和 X 相关的所有 Y")、复杂的因果链推导。不适合的场景:纯语义相似查询、小知识库、动态频繁更新的数据。判断标准:如果用户问题的答案需要"跨文档追踪关系链",就适合 Graph RAG;如果只需要"找相关文档段落",混合检索就够了。
Agentic RAG 和 Graph RAG 是什么关系?
Agentic RAG 解决"如何检索"的问题(多步检索、查询改写、自我验证),Graph RAG 解决"存储什么"的问题(用图结构表示实体关系)。两者关注的层次不同,可以叠加:用 Agentic RAG 的 Router 决定何时触发 Graph RAG 检索,形成完整的知识检索体系。