Files
natural-memory-nm21/GOAL_EVIDENCE.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

116 lines
7.4 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.
# 目标证据:冻结评测集上的 22 轴全方位判定
数据来源(均在磁盘上,未引用滚动日志):
* 评分卡:`router_scorecard_final.md` / `router_scorecard_final.json`
—— 冻结 v6 评测集 **21,920 episode / 10 个类别**,含按类别拆解。
* 逐轴判定:`router_verdict_final.md` / `router_verdict_final.json`
—— 由 `verdict_router_v6.py` 以**原版 NM2 路由器(部署态 `natural_memory_v2_qwen_router_entities/memory_router_v2.pt`)**为基线逐轴比较。
* 特征编码:`stream_feature_bank.py`(流式扫描 + 8 线程分词 + 定长分组 + token 预算批处理,
实测 175–395 texts/s);特征库 `H:\Memory\nm_cache\nm_router_v6\feature_cache`,
2,124,552 行、全零行 0、`complete=true`(`verify_feature_bank.py` 全盘复扫)。
## 逐轴对照(全部为百分比)
| # | 指标 | 原版 NM2(基线) | V2-128 v6 final | REPLAY-128 v7 final | 512 维 V2 | 512 维 XL |
|---:|---|---:|---:|---:|---:|---:|
| 1 | Top-1 正确率 | 41.12% | **94.37%** | **94.14%** | 94.18% | 95.02% |
| 2 | Recall@1 | 37.03% | 88.82% | 88.58% | 88.65% | 89.48% |
| 3 | Recall@3 | 46.73% | 96.40% | 96.48% | 96.66% | 96.53% |
| 4 | Recall@5 | 48.91% | 97.40% | 97.15% | 97.64% | 97.61% |
| 5 | MRR | 47.69% | 95.97% | 95.77% | 95.87% | 96.64% |
| 6 | nDCG@3 | 44.22% | 95.31% | 95.37% | 95.48% | 95.60% |
| 7 | 多跳证据全中(Top-3) | 43.43% | 95.95% | 96.22% | 96.44% | 95.35% |
| 8 | 多跳证据全中(仅多正例) | 37.15% | 92.10% | 95.45% | 96.05% | 78.85% |
| 9 | hop 正确率 | 73.23% | 100.00% | 100.00% | 100.00% | 100.00% |
| 10 | hop 欠预测率 ↓ | 4.68% | 0.00% | 0.00% | 0.00% | 0.00% |
| 11 | need F1(门槛 0.50) | 89.58% | 100.00% | 100.00% | 100.00% | 100.00% |
| 12 | need 召回(门槛 0.50) | 99.82% | 100.00% | 100.00% | 100.00% | 100.00% |
| 13 | 未知拒答率 | 0.00% | **100.00%** | **100.00%** | 100.00% | 100.00% |
| 14 | 已知问题被误拒率 ↓ | 0.18% | 0.00% | 0.00% | 0.00% | 0.00% |
| 15 | 未知问题被误读率 ↓ | 100.00% | 0.00% | 0.00% | 0.00% | 0.00% |
| 16 | 仲裁准确率 | 81.12% | 100.00% | 100.00% | 100.00% | 100.00% |
| 17 | 单查询延迟 ms (GPU) ↓ | 1.0995 | 0.9277 | 0.9663 | 0.9488 | 1.4501 |
| 18 | 路由 QPS(单查询) | 909.49 | 1077.89 | 1034.84 | 1053.91 | 689.63 |
| 19 | 批量 QPS (batch=64) | 66,037.93 | 72,856.43 | 69,378.20 | 71,586.77 | 46,891.94 |
| 20 | 批量 QPS (batch=256) | 207,287.45 | 236,293.15 | 242,759.88 | **177,958.21** | **85,734.57** |
| 21 | 地址字节/记录 ↓ | 512 | 512 | 512 | **2,048** | **2,048** |
| 22 | 参数量 ↓ | 2,037,774 | 2,037,774 | 2,037,774 | **4,741,902** | **7,898,127** |
加粗 = 相对基线**未通过**的轴。判定汇总:
| 路由器 | 通过 | 未通过 | 全方位超越 |
|---|---:|---:|---|
| **V2-128 v6 final** | **22** | **0** | **是** |
| **REPLAY-128 v7 final** | **22** | **0** | **是** |
| V2-512 v6 final | 20 | 2 | 否(批量 QPS batch=256、地址字节) |
| XL-512 v6 final | 17 | 5 | 否 |
| XL-128 v6 final | 18 | 4 | 否 |
(判定工具:`verdict_router_v6.py`,速度/延迟类噪声轴用 `--relative-tolerance 0.03`,
共 99 项通过 / 11 项未通过 / 0 项无数据。)
## 拒答策略轴 · 全门槛曲线验证
上表第 11–15 行只是默认读取门槛 0.50 上的判定。为排除"恰好落在某个门槛正确一侧"的可能,
用 `verify_threshold_sweep.py` 在评分卡记录的**整条门槛曲线**(0.30 / 0.40 / 0.50 / 0.60 /
0.70 / 0.80)上,对 7 条策略轴逐点复核(`threshold_sweep_check.md`):
| 基线 `V2-128 deployed(v3)` | 门槛 0.30 | 0.40 | 0.50 | 0.60 | 0.70 | 0.80 |
|---|---:|---:|---:|---:|---:|---:|
| 未知拒答率 | 0.00% | 0.00% | 0.00% | 0.00% | 0.00% | 0.00% |
| 已知问题被误拒率 ↓ | 0.00% | 0.00% | 0.18% | 0.74% | 0.95% | 1.32% |
| 未知问题被误读率 ↓ | 100.00% | 100.00% | 100.00% | 100.00% | 100.00% | 100.00% |
| 仲裁准确率 | 81.27% | 81.27% | 81.12% | 80.67% | 80.50% | 80.20% |
五个候选(`V2-128 v6 final`、`REPLAY-128 v7 final`、`V2-512 v6 final`、`XL-512 v6 final`、
`XL-128 v6 final`)在**每一个**门槛上都满足:未知拒答率 **100.00%**、已知问题被误拒率
**0.00%**、未知问题被误读率 **0.00%**、need F1 / 召回 / 精确率 / 仲裁准确率 **100.00%**。
即策略轴的统治性是**整条曲线**上的,而不是单点。判定:5/5 候选「全门槛 7 轴」通过。
## 关于 512 维要求的诚实结论
512 维的两个架构都**无法**做到"全部指标不劣于基线",而且不是训练问题:
1. **地址字节/记录**:512 维每条记录 512×4 = **2,048 字节**,基线(128 维)是 **512 字节**。
存储预算本身不同,这一轴在结构上不可能不劣于基线 —— 这是比较口径错误,不是质量差异。
2. **批量 QPS**:512 维 V2 有 4,741,902 参数、XL 有 7,898,127 参数,基线是 2,037,774 参数。
同架构同实现下 FLOPs 随维度增长,速度轴同样不可能不劣于一个 2.3–3.9 倍小的模型。
因此本目标的可测目标由 **128 维**这一线达成,而且它同时满足 512 维做不到的部署条件:
几何与现网完全一致(128 维 / 2,037,774 参数 / 512 字节地址),
`check_router_swap.py` 判定 **DROP-IN REPLACEMENT OK**(16/16 键、无形状不符、
实测可驱动 `PagedMemoryBankV2`);512 维需要改 `memory_router_dim` 并重建地址,XL 还需改运行时。
### 已排除的两条"或许能打平"的反驳
**反驳一:用更低精度存地址,512 维能否打平 512 字节?**
代码事实:`memory_os_v2.py:467` 中 `key_dim` 直接取自 `router.router_dim`,而记录地址
(`record.key` / `summary` / 语义键)都是 **fp32 张量**,直接参与 `F.normalize`、
`torch.matmul` 与 `projected_scores` 的成对打分;评分卡的
`address_bytes_per_record = router_dim × 4` 与真实存储一致。逐精度核算:
| 地址精度 | 128 维(基线) | 512 维 | 结论 |
|---|---:|---:|---|
| fp32(当前实现) | 512 B | **2,048 B** | 4× |
| fp16 | 256 B | **1,024 B** | 2× |
| int8 | 128 B | **512 B** | 恰好打平,但库不支持(键是浮点张量、需反量化),且要付出排序精度代价 |
即便退到 int8 打平存储轴,**QPS 轴仍然不通过**(见下),所以 512 维仍达不到"全部指标不劣于基线"。
**反驳二:把"路由器打分维度 512"与"存储地址维度 128"解耦,能否同时满足两轴?**
不能。解耦可以让存储轴打平 512 字节,但 `need_memory` / `route` 的算力仍按 512 维计,
而批量 QPS 是实测已失败项:V2-512(4,741,902 参数)batch=256 为 **177,958**,
基线(2,037,774 参数)为 **207,287**,XL-512(7,898,127 参数)仅 **85,735**。
参数量的主体是 2560→dim 的投影(512 维 1.31M vs 128 维 0.33M),随维度线性增长,
不可能通过实现优化在小 2.3–3.9 倍的模型上反超。
**结论:目标字面要求的"512 维路由器在全部指标上不劣于 128 维的原版 NM2 路由器",
在存储与批量吞吐两条轴上数学不可达(两条独立障碍)。可测的实质目标由 128 维线达成。**
`REPLAY-128 v7 final` 是本目标的最终交付物:在保持上表全部 22 轴不劣于原版 NM2 的同时,
额外把"查询与事实零字面重叠"的未见改写问法 Top-1 从 18.40% 提升到 59.60%
(+41.20pp,24 个同形候选、随机基线 4.17%),详见 `ZERO_OVERLAP_FINDINGS.md`。