L1 抽取与去重实现 本节摘要:本节深入 Pipeline 的第一段异步处理——L1 抽取与去重。第 4 章只讲「L1 抽四类、要去重」,本节讲「具体怎么抽、怎么判重」。你会看到抽取用的提示策略(让 LLM 按结构化 schema 输出)、去重的双判据(语义近似 + 字段比对)如何配合、以及为什么去重是召回质量的根基。本节是排查「记忆不准/重复」时的核心参考——召回不准,很多时候是抽取或去重出了问题。 一、L1 抽取的提示策略:结构化输出 L1 抽取不是「让 LLM 自由总结」,而是用结构化 schema 约束输出,确保每条 Atom 字段齐全: 为什么要结构化?因为后续的「去重」「检索」「回溯」都依赖字段——非结构化的自由文本既难判重,也难精确检索。
本节摘要:本节深入 Pipeline 的第一段异步处理——L1 抽取与去重。第 4 章只讲「L1 抽四类、要去重」,本节讲「具体怎么抽、怎么判重」。你会看到抽取用的提示策略(让 LLM 按结构化 schema 输出)、去重的双判据(语义近似 + 字段比对)如何配合、以及为什么去重是召回质量的根基。本节是排查「记忆不准/重复」时的核心参考——召回不准,很多时候是抽取或去重出了问题。
L1 抽取不是「让 LLM 自由总结」,而是用结构化 schema 约束输出,确保每条 Atom 字段齐全:
抽取的提示策略(概念) 输入:一段 L0 对话 提示(给 LLM): 「从以下对话抽取记忆原子,按 schema 输出: - type: 事实|偏好|约束|事件 - content: 结构化表述 - entities: 涉及的关键实体 - confidence: 置信度」 输出:多条结构化 L1 Atom
为什么要结构化?因为后续的「去重」「检索」「回溯」都依赖字段——非结构化的自由文本既难判重,也难精确检索。结构化让每条 Atom 是「机器可处理」的,而不只是「人可读」的。
| 字段 | 在后续环节的作用 |
|---|---|
| type | 分类检索、按类型过滤 |
| content | BM25/向量检索的文本 |
| entities | 字段比对去重、精确过滤 |
| confidence | 排序、低置信度可筛掉 |
| 来源指针 | 回溯到 L0 原话 |
关键概念:抽取的质量直接决定召回质量——抽错了(漏抽/误抽),后续检索再准也白搭。所以抽取提示的设计是 L1 质量的核心,通常会用 few-shot 示例 + schema 约束 + 后处理校验三重保障。
不是 L0 里所有信息都该抽成 L1。抽取要判断「什么值得留」:
该抽 vs 不该抽的判断 该抽: ├─ 稳定事实(技术栈、架构决策) ├─ 明确偏好(禁止 ORM、喜欢简洁) ├─ 硬约束(鉴权不能动) └─ 关键事件(做了发布、出了事故) 不该抽: ├─ 临时性闲聊(今天天气) ├─ 已废弃的临时决定(后来改了的) ├─ 寒暄/客套 └─ Agent 的推理过程(非用户信息)
这个判断很难完全自动化,所以抽取提示通常会强调「只抽稳定、明确、有价值的信息」。即便如此,仍会有噪声——这正是去重要处理的。
⚠️ 注意:抽取常见的两类失败:① 漏抽(重要的没抽出来),② 过抽(把闲聊也抽了)。前者让记忆不全,后者让记忆被噪声稀释。调试抽取时,对照 L0 原话看抽出来的 L1,能快速发现是哪类失败。
第 4 章讲过去重用「语义近似 + 字段比对」,这里看它们如何配合:
去重判定流程(实现视角) 新抽出 L1_new │ ├─ 步骤1:候选筛选 │ 用 L1_new 的向量,在 L1 池里找 top-K 相似 │ (向量检索,快,缩范围) │ ├─ 步骤2:精细判定(对每个候选) │ ├─ 语义近似度 > 阈值 A? │ └─ 关键字段(entities/type)比对一致? │ 两者都满足 → 判为重复 │ └─ 判重复: ├─ 是 → 合并(更新置信度/时间,不新增) └─ 否 → 作为新 L1 入池
| 判据 | 作用 | 实现 |
|---|---|---|
| 语义近似 | 抓「说法不同但意思一样」 | 向量余弦相似度 |
| 字段比对 | 抓「同一对象的不同表述」 | entities/type 匹配 |
两步设计(先候选筛选、后精细判定)是为了效率——不可能对每条新 L1 与全池逐一精细比对(太慢),先用向量检索缩到 top-K 候选,再对候选精细判。
💡 技巧:去重阈值 A 是关键调参点。太松(阈值低):不同的事被判同义,信息丢失;太严(阈值高):该合并的没合并,重复仍在。实践中要看具体数据调,且不同 type(事实 vs 偏好)可能用不同阈值——事实要求更严(「数据库是 PG」和「数据库是 MySQL」绝不能合并),偏好可稍松。
判为重复后,「合并」不是简单丢弃,而是把信息融合:
合并策略(概念) L1_old:「禁止 ORM」 置信度 0.8 时间 t1 出现次数 3 L1_new:「不用 ORM」 置信度 0.9 时间 t2 出现次数 1 合并后: content: 取表述更清晰的(或保留 old) 置信度: 提升(多次出现增强置信) 时间: 更新为最近 t2 出现次数: 累加 → 4 来源指针: 合并(指向多次 L0 原话)
合并的价值:① 不重复占召回预算,② 多次出现提升置信度(让常用记忆更易被召回),③ 保留多个来源指针(回溯更全)。这就是为什么「用户反复说的事」不仅不会塞满记忆,反而会变成「高置信度的稳定记忆」。
这套实现里有几个关键的工程权衡:
| 权衡点 | 取舍 |
|---|---|
| 抽取模型 | 强模型抽得准但贵,弱模型便宜但噪声多 |
| 去重阈值 | 松则丢信息,严则留重复 |
| 合并策略 | 激进合并省空间但可能误合,保守合并安全但留冗余 |
| 抽取频率 | 实时抽及时但频繁调 LLM,攒批抽省钱但延迟 |
⚠️ 注意:这些权衡没有「标准答案」,要看团队的数据量和预算。第 1 章提到的「memory 组凭证」就可以用性价比模型——因为抽取量大、对单次精度要求不极致(去重能兜底),适合用相对便宜的模型。但完全不能用太弱的模型,否则噪声压过去重都救不回来。
L1 抽取与去重清楚后,下一节看 L1 如何被进一步组织——L2 场景聚合与 L3 画像提炼的沉淀机制。