从 Neo4j 到 GraphRAG:用 Text-to-Cypher 构建图检索 RAG

传统 RAG 通常通过向量检索或全文检索寻找相关文档。

Milvus 更擅长解决"哪些内容和问题语义相似",Elasticsearch 更擅长解决"哪些内容包含指定关键词"。

但如果问题变成:

珍珠奶茶属于哪种类型?

珍珠奶茶包含哪些配料?

这些配料使用什么制作工艺?

台式奶茶下面的产品又包含哪些配料?

真正重要的就不再是文本相似度,而是实体之间的关系。

这正是 Neo4j 和 GraphRAG 擅长解决的问题。

整套流程可以先记成:

vbnet 复制代码
Question
   ↓
Text-to-Cypher
   ↓
Neo4j
   ↓
Graph Context
   ↓
LLM
   ↓
Answer

一、Neo4j 解决的是什么问题

可以把几种检索方式简单区分为:

复制代码
Milvus
→ 语义相似
→ "意思像不像?"

Elasticsearch
→ 关键词匹配
→ "字面有没有?"

Neo4j
→ 实体关系 / 图路径
→ "它们怎么关联?"

例如:

复制代码
珍珠奶茶
   │
   │ 包含
   ▼
珍珠
   │
   │ 使用
   ▼
煮制

这里表达的不再是三个孤立的数据,而是一条知识路径:

sql 复制代码
Product
   ↓ 包含
Ingredient
   ↓ 使用
Method

所以图数据库真正有价值的地方,不只是"存了哪些实体",而是:

实体之间可以沿着什么关系继续走。


二、Neo4j 的基本心智模型

Neo4j 最核心的是节点、关系和属性。

例如:

css 复制代码
(:Product {name: "珍珠奶茶"})

Product 是节点类型,name 是属性。

关系可以写成:

scss 复制代码
(:Product)-[:包含]->(:Ingredient)

表示:

复制代码
Product ──包含──▶ Ingredient

在知识图谱里,可以定义:

scss 复制代码
(Product)-[:属于]->(Type)
(Product)-[:包含]->(Ingredient)
(Product)-[:适合]->(People)
(Ingredient)-[:使用]->(Method)

最终形成类似:

markdown 复制代码
                         珍珠 ──使用──▶ 煮制
                         ▲
                         │ 包含
                         │
年轻人 ◀──适合── 珍珠奶茶 ──属于──▶ 台式奶茶
学生   ◀──适合──    │
                    ├──包含──▶ 果糖
                    ├──包含──▶ 红茶
                    └──包含──▶ 牛奶

这时知识不再只是"珍珠奶茶""珍珠""煮制"几个词,而是:

复制代码
珍珠奶茶 ──包含──▶ 珍珠
珍珠 ──使用──▶ 煮制

也就是可以继续遍历的关系网络。


三、Cypher:用文本描述图

Neo4j 使用 Cypher 查询图。

例如:

css 复制代码
MATCH (p:Product {name: "珍珠奶茶"})
      -[:包含]->
      (i:Ingredient)
RETURN i.name

不要把它理解成传统数据库里的 JOIN。

更自然的理解方式是直接看成:

复制代码
Product
   │
   │ 包含
   ▼
Ingredient

MATCH 本质是在说:

在数据库中寻找符合这个图形模式的数据。

因此多跳查询也非常直观。

例如:

less 复制代码
MATCH (p:Product {name: "珍珠奶茶"})
      -[:包含]->(i:Ingredient)
      -[:使用]->(m:Method)
RETURN p.name, i.name, m.name

表示:

sql 复制代码
Product
   ↓ 包含
Ingredient
   ↓ 使用
Method

而"台式奶茶有哪些产品配料"则需要走:

复制代码
台式奶茶
   ▲
   │ 属于
Product
   │
   │ 包含
   ▼
Ingredient

对应:

less 复制代码
MATCH
  (t:Type {name: "台式奶茶"})
  <-[:属于]-
  (p:Product)
  -[:包含]->
  (i:Ingredient)

RETURN DISTINCT i.name

这就是图数据库最核心的能力之一:沿关系完成多跳检索。


四、从 Cypher 到 Text-to-Cypher

真正的用户不会自己写 Cypher。

用户只会问:

复制代码
珍珠奶茶有哪些配料?

所以需要 LLM 完成:

复制代码
自然语言
   ↓
LLM
   ↓
Cypher

例如:

scss 复制代码
async function generateCypher(state) {
  const prompt = `
你是 Neo4j Cypher 生成器。

图谱结构:

(Product)-[:属于]->(Type)
(Product)-[:包含]->(Ingredient)
(Product)-[:适合]->(People)
(Ingredient)-[:使用]->(Method)

只返回可以直接执行的 Cypher。

用户问题:
${state.query}
`;

  const res = await llm.invoke([
    new HumanMessage(prompt),
  ]);

  return {
    cypher: res.content,
  };
}

用户输入:

复制代码
珍珠奶茶有哪些配料?

LLM 可能生成:

css 复制代码
MATCH (p:Product {name: "珍珠奶茶"})
      -[:包含]->
      (i:Ingredient)
RETURN i.name AS ingredient

注意,这时候 LLM 还没有回答问题。

它只是在完成:

sql 复制代码
Natural Language
→
Graph Query Language

也就是 Text-to-Cypher。

这里必须把图谱 Schema 告诉 LLM,因为模型本身并不知道数据库有哪些节点、关系以及关系方向。

可以把 Schema 理解成:

LLM 在图数据库里的地图。


五、Graph Retrieval:真正从知识图谱取事实

拿到 Cypher 后,就可以交给 Neo4j:

javascript 复制代码
async function executeGraphQuery(state) {
  const result = await graph.query(
    state.cypher
  );

  return {
    context: JSON.stringify(result),
  };
}

例如 Neo4j 返回:

css 复制代码
[  {"ingredient":"珍珠"},  {"ingredient":"果糖"},  {"ingredient":"红茶"},  {"ingredient":"牛奶"}]

这一步才是真正的 Retrieval。

也就是说:

复制代码
Question
   ↓
LLM
   ↓
Cypher
   ↓
Neo4j
   ↓
Graph Facts

LLM 负责决定"怎么查",Neo4j 负责回答"数据库里真实有什么"。


六、基于图谱结果生成答案

有了检索结果之后,再进行第二次 LLM 调用:

javascript 复制代码
async function generateAnswer(state) {
  const prompt = `
请严格根据知识图谱检索结果回答问题。

检索结果:
${state.context}

用户问题:
${state.query}

不要补充检索结果中不存在的信息。
`;

  const res = await llm.invoke([
    new HumanMessage(prompt),
  ]);

  return {
    answer: res.content,
  };
}

数据流变成:

markdown 复制代码
Question
   +
Graph Context
   ↓
LLM
   ↓
Answer

最终可能得到:

复制代码
珍珠奶茶包含珍珠、果糖、红茶和牛奶。

因此同一个 LLM 实际扮演了两个角色:

复制代码
第一次:
Question → Cypher
负责"怎么查"

第二次:
Question + Context → Answer
负责"怎么回答"

而 Neo4j 位于中间,负责提供真实的结构化知识。


七、用 LangGraph 把流程串起来

整个 GraphRAG 的 State 可以设计成:

yaml 复制代码
const state = {
  messages: {
    value: (left, right) =>
      left.concat(
        Array.isArray(right)
          ? right
          : [right]
      ),
    default: () => [],
  },

  query: null,
  cypher: null,
  context: null,
  answer: null,
};

因此真正的数据流是:

erlang 复制代码
messages
   ↓
query
   ↓
cypher
   ↓
context
   ↓
answer

工作流:

sql 复制代码
const workflow = new StateGraph({
  channels: state,
})
  .addNode("parse", parseQuestion)
  .addNode("generateCypher", generateCypher)
  .addNode("executeGraph", executeGraphQuery)
  .addNode("generateAnswer", generateAnswer)

  .addEdge(START, "parse")
  .addEdge("parse", "generateCypher")
  .addEdge("generateCypher", "executeGraph")
  .addEdge("executeGraph", "generateAnswer")
  .addEdge("generateAnswer", END);

对应:

sql 复制代码
START
  ↓
parse
  ↓
generateCypher
  ↓
executeGraph
  ↓
generateAnswer
  ↓
END

调用:

arduino 复制代码
await app.invoke({
  messages: [
    new HumanMessage(question),
  ],
});

这里传进去的 { messages: [...] } 本身就是初始 State 的一部分。

parseQuestion():

ini 复制代码
async function parseQuestion(state) {
  const lastMessage =
    state.messages[state.messages.length - 1];

  return {
    query: lastMessage.content,
  };
}

返回的 { query } 是一次局部 State 更新,LangGraph 会自动合并,再把新的 State 传给下一个节点。

所以整套流程可以进一步压缩成:

erlang 复制代码
messages
→ query
→ cypher
→ context
→ answer

八、GraphRAG 和传统 RAG 的区别

传统 RAG:

复制代码
Question
   ↓
Embedding / BM25
   ↓
Vector DB / Elasticsearch
   ↓
Document Chunks
   ↓
LLM
   ↓
Answer

这里实现的 GraphRAG:

vbnet 复制代码
Question
   ↓
Text-to-Cypher
   ↓
Neo4j
   ↓
Entities / Relationships / Paths
   ↓
LLM
   ↓
Answer

两者本质上仍然都是:

复制代码
Retrieval
   ↓
Augmented
   ↓
Generation

真正不同的是 Retrieval。

传统 RAG 更多是在找:

复制代码
相关文本

图检索则可以直接找:

复制代码
实体
关系
路径
多跳事实

所以 GraphRAG 并不是简单替代向量检索,而是在"需要关系、层级和多跳推理"的场景下提供另一种检索能力。


总结

如果以后忘记所有代码,只需要记住下面这一条:

复制代码
Question
→ Cypher
→ Graph
→ Context
→ Answer

对应到各组件:

复制代码
LLM
→ 理解问题、生成 Cypher、组织答案

Neo4j
→ 保存实体关系、执行图检索

LangGraph
→ 编排流程、管理 State

因此 GraphRAG 可以理解为:

让 LLM 把自然语言问题翻译成图查询,通过知识图谱检索实体关系和多跳路径,再将检索到的结构化事实作为上下文,生成最终答案。

这就是从 Neo4j 到 GraphRAG 最值得建立的心智模型。

相关推荐
冬奇Lab1 小时前
LLM 自动化测试系列(05):移动端自动化(一)——ARTEMIS 的双模式架构拆解
人工智能·测试
DisonTangor1 小时前
llama.cpp 新特性:决策模型
人工智能·开源·aigc
鲲穹AI种草1 小时前
AI 生成 PPT 工具怎么选?鲲穹 PPT 功能实测与横向对比
人工智能·powerpoint
AI技术新视界1 小时前
Strata 的工作原理
人工智能·推理引擎·本地ai
2501_926978332 小时前
给自指系统接一个外部锚 —— 一个关于「用 AI 观察自己」的方法
人工智能·经验分享·笔记·机器学习·ai写作
不悔哥2 小时前
小智AI聊天机器人:ESP32上的开源语音助手拆解
人工智能·机器人·开源
枯木◊靠推文躺平版2 小时前
2026 企业级 AI 办公平台选型指南:如何评估可落地的办公 AI 能力
大数据·人工智能
空奈qwq2 小时前
ANN 全连接神经网络进阶:从反向传播到完整实战
人工智能·深度学习·神经网络
Dawson Zhu2 小时前
《Agentic Design Patterns》第 4 章导读:反思(Reflection)
人工智能·语言模型·架构·aigc·agi