Files
natural-memory-nm21/Natural_Memory_v2_对外技术总结.md
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

279 lines
14 KiB
Markdown
Raw Permalink 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 v2
## 对外技术说明
版本:v2
本文只描述当前实现已经完成并实际测量的内容。它不把系统描述成通用智能,也不把实验室结果表述成线上服务承诺。
## 1. 一句话说明
Natural Memory v2 是接在本地 Qwen3.5-4B 上的一个模型内记忆层:它把适合长期复用的个人事实、项目事实和短对话片段写入有地址的记忆记录,当前问题只读取少量相关记录,再把这些记录作为模型内部前缀交给 Qwen 生成答案。
它要解决的具体问题是:模型重启后不携带历史聊天记录,仍能访问已经保存的个人或项目事实,同时不把全部历史转换成 GPU 上的长 KV Cache。
## 2. 当前实现
### 2.1 记忆与 KV 的分工
```text
最近对话 Qwen 热 KV
长期个人事实/项目事实 Natural Memory 记录
当前问题 有界路由与 Top-K 读取
原始持久化状态 嵌入式 memory safetensors 切片
```
Memory Slot 不试图逐 token 模拟完整 KV。它保存的是更适合跨会话复用的内容:事实、版本、来源、短文本证据和语义地址。当前对话的顺序关系仍由 Qwen 的普通上下文负责。
### 2.2 读取路径
```text
用户问题
-> Qwen hidden state 生成紧凑查询地址
-> LSH/地址粗索引
-> 候选页
-> 页内记录重排
-> Top-K 记录
-> 证据前缀注入 Qwen
-> 普通生成
```
当前 token 不会与全部记忆记录做全量注意力。当前默认读取上限为少量页面和记录;实际运行中只把命中的短证据提升到 GPU,记忆主体保留在进程内存。
### 2.3 写入与版本
每条记录包含:
- 原始短文本和可选 token 序列;
- 语义地址、实体、属性和值;
- 时间、来源、置信度、重要性;
- active、superseded、retracted、quarantined 状态;
- 版本关系和审计信息。
同一实体和属性出现新值时,旧值会被标记为 `superseded`。低置信度内容可以进入 quarantine,不参与正常读取。撤回记录不会从审计中消失,而是变成 `retracted`。
### 2.4 重启与存储
当前交付配置采用 embedded weight-shard:记忆快照、路由器参数、页面元数据和短文本证据写入模型包的 memory safetensors 切片。启动时加载到进程内存,命中的热点记录才进入有界 GPU cache。
当前默认路径不使用 SQLite,也不使用磁盘分页。该设计减少了运行时依赖,但意味着模型包会随持久化记忆增长而变大,且需要重新保存权重切片才能固化更新。
## 3. 正式脏数据迁移测试
### 3.1 数据来源
本次正式测试使用了两类来源:
1. 当前 Natural Memory 工程自身的真实源码、文档和少量随包配置:65 个文件、1,110,524 字节、620 个源码/文档分片。
2. 用户在本项目对话中明确说过的短事实和工程要求:15 条记录,包含工作目录变更、模型命名、对照模型、存储限制、显存限制、训练取向和模型内读取要求。
本轮由这些记录派生出的用户对话题共 44 题,其中 38 个可回答、6 个未知;其余 220 题来自真实源码和文档。
为了避免答案泄漏,正式数据排除了:
- 以前的 benchmark JSON 结果;
- synthetic hardset 和其他合成数据集;
- checkpoint 和模型权重;
- tokenizer 大文件。
用户对话部分不是从外部用户数据库导出的日志。它是本次项目对话里用户已经明确写出的要求;其测试问题由人工改写成口语、跨会话、时间冲突和未知问题。不能把这部分描述成大规模真人日志验证。
### 3.2 测试协议
- 模型:本地 Qwen3.5-4B 原版与 Natural Memory v2;
- 量化:4-bit NF4;
- 解码:greedy;
- 最大新生成:64 token;
- GPU 进程上限:10 GiB;
- Natural Memory 读取:最多 2 条记录;
- 语义地址编码:单条 batch,避免 12 GiB 显卡在源码证据编码阶段产生瞬时峰值;
- 题目总数:264;
- 可回答题:246;
- 未知/拒答题:18。
题目类型不是单纯的随机字符串记忆,包括:
- 真实函数和类的源码定位;
- 面向工程使用的架构解释;
- 用户事实的自然改写;
- 早期目录到当前目录的时间冲突;
- 写入安全、版本替换和显存约束;
- 目标不存在时的拒答。
### 3.3 总体结果
| 系统 | 可回答正确率 | 未知拒答正确率 | 总体正确率 |
|---|---:|---:|---:|
| 原版 Qwen3.5-4B,无记忆 | 3/246 = 1.22% | 17/18 = 94.44% | 20/264 = 7.58% |
| Natural Memory v2 | 154/246 = 62.60% | 16/18 = 88.89% | 170/264 = 64.39% |
Natural Memory 把真实工程与用户事实带来的可回答率从 1.22% 提升到 62.60%。这证明记忆路径能够迁移到非构造的短事实和真实代码内容,但距离稳定的生产级自然语言记忆仍有明显差距。
### 3.4 按数据域拆分
| 数据域 | 系统 | 可回答结果 | 未知拒答 |
|---|---|---:|---:|
| 用户对话事实 | 原版 Qwen | 1/38 = 2.63% | 6/6 = 100.00% |
| 用户对话事实 | Natural Memory v2 | 21/38 = 55.26% | 6/6 = 100.00% |
| 真实源码/文档 | 原版 Qwen | 2/208 = 0.96% | 11/12 = 91.67% |
| 真实源码/文档 | Natural Memory v2 | 133/208 = 63.94% | 10/12 = 83.33% |
源码定位是当前表现最好的真实任务:
- 用户对话事实:21/38 = 55.26%;
- 符号定位:129/192 = 67.19%;
- 时间冲突目录查询:2/2;
- 写入安全解释:2/2;
- 基线局限说明:2/2;
- 用户自然改写:4/5;
- 用户约束类问题:1/4;
- 开放式架构解释类问题:当前严格锚点评估中仍不稳定。
### 3.5 路由与生成的差距
Natural Memory 在 246 个可回答问题上的目标记忆召回为 166/246 = 67.48%,最终回答正确为 154/246 = 62.60%。这说明当前主要问题已经不只是“有没有记忆”,而是两段链路都需要改进:
1. 路由器在口语化问题、短问题和没有显式文件名的问题上会召回相邻但错误的记录;
2. 即使证据已进入前缀,Qwen 仍可能拒答、过度解释或没有按要求输出关键事实。
因此,当前结果不能写成“检索准确率等于回答准确率”,两者必须分开报告。
## 4. 显存、速度和记忆容量
以下数字来自同一次正式脏数据测试。显存字段是每次请求结束后的 allocated/reserved 快照,不是 `torch.cuda.max_memory_allocated()` 记录的严格峰值;`reserved` 还包含 PyTorch 分配器保留的缓存。
| 指标 | 原版 Qwen3.5-4B | Natural Memory v2 | 变化 |
|---|---:|---:|---:|
| 平均总延迟 | 2650.4 ms | 2718.9 ms | +2.58% |
| 平均解码速度 | 24.06 tok/s | 21.68 tok/s | -9.90% |
| 平均输入 token | 30.8 | 641.4 | 记忆证据前缀增加 |
| 读取额外耗时 | 无 | 61.1 ms | 新增路径 |
| allocated 快照峰值 | 3.084 GiB | 3.134 GiB | +0.050 GiB |
| reserved 快照峰值 | 3.234 GiB | 5.021 GiB | +1.787 GiB |
本次记忆状态统计:
- active records:723;
- pages:23;
- 页面容量:32 records/page;
- 设计容量:1,048,576 records;
- GPU cache 上限:256 records、131,072 token;
- 实际 GPU cache token:15,885;
- GPU cache fallback:0;
- GPU cache allocation failure:0;
- cold page:0,原因是本次使用 embedded/process-RAM 模式。
这里的“一百万记录容量”是地址空间和分页结构的容量,不是本次已经装入了一百万条语义记忆,也不是一百万条记录已经通过端到端测试。
## 5. 之前的同协议工程基准
下面是先前在当前工程项目库上的 Stage 5 对照,用于说明系统在结构化项目事实上的上限。它与本次脏数据迁移集不是同一题集,不能合并成一个总分。
### 通用个人事实
| 系统 | 可回答 | 未知拒答 | 平均延迟 | 解码速度 |
|---|---:|---:|---:|---:|
| 原版 Qwen3.5-4B | 4/107 = 3.74% | 21/21 = 100% | 1233.2 ms | 23.51 tok/s |
| 强 RAG 基线 | 106/107 = 99.07% | 20/21 = 95.24% | 885.8 ms | 21.67 tok/s |
| Natural Memory v2 | 107/107 = 100% | 21/21 = 100% | 994.3 ms | 21.70 tok/s |
### 项目库
| 系统 | 正确率 | 平均延迟 | 解码速度 |
|---|---:|---:|---:|
| 原版 Qwen3.5-4B | 45/64 = 70.31% | 1351.5 ms | 23.70 tok/s |
| 强 RAG 基线 | 64/64 = 100% | 1395.3 ms | 22.94 tok/s |
| Natural Memory v2 | 64/64 = 100% | 1463.2 ms | 21.85 tok/s |
该强 RAG 使用本地 CPU `bert-base-chinese` 向量、稀疏特征和固定规则重排。它不是训练好的公开 cross-encoder,因此可以作为更强的本地基线,但不能代表所有生产 RAG 服务。
## 6. 已经解决的问题
当前实现已经能够在本地 12 GiB GPU 上完成以下闭环:
1. 普通自然语言触发自动记忆读取,不要求用户输入 `/remember`;
2. 模型重启后不回放历史聊天,只加载已保存的 memory shard;
3. 旧值和新值保留版本关系,旧值不会继续作为 active 事实参与正常读取;
4. 记忆读取器、地址索引和证据注入位于模型适配架构内部;
5. 记忆主体留在进程内存,热点记录使用有界 GPU cache;
6. 当前问题只读取 Top-K 记录,不对全量 slot 做注意力;
7. 低置信度写入、撤回和审计状态有独立表示;
8. 在真实工程源码定位任务上,相比无记忆 Qwen 有明显的可回答性提升。
## 7. 当前不能宣称的内容
以下说法目前没有足够证据支持:
- “Natural Memory 已经等价于百万 token 的完整 KV”;
- “Natural Memory 已经击败生产级 embedding + reranker RAG”;
- “任何自然语言表达都能稳定召回正确记忆”;
- “记忆写入永远不会出错”;
- “一百万条记录已经完成端到端验证”;
- “当前 4B 结果可以直接外推到 14B、32B 或更大模型”;
- “reserved VRAM 就是实际模型峰值显存”;
- “本次用户事实测试代表大规模真实用户群体”。
## 8. 主要局限
### 8.1 训练数据仍不够自然
当前路由器的主体训练仍来自本地构造的实体—属性—值事实和 hard negatives。正式脏数据集虽然使用了真实工程内容和真实项目对话片段,但自然改写仍是人工编写的测试变体,不是大规模脱敏真人会话。
### 8.2 真实仓库的语义索引覆盖有限
本次运行把全部 620 个真实源码/文档分片放入记忆库,但为控制 GPU 压力,只有 96 个符号目标和 8 个操作性事实建立了 Qwen 语义地址,其余分片作为真实背景记录保留。这使测试更安全、更可复现,但不能等同于“整个仓库都被高质量语义索引”。
### 8.3 开放式解释弱于明确定位
对于“某个函数在哪个文件”这类有明确地址的任务,表现明显好于“结合多个文件解释系统为什么这样设计”。后者需要多跳证据合并、冲突处理和生成控制,当前仍会出现证据已召回但最终回答不完整的情况。
### 8.4 速度仍有真实代价
正式脏数据测试中,Natural Memory 平均延迟高约 2.58%,解码速度低约 9.90%,并增加了平均输入前缀长度。这个代价来自 Qwen 查询编码、稀疏路由、证据前缀和热点缓存,而不是免费获得的能力。
### 8.5 生产级基线还不完整
本次正式脏库对照聚焦原版 Qwen3.5-4B 无记忆基线。要作出服务经济学结论,还需要在同一脏数据、同一题集上加入强 embedding 检索器、cross-encoder 或训练好的 reranker、滑动窗口和分页 KV 等基线。
## 9. 下一阶段的工程任务
按对正确率最有帮助的顺序:
1. 使用有用户同意的脱敏对话,增加自然省略、指代、错别字、时间间隔、互相矛盾的旧说法和多轮项目协作样本;
2. 重新训练路由器,重点覆盖“同一事实的多种问法”和“相似但错误的记录”;
3. 对“检索正确但回答错误”的样本单独训练证据使用与拒答策略;
4. 将真实仓库的语义地址覆盖从目标记录扩展到完整索引,仍保持单条/小批次编码以保护显存;
5. 加入多跳证据合并和当前版本优先规则;
6. 将写入、冲突解决和摘要从生成热路径移到回合边界或后台线程;
7. 把显存测试改为记录真正的 CUDA high-water mark,并分别报告 live allocated、reserved 和 cache payload;
8. 在同一协议下补齐强 RAG、滑动窗口和分页 KV 的成本—质量曲线。
## 10. 复现实验
在 `H:\Memory` 下运行:
```powershell
& C:\Users\Administrator\miniconda3\envs\LLM\python.exe `
-m V2_dpskw.benchmark_dirty_real_corpus_4b `
--project-records 8192 `
--project-targets 96 `
--max-new-tokens 64 `
--encode-batch-size 1 `
--skip-chunk-rag `
--output H:\Memory\V2_dpskw\dirty_real_corpus_compare_4b.json
```
对应的原始结果文件为:
`H:\Memory\V2_dpskw\dirty_real_corpus_compare_4b.json`
评测脚本为:
`H:\Memory\V2_dpskw\benchmark_dirty_real_corpus_4b.py`
## 11. 结论
Natural Memory v2 当前已经不是只有构造数据上的演示:在真实工程源码、文档和本项目用户要求组成的脏数据迁移测试中,它显著提高了窗口外事实的可回答性,并在 10 GiB GPU 进程上完成了 723 条 active records 的读取运行。
同时,62.60% 的可回答正确率、88.89% 的未知拒答正确率和约 10% 的解码速度下降说明它仍处于研究原型到工程验证之间。当前最值得继续投入的不是增加宣传口径,而是提高自然语言路由泛化、证据到回答的闭环稳定性,并在同一题集上完成强 RAG 和 KV 基线的公平对照。