slug
Graph RAG 工程化|如何让 LLM 抽取的"漂移"可治理
type
Post
status
Published
date
May 9, 2026
tags
推荐
文字
开发
summary
category
AI&机器学习
icon
password
Graph RAG 工程化|如何让 LLM 抽取的"漂移"可治理
上一篇我把 Schema 设计的六条判据写完了,本以为 Schema 设计完,抽取就是"调 prompt + 喂文本"的简单事。 真做起来才发现:LLM 是概率模型,不是程序。Schema 写得再严,它还是会偷偷"自由发挥"。 这一篇是踩坑总结:抽取阶段的"漂移"到底是什么、有哪几种、怎么系统性治理。
一、一个具体的踩坑场景
我用 v2.1 Schema 跑了一段真实文本:
"苹果公司CEO库克于2024年在加州库比蒂诺总部宣布发布iPhone 16,售价799美元起,同时宣布投资台积电20亿美元用于产能扩张。"
抽出来的 5 条 triple,每一条都有问题:
5 条里只有 1 条干净。这个比例不夸张——zero-shot 状态下,抽取漂移率通常在 20%~30%。
如果直接入图,下游就毁了:
- 查"苹果公司投资了哪些公司"——查不到,因为投资关系挂在"Apple"节点下
- 查"库克任职于哪家公司"——拿到两条结果,一条
任职于一条担任CEO
- 查"哪些公司发布了产品"——
苹果和苹果公司是两个节点,统计错乱
二、漂移到底是什么
漂移(Drift):在 Schema 不变的前提下,LLM 对相同或相似输入给出不一致输出的现象。
关键词是"不一致"——不是错,是前后不一。错可以修,不一致难以下游处理。
容易混的两个概念,必须分清:
现象 | 定义 | 根因 | 解法 |
漂移 | 同一输入,不同输出 | Schema 模糊 / prompt 不约束 | 收紧 Schema / closed list / 降温 |
幻觉 | 输出原文没说的内容 | 模型靠世界知识脑补 | Evidence 强约束 / 引用原文片段 |
例子:
- 原文:"雷军是小米的高管。"
- 漂移:一次抽
(雷军, 任职于, 小米),一次抽(雷军, 工作于, 小米)
- 幻觉:抽
(雷军, 担任CEO, 小米)——原文没说他是 CEO
两个都是问题,但解法不同。把它们混在一起诊断,治不对症。
还有第三类容易和漂移混淆的:Schema 设计错误。比如上面案例里的
(iPhone 16, 售价, 799美元)——这条 triple 不该被抽出来,但不是因为漂移,是因为 Schema 当初就不该把"售价"建成 Relation。这是设计层面的错,不是抽取层面的错。三、四类漂移
漂移按发生位置分为四类。诊断时要先定位是哪一类,才能选对治法。
Type 漂移
同一个实体,不同次抽取被标成不同 Entity Type。
根因: type 列表太长 + type 间边界模糊。
Relation 漂移
同一个语义关系,被表达成不同 Relation Type——这是最常见也最毁图谱的一类。
下游查
[:任职于] 时,前三条全部漏检。实体名漂移
同一实体,名字被抽成不同字符串。
这一类 Schema 帮不上忙——它不是 Schema 设计能解决的问题。必须靠后处理实体归一化。
粒度漂移
同一段文本,每次抽出的 triple 数量和细致程度差异巨大。
这种漂移最阴险——它会让 self-consistency(多次抽取取交集)这种降噪手段失效,因为粒度差太大就没"交集"可言。
四、治理框架:事前 / 事中 / 事后
漂移治理不是单点优化,是三层叠加。
事前(Schema 层)
- 合并模糊边界
- closed list 控制在 5~15 个
- Domain/Range 约束写清楚
事中(Prompt 层)
- closed list 强约束("只能从以下选")
- few-shot in-domain 示例(3~5 个)
- temperature 降到 0.0~0.3
- 强制输出 evidence 字段
事后(代码层)
- Validation 守门(Pydantic + Domain/Range)
- 失败处理:drop / retry / auto-fix
- Normalize 映射表(就职 → 任职于)
- 实体归一化(解决跨 triple 的名字漂移)
每一层挡掉的是不同问题,少一层,整条链路就漏。
五、五个工程概念
把这五个词搞清楚,整个抽取 pipeline 的设计语言就通了。
Closed list
穷举的、不允许超出的列表。比如
[Person, Organization, Product, Location, Event]。为什么有效? LLM 看到 closed list,输出概率分布会向这几个 token 集中。如果你不给 list,模型可能输出 "Company"、"Org"、"Persons"、"个人"——每次不一样。
长度甜蜜区:5~15 个。 少于 5 表达力不够,多于 15 开始漂移失控。
Closed schema
多个 closed list + 它们之间的约束(Domain/Range)。
不是简单的"进阶版",是"组合 + 约束"。一个完整的 closed schema 至少包含:Entity Type list + Relation Type list + Domain/Range 映射表。
Few-shot
给 2~10 个示例隐式定义任务。LLM 不是在"学"示例(参数没更新),是在 in-context 推断:"用户想要的输出格式、抽取粒度、关注的关系,应该是这种样子"。
示例的质量 >> 数量。 3 个高质量 in-domain 示例 >> 10 个杂七杂八的示例。
In-domain
示例和真实任务同分布。判断 in-domain 的四个维度:
- 语言(中文 vs 英文)
- 文体(新闻 vs 论文 vs 对话 vs 合同)
- 领域(财经 vs 医疗 vs 法律)
- 粒度(短文本 vs 长文档;密集抽取 vs 稀疏抽取)
四个全对 = 完美 in-domain。错一个就开始打折,错两个以上基本无效。
Validation
代码层的守门员。
这是最容易被忽略但最关键的一环。Prompt 里的 closed list 是"愿望",Validation 代码是"执法"。LLM 不是程序,所以愿望必须配执法:
没有 validation 的 closed schema = 没有警察的法律。
六、三者的角色定位
如果只能记一句话,记这个:
Closed schema 定义合法边界(事前),few-shot 在边界内给优质范例(事中),validation 在出口处守门(事后)。三者作用于抽取的事前、事中、事后——缺一个,前两个的努力都会漏到下游。
七、漂移诊断速查表
把今天讲的所有内容浓缩成一张表。这就是抽取 pipeline 的肌肉记忆。
输出问题 | 诊断 | 治法 |
Relation 名不在 closed list | Relation 漂移 | closed list 强约束 + few-shot |
同一语义出现多个 Relation | Relation 漂移 | 后处理 normalize 映射 |
同一实体出现不同名字 | 实体名漂移 | prompt 约束 + 后处理实体归一化 |
同一实体被标不同 type | Type 漂移 | 缩短 type 列表 + few-shot |
多次抽取 triple 数差异大 | 粒度漂移 | 降温 + few-shot 统一粒度 |
输出原文没说的内容 | 不是漂移,是幻觉 | evidence 字段强约束 |
不该抽的内容被抽了 | 不是漂移,是 Schema 设计问题 | 重新设计 Schema |
八、收束
这一轮学习最大的认知升级,不是任何一条具体规则,而是这件事:
LLM 抽取的稳定性不来自"模型够强",来自"约束够严 + 守门够紧"。
所有想"靠换更大的模型解决漂移问题"的尝试都会失败——因为漂移不是能力问题,是任务定义模糊 + 输出空间过大的结构性问题。换 GPT-5 救不了你。
下一篇继续往下挖:实体归一化。你刚才看到的"苹果 vs 苹果公司 vs Apple"问题,正是它要解决的——这是 Graph RAG 工程化里最脏最累但最关键的一块,Schema 解决不了的硬骨头,只能靠工程方法硬磕。
- Author:盛溪
- URL:https://tangly1024.com/article/Graph%20RAG%20%E5%B7%A5%E7%A8%8B%E5%8C%96%EF%BD%9C%E5%A6%82%E4%BD%95%E8%AE%A9%20LLM%20%E6%8A%BD%E5%8F%96%E7%9A%84%22%E6%BC%82%E7%A7%BB%22%E5%8F%AF%E6%B2%BB%E7%90%86
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!



.jpg?table=block&id=26f7c1d5-a1e9-80d7-a52b-e71bb7079501&t=26f7c1d5-a1e9-80d7-a52b-e71bb7079501)




