L1 Atom 抽取与去重 本节摘要:L0 是原封不动的底座,L1 是第一层「提炼」——从 L0 对话里抽出结构化的事实、偏好、约束、事件,称为 L1 Atom(原子记忆)。这一层让记忆从「一整段对话」变成「一条条可精确召回的原子」。本节讲清 L1 抽取什么、为什么必须去重、去重的大致策略。L1 是召回引擎最常检索的层(因为它既精确又轻量),它的质量直接决定「记忆准不准」,所以抽取与去重是整套系统的质量根基。
本节摘要:L0 是原封不动的底座,L1 是第一层「提炼」——从 L0 对话里抽出结构化的事实、偏好、约束、事件,称为 L1 Atom(原子记忆)。这一层让记忆从「一整段对话」变成「一条条可精确召回的原子」。本节讲清 L1 抽取什么、为什么必须去重、去重的大致策略。L1 是召回引擎最常检索的层(因为它既精确又轻量),它的质量直接决定「记忆准不准」,所以抽取与去重是整套系统的质量根基。
从一段 L0 对话里,L1 抽取的不是「对话摘要」,而是四类离散的结构化信息:
| 类型 | 抽取什么 | 例子 |
|---|---|---|
| 事实 | 客观存在的陈述 | 「后端用 Go,数据库 PostgreSQL」 |
| 偏好 | 主观倾向 | 「禁止用 ORM」「喜欢简洁注释」 |
| 约束 | 限制性条件 | 「鉴权模块不能动,移动端在用」 |
| 事件 | 发生过的事 | 「上周三做了 v2 发布」 |
L0(一段对话) 用户:我们后端用 Go,数据库是 PostgreSQL,禁止 ORM, 所有 SQL 手写。另外鉴权模块别动,移动端在用。 对了上周三刚做完 v2 发布。 L1(抽出多条 Atom) ├─ 事实:「后端技术栈 = Go + PostgreSQL」 ├─ 偏好:「SQL 写法 = 手写,禁止 ORM」 ├─ 约束:「鉴权模块不可改(移动端依赖)」 └─ 事件:「v2 发布于上周三」
关键概念:L1 抽取的价值在「离散化」——把一整段对话拆成一条条独立的、可单独召回的原子。这样召回时能精确取「技术栈」这一条,而不必带上一整段对话。这是「精确召回」的基础。
每条 L1 Atom 是结构化的、轻量的记录,大致包含:
一条 L1 Atom 的形态 ├─ 类型(事实/偏好/约束/事件) ├─ 内容(结构化表述) ├─ 来源(指向 L0 原话,可回溯) ├─ 时间(抽取时间 + 原话时间) ├─ 向量(用于向量检索) └─ 关键词(用于 BM25 检索)
注意两个关键字段:来源指向 L0(保证可回溯核对)、向量与关键词并存(支持混合检索)。L1 是召回引擎最常检索的层,因为它既比 L0 精确,又比 L2/L3 轻量——一条 L1 通常就一句话,占上下文极少。
💡 技巧:第 1 章验收时你在控制台看到的「措辞与原话不同的记忆」,大概率就是 L1 Atom——它是抽取后的结构化表述,不是原话。比如原话「禁止 ORM」,可能被提炼成 L1「约束:不使用对象关系映射」。这是正常的,不是 bug。
L1 抽取面对一个严峻问题:用户会反复说同样的事。如果不去重,L1 池里会有大量重复:
不去重的后果(反面) 用户在 10 次对话里都提到「禁止 ORM」 → 抽出 10 条「禁止 ORM」的 L1 → 召回时这 10 条全命中,占满召回预算 → 真正有用的其他记忆被挤出上下文 → 重复 = 记忆质量的杀手
去重后:
去重的效果 10 条「禁止 ORM」 → 去重合并为 1 条(可能更新置信度/时间) → 召回时只占 1 条预算 → 其他记忆有空间进上下文 → 去重 = 让每条记忆都是「新的信息」
这就是为什么去重不可省——它直接决定召回预算的利用效率。没有去重,系统会被重复记忆塞满,反而变笨。
去重怎么判断「两条 L1 是不是同一件事」?大致用两类判据组合:
| 判据 | 怎么用 | 适合 |
|---|---|---|
| 语义近似 | 算两条 L1 向量的相似度,超阈值视为同义 | 「禁止 ORM」与「不用对象关系映射」 |
| 字段比对 | 比对类型、关键实体、约束对象等字段 | 同一对象的两条「事实」合并 |
去重判定流程(概念) 新抽出 L1_new │ ├─ 与已有 L1 池做语义近似匹配 │ └─ 找到相似度 > 阈值的 L1_old? │ ├─ 是 → 进一步字段比对确认 │ │ ├─ 确认同义 → 合并(更新置信度/时间,不新增) │ │ └─ 不同义 → 作为新 L1 入池 │ └─ 否 → 作为新 L1 入池 │ ▼ L1 池(去重后,每条都是新信息)
⚠️ 注意:去重是「双刃剑」——阈值太松,会把不同的事误判为重复(信息丢失);阈值太严,该合并的没合并(重复仍在)。实践中阈值需要调,这是第 6 章源码精读会涉及的工程细节。对使用者而言,要知道「去重存在、它在默默工作」,但不必纠结具体阈值。
L1 抽取后,L0 并不删除(上一节讲的「叠加」)。两者协作构成「精确召回 + 可回溯」的组合:
典型召回流程 问题:「我们用什么数据库?」 │ ├─ L1 检索:命中「后端技术栈 = Go + PostgreSQL」 │ (精确、轻量、直接可用) │ └─ 若需核对原话: └─ 通过 L1 的「来源」字段 → 回到 L0 取原话 (可回溯、不失真)
L1 负责「快和准」,L0 负责「真和全」。两者叠加,既能让 Agent 秒答常见问题,又能在需要时追溯到原话。这就是四层架构里「L0+L1」这一对的价值——精确与可信兼备。
L1 是离散的原子,下一节看它们如何被「聚合成块」——L2 Scenario 围绕场景把 L1 组织起来,用于快速恢复一个工作场景。