Files
natural-memory-nm21/V6_FINAL_REPORT.md
T
WpyQwq 643e22ecb9 Natural Memory NM2.1: 记忆路由器分叉、数据集缺陷修复与全轴评测证据
- 引入 MemoryRouterXL 与 v5/v6 流式多线程训练/编码管线
- 修复 prepare_memory_router_dataset 候选池重建缺陷(mega 家族 3568x 加速,输出逐字节相同)
- 修复 v5 被破坏的拒答与多跳标签(train 未知样本 319 -> 16319,multi_hop 平均正例 1.00 -> 2.00)
- 同存储预算下 V2-128 v6 逐轴 22/22 通过:Top-1 41.12% -> 94.62%,未知拒答 0.00% -> 100.00%
- 记录三条被实测推翻的显然优化(logits_to_keep=1 反而慢 55%、XL 容量未带来收益)
- 记忆手术跨架构可移植性 14/14,读写关闭时与原生模型逐位相同
2026-09-19 11:11:31 +08:00

75 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Natural Memory 路由器 v6 —— 最终报告
本文件是 v6 阶段的**单一汇总证据**。所有比率均为百分比;所有结论都指向可复现的产物文件。
## 1. 做了什么
在分叉 `H:\Memory\V2_dpskw` 内,用**流式加载 + 多线程/批量化特征编码**在修正后的 v6 全量数据集上训练 512 维路由器,并与原版 NM2 路由器在同一冻结评测集上逐轴对比。
| 环节 | 实现 | 实测 |
|---|---|---|
| 流式加载 | `stream_feature_bank.py`:只保留 `sha1→行号` 字典,文本落盘;训练器 `train_router_v5.py` 逐行流式建索引 | scan 212 万条唯一文本 **15.1 秒**;训练不解析 episode 进内存 |
| 多线程编码 | 8 线程 tokenizer 池 + 按精确 token 长度分组 + token 预算限批 | tokenize **41.8–46.5 秒**(约 5.7 万 texts/s);encode 约 160–180 texts/s |
| 特征库 | `features.f16.npy` mmap,10.86 GB(放 D: NVMe) | 打开 1.0 秒;训练按需读页 |
| 断点续跑 | `--resume` + `progress.json` + 编码方法指纹 | 两次中断共用已编码的 75 万行 |
| 完整性验证 | `verify_feature_bank.py` 全量扫描 | 2,124,552 行、**零值行 = 0** |
数据:`data/router_training_v6`,train **87,155** / eval **21,920**(10 类别 × 2,000 + policy 1,920),`group_overlap = 0`。
## 2. 评测协议
- 冻结 eval 21,920 条,`eval.sha256` 在训练前生成并被训练器强制校验;
- 所有路由器在**同一冻结特征库**上评分(编码保真度:与旧缓存共有文本余弦 **0.999983**);
- 读取/拒答阈值以 0.50 为主,另给 0.30–0.80 曲线;
- 速度轴以 `bench_router_latency.py` 的**交替轮流测量**(5 轮,模型轮转抵消漂移)为准,实测波动带 **2.8–5.3%**,故速度轴用 3% 相对容差,质量轴用严格容差;
- 逐轴判定:`verdict_router_v6.py`,对每个候选分别给出「是否全方位超越」。
## 3. 结果:同存储预算下全方位超越
| 路由器 | 参数 | 地址字节 | Top-1 | Recall@3 | MRR | 多跳证据全中 | hop | 未知拒答率 | 已知被误拒率 | 延迟(中位) | batch256 QPS | 判定 |
|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---|
| V2-128 生产(v3) | 2,037,774 | 512 | 41.12% | 46.73% | 47.69% | 43.43% | 73.23% | 0.00% | 0.18% | 1.1558 ms | 199,554 | 基线 |
| **V2-128 v6 best** | 2,037,774 | 512 | **94.62%** | **97.81%** | **96.49%** | **97.75%** | **100.00%** | **100.00%** | **0.00%** | 1.1679 ms | 196,829 | **22/22 → 是** |
| **V2-128 v6 final** | 2,037,774 | 512 | 94.37% | 96.40% | 95.97% | 95.95% | 100.00% | 100.00% | 0.00% | 1.1653 ms | 198,026 | **22/22 → 是** |
| XL-128 v6 best | 6,714,639 | 512 | 95.66% | 98.75% | 97.37% | 98.70% | 99.95% | 99.59% | 0.00% | 1.5783 ms | 141,501 | 18/22 |
| V2-512 v6 best | 4,741,902 | 2048 | 95.05% | 98.84% | 97.12% | 98.64% | 100.00% | 99.81% | 0.00% | 1.1623 ms | 154,085 | 20/22 |
| XL-512 v6 best | 7,898,127 | 2048 | **95.78%** | 97.59% | 97.24% | 96.86% | 100.00% | 100.00% | 0.00% | 1.5855 ms | 94,647 | 17/22 |
逐类别拆解、family 拆解、阈值曲线见 `router_scorecard_v6_128.md`(另附 `router_scorecard_v6.md` 为 512 维版本)。
**相对已交付生产路由器**:Top-1 **+53.49pp**、未知拒答率 **+100.00pp**、已知问题被误拒率 **−0.18pp**、hop **+26.77pp**、多跳证据全中(仅多正例)**37.15% → 99.00%**;参数与地址字节完全相同,延迟/吞吐差异 ≤1.4%(在 2.8–5.3% 的测量噪声带内)。
## 4. 两个必须如实说明的结论
1. **512 维配置无法在「地址字节」轴上不劣于 128 维基线**:2048 vs 512 字节是几何决定的 4 倍差异,不是训练能解决的;把它算作失败属于不同存储预算的错位比较。此外 512 维 V2 还真实输一项 batch-256 吞吐(−22.8%)。因此目标里「512 维 + 全部轴不劣」在字面上不可达,在**同预算**下才可达且已达成。
2. **新架构 XL 没有赢**:准确率最高(Top-1 95.78%)但吞吐真实低 26–52%(3.3–3.9 倍参数)。本次提升来自**数据与标签**(拒答样本 106→4,106、多跳 2 正例/hop=2、12 倍数据量、10 类别均衡评测),**不是来自更多维度与参数**。该假设被数据否定。
## 5. 部署就绪:直接替换已验证
`check_router_swap.py` 结论 `DROP-IN REPLACEMENT OK`:
- 与生产包第 5 分片 `dynamic_memory.memory_router_v2.*` 的 **16 个键、形状零差异**(缺 0 / 余 0 / 不匹配 0),替换只是重命名;
- 可加载进运行时同一 `MemoryRouterV2` 构造(hidden 2560 / dim 128 / heads 8 / hops 3);
- 能驱动 `PagedMemoryBankV2` 正常写入与路由(`key_dim = 128`,返回记录数 3)。
## 6. 过程中发现并修复的缺陷(每条都有验证)
| 缺陷 | 影响 | 验证方式 |
|---|---|---|
| mega 适配器把 `metadata.answerable=false` 当成可回答 | 2000 条拒答样本全被错标,拒答轴与多跳轴**无法测量** | 重建后 eval 未知样本 106 → **4,106**;审计表逐类核对 |
| multi_hop 只标最终事实、hop 用 `len(positive_ids)` | 多跳证据链缺失、hop 标签全为 1 | 沿实体→值链扩展后 2 正例 / hop=2 |
| `_source_candidates` 每条 episode 复制 265.6 万条候选池 | 8 万条 episode 需 **46.8 小时** | 修复后 mega 单条 2105ms → 0.59ms(**3568×**),A/B **sha256 逐字节一致** |
| 续跑守卫 `if start < done: continue` 整组跳过 | 49.4 万行保持零值,且写出「完整」manifest,训练已在零值上开跑 | 全量扫描定位缺失区间 → 补齐 → 零值行 0 → 新增完整性标志/训练器拒收/抽样检查 |
| 补丁模式误用 `w+` 打开特征库 | 若成功会清零已编码的 183 万行 | `OSError` 中止;改为仅全新运行用 `w+` |
| 评分卡 `Recall@k` 用命中**个数**而非比例 | 输出 105%、109% 的"召回率" | 修正为「命中/应有」,全部 ≤100% |
| `logits_to_keep=1` 看似省算力 | 实际**慢 1.55×**(非连续视图掉进 bnb 慢路径) | 交替重复 7 轮测量;默认关闭并写入 `--help` |
| 用相同文本测吞吐 | 虚高 1.6×(283 vs 真实 175 texts/s) | 用 192 条不同真实文本重测 |
## 7. 产物清单
- 数据:`data/router_training_v6/{train,eval,manifest,eval.sha256}`、`router_dataset_audit_v6.json`
- 特征库:`H:\Memory\nm_cache\nm_router_v6\feature_cache`(+ `feature_bank_verification.json`)
- 路由器:`checkpoints/router_v6_v2_128`、`router_v6_xl128`、`router_v6_v2_512`、`router_v6_xl512`
- 证据:`router_scorecard_v6_128.md`、`router_verdict_v6_128.md`、`router_latency_bench.json`、`router_swap_check.json`、`router_scorecard_v6.md`、`router_verdict_v6.md`
- 工具:`stream_feature_bank.py`、`train_router_v5.py`、`eval_router_v5.py`、`verify_feature_bank.py`、`bench_router_latency.py`、`check_router_swap.py`、`audit_router_dataset.py`、`verdict_router_v6.py`、`router_xl.py`