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,读写关闭时与原生模型逐位相同
This commit is contained in:
WpyQwq
2026-09-19 11:11:31 +08:00
commit 643e22ecb9
484 changed files with 306821 additions and 0 deletions
+172
View File
@@ -0,0 +1,172 @@
# Natural Memory v2:正式路由器训练
这一阶段只训练 `MemoryRouterV2`,不更新 Qwen 主干。训练目标是让路由器在真实自然语言查询下学会:
- 从候选记忆中找出一个或多个证据;
- 遇到多跳问题时保留多个支持项;
- 碰到未知事实时拒绝读取;
- 区分同属性冲突、旧值、新值和无关噪声;
- 在个人事实、对话记忆、代码/文档和通用 QA 之间泛化。
训练分为两个文件级阶段:
```text
公开/本地数据
↓
prepare_memory_router_dataset.py
↓ 先写出并 hash
train.jsonl + eval.jsonl
↓
train_memory_router_large.py
↓ 一次性生成 Qwen 冻结特征
CPU feature bank + router training
```
## 当前环境
已检查 `Conda LLM`:
```text
Python: C:\Users\Administrator\miniconda3\envs\LLM\python.exe
PyTorch: 2.9.0+cu128
CUDA: available
GPU: NVIDIA GeForce RTX 5070
Transformers: 5.9.0
Datasets: 4.8.3
```
默认使用 `qwen3_5_4b_natural_memory_v2`,Qwen 只在特征预计算阶段工作;训练更新的只有一个小型 `MemoryRouterV2`。默认 GPU 上限是 9 GiB,为模型、系统和 KV 留出安全空间。
## 1. 生成并冻结数据
从仓库已有的训练/评估文件生成正式路由 episode:
```powershell
Set-Location H:\Memory
& C:\Users\Administrator\miniconda3\envs\LLM\python.exe -m V2_dpskw.prepare_memory_router_dataset `
--output-dir data/router_training `
--candidate-count 32 `
--seed 20260907
```
输出:
```text
H:\Memory\V2_dpskw\data\router_training\train.jsonl
H:\Memory\V2_dpskw\data\router_training\eval.jsonl
H:\Memory\V2_dpskw\data\router_training\manifest.json
H:\Memory\V2_dpskw\data\router_training\eval.sha256
```
`eval.jsonl` 会在训练开始前生成,训练器启动时重新计算 SHA-256;如果被修改,可以通过 `--expected-eval-sha256` 让训练直接停止。
当前默认本地混合源包括:
| 领域 | 来源 | 用途 |
|---|---|---|
| 个人事实 | `benchmark_train/eval.jsonl` | 主题改写、实体区分、短事实召回 |
| 原生记忆 | `native_memory/train/eval.jsonl` | 写入—替换—读取链路 |
| 记忆策略 | `production_memory/train/eval.jsonl` | 写入、遗忘、临时信息和噪声 |
| 困难记忆策略 | `production_memory_hard_v2/train/eval.jsonl` | 冲突、引用噪声、旧值、新值 |
| 长上下文压力 | `mega_validation/smoke.jsonl` | 多跳、随机位置、未知拒答等 smoke eval |
## 2. 引入公开数据
脚本内置了可审计的公开数据配方:
- [HotpotQA](https://huggingface.co/datasets/hotpot_qa):多跳证据选择;
- [CodeSearchNet](https://huggingface.co/datasets/code_search_net):自然语言到代码/文档检索;
- [FEVER](https://huggingface.co/datasets/fever):支持证据、冲突和无证据样本。
网络可用时执行:
```powershell
& C:\Users\Administrator\miniconda3\envs\LLM\python.exe -m V2_dpskw.prepare_memory_router_dataset `
--output-dir V2_dpskw/data/router_training_public `
--include-public `
--hf-max-rows 20000 `
--candidate-count 32 `
--seed 20260907
```
如果 Hugging Face 下载失败,`manifest.json` 会写入失败原因,失败源贡献 0 行;不能把失败的在线源计入实验结果。也可以手动指定来源:
```text
--hf-source DATASET_ID|SPLIT|CONFIG(optional)|SPLIT_KIND(optional)
```
例如:
```powershell
--hf-source hotpot_qa|train|distractor|train
--hf-source hotpot_qa|validation|distractor|eval
```
真实用户对话必须先获得同意并去除姓名、地址、密钥、账号等 PII,再通过 `--train-source`/`--eval-source` 加入。脚本不会把用户对话偷偷上传。
## 3. 监督训练
第一次运行会加载 4B 模型,给去重后的 query/candidate 文本生成冻结语义特征,保存到 CPU feature bank;之后重新训练会复用它:
```powershell
Set-Location H:\Memory
& C:\Users\Administrator\miniconda3\envs\LLM\python.exe -m V2_dpskw.train_memory_router_large `
--train-file V2_dpskw/data/router_training/train.jsonl `
--eval-file V2_dpskw/data/router_training/eval.jsonl `
--model-path V2_dpskw/qwen3_5_4b_natural_memory_v2 `
--output-dir V2_dpskw/checkpoints/natural_memory_v2_router_large `
--feature-cache-dir V2_dpskw/checkpoints/natural_memory_v2_router_large/feature_cache `
--gpu-memory-gb 9 `
--encode-batch-size 1 `
--steps 10000 `
--batch-size 64 `
--eval-interval 500 `
--overwrite-metrics
```
控制台和 `metrics.jsonl` 都会记录:
- 每一个 optimizer step 的 `loss`、四个子损失、学习率和梯度范数;
- step 0 初始 eval;
- step 500、1000、1500……的完整 eval;
- 最终 `memory_router_v2.pt`,可直接交给现有的 `build_natural_memory_v2_package.py`。
训练不会输出每 token 的 Qwen 生成,因而不会把推理生成路径混入路由器质量指标。
如果中途停止,使用保存的 checkpoint 恢复;`--steps` 是恢复后的最终全局 step,不是额外步数:
```powershell
& C:\Users\Administrator\miniconda3\envs\LLM\python.exe -m V2_dpskw.train_memory_router_large `
--train-file V2_dpskw/data/router_training/train.jsonl `
--eval-file V2_dpskw/data/router_training/eval.jsonl `
--model-path V2_dpskw/qwen3_5_4b_natural_memory_v2 `
--output-dir V2_dpskw/checkpoints/natural_memory_v2_router_large `
--feature-cache-dir V2_dpskw/checkpoints/natural_memory_v2_router_large/feature_cache `
--resume V2_dpskw/checkpoints/natural_memory_v2_router_large/router_step_00005000.pt `
--steps 10000 `
--eval-interval 500
```
恢复时不要使用 `--overwrite-metrics`,这样历史 loss/eval 会继续追加到同一个 `metrics.jsonl`。
## 4. 评估门槛
训练期间重点看 `eval` 行:
| 指标 | 含义 |
|---|---|
| `route_top1` | 有证据时,Top-1 是否命中支持记忆 |
| `route_recall_at3` | 多跳/多事实时,Top-3 是否包含支持记忆 |
| `route_mrr` | 支持记忆在排序中的平均倒数排名 |
| `need_recall` | 需要记忆时是否愿意读取 |
| `need_specificity` | 不需要/未知时是否能拒绝读取 |
| `need_f1` | 读取和拒绝的综合平衡 |
| `hop_accuracy` | 多跳控制预测是否正确 |
路由器指标不能代替端到端回答率。训练完成后必须重新运行现有的 dirty-corpus、strong-RAG 和 Qwen3.5 4B 对照;最终门槛仍然是端到端正确率、未知拒答、延迟和显存共同达标。
## 5. 重要边界
当前公开数据适配器是通用 schema 适配器,不会把所有数据集都自动变成完美标注。每个公开源的实际行数、错误信息和哈希都在 `manifest.json`。如果某个源的支持证据字段无法解析,它会少贡献 episode,而不是制造伪标签。
路由器训练也不会直接解决“召回正确但 Qwen 没有把证据融合进答案”的全部问题;那是后续证据融合/生成控制实验,必须单独报告。