# 知识图谱生成
本文件说明**如何从文本生成知识图谱**——也就是「从一篇文档到实体与关系」这一步的标准。它是[数据模型](data-model.md)里实体/关系/事件三张表**上游**的约定。
一句话定位:
> **先定生成标准,再谈落库。图是标准的产物。**
## 1. 这一层管什么、不管什么
图谱在入口就已经定型。如果「从文本抽关系」这一步没有标准,每一步都是自由发挥,落库的东西结构各不一样,后面的清洗怎么补都补不回来。
这一层只定**生成格式**,也就是「一条关系长什么样、方向怎么锁」。它**不定**下面这些:
| 实体消解成谁 | 生成之后的归并步骤(同名返回候选、不自动合并,见 [data-model](data-model.md)) |
| 关系词/角色词/类型词表 | 数据,放配置或后处理归一,**不进生成语法** |
| 语义类别(这是动作还是身份) | 消费端解释,**生成端不判** |
| 出处怎么定位到切片 | 笔记层的 `notes`/`chunks`,见 [data-model](data-model.md) |
**核心原则:生成端只负责把「方向」和「内容」填对,交出一条关系式;语义、类别、解释全在消费端。**
方向不靠 LLM「理解」语义来判,靠**关系式的形状**锁死——就像数学里 `A ÷ B` 只有一个意思,因为 `÷` 的定义里写着「左是被除数」。定义一次,方向就是语法的一部分。
## 2. 生成格式:四段
一条关系输出四行:
```
实体列表: ...
关系: ...
关系式: ...
出处: ...
```
- `实体列表`:本条关系用到的实体,逗号分隔。
- `关系`:关系名(稳定的关系标签)。
- `关系式`:本条关系的方向与结构,用关系式表达。
- `出处`:来源定位,每条关系式各带一条。
一段一条,没有分支。
## 3. 关系式:一式
关系式只有一个形状:**关系名永远在最左,方向就是「有没有等号右边」**。
```
有向: 关系名(参数...) = 结果
对等: 关系名(参数...)
```
- **有向**关系有落点,`=` 右边是结果。
- **对等**关系两端平级、没有落点,右端为空,等号不写。
**「等号右端的有无」就是「方向的有无」。** 整件事只是同一根可有可无的尾巴,长在同一个式子上。对等属于方向「对称的那一档」——语法层面不需要额外操心,只要判断「这条关系有没有落点」。
解析规则只有一条:**行首读关系名,括号里是参数,遇到 `=` 再读右端。**
参数与右端都可以是多个。
### 有向
```
父亲(林昭) = 林远
创造(林远) = 林昭
审判(陈默) = 林昭
```
多值直接并列在右端:
```
子女(顾青) = 周敏, 周静
```
### 对等
没有落点,右端为空,关系名同样在最左。**写一条即可**——参数就是双方,不需要反向再写一条。
```
同事(林昭, 陈默)
合作(秦朗, 顾青)
```
### 语义不标
动作还是身份,**不用标**——LLM 自己分得清「审判」是动作、「师傅」是身份。语法只有一个目标:让 LLM 生成得顺、填得准,所以形状唯一、位置好认、短。
`审判(陈默) = 林昭` 和 `父亲(林昭) = 林远` 是同一个形状,方向都不会错。语义类别的维度是为了救方向才存在的;方向被关系式锁死后,它就不再需要在生成端出现。
## 4. 样例
```
实体列表: 林远, 林昭
关系: 创造
关系式: 创造(林远) = 林昭
出处: docs/characters/lin-zhao/overview
实体列表: 陈默, 林昭
关系: 审判
关系式: 审判(陈默) = 林昭
出处: docs/plot/chapter-5
实体列表: 秦朗, 顾青
关系: 合作
关系式: 合作(秦朗, 顾青)
出处: notes/interviews/gu-qing
```
## 5. 与落库的衔接
生成端产出的是关系式,落库要把它转成 [data-model](data-model.md) 的结构:
```
文档 →【按标准生成关系式】→【消解成实体 id】→【写 entity / relation 表】→ 图
```
| `C(A) = B` 有向 | `RelationInput { subject_id: A, predicate: C, object_id: B }` |
| `C(A, B)` 对等 | `RelationInput { subject_id: A, predicate: C, object_id: B }`(无向关系落成一条有向记录,由谓词标记其对称性) |
`subject_id` / `object_id` 是库分配的实体整数 id,因此落库前必须先完成实体消解;同名实体返回候选、不自动合并。