知识图谱进 RAG
这一章讲三件事: 本体怎么变成 Neo4j 里能查的图;hybrid embeddings 怎么让「用户的大白话」 找得到图里的节点;以及一段会改变你对「KG 数据怎么喂给 LLM」认知的研究。 最后一幕:第 09 章立的五个验收问题,全部答对。
1. 先辨名:本章不是讲 GraphRAG
原书特意不给这一章起名「GraphRAG」——GraphRAG 是微软研究院一个具体项目的名字: 用 LLM 自动从非结构化文本抽实体建图、聚类(即把相近的东西自动归成一堆一堆)、生成社区摘要的完整管线,查询还分两种模式 (global search 看全局聚类概览,local search 缩放到具体节点)。它的实验显示多跳问题准确率 超过标准 RAG 管线。论文 arXiv:2404.161301。
本书讲的是更朴素的 graph-based RAG:本体是人写的(第 09 章),图是确定性(即同问同答、不带随机)的, 检索走「语义找入口 + 图上扩展」。两者共同点是:把结构化、天然带关系的图 数据喂给 LLM。 (补充(不在书里,依据我们的 frontier 书架):微软 GraphRAG 的索引管线、Leiden 聚类与四种查询模式, 在我们对 microsoft/graphrag 源码的拆解里有逐文件分析。 依据: shelf=ai-frontier-reference/graphrag#04-query-search.md 事实=GraphRAG 查询层提供 global(map-reduce 全局)/local(实体邻域)/drift/basic 四种搜索,与原书对 GraphRAG 搜索方式的描述一致。)
2. 图能给 RAG 什么
原书列了七条 KG+RAG 的优势,归成三组2:
- 准: 沿显式的边遍历,而不是赌向量距离——噪声被过滤,返回的是精准匹配意图的子图;
- 深: 多跳推理(A→B→C 的关系链)把分散的事实接起来;同义词与消歧路径写进图里, 多义词不再被张冠李戴;
- 可信与常新: 每个节点、每条边带出处元数据,审计可追溯(医疗、金融刚需); 图可以增量更新,总在查最新事实,还能顺带压幻觉、免掉昂贵的模型重训。
3. 两种图,别搞混
第 08 章 LangGraph 的循环图(cyclical graph)和本章的本体 KG 是两种不同的图3:
| 循环图(LangGraph) | 本体 KG(本章) | |
|---|---|---|
| 形状 | 有环,允许回到起点 | DAG(有向无环图),沿着边走不回起点 |
| 类型层级 | 无强制 | is-a / part-of 的分类树,类不能是自己的祖先 |
| 用法 | agent 的控制流:提出假设、探索、迭代 | 查询库:按 schema 精确取事实,过滤出合规数据给 LLM |
| 风险 | 死循环,要做环检测 | 表达力受 schema 限制 |
本章的金融本体正是后者:Stock、Bond、Organization 的清晰层级,加上 issuedBy、 isRegulatedBy 的显式关系——一块给 LLM 的回答托底的稳定骨架4。
4. 主走查(上):本体进 Neo4j
原书的代码实验室把第 09 章的 FinancialOntology.ttl 变成 Neo4j 里活的数据,关键步骤:
- 解析与转换: rdflib 解析 Turtle 文件的三元组,转成节点表、边表、数据表三份 CSV,经 Python 驱动导入 Neo4j Desktop(本地
bolt://127.0.0.1:7687)5; - 补类型边: 导入用的都是通用
:Resource标签(而不是 :Stock、:Bond),所以要回填 rdf:type 的成员关系——从 TTL 里抽 出(个体, 类)对,共 12 对,建成(:AAPL)-[:IS_A]->(:Stock)这样的边6; - 建锚点节点: 为每类造一个「枢纽」概念节点(All Stocks、All Bonds、All Orgs、All Regulators),用
:INCLUDES边连到全部成员——查询入口从此有个「目录页」。验证输出:All Bonds 包含 1 个成员,All Stocks 包含 2 个7。
到这里,「AAPL 是股票、由 Apple_Inc 发行、受 SEC 监管」这些事实在图里是可以精确查询的 ——但用户的输入是自然语言,不知道你的 schema、不知道边叫什么名字。缺口怎么补?
5. 主走查(中):hybrid embeddings,本书的独门机制
问题: 用户问「equities regulated by the SEC」。图里类的标签是 Stock,没有「equity」这个词; 边名 IS_REGULATED_BY 用户也不知道。纯图查询接不住,纯向量搜索又够不着图的结构。8
解法(hybrid embeddings): 给每个实体生成一段「图文并茂」的文本—— 它自己的属性 加上沿边能走到的上下文——把这段文 字变成向量(嵌入,即把文字转成向量)。AAPL 的完整版长这样9:
Stock AAPL [AAPL] issued by Apple Inc. regulated by SEC —
A security representing equity ownership in a corporation.
Issuer regulated by SEC.
注意最后一句「Issuer regulated by SEC」——发行人的监管者是二阶邻居(多跳)信息, 被预先埋进了向量。生成它的是一条 Cypher 查询:匹配实体,可选匹配 ISSUED_BY、 IS_REGULATED_BY、发行人的 IS_REGULATED_BY,拼成一段描述文本10。
这个设计买到了三样东西11:
- 召回: 「equity」在图里不存在,但这段文本里有——语义搜索照样命中 AAPL;
- 分工: 语义搜索负责「找到对的实体」,Cypher 负责「取回精确事实」——两套机制各干各的强项;
- 预埋的多跳: 问「发行人的监管者是谁」,不用真的扩展图,向量的相似度已经把答案顶上来了。
作者给这个机制的最高评价是:它是 KG-based RAG 常常胜过纯向量 RAG 的最大单项原因12。
6. 主走查(下):检索、扩展、按「字典格式」喂给 LLM
查询时的流水线13:
用户问题 → 向量化 → 在 hybridText 向量里搜 top-5 → 拿实体 ID 回 Neo4j
→ 沿边扩展(深度 2)取邻居事实 → 组装上下文 → LLM 生成
图说:语义搜索定入口,图扩展取事实;引用键 [E1][E2] 标注每个命中实体。
一个反直觉的研究:喂图数据,JSON 是差生
KG 查出来的结构化数据,给 LLM 时用什么格式?直觉会说自然语言或 JSON。 原书引了 Wu & Tsioutsiouliklis(2024)的实验,结论反直觉14:
| KG 表示格式 | 多跳推理准确率 |
|---|---|
| 自然语言 | 44.6% |
| JSON | 26.1%(比基线还低!) |
| Python 静态字典 | 67.9%(比基线高 78%) |
| Python 格式 + 微调 | 91.5% |
解释:LLM 的预训练语料里有海量代码,它能把 relationships['type']['AAPL'] 这样的字典查找
当作显式的推理步骤来「执行」,而不是含糊的模式匹配。所以组装上下文时,输出长这样:
relationships = {
'type': {'AAPL': 'Stock', 'USTB': 'Bond'},
'issuedBy': {'AAPL': 'Apple Inc', 'USTB': 'US Treasury'},
'isRegulatedBy': {'AAPL': 'SEC', 'MSFT': 'SEC'},
}
# Example: relationships['type']['AAPL'] returns 'Stock'
验收:五个问题全过
LangChain 链(make_context → 提示词 → LLM)跑第 09 章立的五个能力问 题15:
| 能力问题 | agent 的回答 |
|---|---|
| AAPL 是股票还是债券? | AAPL is a stock. |
| USTB 是什么工具? | USTB is a bond. |
| 谁监管 MSFT? | MSFT is regulated by the SEC. |
| SEC 监管哪些股票?发行人是谁? | AAPL(Apple Inc)和 MSFT(Microsoft Corp) |
| 你知道哪些股票/债券? | 两只股票:AAPL、MSFT;一只债券:USTB |
第 4 问是真多跳:股票→监管者是一跳,监管者→受监管的全部股票→各自的发行人,又两跳。 Python 字典格式把答案钉在结构化事实上,LLM 没有机会动用训练数据里的旧知识或幻觉16。
7. 边界与局限
- 本体要人工维护:本体演化后要「定期导出、重新导入」;原书的最佳实践清单把它列为第一条17;
- hybridText 是「快照式」的——图变了必须重生成、重嵌入,这是它相对于「查询时实时扩展」的额外成本(书里未展开讨论这一权衡);
- Wu & Tsioutsiouliklis 的实验基于特定数据集与模型,数字不宜外推——即推广到自己的场景——为普适定律;但「给 LLM 代码格式优于 JSON」这个方向,与我们在 LangChain 拆解里见到的「结构化输出优先」倾向一致。
8. 可带走的
- GraphRAG 是微软的项目名;graph-based RAG 是本书的朴素路线,别混用。
- 循环图(agent 控制流)与本体的 DAG 是两种图——一个管「怎么推理」,一个管「事实长什么样」。
- hybrid embeddings = 把图上下文拍平进文本再嵌入;它是「自然语言找得到结构化图」的桥。
- 多跳信息可以预埋进向量,减少运行时的图扩展。
- 给 LLM 喂 KG 数据,Python 字典格式大幅优于 JSON(26.1% vs 67.9%)——JSON 反而比基线差。
- 语义搜索定入口、Cypher 取事实——两套检索各干各的强项。
- 验收靠 competency questions——上一章立的问题,这一章全过,闭环完成。
9. 原文地图
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| GraphRAG 是微软项目名与两种搜索 | Graph-Based RAG | text/77-fm-graph-based-rag.txt:32(搜「GraphRAG」) · text/77-fm-graph-based-rag.txt:35(搜「Microsoft Research」) |
| GraphRAG 论文与 仓库 | Graph-Based RAG | text/77-fm-graph-based-rag.txt:35(搜「2404.16130」) |
| KG+RAG 七优势 | Graph-Based RAG | text/77-fm-graph-based-rag.txt:53(搜「Enhanced retrieval precision」) · text/77-fm-graph-based-rag.txt:71(搜「incrementally updatable」) |
| 循环图 vs 本体 DAG | Graph-Based RAG | text/77-fm-graph-based-rag.txt:81(搜「directed acyclic graphs」) · text/77-fm-graph-based-rag.txt:95(搜「cyclical graphs」) |
| 本体 KG 给 LLM 过滤合规事实 | Graph-Based RAG | text/77-fm-graph-based-rag.txt:101(搜「schema-compliant」) |
| 导入流程(ttl→CSV→Neo4j) | Step 4 – importing nodes, edges, and data properties into Neo4j | text/81-fm-step-4-importing-nodes-edges-and-data-properties.txt:1(搜「importing」) |
| 环境与库(nutneo4j/rdflib/faiss) | Step 2 – preparing your notebook environment | text/79-fm-step-2-preparing-your-notebook-environment.txt:59(搜「neo4j ==6.0.3」) · text/79-fm-step-2-preparing-your-notebook-environment.txt:60(搜「rdflib」) |
| 12 对类型边 | Step 5 – add navigational anchor nodes (stocks, bonds, and so on) | text/82-fm-step-5-add-navigational-anchor-nodes-stocks-bond.txt:61(搜「The output is 12」) |
| 锚点节点与验证 | Step 5.2 – create All X concept nodes and wire members | text/83-fm-step-5-2-create-all-x-concept-nodes-and-wire-mem.txt:9(搜「All Stocks」) · text/83-fm-step-5-2-create-all-x-concept-nodes-and-wire-mem.txt:88(搜「members」) |
| 用户不知道 schema 的问题 | Step 6 – enable hybrid embeddings (text + structure) and multi-hop support | text/84-fm-step-6-enable-hybrid-embeddings-text-structure-a.txt:7(搜「without knowing the schema」) |
| hybrid embeddings 定义 | Step 6 – enable hybrid embeddings (text + structure) and multi-hop support | text/84-fm-step-6-enable-hybrid-embeddings-text-structure-a.txt:1(搜「hybrid embeddings」) |
| AAPL 的 hybridText | Step 6 – enable hybrid embeddings (text + structure) and multi-hop support | text/84-fm-step-6-enable-hybrid-embeddings-text-structure-a.txt:30(搜「Stock AAPL」) |
| 多跳信息预埋 | Step 6 – enable hybrid embeddings (text + structure) and multi-hop support | text/84-fm-step-6-enable-hybrid-embeddings-text-structure-a.txt:36(搜「multi-hop information」) |
| equity 命中与两套检索分工 | Step 6 – enable hybrid embeddings (text + structure) and multi-hop support | text/84-fm-step-6-enable-hybrid-embeddings-text-structure-a.txt:50(搜「equities regulated by SEC」) |
| 「最大单项原因」断言 | Step 6 – enable hybrid embeddings (text + structure) and multi-hop support | text/84-fm-step-6-enable-hybrid-embeddings-text-structure-a.txt:46(搜「secret sauce」) |
| Cypher 拼 hybridText | Step 6 – enable hybrid embeddings (text + structure) and multi-hop support | text/84-fm-step-6-enable-hybrid-embeddings-text-structure-a.txt:4(搜「ISSUED_BY」) |
| 检索+扩展流水线 | Step 7 – vector search and graph expansion (ready-to-prompt context) | text/85-fm-step-7-vector-search-and-graph-expansion-ready-t.txt:8(搜「Gets embedded and matched」) |
| 三种上下文格式与 JSON 反而差 | Step 7 – vector search and graph expansion (ready-to-prompt context) | text/85-fm-step-7-vector-search-and-graph-expansion-ready-t.txt:140(搜「Natural language」) |
| Wu & Tsioutsiouliklis 实验数字 | Step 7 – vector search and graph expansion (ready-to-prompt context) | text/85-fm-step-7-vector-search-and-graph-expansion-ready-t.txt:157(搜「67.9%」) · text/85-fm-step-7-vector-search-and-graph-expansion-ready-t.txt:157(搜「91.5%」) |
| LLM 把字典查找当推理步骤 | Step 7 – vector search and graph expansion (ready-to-prompt context) | text/85-fm-step-7-vector-search-and-graph-expansion-ready-t.txt:160(搜「mentally」所在段,搜「execute」) |
| 引用键与上下文组装 | Step 7 – vector search and graph expansion (ready-to-prompt context) | text/85-fm-step-7-vector-search-and-graph-expansion-ready-t.txt:17(搜「citations」) |
| 生成链与五问全答 | Step 8 – generate with LangChain and OpenAI | text/86-fm-step-8-generate-with-langchain-and-openai.txt:14(搜「make_context」) · text/86-fm-step-8-generate-with-langchain-and-openai.txt:54(搜「Is AAPL a stock or bond?」) |
| 多跳验证(SEC 监管的股票) | Step 8 – generate with LangChain and OpenAI | text/86-fm-step-8-generate-with-langchain-and-openai.txt:61(搜「issued by Apple Inc」) |
| 字典格式防幻觉 | Step 8 – generate with LangChain and OpenAI | text/86-fm-step-8-generate-with-langchain-and-openai.txt:102(搜「hallucinated information」) |
| 最佳实践清单 | Best practices and next steps | text/87-fm-best-practices-and-next-steps.txt:1(搜「best practices」) · text/87-fm-best-practices-and-next-steps.txt:36(搜「larger ontologies」) |
| 别局限于本体 | Best practices and next steps | text/87-fm-best-practices-and-next-steps.txt:48(搜「limit yourself to ontologies」) |