p-memory 0.1.0

Embedded memory, knowledge graph, and note storage for Rust and Python
Documentation
# 知识图谱生成

本文件说明**如何从文本生成知识图谱**——也就是「从一篇文档到实体与关系」这一步的标准。它是[数据模型](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,因此落库前必须先完成实体消解;同名实体返回候选、不自动合并。