# NM2.1:合并包 + 整体记忆测试报告 ## 1. NM2.1 是什么 **NM2.1 = 原版 NM2 的 Qwen3.5-4B 记忆包 + 本会话交付的路由器**,合并方式是把路由器权重 **写进模型包本体**(不是外挂 sidecar 文件),因此 NM2.1 是一个自包含的模型包。 * 产物:`H:\Memory\dynamic_memory_lab\qwen3_5_4b_natural_memory_v2_1` * fork 内以 junction 暴露:`H:\Memory\V2_dpskw\qwen3_5_4b_natural_memory_v2_1` * 构建脚本:`build_nm2_1_package.py`(`nm2_1_build_report.json`) **合并做法**:复制原包 22 个文件后,只把记忆分片 `model.safetensors-00005-of-00005.safetensors` 里的 16 个 `dynamic_memory.memory_router_v2.*` 张量替换为交付路由器;其余 **47 个张量(含 `text_retriever`、持久槽、memory policy)逐字节未变**。 **验证(不是"脚本退出码为 0")**: | 检查 | 结果 | |---|---| | 路由器张量与交付件逐位一致(写出后重新读取比对) | **16/16 一致,0 处不符** | | 非路由张量是否被改动 | **0 处改动** | | 交付件来源 sha256 | `69f8295e78821e52c0b41b248e7eddbfa47d7e409539f4a13382c0c82d189deb` | | 实际加载(`load_qwen_dynamic`) | `router ready: True`、`text_retriever ready: True` | | 加载出的路由器 == 交付件 | **True(0 处不符)**,2,037,774 参数 | ## 2. 原版 NM2 已归档 * 包:`E:\归档\01_人工智能\01_训练产物\NM2_原版_qwen3_5_4b_natural_memory_v2_20260912_142722.7z` * 22 文件 / 9,535,448,852 字节 → **6.55 GB**,`7z t` 报 **Everything is Ok** * 已记入 `E:\归档\00_索引\操作日志.jsonl`;守恒复核精确对上: 45,059 文件 / 110.147 GB = 改动前 45,058 / 103.597 GB **+ 1 文件 / 6.55 GB** * 原包**仍留在 H: 原地**(归档按该归档库惯例是"复制保留"),所以历史基线对照仍可复现 ## 3. 整体记忆测试结果 同一套电池、同一份运行时,**只有模型包不同**(`run_nm2_battery.ps1`)。 | 指标 | 原版 NM2 | **NM2.1** | |---|---:|---:| | A 用例数(10 类别) | 110 | 110 | | A 总体正确率 | 89.09% | 88.18% | | A **可回答正确率** | **100.00%** | **100.00%** | | A 未知拒答率 | 60.00% | 56.67% | | A **已知问题被误拒率** | **0.00%** | **0.00%** | | B **零字面重叠改写回答正确率** | 43.75% | **68.75%** | | B 答成别的属性 | 18.75% | 18.75% | | B 触发读取 | 56.25% | **93.75%** | | B 平均选中记录 | 3.0625 | 6.0625 | | C 可回答正确率(24 同形候选) | 65.00% | 65.00% | | C 答成别的属性 | 35.00% | 35.00% | | C **未知泄漏率** | 75.00% | 75.00% | | C 活跃记录 min/max | 23 / 24 | 23 / 24 | | D 重启后召回 / 作答正确 / 清理生效 | 通过 / 通过 / 通过 | 通过 / 通过 / 通过 | **可复现性说明(重要)**:NM2.1 的 A 段跑了两次,得到 89.09% 与 88.18%(各差 **1 个用例**), 未知拒答率 60.00% 与 56.67%(同样差 1 个用例)。因此在这套 110 用例的尺度上, **< 1 个百分点(≈1 个用例)的差异属于运行间波动,不作为结论**。 ### 结论 1. **B 段(零字面重叠改写)真实提升 +25.00pp**(43.75% → 68.75%),机制是**读取门开启率 从 56.25% 升到 93.75%**:原版路由器的 `need_memory` 门对这类改写提问过于保守,新路由器 更愿意去查记忆,因此拿到证据并答对。**门是本配置下路由器唯一影响端到端结果的杠杆**, 这与本会话早先的取证完全一致(随机化排序通路端到端零变化、混合权重独立进程复测零变化)。 2. **A、C 两段与基线相同**:这两套的答案由打包的 `text_retriever` 排序与词面/地址先验决定, 换路由器不改变注入记录集合,所以不改结果。**换路由器带来的不是"整体都更强", 而是"该查的记忆会去查了"。** 3. **D 段两边都通过**:写入→保存→重启→召回→作答链路完好,清理也生效。 ## 4. 换路由器**没有**解决的问题(同一份测试里可见,避免误判) | 问题 | 实测 | 说明 | |---|---:|---| | **未知问题泄漏** | **75.00%**(C 段) | 问库中不存在的属性时仍然给出编造答案;两组检索最高分分布几乎完全重叠,**阈值方案已被测量排除** | | 答成别的属性 | 35.00%(C 段) | 24 个同形候选里排错属性 | | A 段未知拒答率 | 56.67~60.00% | 未见提升 | | 记录级排序不由路由器决定 | —— | `_record_scores` 用打包 `text_retriever` 覆盖路由器分数(该 retriever 同任务 Top-1 仅 23.20%,路由器 59.60%) | 另外:`eval_general_capability.py` 需要 `comprehensive_general.jsonl`,该文件**不存在**, 所以通用能力回归这一项**本次没有跑**(A 段里的 `benchmark_qa` / 未知类别可作部分代理)。 ## 5. 产物清单 | 文件 | 内容 | |---|---| | `H:\Memory\dynamic_memory_lab\qwen3_5_4b_natural_memory_v2_1\` | **NM2.1 合并包本体**(22 文件) | | `build_nm2_1_package.py` / `nm2_1_build_report.json` | 合并脚本与构建验证报告 | | `run_nm2_battery.ps1` | 整体记忆测试电池(`-Tag` 区分输出,避免互相覆盖) | | `compare_nm2_batteries.py` / `nm2_battery_comparison.{json,md}` | 对照表 | | `nm2_1_e2e.{json,md}` / `nm2_1_critical_e2e.{json,md}` / `nm2_1_runtime_e2e.{json,md}` / `nm2_1_restart.json` / `nm2_1_battery_summary.json` | NM2.1 四段结果 | | `nm2_orig_*.json/md` | 原版 NM2 同套结果(用于对照) | | `PRODUCTION_ROUTER.md` | 路由器交付说明(含安装与复现命令) |