HEL-847 v4: Mem0 capability corrections per manager review - additive-only infer, backend filter/BM25 facts, pre-isolation privacy design, concrete spike spec

Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
zonggong
2026-10-25 22:23:53 +08:00
co-authored by multica-agent
parent 800d3b75b6
commit bb9cbe915e
+198
View File
@@ -0,0 +1,198 @@
# HEL-847 · 成熟方案优先复用:有界方案修订 v4(Mem0 能力表纠正 + 前置隐私隔离 + 可批准的验证卡规格)
> 角色:总工。性质:**只读源码核对 + 方案修订**,零模型调用、零依赖安装、零部署、零现网/真实档案访问、零产品代码变更。本文是对 v3(`mature-reuse-plan-v3.md`,800d3b7)的**有界返修**,依据总管 2026-10-25 独立复核与《Mem0-v3-总管源码复核材料》附件完成。v3 文件原样保留为历史,不作涂改;本文§1 给出逐条勘误表。
>
> **本轮不动的东西**:v1.11 治理补丁(总管已复核通过,60 项/三分支检查通过,保留 800d3b7 成果);v2 方案与 probe 证据(`openclaw-reuse-plan.md`、`probe_recall.py`、`probe-result.json` 原样);v2 probe 的旧断言不转称"Mem0 路径已验"。不合 main、不合产品 PR。
>
> 证据来源:Mem0 固定提交 `2c81af3bbe27d9bccb09c772d583df9e9be72ee5`(mem0ai 2.2.1)五个文件——`mem0/memory/main.py`、`mem0/vector_stores/chroma.py`、`mem0/vector_stores/faiss.py`、`mem0/embeddings/fastembed.py`、`pyproject.toml`,原文与 SHA256 见附件 `source-manifest.json`(与总管材料逐字节一致,本轮核验)。行号均指该提交。
## 0. 一页结论(v4)
**维持"Mem0 OSS 嵌入式 SDK 为首选实施候选(待 spike 实证)"的推荐方向,但 v3 的能力表有三处实质性错误,本轮全部纠正:**
1. **infer 不是自动冲突消解。** `add(infer=True)` 实际是**纯增量管道**:单次 LLM 提取(`main.py:944,958`)→ 新 UUID(1030)→ MD5 hash 去重(1022-1026)→ 批量插入(1057)→ 只写 ADD 操作史(1079-1098);全程无 `_update_memory`/`_delete_memory` 调用(二者仅由显式 `update()`/`delete()`/`delete_all()` API 触发,main.py:1879/1896/1948)。**改口更正、事实/感受更新 = 上游提供原语(带完整操作史的 update/delete API),检测与编排归我们**。
2. **本地后端不是现成混合检索。** main.py:543-550 明确:后端未实现 `keyword_search` 则禁用 BM25、仅语义检索;本提交 chroma/FAISS 均未实现(两文件无该定义)。无新服务路线的首选组合改为 **qdrant 嵌入式(qdrant-client 为默认硬依赖,本地 `path=` 即进程内,main.py:548 点名其支持 keyword_search)**——qdrant.py 不在本轮材料内,列为 spike 第 0 步验证项;FTS5 自建词面通道降为备选并明确我方维护清单。
3. **"mem0 不存原对话"是错的。** `add()` 每次把**原始输入消息**存进 history.db(`save_messages`,main.py:990/1044/1073/1207),且提取前会把同 scope 最近 10 条原始输入喂进提示词(`get_last_messages`,main.py:921-922)。导出工件数、隐私面、CG-009 表述相应修正(§2.3、§4.3)。
**推荐路线不变的理由与不变的部分**:GOV-006 举证责任不变——提取提示词、ADD 管道、语义索引、操作史、(qdrant 嵌入式下)混合检索打分仍是上游维护;但**冲突检测/更新编排、隐私前置隔离、词面通道兜底**移回我方归责表(§3)。八机制中生活连续(M4)、情绪(M6)、主动联系(M5)**不是记忆 SDK 独立可验证的**,本轮在验证规格里明确拆开"SDK 覆盖验证"与"产品接线验收"(§6.4)。
## 1. v3 → v4 勘误表(逐条,含源码证据)
| # | v3 原表述(位置) | 纠正后事实 | 证据(2c81af3) |
| --- | --- | --- | --- |
| E-1 | §2.2「add(infer=True):LLM 从消息提取记忆**并决定 ADD/UPDATE/DELETE**」 | add() 文档串(main.py:790-792)确实这么写,**但代码路径不这么做**:infer 管道纯增量(ADD-only),不调用 update/delete。文档串与实现矛盾,以调用链为准 | main.py:918-1220 全程;`_update_memory`/`_delete_memory` 调用点仅 1879/1896/1948 |
| E-2 | §2.2「整理/冲突:DEFAULT_UPDATE_MEMORY_PROMPT 对照旧记忆决定 ADD/UPDATE/DELETE」 | 该提示词**不在当前 infer 调用链上**(infer 用 ADDITIVE_EXTRACTION_PROMPT,main.py:944);"旧记忆列表"只用于让 LLM 避免重复提取 + hash 精确去重,不做 UPDATE/DELETE 决策 | main.py:942-955(提取提示组装)、1022-1026(hash 去重);复核材料 review-note 第 1 条 |
| E-3 | §2.5/M7「混合检索:库内(语义+BM25 融合)现成上游实现」 | 融合框架在(`_search_vector_store` main.py:1642-1701),**但 BM25 依赖后端实现 `keyword_search`**;本提交 chroma/FAISS 均未实现→BM25 被禁用、仅语义检索。`lemmatize_for_bm25`/实体加权仍在,但词面通道在本地后端实际缺失 | main.py:543-550(禁用警告,点名 qdrant/elasticsearch/pgvector);chroma.py/faiss.py 全文无 `keyword_search` |
| E-4 | §2.2「富过滤支持 eq/ne/in/gt/contains/AND/OR/NOT 通配」 | 这是 main 层**语法**(main.py:1416-1431);实际能力按后端衰减:**Chroma** 支持 eq/ne/gt/gte/lt/lte/in/nin + $or/$not(contains/icontains **退化为等值**,无子串匹配);**FAISS 只支持等值/list**,算子字典与 $or/$not 会**静默过滤掉全部结果**,且是取 top_k×2 后事后过滤(召回受限)。AND 语义两后端均成立(顶键合取) | chroma.py:253-364(`_generate_where_clause`,281-283/306-307 contains 等值退化,364 $and 合并);faiss.py:419-443(`_apply_filters`)、403(fetch_k=2×top_k) |
| E-5 | §2.3「mem0 存提取条目+操作史,**不存原对话**」 | **原输入消息每次 add 都写入 history.db**(save_messages,四条路径全覆盖含零提取/全失败分支),提取前还把同 scope 最近 10 条原输入进提示词。原文留存主责仍在我们 chat_message,但 mem0 侧**存在一份派生副本**,导出与隐私设计必须覆盖它 | main.py:921-922、990、1044、1073、1207;复核材料 review-note 第 3 条 |
| E-6 | §4.2 归责表「整理/冲突消解/去重:Mem0 上游维护(infer 管道)」 | 去重(hash)是上游;**冲突消解不是**。改为「去重=上游;矛盾检测与 UPDATE/DELETE 编排=我们(调上游原语)」 | 见 E-1/E-2 |
| E-7 | §4.3「导出纳入 mem0 history.db + 向量目录**两工件**」 | 工件数按实例与后端实算:每个 Memory 实例 = 1 向量库目录(含主 collection + 派生实体 collection `{name}_entities`,main.py:422-424)+ 1 history.db;§4 双实例隔离设计下 = **2 向量目录(或同目录 4 collection)+ 2 history.db + 我方锚点表**。数字列入 CG-009 知情项 | main.py:422-424、500;chroma.py:68-69 |
| E-8 | §4.3「infer 写入调用与现有 mem_job gist 提取同量级,**预估不增调用次数**」 | 无证据的预估,撤回。事实:infer 每 add 批 = **1 次 LLM** + 输入嵌入 1 次 + 提取条目嵌入(批量,失败逐条回退)+ 实体嵌入(批量,失败逐条回退)。设计意图是**替换**同一写入上的 mem_job gist 提取(净次数≈持平),属设计目标,spike 实测核对 | main.py:927、957-971、993-1005、1100-1131;§2.4 调用模型 |
| E-9 | §4.2「适配层约**数百行**」 | 无证据的量级承诺,撤回。改为:量级在施工卡按 §3 归责表逐项估算后报,本轮不承诺行数 | — |
| E-10 | §6「**少量测试额度**」 | 无量纲的额度表述,撤回。改为 §6 的具体配置、次数硬上限、失败计数与停止规则 | §6 |
| E-11 | M1/M8「UPDATE 保留旧值操作史可达成感受/事实演化」 | 机制成立但**触发方式纠正**:UPDATE 史只在**我方显式调 update()** 时产生(main.py:2094-2103,prev_value→new_value 全留史),infer 不会自动触发。M1/M8 的薄适配相应改写(§3.1) | main.py:2052-2112、2114-2142 |
## 2. 修正后的 Mem0 能力表(2c81af3 实证)
### 2.1 infer 管道真实形态(ADD-only)
```
add(messages, infer=True)
├ Phase0 get_last_messages(session_scope, 10) # 同scope最近10条原始输入进提示词 (921-922)
├ Phase1 语义检索旧记忆 top_k=10 # search_filters 只含 user_id/agent_id/run_id (926)
├ Phase2 单次LLM:ADDITIVE_EXTRACTION_PROMPT # (944, 958);失败抛LLMError,本路径无SDK自动重试 (957-971)
├ Phase3 提取文本批量嵌入,失败逐条回退 # (993-1005)
├ Phase4/5 新UUID + MD5 hash 去重(对旧结果+批内)# (1022-1030)
├ Phase6 批量插入(失败逐条回退)→ 仅 ADD history # (1047-1098)
├ Phase7 实体批量链接(嵌入+批量查插,独立collection)# (1100-1204)
└ Phase8 save_messages:原始输入无条件落 history.db # (990/1044/1073/1207)
```
含义:**重复提取靠提示词里列旧记忆 + hash 精确去重**;"她改口了""感受变了"不会自动改旧条目,只会再添新条目(除非我方编排 update/delete)。ADD/UPDATE/DELETE 三类操作史在 history.db 均有(UPDATE 留 prev_value,DELETE 置 is_deleted,main.py:2094-2103、2126-2136),审计面完整——但 UPDATE/DELETE 行只能由我们显式产生。
### 2.2 后端真实能力矩阵(无新服务路线)
| 能力 | chroma(本地目录) | faiss(本地文件) | qdrant 嵌入式(本地 path,进程内) |
| --- | --- | --- | --- |
| 材料内源码实证 | ✔ chroma.py 全文 | ✔ faiss.py 全文 | **✘ qdrant.py 不在本轮材料**,以下为代码推断,spike 第 0 步验证 |
| keyword_search/BM25 | ✘ 未实现→BM25 禁用 | ✘ 同左 | △ main.py:548 点名支持;`lemmatize_for_bm25`/打分框架上游现成 |
| 过滤算子 | eq/ne/gt/gte/lt/lte/in/nin、$or/$not;**contains 退化等值** | **仅等值/list**;算子字典/$or/$not 静默清空结果;事后过滤 fetch_k=2×top_k | △ 待验证(qdrant 原生 where 支持较富) |
| 持久化/重启 | ✔ is_persistent=True + persist_directory(chroma.py:68-69),进程重启自动挂载 | ✔ 每次插入即落盘(faiss.py:373)+ 启动自动加载(168-172),docstore JSON 安全格式 | △ qdrant local 快照机制,待验证 |
| 依赖面 | extras:`chromadb>=0.4.24` | extras:`faiss-cpu>=1.7.4` | **默认硬依赖** `qdrant-client>=1.12.0`(pyproject:17),装 mem0ai 即已带入 |
| 结论 | 可用但无词面通道;过滤最全 | 本路线**不建议**(过滤静默失效+召回受限) | **首选组合**:零新增服务(进程内)+ 有望词面通道;未验证即不宣称 |
**选定组合(拟用,待授权验证)**:`mem0ai==2.2.1`(固定 2c81af3)+ **qdrant 嵌入式本地路径** + fastembed 本地中文嵌入(§6.1)。若 spike 第 0 步证实 qdrant.py 未实现 keyword_search 或本地模式缺陷,则**停下来回报候选复评**,备选两条均明确我方维护量:①chroma + 我方 FTS5 词面镜像(维护:add/update/delete 三钩子同步 FTS5 表 + 查询融合层,约等于把 v2 probe 的词面路径搬进适配层);②维持纯语义 + 接受词面缺口(不可接受,v2 E1 已证缺口存在)。**不把上游通用接口当已提供功能**。
### 2.3 "不存原对话"修正与数据面实况
mem0 实例数据 = ①向量库主 collection(提取条目+metadata)②派生实体 collection(同后端同目录,`{name}_entities`)③history.db(操作史 + **原始输入消息副本**,按 session_scope 组织,`user_id=X&agent_id=Y` 字符串键,main.py:412-419)。三点后果:CG-009 导出工件数按 §1 E-7 实算;隐私边界必须覆盖 history.db(§4);"原话永远在 chat_message"仍成立,但**多了一份派生副本**,泄露面审计要把 history.db 算进去。
### 2.4 调用计数模型(验证卡费用核算基础)
| 操作 | LLM 调用 | 嵌入调用 | 备注 |
| --- | --- | --- | --- |
| add(infer=True) | **恰 1 次**(批内单次提取) | 输入 1 + 提取条目批量(失败逐条回退)+ 实体批量(失败逐条回退) | 本路径 LLM 失败即抛 LLMError,**无 SDK 自动重试**(main.py:957-971 注释明示留给调用方);llms/ 各 provider 内部重试策略本轮材料未含,按"可能存在"计入上限防御 |
| search | 0 | 查询 1 + 实体加权最多 8 个实体各 1(main.py:1747-1765) | rerank 若启用另计 |
| update / delete | 0 | 新文本 1(update,main.py:1877) | — |
| 嵌入批量语义 | — | fastembed 适配器只实现单条 `embed`(fastembed.py:21-32);`embed_batch` 由基类提供(材料未含,**推断为逐条循环**)——本地 ONNX 下零 API 费用,仅算力 | spike 实测核对 |
## 3. 修正后的归责表(上游负责 vs 我们自写)
| 职责 | 上游(mem0ai 2.2.1) | 我们 |
| --- | --- | --- |
| 提取提示词/ADD 管道/解析 | ✔(ADDITIVE 管道) | 调用编排;中文提取质量实测验收 |
| 去重 | ✔(hash+提示词列旧记忆) | — |
| **矛盾检测→UPDATE/DELETE** | 原语(update/delete API+完整操作史) | **检测与编排全部**:何时对照、选哪条、改成什么(挂在既有 mem_job 租约,沿用 v2 门控纪律:模型只选操作、宿主拼装、append-only 回退) |
| 语义检索+向量索引 | ✔ | embedder 配置 |
| **词面通道** | △ qdrant 嵌入式下有望(BM25 框架上游);未验证 | 第 0 步验证;若走 FTS5 兜底则镜像同步+融合查询全归我们 |
| **隐私前置隔离** | ✘(scope 机制可承载,见 §4) | **全部**:双实例/双 scope 设计、内部→公开桥接、逐消息 AM-001 门 |
| 原文存储与回读 | —(history.db 副本须纳管) | chat_message 主责不变;导出打包纳 history.db |
| 八字/情绪/生活/主动联系 | ✘ | 全部(产品专属层,v2 §8/§4.4 保留) |
| 记忆机器代码量级 | — | **不承诺行数**;施工卡按本表逐项估算后报 |
### 3.1 八机制矩阵受影响行的改写(其余行 v3 维持)
- **M1/M8**:v3 "UPDATE 演化留史" 改为——事实/感受分层仍靠条目独立+原话在 chat_message;演化 = **我方反思编排显式调 update()**,history 留 prev→new 全链(main.py:2094-2103)。spike 断言相应改为:"我方编排 update 后 feeling 条目独立存在、事实条目不变、history 可回放"。
- **M3**:承诺流转(open→resolved)本来就是显式 update,归责不变,但补一句:infer 不会替我们改 status metadata,编排归我方。
- **M7**:混合检索从"现成上游实现"改为"**qdrant 嵌入式待验证**;验证不过则 FTS5 兜底我方维护"。换说法命中是 spike 核心指标不变。
## 4. 隐私前置隔离设计(SDK 现有配置/collection/scope,非读取后过滤)
### 4.1 泄露路径(源码实证,正是隔离设计要堵的三条)
1. 提取前旧记忆检索的 `search_filters` 只保留 user_id/agent_id/run_id(main.py:926)——同 scope 内 told=0/kind=private 的旧条目**会进提取提示词**;
2. `get_last_messages(session_scope, 10)`(main.py:921-922)——同 scope 最近 10 条**原始输入**(含私密)进提示词;
3. `save_messages` 无条件落 history.db——私密原话在 mem0 侧留副本。
结论:**公开/私密共用 scope 时,"读取后过滤"与"custom prompt 叮嘱"都堵不住提取输入这一层**——污染发生在 LLM 看到输入的时刻。隔离必须前置于 scope/collection 划分。
### 4.2 设计:双 collection + 双实例(全部用 SDK 现有配置面)
```
Memory 实例 A(私密):vector_store.collection_name="cg_private"
history_db_path=<数据目录>/mem0_private_history.db
写入:agent_id=<伴侣id>(她的内部经历、未分享生活)
Memory 实例 B(公开):vector_store.collection_name="cg_public"
history_db_path=<数据目录>/mem0_public_history.db
写入:user_id=<用户id> + agent_id=<伴侣id>(已对外的事实/感受)
实体 collection 由 SDK 派生({name}_entities,main.py:422-424)→ 随主 collection 天然隔离
```
- **效果对照泄露路径**:①提取前检索在实例内进行,私密池永不进公开实例的提示词;②`get_last_messages` 按 history.db 分库隔离;③私密原话副本只落 private history.db,公开导出包不含。**这是物理前置隔离,不依赖读取后过滤,不依赖提示词自律。**
- **scope 组合语义(核对结论)**:两本地后端 scope 间均为 AND 合取(chroma 顶键 $and,chroma.py:364;faiss 全键匹配,faiss.py:433-441);OR 仅 chroma 经 $or(由平台 OR 翻译,main.py:1590-1599"交由后端实现")。设计只用等值合取,不依赖 OR/NOT。
- **内部读取(她的连续性)**:我方内部链路(下一次生活衔接、情绪冲激)可查实例 A+B 合并池——AM-001 允许她内部记得未分享经历(CG-008/015:继续自己的生活、积累、延续;v1.11 边界:不是"她不能内部记住")。**一切用户可见出口**(注入、摘要、关联、导出)只查实例 B,且逐条再过既有 `source()/told` 门(纵深防御,门是主控)。
- **内部经历转公开的来源链**:她决定讲出时,由我方桥接层在**用户可见响应组装之前**,从实例 A 读取→过 AM-001 门→以显式 add() 写入实例 B,metadata 携带 `{life_event_id, source_event_id, revealed_at, message_id}`;history.db 记录这次 ADD,锚点链可从公开条目回溯到内部事件。**不允许**搜索阶段从 A 池拉私密文本再"过滤后"给 B。
- **与 v2 §4.4 双权限模型的关系**:self_life 的"内部留存/对外过门"两权限语义不变;本设计是其记忆机器层的落地形态。
### 4.3 无模型合成风险用例设计(本轮仅设计,未运行)
fixtures:`priv_old`(实例 A 条目:未分享经历,含独有细节"某某桥")、`pub_new`(实例 B 新输入:公开话题、语义上与 priv_old 相邻)、`priv_hist`(实例 A history.db 中同 scope 原始输入,含 priv_old 原话)。全部合成数据,不涉真实语料。核心手法:**stub LLM**(固定返回的 `generate_response` 假实现,捕获收到的提示词全文)+ 直接检查两库内容,全程零真实模型、零网络。
| 用例 | 断言(全过=零泄漏) | 覆盖 |
| --- | --- | --- |
| P1 提取输入池 | 实例 B 上触发 add(infer=True),stub 捕获的提示词中**不含** priv_old 文本与"某某桥" | §4.1 路径① |
| P2 提取历史窗 | 同上提示词中不含 priv_hist 任何原句(get_last_messages 分库) | §4.1 路径② |
| P3 更新路径 | 实例 B 的 update() 只接受显式文本;对 B 条目更新后 A 库逐字节不变 | 派生污染-更新 |
| P4 回读与预算装配 | 公开回读走实例 B+我方门;模拟 600 字预算装配后输出不含私密细节;A 库条目数/内容不变 | 检索、summary、回读、最终预算 |
| P5 导出 | 实例 B 导出包(向量目录+public history.db)解包全文检索无 priv_old/priv_hist 串;恢复到新实例后 P1-P4 复跑仍过 | 导出/恢复 |
未运行声明:本轮零安装零调用,以上为**可复现设计**(stub 与断言脚本随 spike 卡交付);此前 v2 probe 的 E4b 验证的是我方门语义,**不转称 Mem0 路径已验**。
## 5. 与既有结论的关系
- v2 五条 OpenClaw 硬冲突与 Letta/Memobase 淘汰证据:保留有效。
- v2 probe 九实验:隐私门语义、回读机制、排序收益——全部是我方层的证据,与底座无关,继续有效;不冒充 Mem0 路径验证。
- 方案C:仍为 spike 失败时的回退实施路线;本轮纠正后,方案C与路线E的差距缩小了一项(冲突编排两头都要自己做),选型结论**服从主卡拍板**。
- 治理:v1.11/60项与 GOV-006 不动;本轮无需求变更,无新增用户原话。
## 6. spike 验证卡规格(待授权,本轮零执行)
### 6.1 单一拟用配置(供白栖知批准的具体对象)
| 项 | 拟用值 | 说明 |
| --- | --- | --- |
| SDK | `mem0ai==2.2.1`(源提交 2c81af3) | Apache-2.0;python ≥3.10;默认依赖即含 qdrant-client |
| 向量后端 | **qdrant 嵌入式**(`path=` 本地目录,进程内,无新服务) | 第 0 步先验证 keyword_search/本地快照/重启挂载;不过线→停,回报候选复评(§6.5) |
| 嵌入 | fastembed 本地 ONNX,`BAAI/bge-small-zh-v1.5`(512维) | 中文;**本地推理零 API 费用**;模型文件下载规模约百MB级——以 spike 实际拉取字节数报告为准,本轮不承诺精确数 |
| LLM | 复用现有网关 openai 兼容端点与现有模型档位 | **不新增账号/密钥/模型**;具体模型名与当时单价在申请授权时如实列出(未知价格不折算费用承诺) |
| 环境 | 隔离目录 + 独立测试库;不触 8300-8350、真实档案、真实私密语料 | 中文材料全部合成 fixtures |
### 6.2 调用核算与硬上限
- 计数口径分列:**LLM 调用数 / 嵌入条目数(本地)/ 实体处理数 / 批量失败回退次数 / provider 内部重试疑似次数**(日志逐条记录,fastembed 本地嵌入计条数不计费)。
- 硬上限(超过即停):LLM ≤ **60 次**(8 场景 × 每场景写入/检索/编排 ≤7 次预算);实体嵌入 ≤ 500 条;连续 LLMError **3 次**停止;任何隐私负例(P1-P5 任一)失败即**立即停**并保全现场。
- 失败计数/停止规则:每类调用带 try/except 日志;到上限或触发停止规则→写失败报告→**停在候选复评**,不得自动转方案C开工(GOV-006 与既有审批边界:失败只产生证据,不产生路线变更授权)。
- HELD 边界:不解零/不清零 HEL-835 额度;真实调用额度授权另行走独立测试闸。
### 6.3 步骤(SDK 覆盖验证与产品接线验收分开列)
**A. SDK 覆盖验证(本卡范围,合成数据)**:第 0 步 qdrant 嵌入式三查(keyword_search 存在性/本地快照重启/基本读写)→ 八场景 fixtures(跨会话回忆、改口更正、承诺到期、原文回读锚点、P1-P5 隐私负例、重启恢复、导出→恢复)→ 断言组(换说法命中、M1/M3/M8 编排断言、导出恢复锚点可解析、重启一致、调用计数如实落表)→ A/B 对照现状路径同候选集。
**B. 产品接线验收(不在本卡,后续卡)**:M4 生活连续(v2 §8.2 状态机)、M6 情绪接线(v2 §8 三条)、M5 主动联系触发——这些**不是记忆 SDK 独立可验证的**,分别开接线卡,验收挂可观察行为,不与 spike 混算。
**C. 真实链路**:真实语料"记住昨日细节/模型是否用了记忆"类验收(v2 E3 教训)按额度另批,本卡不含。
### 6.4 验收线建议(供总管/白栖知确认)
八场景 SDK 路径不劣于现状路径且换说法场景严格优于;**P1-P5 零泄漏一票否决**;qdrant 嵌入式第 0 步三查全过;调用计数不超上限;失败处置=停+报告(无路线自动切换)。
## 7. 需求编号关联与承接
| 编号 | 本轮关联 |
| --- | --- |
| GOV-006 | 直接复用优先;本轮即按"证据服从调用链"纠正自身;最终底座仍待用户拍板 |
| CG-008/009 | §4 隔离设计保她内部记忆延续;导出工件数按 E-7 实算列入知情项 |
| CG-014/015/016 | M1/M8 改写后仍守住不改写过去、成长另存、诠释空间 |
| CG-021 | §6.1 单一配置列明待评审 |
| AM-001 | §4 前置隔离+逐消息门主控;P1-P5 一票否决 |
| UX-004/006 | M5 范围不扩大,接线验收独立 |
| GOV-001–005/DEL-001 | 边界遵守;本轮零产品代码变更、零模型调用、零安装、零部署 |
**未完成承接**:①spike 授权与执行卡(§6 规格);②回读接缝最小合入卡(v2 已列,底座无关);③M5/M6 产品接线卡;④v2 §8 三接线实施卡;⑤qdrant.py 补核(随 spike 第 0 步);⑥Memobase/Graphiti 组件级再评估(仅当硬门槛出现)。
## 8. 诚实声明
- **已证**:本文 §1-§4 全部 Mem0 源码事实(固定提交 2c81af3,材料与总管附件 SHA256 一致);v1.11 治理与 v2/probe 既有证据不变。
- **代码推断**:qdrant 嵌入式的 keyword_search/快照行为(main.py:548 点名+默认硬依赖,qdrant.py 未在材料内);fastembed embed_batch 基类逐条循环;llms/ provider 内部重试策略。均已标注,spike 第 0 步/计数日志验证。
- **待实测**:中文提取/召回质量、隐私负例 P1-P5 实跑、导出恢复、重启一致、调用计数——全部在 §6,未运行不以设计冒充通过。
- 本轮零模型调用、零依赖安装、零部署、零现网与真实档案访问;分支仅文档,不合 main、不合产品 PR。
*HEL-847 · 总工 · 修订版 v4 · 2026-10-25 · 依据总管 v3 独立复核意见与 Mem0 固定提交源码材料。*