跳到主要内容

text2cypher — 让自然语言直通图数据库

这一章讲三件事: 为什么有一类问题向量检索永远答不了; text2cypher(自然语言转 Cypher)的完整流程;以及撑住翻译质量的四个抓手 ——这四个抓手也是你以后维护任何「LLM 生成代码」系统的抓手。

1. 顶层全景:翻译,而不是检索

前四章的检索器都在做同一件事:找「像」的文本。这一章换了一个动作: 让 LLM 把用户问题翻译成一条数据库查询,执行它,把精确结果拿回来。

用户问题 ─┬─ 图模式(schema)──┐
├─ 术语映射 ────────┤
├─ few-shot 示例 ───┼─→ 拼 prompt → LLM ─→ Cypher 语句 ─→ 执行 ─→ 精确结果
└─ 格式指令 ────────┘

图说:LLM 在这里不是「答题人」,是「翻译官」——把中文/英文翻成数据库语言。

Cypher 是图数据库 Neo4j 的查询语言,本书全文的数据库操作都用它; 它的来历(开放标准、六家数据库采用、正在进 ISO 标准)在第 12 章专讲, 本章只需要会认它的样子:圆括号是节点,方括号是关系,箭头是方向——

(:Person)-[:ACTED_IN]->(:Movie) -- 「某个人出演了某部电影」

2. 为什么向量检索答不了:聚合问题走查

书里给的问题,值得先自己想一想怎么做:「列出 Steven Spielberg 执导的 评分最高的三部电影,以及平均分1

  • 向量检索?它只会捞回「和问题字面最像」的几段文字—— 可能是一篇讲 Spielberg 的影评,里面并没有全库排名;
  • 要回答它,必须:筛出 Spielberg 导演的所有电影 → 按评分排序 → 取前三。 这是对全库的过滤、排序、聚合,是数据库查询的定义性工作。

结论:这不是「检索不准」,是动作类型就错了——找相似节点和聚合数据, 是两种不同的操作2。这类问题只能靠让数据库执行查询来解决, 而查询语句的生成,交给 LLM 翻译。

3. 翻译的难点:schema 是那本对照词典

LLM 大多认识 Cypher 语法——真正的难点不是语法,是你这张图的专用词汇表: 节点叫什么标签、关系有哪几种、属性叫什么名字。不给 schema (图模式:对「图里有什么标签、什么关系、什么属性」的完整描述), LLM 只能瞎猜名字;给了 schema,它就成了「用户语义」和「图模型」之间的对照词典3

流程五步:拿问题 → 拿 schema → 备好其他材料(术语映射、格式指令、few-shot) → 拼 prompt → 生成 Cypher4

4. 四个抓手,逐一讲透

抓手一:schema——把图的词汇表递给翻译官

schema 放进 prompt,并且附带一条紧箍咒:只准用 schema 里列出的 标签、关系、属性,不准自己发明5

schema 可以从数据库自动推断(用 Neo4j 的 APOC 插件读元数据; APOC 是 Neo4j 的过程函数库,第 12 章详述),但全库推断可能很贵, 常见做法是采样(抽一部分有代表性的数据)来推6。书里还给了个来自 Neo4j 内部研究的 松弛判断:schema 用什么文字格式呈现,影响不大7——内容对就行。

抓手二:few-shot 示例——LLM 犯过的错,变成教材

few-shot(第 04 章讲过:在提示里附几个输入输出示例)在这里有明确的生产纪律: 示例是每个图手工定制的——你观察到 LLM 反复犯哪类错, 就把那个错的正确写法做成示例喂回去8

书里的实例:LLM 答「某部电影在哪个国家拍摄」时,去读电影节点上的 country 属性;但在这张图里,国家是一个节点,要用 PRODUCED_IN 关系走过去。修法不是改模型,是加一条示例:

Question: In what country was the movie Ready Player One produced?
Cypher: MATCH (m:Movie {title: 'Ready Player One'})
-[:PRODUCED_IN]->(c:Country)
RETURN c.name

有了这条示例,不止这道题被修好,所有「找国家」的同类问题都学会了走关系9

抓手三:术语映射——用户的词 ≠ 图里的词

用户说「电影」,图里叫 Movie;用户说「演员、导演、制片人」, 图里都叫 Person(靠关系区分)。术语映射就是一张小字典, 明写「用户说 X 时,指的是图里的 Y」10。 它同样是图特定的,而且会随你发现的新错误持续演化11

抓手四:格式指令——只要查询语句本身

不同模型有的爱在查询外包代码块、有的爱加解释。格式指令把口子扎死: 「不要解释、不要道歉、不要回答别的问题、只输出 Cypher、不要代码块12。 没有这一条,下游执行器拿到一坨带解释的文本会直接报错。

5. 主走查:一个问题从 prompt 到结果

拿书里的实战问题走全程,每个部件看它长什么样13:

问题:"Who directed the most movies?"(谁导演的电影最多?)

schema(节选):
Movie {tagline: STRING, title: STRING, released: INTEGER}
Person {born: INTEGER, name: STRING}
关系: (:Person)-[:DIRECTED]->(:Movie)、ACTED_IN、REVIEWED …
——注:ACTED_IN 带 roles 属性,REVIEWED 带 summary 和 rating

术语映射:「用户问某某职业的人 → Person 标签;问电影 → Movie 标签」

few-shot:一条「合作最多的两位演员」的聚合查询示例

格式指令:只输出 Cypher,不带代码块

↓ LLM 生成 ↓

MATCH (p:Person)-[:DIRECTED]->(m:Movie)
RETURN p.name, COUNT(m) AS movieCount
ORDER BY movieCount DESC LIMIT 1[^14]

↓ 执行 ↓

数据库里每个 Person 节点被数一遍 DIRECTED 关系,按计数降序,取第一行。

注意生成的查询做了什么:COUNT(计数)+ ORDER BY(排序)+ LIMIT(限量)—— 这三个动作正是第 02 章说「非结构化数据答不了」的那一类。 翻译完成后,精度(答得准不准)由数据库保证,LLM 的概率本性被排除在计算之外。

6. 作者的判断与证据

  • text2cypher 的定位是「专用问题的精确通道」和「其他检索器都不匹配时的兜底」14 ——它和向量检索不是竞争关系,是分工(第 06 章的 agent 路由器会把它们编进同一个系统);
  • 维护模式是「错误驱动」的:书里明说,示例和术语映射会随着你观察到的 新错误持续增加11。这是这套系统的日常运维成本,书里没有回避;
  • 微调模型路线:Neo4j 把 text2cypher 训练数据开源(源码与数据公开、人人可用)了,也放出了微调过的 开源小模型(Gemma2、Llama 3.1 底座);书里的判断很坦率—— 它们仍明显落后于最大的商业模型,但更快更省,适合生产15

判断(我们的,不是书里的): 四个抓手的本质是同一条—— 把「让模型更聪明」换成「让上下文更准确」。schema 防它瞎猜名字, 示例防它走错关系,术语映射防它对错词,格式指令防它输出废料。 这条经验可以平移到任何「LLM 生成结构化产物」的场景(SQL——另一种数据库查询语言、正则、API 调用), 差别只在「词典」的内容。 如果错,会错在: 如果任务的语言本身太难(查询要嵌套三层以上), 上下文再准模型也会写错——那时该做的是把问题拆简单,或退回预写模板查询 (书里第 06 章的专用检索器正是这个思路的伏笔)。

7. 边界与局限

  • schema 是天花板也是地板:图里的命名若语义不清(标签叫 A、B、C), 四件套全上也没救——书里点名「数据库 schema 元素语义命名不清」是出错源之一16;
  • 错一个字符就全盘失败:生成的查询语法错或语义偏,执行直接失败或答非所问; 书里没有在本章给重试/修复机制,那是第 06 章 agent 系统的部分职责;
  • 私有数据的值映射是另一道坎:书里在讲评测的第 11 章顺带指出, 出名电影演员靠预训练就能对上,私有数据集必须有专门的值映射系统17—— 这句提前剧透了 text2cypher 在企业场景的真实成本;
  • 书里全程用 OpenAI 模型演示,微调小模型的性能差距只给了定性描述15

8. 可带走的

  1. 聚合/过滤/排序类问题与向量检索是两种动作,只能靠数据库查询解答;
  2. text2cypher = LLM 当翻译官;schema 是对照词典,不给就瞎猜;
  3. few-shot 示例的生产纪律:观察错误 → 把正确写法做成示例 → 喂回去;
  4. 术语映射把「用户的词」对到「图里的词」,随错误持续演化;
  5. 格式指令保证输出可执行——只给查询,别给散文;
  6. 生成的查询里出现 COUNT/ORDER BY/LIMIT,正是「结构才能答」的实证;
  7. 这套「schema+示例+映射+格式」四件套可平移到一切「LLM 生成结构化产物」的场景。

9. 原文地图

主题原书章原文位置
text2cypher 定义与难点4 Generating Cypher queries from natural language questionstext/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:27(搜「converting a natural language」)
schema=语义到图模型的映射4 Generating Cypher queries from natural language questionstext/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:35(搜「mapping between the semantics」)
流程五步4 Generating Cypher queries from natural language questionstext/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:40(搜「Retrieve the question」)
Spielberg 聚合问题4 Generating Cypher queries from natural language questionstext/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:68(搜「top three highest-rated」)
「不是找相似,是聚合」4 Generating Cypher queries from natural language questionstext/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:82(搜「aggregating」)
catchall 定位4 Generating Cypher queries from natural language questionstext/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:89(搜「catchall」)
few-shot 图特定、手工建4 Generating Cypher queries from natural language questionstext/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:106(搜「specific to the knowledge graph」)
country 属性 vs 节点例4 Generating Cypher queries from natural language questionstext/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:112(搜「actually a node」) · text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:128(搜「PRODUCED_IN」)
schema 格式影响不大4 Generating Cypher queries from natural language questionstext/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:142(搜「doesn't matter that much」)
只准用 schema 里的4 Generating Cypher queries from natural language questionstext/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:334(搜「Do not use any other」)
采样推断、APOC4 Generating Cypher queries from natural language questionstext/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:168(搜「sample the database」) · text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:171(搜「APOC」)
术语映射4 Generating Cypher queries from natural language questionstext/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:279(搜「map the terminology」)
术语映射会演化4 Generating Cypher queries from natural language questionstext/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:287(搜「evolve over time」)
格式指令4 Generating Cypher queries from natural language questionstext/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:308(搜「ONLY」)
主走查问题与生成结果4 Generating Cypher queries from natural language questionstext/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:363(搜「Who directed the most movies」) · text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:437(搜「DIRECTED」)
schema 实例(Movies)4 Generating Cypher queries from natural language questionstext/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:393(搜「tagline」)
微调模型与差距4 Generating Cypher queries from natural language questionstext/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:444(搜「finetuning」) · text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:448(搜「pretty far behind」)
命名语义不清是出错源4 Generating Cypher queries from natural language questionstext/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:97(搜「semantically named」)

Footnotes

  1. 出处:「4 Generating Cypher queries from natural language questions」第 68 段(text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:68,搜「top three highest-rated」)。原文:这个问题永远无法被向量相似度搜索回答。

  2. 出处:「4 Generating Cypher queries from natural language questions」第 82 段(text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:82,搜「aggregating」)。原文:这条查询的重点不是找最相似的节点,而是以特定方式聚合数据。

  3. 出处:「4 Generating Cypher queries from natural language questions」第 33 段(text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:33,搜「can only assume」)与第 35 段(text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:35,搜「mapping between the semantics」)。

  4. 出处:「4 Generating Cypher queries from natural language questions」第 40 段(text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:40,搜「Retrieve the question」)。

  5. 出处:「4 Generating Cypher queries from natural language questions」第 334 段(text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:334,搜「Do not use any other」)。

  6. 出处:「4 Generating Cypher queries from natural language questions」第 168 段(text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:168,搜「sample the database」)。

  7. 出处:「4 Generating Cypher queries from natural language questions」第 142 段(text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:142,搜「doesn't matter that much」)。

  8. 出处:「4 Generating Cypher queries from natural language questions」第 106 段(text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:106,搜「specific to the knowledge graph」)。

  9. 出处:「4 Generating Cypher queries from natural language questions」第 134 段(text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:134,搜「not only fix the issue」)。

  10. 出处:「4 Generating Cypher queries from natural language questions」第 279 段(text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:279,搜「map the terminology」)。

  11. 出处:「4 Generating Cypher queries from natural language questions」第 287 段(text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:287,搜「evolve over time」)。 2

  12. 出处:「4 Generating Cypher queries from natural language questions」第 308 段(text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:308,搜「ONLY」)。原文:不要解释、不要道歉、除生成的 Cypher 语句外不要任何文本、只要 Cypher 不要代码块。

  13. 出处:「4 Generating Cypher queries from natural language questions」第 363 段(text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:363,搜「Who directed the most movies」);完整 prompt 的展开见第 387-430 段(text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:387,搜「Instructions」)。

  14. 出处:「4 Generating Cypher queries from natural language questions」第 89 段(text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:89,搜「catchall」)。原文:text2cypher 可以作为其他检索器都不匹配的问题类型的兜底检索器。

  15. 出处:「4 Generating Cypher queries from natural language questions」第 444 段(text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:444,搜「finetuning」)与第 448 段(text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:448,搜「pretty far behind」)。训练数据在 huggingface.co/datasets/neo4j/text2cypher。 2

  16. 出处:「4 Generating Cypher queries from natural language questions」第 97 段(text/13-ch04-4-generating-cypher-queries-from-natural-languag.txt:97,搜「semantically named」)。原文:问题复杂或含糊、或数据库 schema 元素没有语义化命名时,LLM 容易出错。

  17. 出处:「8 RAG application evaluation」第 198 段(text/20-ch08-8-rag-application-evaluation.txt:198,搜「dedicated mapping system」)。原文:出名电影和演员靠预训练就能生成正确查询,但冷门或私有数据集需要专门的映射系统做实体对齐。