Neo4j Fundamentals:graphacademy.neo4j.com/courses/neo4j-fundamentals

1.节点、关系、属性、标签

  1. 节点:图中的基本实体-人。
  2. 标签:描述节点的内容-一个人,一个公司职员。一个节点可以有很多标签。
  3. 关系:人际关系,a在公司b工作。有一个类型+一个方向组成。
  4. 属性:节点和关系的数据。属性以键值对的形式命名;例如firstName(Yunqi)和position(student)。节点和关系可以有任意数量的属性,同一类型的节点和关系不必具有相同的属性;属性具有类型(整数、布尔值、字符串、列表等),并且可以是特定节点标签的唯一标识符(键)。

在两个节点之间创建关系时,数据库会将指向该关系的指针存储在每个节点中。读取数据时,数据库会沿着内存中的指针查找数据,而不是依赖底层索引。

这意味着,无论数据总量如何,查询时间都与扩展的关系规模保持恒定。

2.Cypher 语法

2.1 查询

1. 节点匹配基础 (Node Matching)​

用于在图中定位特定类型的实体。

  • 语法结构MATCH (变量名:标签名)
  • 关键点
    • 圆括号 ():代表一个节点。
    • 变量名:用于在后续查询(如 WHERERETURN)中引用该节点。
    • 标签名:指定节点的类型(如 :Person:Movie)。
  • 示例MATCH (p:Person) —— 查找所有带有 Person 标签的节点,并将其命名为 p
2. 关系匹配基础 (Relationship Matching)​

用于描述节点之间的连接方式。

  • 语法结构(起始节点)-[:关系类型]->(目标节点)
  • 关键点
    • 方括号 []:位于短横线中间,代表关系。
    • 箭头 -><-:代表关系的方向。图数据库中的关系是有方向的。
    • 变量引用:关系也可以赋予变量名,如 -[r:ACTED_IN]->,其中 r 代表关系变量。
  • 示例MATCH (p:Person)-[:ACTED_IN]->(m:Movie) —— 查找所有“参演”了电影的“人”。
3. 条件过滤 (Filtering)​

用于缩小搜索范围,精确匹配特定属性。

  • 语法结构WHERE 变量名.属性名 = '值'
  • 关键点
    • 支持逻辑运算符:AND, OR, NOT
    • 支持比较运算符:=, <>, <, >, IN 等。
  • 示例WHERE p.name = 'Tom Hanks' —— 仅筛选出姓名属性为汤姆·汉克斯的节点。
4. 结果返回 (Returning Results)​

定义查询最终输出的内容。

  • 语法结构RETURN 表达式1, 表达式2
  • 关键点
    • 返回对象:直接返回变量(如 RETURN p)将输出整个节点实体(包含所有属性和元数据),在 UI 中通常显示为图形。
    • 返回属性:返回特定字段(如 RETURN p.name)将仅输出该属性的值,在 UI 中通常显示为表格。
  • 示例RETURN p.name, m.title —— 仅输出人的姓名和电影的标题。

2.2模式匹配

1. 模式语法解构 (Pattern Anatomy)​

Cypher 的核心是“所见即所得”,通过字符模拟图形结构。

  • 节点 (Nodes)​:使用圆括号 ( ) 表示。
    • 匿名节点:(:Person)(仅指定标签)。
    • 具名节点:(p:Person)(指定标签并赋予变量名 p)。
  • 关系 (Relationships)​:使用方括号 [ ] 和连线表示。
    • 无向连线:--
    • 有向连线:--><--
    • 带类型的关系:-[:ACTED_IN]->
    • 带变量的关系:-[r:ACTED_IN]->(变量 r 可用于获取关系属性,如 r.role)。
2. 多节点路径匹配 (Matching Paths)​

可以将多个节点和关系串联,描述复杂的业务逻辑。

  • 语法结构MATCH (n1)-[r1]->(n2)<-[r2]-(n3)
  • 应用场景:查找“共同点”。例如,查找与汤姆·汉克斯(Tom Hanks)合作过的所有演员。
  • 示例

    MATCH (p:Person)-[:ACTED_IN]->(m:Movie)<-[:ACTED_IN]-(p2:Person)

    WHERE p.name = 'Tom Hanks'

    RETURN p2.name

    逻辑:找到汤姆·汉克斯演过的电影 m,再反向找到同样演过电影 m 的另一个人 p2
3. 结果别名 (Aliasing with AS)​

为了提高输出结果(尤其是表格形式)的可读性,可以为返回的列重命名。

  • 语法结构RETURN 表达式 AS 自定义名称
  • 关键点AS 关键字可以将复杂的属性路径(如 p2.name)映射为一个简洁的列标题(如 actor)。
  • 示例

    RETURN p2.name AS actor, m.title AS movie

4. 关系属性的访问 (Accessing Relationship Properties)​

关系不仅连接节点,自身也可以携带属性(如演员在电影中的角色名、用户评分的分值)。

  • 前提条件:必须为关系定义变量名。
  • 语法结构MATCH ()-[r:TYPE]->() RETURN r.propertyName
  • 示例RETURN r.role AS role —— 返回演员在特定电影中扮演的角色名称。
5. 模式匹配的执行逻辑
  1. 定位起始点:通过 MATCHWHERE 找到图中的锚点节点。
  2. 路径扩展:从锚点出发,根据定义的箭头方向和关系类型,在内存中遍历相连的指针。
  3. 提取数据:根据 RETURN 子句,从匹配成功的整条“路径”中提取出指定的节点、关系或属性。

2.3.创建图

1. 智能创建与更新 (The MERGE Clause)​

MERGE 是 Cypher 中最强大的写入语句,它结合了“查找”和“创建”的功能。

  • 核心逻辑
    • 检查存量:先检查图中是否存在匹配该模式的节点或关系。
    • 存在则匹配:如果已存在,则像 MATCH 一样直接使用它。
    • 不存在则创建:如果不存在,则像 CREATE 一样新建一个。
  • 语法结构MERGE (变量:标签 {唯一标识属性: 值})
  • 示例

    MERGE (m:Movie {title: "Arthur the King"})

    逻辑:如果库里有这部电影,就选中它;如果没有,就新建一个名为 "Arthur the King" 的电影节点。
2. 属性赋值 (The SET Clause)​

用于为节点或关系添加、更新属性。

  • 语法结构SET 变量名.属性名 = 值
  • 关键点:常与 MERGE 配合使用,确保在创建或匹配后完善数据信息。
  • 示例

    MERGE (m:Movie {title: "Arthur the King"})

    SET m.released = date('2024-03-22')

3. 关系的安全创建

在创建关系时,推荐先 MERGE 节点,再 MERGE 关系,以防止重复创建节点或产生断开的关系。

  • 标准工作流
    1. MERGE 起始节点。
    2. MERGE 目标节点。
    3. MERGE 它们之间的关系。
  • 示例

    MERGE (m:Movie {title: "Arthur the King"})

    MERGE (u:User {name: "Adam"})

    MERGE (u)-[r:RATED {rating: 5}]->(m)

4. 结果排序 (The ORDER BY Clause)​

用于对返回的表格数据进行逻辑排序。

  • 语法结构ORDER BY 变量名.属性名 [ASC/DESC]
  • 关键点
    • ASC:升序(默认)。
    • DESC:降序。
  • 示例ORDER BY m.released DESC —— 按上映时间从新到旧排列。
5. 数量限制 (The LIMIT Clause)​

用于控制返回结果的条目数,常用于获取“前 N 名”或分页显示。

  • 语法结构LIMIT 数字
  • 示例

    MATCH (m:Movie)

    RETURN m.title

    ORDER BY m.released DESC

    LIMIT 5

    逻辑:返回最新上映的 5 部电影。

3.GraphRAG和RAG的区别

1. 传统 RAG 的局限性:只见树木,不见森林

传统的 RAG(基于向量搜索)主要解决的是​“局部”​问题。

  • 工作原理:将文档切碎成块,通过关键词或语义相似度找到最相关的几个碎片。
  • 痛点:如果你问“这篇文章的主题是什么?”或者“这 100 份文档里关于某个实体的总体评价如何?”,传统 RAG 会因为只能检索到局部碎片,而无法拼凑出全局的全貌。
  • 直觉比喻:传统 RAG 像是在图书馆里找几本具体的书;而 GraphRAG 则是要理解整个图书馆里所有书之间的逻辑网。

2. 为什么需要 GraphRAG?​

微软和 Neo4j 提出的 GraphRAG 引入了一个关键步骤:将非结构化文本转化为结构化的知识图谱

  • 信息压缩:它将分散在不同文档里的实体(Entity)和关系(Relationship)提取出来,合并到同一个图谱中。
  • 消除冗余:通过“实体解析(Entity Resolution)”,它能发现文档 A 里的“苹果公司”和文档 B 里的“Apple Inc”是同一个东西,从而把碎片信息连接起来。

3. GraphRAG 的核心创新:从 Local 到 Global

neo4j.com/blog/developer/global-graphrag-neo4j-langchain,这篇博客重点解释了微软 GraphRAG 论文中的一个神来之笔——社区发现(Community Detection)​

  • 图社区(Graph Communities)​:算法会自动发现图中哪些节点联系紧密(比如“高血压”和“氨氯地平”属于医疗社区)。
  • 社区摘要(Community Summaries)​:LLM 会为每个社区写一份“总结报告”。
  • 全局回答:当你问一个宏观问题时,系统不再去翻原始文档碎片,而是去阅读这些预先写好的社区总结。这让它能够回答跨文档、跨实体的全局性问题。

特性 传统 RAG (Vector-only) GraphRAG (Neo4j + LLM)
检索单位 文本块 (Text Chunks) 实体、关系、社区摘要
擅长问题 具体事实(“某人的生日?”) 宏观总结(“这个行业的主要风险?”)
数据关联 靠语义相似度(可能断裂) 靠物理指针直接连接(无索引邻接)
处理成本 检索时成本低 索引阶段(建图)成本高,但回答质量极高

4.Text2Cypher 的工作流

GraphRAG 是"为什么要用图做检索"(理念层)
Text2Cypher 是"怎么把自然语言变成图查询"(机制层)√
GraphCypherQAChain 是"LangChain 里怎么封装这个机制"(实现层)

也就是:"用户说了一句人话,图数据库是怎么听懂的?"———通过Text2Cypher


Text2Cypher 是 GraphRAG 中实现"用户用自然语言查询知识图谱"的关键技术。它的工作流分为四个阶段:

阶段一:读取 Schema

LLM 不是凭空知道数据库结构的。它需要先读取图数据库的 Schema,了解有哪些节点类型、属性、以及节点之间的关系。例如:

Node properties:
Movie {runtime: INTEGER, name: STRING}
Actor {name: STRING}

The relationships:
(:Actor)-[:ACTED_IN]->(:Movie)

阶段二:生成 Cypher

LLM 根据 Schema 和用户问题,生成 Cypher 查询语句。例如用户问 "Who played in Top Gun?",LLM 生成:

MATCH (a:Actor)-[:ACTED_IN]->(m:Movie)
WHERE m.name = 'Top Gun'
RETURN a.name

这一步的本质是:把自然语言的语义意图,翻译成图数据库的结构化查询。

阶段三:数据库执行

Cypher 语句被发送到 Neo4j 执行,返回结构化数据:

[
    {"a.name": "Tom Cruise"},
    {"a.name": "Val Kilmer"},
    {"a.name": "Anthony Edwards"},
    {"a.name": "Meg Ryan"}
]

阶段四:结果翻译

LLM 再次介入,把结构化查询结果组织成自然语言:

Tom Cruise, Val Kilmer, Anthony Edwards, and Meg Ryan played in Top Gun.
 

Text2Cypher 的核心是 LLM 的两次转换——第一次把自然语言转成 Cypher,第二次把数据库结果转成自然语言。Neo4j 在中间负责提供真实数据。这意味着答案不是来自 LLM 的记忆,而是来自数据库的真实查询结果,从根本上减少了幻觉。

5.GraphCypherQAChain 是什么

是 LangChain 中用于 Neo4j 图数据库问答的链。它的作用是让用户可以用自然语言查询图数据库,而不需要手写 Cypher 查询语句。

它的核心流程是:

用户自然语言问题
→ LLM 根据图数据库 schema 生成 Cypher 查询
→ Neo4j 执行 Cypher 查询并返回结果
→ LLM 根据数据库结果生成自然语言回答
 

为什么需要它:

普通 LLM 只能根据模型自身知识回答,容易产生幻觉,也无法直接访问我的私有数据库。

GraphCypherQAChain 的价值在于:它让 LLM 先查询 Neo4j 中的真实数据,再根据查询结果回答问题。因此它适合用于知识图谱问答、GraphRAG、企业内部数据问答、实体关系查询等场景。

举例:

提问:

        Who played in Top Gun?

LLM 根据图数据库 schema 生成 Cypher:

        MATCH (a:Actor)-[:ACTED_IN]->(m:Movie)
        WHERE m.name = 'Top Gun'
        RETURN a.name

Neo4j 执行后返回:

        [
            {"a.name": "Tom Cruise"},
            {"a.name": "Val Kilmer"},
            {"a.name": "Anthony Edwards"},
            {"a.name": "Meg Ryan"}
        ]

LLM 再把结果翻译成自然语言:

        Tom Cruise, Val Kilmer, Anthony Edwards, and Meg Ryan played in Top Gun.

重点理解的点:

GraphCypherQAChain不是让 LLM 直接回答,而是让 LLM 先生成数据库查询语句。Neo4j 负责提供真实数据,LLM 负责两次转换:第一次把自然语言转换成 Cypher,第二次把数据库结果转换成自然语言答案。

这条链路的可靠性取决于几个因素:图数据库的 schema 是否清晰,LLM 生成的 Cypher 是否正确,Neo4j 返回的数据是否完整,以及最终回答是否严格基于查询结果。

6.rag-demo

git clone https://github.com/neo4j-examples/rag-demo

1.运行起来

1.neo4j

我连接不到云,最后选择neo4j desktop,下载https://neo4j.com/download/,然后在settings设置代理,然后创建instance。

将demo里面的secrets.toml.example复制一份secrets.toml,将url改成bolt://localhost:7687,写入自己的NEO4J_PASSWORD

2.改openai,chat部分用deepseek-chat,embedding部分用硅基流动的BAAI/bge-large-zh-v1.5

直接让trae改就行:“原来的rag-demo用的是openai,我要用deepseek,这导致没有embedding,我想用硅基流动平台的BAAI/bge-large-zh-v1.5,我有硅基流动的api,我想用的这个模型也是免费的。帮我把对话和embbding拆开,对话走deepseek,embedding走硅基流动,同时我还会在配置密钥的地方加入SILICONFLOW_API_KEY。”

2.逐文件解释demo

1. 入口文件:main.py

核心功能 :

- Streamlit 前端界面,处理用户输入
- 显示聊天历史
- 调用 rag_agent.get_results() 获取 AI 回答
关键代码位置 :

- 第 90-92 行 :调用 rag_agent.get_results() ,这是核心入口:

agent_response = rag_agent.get_results(question=user_input, callbacks=[])

入口总结 :用户在 Streamlit 输入 → main.py 接收 → 调用 rag_agent.get_results()

2. 核心逻辑:rag_agent.py(Chain 组装的地方)

核心功能 :

- 初始化 LLM
- 组装三个 Tool(vector_tool、vector_graph_tool、graph_cypher_tool)
- 创建 ReAct Agent(LangChain 的 Agent)
- 暴露 get_results() 函数供 main.py 调用


关键代码位置 :

- 初始化 DeepSeek LLM
- 加载三个 Tools
- 组装 AgentExecutor (LangChain 的 ReAct Agent)
-  agent_executor.invoke() 执行 Agent


Chain 组装总结 : llm + [vector_tool, graph_cypher_tool, vector_graph_tool] → AgentExecutor

3. 工具实现:vector_tool.py、vector_graph_tool.py、graph_cypher_tool.py

- vector_tool.py → 调用 vector_chain.get_results()
- vector_graph_tool.py → 调用 vector_graph_chain.get_results()
- graph_cypher_tool.py → 调用 graph_cypher_chain.get_results()

4. Chain 实现:vector_chain.py、vector_graph_chain.py、graph_cypher_chain.py

这三个文件结构几乎一样,都包含:

- Neo4j 连接初始化
- Chain 组装
- get_results() 函数

  •  vector_chain.py - 纯向量检索链

关键代码 :

- 第 68-70 行 :从 st.secrets 读取 Neo4j 配置
- 第 76-84 行 : Neo4jVector.from_existing_index() → 初始化 Neo4j 向量存储
- 第 112-124 行 : RetrievalQAWithSourcesChain.from_chain_type() → 组装 Chain
流程 :用户问题 → 向量化 → 从 Neo4j 找相似 Chunk → 传给 LLM 回答

  •  vector_graph_chain.py - 向量 + 图增强

关键代码 :

- 第 60-82 行 : retrieval_query - 这是核心!不仅找相似 Chunk,还通过图遍历找关联的 Company、Manager 等!
- 第 88-97 行 : Neo4jVector.from_existing_index() ,但多传了 retrieval_query
- 第 126-138 行 :同样用 RetrievalQAWithSourcesChain 组装
流程 :用户问题 → 向量化 → 找相似 Chunk → 通过图遍历扩展上下文(Company、Manager 等)→ 传给 LLM 回答

  •   graph_cypher_chain.py - 纯图查询(Text-to-Cypher)

关键代码 :

- 第 75-81 行 : Neo4jGraph() - 初始化图连接
- 第 84-102 行 : GraphCypherQAChain.from_llm() - 组装 Chain,用两个 LLM:
  - cypher_llm :把自然语言翻译成 Cypher
  - qa_llm :根据 Cypher 查询结果回答问题
流程 :用户问题 → cypher_llm 翻译成 Cypher → 执行 Cypher 查询 Neo4j → qa_llm 根据结果回答

流程图:

┌─────────────────────────────────────────────────────────────────────────────────────┐
│  🖥️  用户浏览器 (Streamlit)                                                            │
│  ┌───────────────────────────────────────────────────────────────────────────────┐ │
│  │  用户输入框:"What companies are in the filings?"                               │ │
│  └───────────────────────────────────┬───────────────────────────────────────────┘ │
└──────────────────────────────────────┼─────────────────────────────────────────────┘
                                       │
                                       │ 1️⃣ 用户输入
                                       │
                                       ▼
┌─────────────────────────────────────────────────────────────────────────────────────┐
│  📄  rag_demo/main.py                                                               │
│  ┌───────────────────────────────────────────────────────────────────────────────┐ │
│  │  Line 90-92: rag_agent.get_results(user_input)                                │ │
│  └───────────────────────────────────┬───────────────────────────────────────────┘ │
└──────────────────────────────────────┼─────────────────────────────────────────────┘
                                       │
                                       │ 2️⃣ 调用 Agent
                                       │
                                       ▼
┌─────────────────────────────────────────────────────────────────────────────────────┐
│  🤖  rag_demo/rag_agent.py (ReAct Agent)                                          │
│  ┌───────────────────────────────────────────────────────────────────────────────┐ │
│  │  Tools Available:                                                             │ │
│  │  [1] vector-tool       ← 对应 vector_chain.py                                 │ │
│  │  [2] vector-graph-tool ← 对应 vector_graph_chain.py                           │ │
│  │  [3] graph-cypher-tool ← 对应 graph_cypher_chain.py                           │ │
│  │                                                                               │ │
│  │  LLM (DeepSeek) 分析问题,决定用哪个 Tool!                                     │ │
│  │  (比如问题涉及计数 → 选 graph-cypher-tool)                                      │ │
│  └───────────────────────────────────┬───────────────────────────────────────────┘ │
└──────────────────────────────────────┼─────────────────────────────────────────────┘
                                       │
                                       │ 3️⃣ 选一个 Tool 调用
                                       │
                                       ▼
┌─────────────────────────────────────────────────────────────────────────────────────┐
│  ⛓️  rag_demo/*_chain.py (选其中一个)                                               │
│                                                                                     │
│  ┌─────────────┐  ┌──────────────────┐  ┌─────────────────────┐                  │
│  │vector_chain │  │vector_graph_chain│  │graph_cypher_chain   │                  │
│  │(纯向量)     │  │(向量+图增强)     │  │(Text-to-Cypher)    │                  │
│  └──────┬──────┘  └────────┬─────────┘  └──────────┬──────────┘                  │
│         │                  │                       │                               │
│         │                  │                       │                               │
│  向量化问题→找相似 Chunk│ 向量化问题→找相似 Chunk  │ 问题→翻译成 Cypher           │
│         │                  │ →图遍历扩展上下文(Company,│ →执行 Cypher 查询 Neo4j      │
│         │                  │ Manager等)            │                               │
│         │                  │                       │                               │
│         └──────────────────┴───────────────────────┘                               │
│                              │                                                      │
│                              │ 4️⃣ 所有 Chain 都会调用 Neo4j                          │
│                              ▼                                                      │
│  ┌───────────────────────────────────────────────────────────────────────────────┐ │
│  │  Neo4j 连接初始化 (在每个 *_chain.py 文件里)                                    │ │
│  │  - vector_chain.py: Neo4jVector (第76-84行)                                     │ │
│  │  - graph_cypher_chain.py: Neo4jGraph (第75-81行)                                 │ │
│  └───────────────────────────────────┬───────────────────────────────────────────┘ │
└──────────────────────────────────────┼─────────────────────────────────────────────┘
                                       │
                                       │ 5️⃣ 从 Neo4j 取回结果
                                       │
                                       ▼
┌─────────────────────────────────────────────────────────────────────────────────────┐
│  🧠 LLM (DeepSeek)                                                                 │
│  ┌───────────────────────────────────────────────────────────────────────────────┐ │
│  │  根据 Neo4j 检索结果,生成最终答案                                             │ │
│  └───────────────────────────────────┬───────────────────────────────────────────┘ │
└──────────────────────────────────────┼─────────────────────────────────────────────┘
                                       │
                                       │ 6️⃣ 返回答案
                                       │
                                       ▼
┌─────────────────────────────────────────────────────────────────────────────────────┐
│  🖥️  用户浏览器 (Streamlit) 显示答案!                                               │
└─────────────────────────────────────────────────────────────────────────────────────┘

总结:

1. 入口在哪?
- 前端入口 : main.py 的用户输入框
- 逻辑入口 : rag_agent.py 的 get_results() 函数(被 main.py 第 90 行调用)


2. Neo4j 连接在哪初始化?
每个 Chain 自己初始化 ,不是全局共享的:

- vector_chain.py 第 76-84 行: Neo4jVector.from_existing_index()
- vector_graph_chain.py 第 88-97 行: Neo4jVector.from_existing_index() (有 retrieval_query)
- graph_cypher_chain.py 第 75-81 行: Neo4jGraph()

3. LangChain Chain 怎么组装?
- vector_chain.py 第 112-124 行: RetrievalQAWithSourcesChain.from_chain_type()
- graph_cypher_chain.py 第 84-102 行: GraphCypherQAChain.from_llm()
- rag_agent.py 第 47-57 行:把三个 Tool 包装成 ReAct Agent

4. Tool、Chain、Agent 的关系?
Tool (vector_tool)  → 包装 Chain 
(vector_chain)
Tool (graph_cypher_tool) → 包装 Chain 
(graph_cypher_chain)
Agent (AgentExecutor)  → 拥有这三个 Tool,由 LLM 决定用哪个

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐