Initial commit: 自然记忆站:12 页纯标准库 Python 静态站点生成器,含真实评测台账(108 条)与全站客户端检索
This commit is contained in:
@@ -0,0 +1,230 @@
|
|||||||
|
# DESIGN.md — Natural Memory 站点重设计
|
||||||
|
|
||||||
|
> 这份文件是**设计动作的产物**,写在动效之前。依据是 `motion-web` skill:
|
||||||
|
> `page-design.md`(静态帧怎么设计)、`design-slop.md`(AI 味闸门)、`data/visual-bank.json`(可选原型)、
|
||||||
|
> `motion-tokens.md`(时长/缓动/弹簧)、`choreography-arc.md`(叙事弧)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 0. 先测量,再设计:旧版站点的问题(实测,不是印象)
|
||||||
|
|
||||||
|
在 `assets/_gate.html` 里按 `design-slop.md` + `page-design.md §2` 的可量化条款跑了一遍旧站(1576px,12 页):
|
||||||
|
|
||||||
|
| 闸门 | 获奖站中位数(n=12) | 旧站实测 | 判定 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 最大渲染字号 | **108 px**(52–218) | **48 px** | ❌ |
|
||||||
|
| 正文字号 | 16 px(12–16) | 12–14 px | ✅ |
|
||||||
|
| **display ÷ body** | **≈ 8×**(3.3–14×) | **3.4–4.0×** | ❌ A6 |
|
||||||
|
| 主色数量 | **4**(1–6) | 6–7 | ❌ A4 |
|
||||||
|
| 渐变 | **0 / 15** | home 2、results 10 | ❌ A4 |
|
||||||
|
| body 全局 max-width | 15/15 无 | 无 | ✅ |
|
||||||
|
| `<h1>` 数量 | — | 1 | ✅ |
|
||||||
|
|
||||||
|
**结论**:旧站最大的问题是**字阶没有落差**。48 px 的标题正好落在 `design-slop.md` A6 点名的
|
||||||
|
「everything between 16 and 48px」区间里 —— 那不是「不够大」,是**整个页面没有尺度对比**。
|
||||||
|
这一条足以解释「普通 / 没设计感」,而且**加留白、换配色都救不回来**。
|
||||||
|
其余是次要的:颜色偏多、有几处渐变、色带落在 2–6 屏这个「中段」(获奖站是双峰的:≈1 屏或 7–57 屏)。
|
||||||
|
|
||||||
|
### 重设计之后(同一把尺子,同样 12 页,1576px)
|
||||||
|
|
||||||
|
| 闸门 | 获奖站中位数 | 旧站 | **新站** | 判定 |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| 最大渲染字号 | 108 px | 48 px | **200 px**(`.mega`)/ 132 px(首屏标题) | ✅ |
|
||||||
|
| display ÷ body | ≈ 8× | 3.4–4.0× | **7.1 – 14.3×**(12/12 页 ≥ 7.1) | ✅ |
|
||||||
|
| 字体家族 | 2 | 3(含一个漏出来的 `monospace`) | **2** | ✅ |
|
||||||
|
| `<h1>` 数量 | — | 1 | 1 | ✅ |
|
||||||
|
| 首屏按钮对 | A1 反模式 | 6 个药丸 | **0** | ✅ |
|
||||||
|
| 横向溢出 / 截断 / undefined / NaN | — | 0 | **0(12 页 × 4 档视口)** | ✅ |
|
||||||
|
| 渐变 | 0 / 15 | home 2, results 10 | 仅剩基线条的**斜纹填充**(语义编码,见下) | ⚠️ 保留 |
|
||||||
|
|
||||||
|
**顺带修掉一个真 bug**:`<pre>` 一直没有显式 `font-family`,掉回 UA 样式表的 `monospace` ——
|
||||||
|
**全站代码块此前都不是 Geist Mono**。这也是「字体家族 = 3」的来源。已修。
|
||||||
|
|
||||||
|
**唯一保留的渐变**:`.bar--base .bar__fill` 用的是 `repeating-linear-gradient` 斜纹,
|
||||||
|
它编码的是「无记忆基线」这一条数据,是数据墨水不是装饰(A4 针对的是渐变**背景处理**)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 明确的偏差与代价(不藏)
|
||||||
|
|
||||||
|
1. **移动端的字阶落差改用「数字」承担 —— 这一条已经解决,不是遗留问题。**
|
||||||
|
中文标题在 320px 上推不到 7×:`page-design.md §4` 自己写了
|
||||||
|
「weight contrast carries hierarchy better than size contrast alone, because a huge 黑体 becomes a solid block」——
|
||||||
|
320px 宽放 98px 的中文标题,一行只有 3 个字,13 个字的标题要断成 5 行,那是排版事故。
|
||||||
|
所以**每个证据页的页眉由一个真实数字领起**(`.doc__figure` + `.mega`),
|
||||||
|
中文标题负责可读性,数字负责落差。实测结果:
|
||||||
|
|
||||||
|
| 视口 | 12 页 ratio 最小值 | ≥ 7× 的页数 | 布局问题 |
|
||||||
|
|---|---:|---:|---:|
|
||||||
|
| 1600 px | **11.1×** | 12 / 12 | 0 |
|
||||||
|
| 768 px | **7.8×** | 12 / 12 | 0 |
|
||||||
|
| 390 px | **7.1×** | 12 / 12 | 0 |
|
||||||
|
| 320 px | **7.1×** | 12 / 12 | 0 |
|
||||||
|
| 1600 px + reduced-motion | **11.1×** | 12 / 12 | 0 |
|
||||||
|
|
||||||
|
这不是把数字调到达标,而是**让每一页自己先把最强的那条数字说出来** ——
|
||||||
|
这些页面本来就是证据页,页眉只有一个标题反而浪费了它们最好的东西。
|
||||||
|
2. **地址空间装置在 `≤900px` 与 `prefers-reduced-motion` 下不下降**,冻结成一帧静态地址空间
|
||||||
|
(窄屏冻结在 t=0.30「Qwen hidden state」,reduced-motion 冻结在 t=0.52「候选页」)。
|
||||||
|
页面高度同时从 340vh 收到 1 屏,不留下 3 屏的空滚动。
|
||||||
|
3. **`--body` 用 `#9a9a92` 而不是 p-07 原型写的 `#909090`** —— 为了 12 页技术文档的连续阅读,
|
||||||
|
在原型值上抬了一档(对比度 7.6:1,AAA 正文标准以上)。这是对原型的**唯一**颜色偏离,特此标明。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 动效闸门自检结果(B1–B8)
|
||||||
|
|
||||||
|
| 闸门 | 实测 | 处置 |
|
||||||
|
|---|---|---|
|
||||||
|
| B1 统一上浮 hover | `translateY(-*)` 命中 **0** | ✅ |
|
||||||
|
| B2 全页统一 fade-up | 原本 ~20 个元素同款入场 → 现在 **3 处,三种不同手势**(擦除 / 数字冲入 / 侧向错峰)+ 路径图自己的画线 | ✅ |
|
||||||
|
| B3 一个缓动一个时长 | 原本 5 个时长令牌有 3 个没用、**15 处硬编码 `120ms ease-out`** → 现在 **23 条 transition 全部走令牌**,实际用到 fast/std/med/slow **4 档** | ✅ |
|
||||||
|
| B4 预算全烧在首屏 | 首屏是装置,但 ~60% 处另有头号数字、重启装置两处收网 | ✅ |
|
||||||
|
| B5 动效与内容无关 | 机制来自「寻址」本身的物理,换到别的题材讲不通 | ✅ |
|
||||||
|
| B6 只有视差做纵深 | 无视差图层 | ✅ |
|
||||||
|
| B7 跟随光标的圆圈 | 无 | ✅ |
|
||||||
|
| B8 reduced-motion 下什么都不剩 | 实测 `wipeTarget=none`、装置冻结成完整静态帧、页高收到 1 屏、12 页 0 布局问题 | ✅ |
|
||||||
|
|
||||||
|
**顺带修掉的三个健壮性问题**(都不是猜的,是量出来的):
|
||||||
|
|
||||||
|
1. **`<pre>` 没有 `font-family`** → 掉回 UA 的 `monospace`,**全站代码块此前都不是 Geist Mono**。
|
||||||
|
2. **入场只靠 `IntersectionObserver`** → IO 在被节流的 iframe / 无头虚拟时间 / 某些低端 WebView 里不保证投递;
|
||||||
|
而 `clip-path` 擦除一旦不触发就是**一个永远看不见的标题**。已加「按滚动位置判定」的兜底,实测未入场元素从 **5 → 0**。
|
||||||
|
3. **首屏循环 latch**:`raf` 句柄非空但帧被冻结时,`kick()` 永远提前返回,循环永久卡死。
|
||||||
|
已改为超时同步走一帧 —— 实测 `spaceT` 从 **0.00 → 0.39**。
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 叙事结构(macrostructure)
|
||||||
|
|
||||||
|
**Editorial + set-pieces** —— 页面主体是**可读的正文**,动效出现 3 次、每次都有明确含义,
|
||||||
|
是段落之间的标点,不是背景装饰。
|
||||||
|
|
||||||
|
选它的理由来自内容本身:这是一个**研究发布站**,主体是 12 页文档、数据表和一份 108 条台账。
|
||||||
|
把它硬塞进「单场景」或「Acts」会牺牲可读性;而纯粹的 Editorial 又浪费了这套内容里
|
||||||
|
**唯一真正有空间感的东西 —— 记忆的地址空间**。
|
||||||
|
|
||||||
|
- **线性内容** → 走 editorial,而不是 index / instrument(`page-design.md §1` 的两条判据之一)。
|
||||||
|
- **相机移动还是世界移动**:世界移动(地址空间被镜头穿过),所以镜头更像「下降」而不是「横摇」。
|
||||||
|
|
||||||
|
**叙事弧:`cold-open`**(安静入场 → 复杂度上升 → 峰值 → 收束)
|
||||||
|
`0–20%` 极简、只有字;`20–70%` 地址空间下降(峰值在此);`70–100%` 结果与边界,留白放开。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 视觉系统(提交一个原型,不混搭)
|
||||||
|
|
||||||
|
来自 `data/visual-bank.json`,**选一个、执行到底**:
|
||||||
|
|
||||||
|
- **调色:`p-07 Bold Black + Signal Accent`**("creative agencies, award sites, experimental portfolios, bold studios")
|
||||||
|
- ground `#000000`(纯黑,不是近黑)
|
||||||
|
- ink `#fffef4`(骨白,不是纯白)
|
||||||
|
- ink-2 `#909090` / ink-3 `#555555`
|
||||||
|
- surface `rgba(255,255,255,.05)` · border `rgba(255,255,255,.12)`
|
||||||
|
- **信号色 `#00ff6a`,每页只出现一次**(原型原文:one per page max)
|
||||||
|
- 主色数量从 6–7 压到 **≤4**;**渐变全部删除**
|
||||||
|
- **字体:两个家族**(获奖站中位数就是 2,range 1–4)
|
||||||
|
- `Archivo Variable`(wght 100–900 · wdth 62–125%)—— 显示与正文的拉丁部分、**全部数字**
|
||||||
|
- `Geist Mono` —— 标签、代码、字段名
|
||||||
|
- 中文回落到系统 CJK(PingFang SC / 微软雅黑 / Noto Sans CJK),**不额外加载 CJK 字体**
|
||||||
|
|
||||||
|
### 2.1 字阶:落差就是设计(`page-design.md §4`)
|
||||||
|
|
||||||
|
| 令牌 | 值 | 用途 |
|
||||||
|
|---|---|---|
|
||||||
|
| `--fs-mega` | `clamp(4.5rem, 12vw, 12.5rem)` = 72 → **200 px** | 拉丁/数字巨字 |
|
||||||
|
| `--fs-display` | `clamp(2.75rem, 7vw, 6.5rem)` = 44 → **104 px** | 页面主标题 |
|
||||||
|
| `--fs-h2` | `clamp(1.75rem, 3.4vw, 3rem)` | 章节标题 |
|
||||||
|
| `--fs-lede` | `1.125rem` | 导语 |
|
||||||
|
| `--fs-body` | `0.875rem` | **正文(14 px)** |
|
||||||
|
|
||||||
|
`mega ÷ body = 200/14 ≈ 14×`(获奖站上沿),`display ÷ body ≈ 7.4×`(≈ 中位数 8×)。
|
||||||
|
旧站是 3.4× —— **这是本次重设计的核心动作**。
|
||||||
|
|
||||||
|
### 2.2 中日韩显示字的特殊处理(`page-design.md §4` 明确点名)
|
||||||
|
|
||||||
|
中文大字和拉丁大字**不是一套参数**:
|
||||||
|
|
||||||
|
| | 行高 | 字距 | 字重 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 拉丁/数字 `.dsp--lat` | 0.90 | `-0.045em` | 700,`font-stretch: 92%` |
|
||||||
|
| 中文 `.dsp` | **1.28** | **-0.005em** | 500 |
|
||||||
|
|
||||||
|
中文行高更大、负字距要收(不然字腔会闭合),层级**靠字重对比**而不是只靠字号。
|
||||||
|
所以拉丁与中文的 display 是两个 class,在标记里显式指定,不靠回落碰运气。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 版面(layout)
|
||||||
|
|
||||||
|
- **全幅页面,逐元素设 measure**(获奖站 15/15 都没有 body 全局 max-width):
|
||||||
|
`--measure: 62ch` 用于连续正文,`--measure-wide: 88ch` 用于说明,媒体全幅。
|
||||||
|
- **间距不是常数**(`page-design.md §6`):`--band-tight 48–80px` / `--band 80–160px` /
|
||||||
|
`--band-wide 120–260px`,按「两块该不该被读成一组」来给。
|
||||||
|
- **至少三种不同的 section 形状**:全幅巨字带 / 非对称 2:1 分栏 / 数据表带 / 卡片网格 /
|
||||||
|
装置带(整屏交互)/ 引用带 —— 不允许「每段都是居中标题 + 段落」。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 动效概念(来自题材自身的物理)
|
||||||
|
|
||||||
|
**概念名:地址空间下降(Address Descent)**
|
||||||
|
|
||||||
|
题材的物理就是**寻址**:1,048,576 个槽位、738 条活跃记录、730 个 LSH 桶、
|
||||||
|
每页 32 条、每次只把少量记录提升到 GPU。整条读取路径本来就是**一次下降**:
|
||||||
|
问题 → 128 维地址 → 粗索引桶 → 候选页 → 页内重排 → Top-K → 证据前缀 → 生成。
|
||||||
|
|
||||||
|
**招牌场景**:一个整屏的地址空间栅格(1,048,576 个槽位画成点阵,738 个亮着)。
|
||||||
|
滚动时镜头**一路下降五个数量级**:整个空间 → 730 个桶 → 一页 32 条 → 一条记录 →
|
||||||
|
这条记录变成注入模型的前缀 token。终点是**一条记录**,不是一句 slogan。
|
||||||
|
|
||||||
|
这个机制满足 `design-slop.md` B5(机制必须来自题材自身的物理):换到任何别的题材上都讲不通。
|
||||||
|
|
||||||
|
**动效令牌**(`motion-tokens.md`,至少三档时长 + 弹簧):
|
||||||
|
|
||||||
|
| 令牌 | 值 | 用途 |
|
||||||
|
|---|---|---|
|
||||||
|
| `--dur-fast` | 160ms | 悬停、按下、开关 |
|
||||||
|
| `--dur-std` | 300ms | 面板、抽屉、状态切换 |
|
||||||
|
| `--dur-med` | 460ms | 区块入场(少数几处) |
|
||||||
|
| `--dur-slow` | 700ms | 巨字入场 |
|
||||||
|
| `--dur-cine` | 1200ms | 冷开场 |
|
||||||
|
| `--ease-exp` | `cubic-bezier(.16,1,.3,1)` | 默认出场 |
|
||||||
|
| `--ease-sharp` | `cubic-bezier(.65,0,.45,1)` | 硬切、品牌感 |
|
||||||
|
| `--ease-in-expo` | `cubic-bezier(.7,0,.84,0)` | **只用于离场** |
|
||||||
|
|
||||||
|
**明确不做什么**(对应 `design-slop.md` B1–B8):
|
||||||
|
- B1 不做「所有卡片统一上浮 4px + 阴影」
|
||||||
|
- B2 不做「每个区块都 fade-up 20px」—— 大多数内容**本来就在那儿**,入场只留给 3 处
|
||||||
|
- B3 不允许全站一个 `0.3s ease`
|
||||||
|
- B4 不把预算全烧在首屏
|
||||||
|
- B7 不做跟随光标的圆圈
|
||||||
|
- B8 reduced-motion 下必须仍然是一张完整的页面
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 移动端降级(`page-design.md §7`,显式写明,不含糊)
|
||||||
|
|
||||||
|
- **地址空间装置**:`< 900px` 关闭点阵与镜头下降,改为一帧静态的地址空间图 + 数字条。
|
||||||
|
降级**不是**隐藏内容,是把动效换成静态帧。
|
||||||
|
- 巨字:`12vw` 下限 72px,320px 宽时仍是 72px(不缩到看不清)。
|
||||||
|
- 悬停不存在 —— 所有悬停信息必须有第二个落点(见设备页/台账页的显式状态)。
|
||||||
|
- 滚动在移动端更长,节奏按移动端重读一遍,不假设等比缩放。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 设计闸门自检(交付前必须全过)
|
||||||
|
|
||||||
|
`design-slop.md` A1–A8 / B1–B8 + `page-design.md §8`,用 `assets/_gate.html` 逐条量:
|
||||||
|
|
||||||
|
- [ ] A1 首屏不是「徽标 + 标题 + 副标题 + 两个按钮」
|
||||||
|
- [ ] A2 没有三张等宽居中卡片
|
||||||
|
- [ ] A3 每页 ≥3 种不同 section 形状
|
||||||
|
- [ ] A4 无紫/靛渐变;主色 ≤4;信号色每页只出现一次
|
||||||
|
- [ ] A5 没有噪点/光晕/网格纸这类「填空装饰」
|
||||||
|
- [ ] A6 display ÷ body ≥ 7×
|
||||||
|
- [ ] A7 没有手绘的假浏览器/假手机外壳
|
||||||
|
- [ ] A8 没有编造的证明(本站所有数字都来自工程内真实报告)
|
||||||
|
- [ ] B1–B8 动效闸门
|
||||||
|
- [ ] D 移动端 320/375/414/768 无横向滚动;reduced-motion 下页面完整
|
||||||
+1448
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||||
|
<!-- Natural Memory 记忆地址点阵标记:暗格为地址空间,亮格为命中记录 -->
|
||||||
|
<rect width="32" height="32" fill="#08090A"/>
|
||||||
|
<g fill="#3A4045">
|
||||||
|
<rect x="3" y="3" width="6" height="6"/>
|
||||||
|
<rect x="13" y="3" width="6" height="6"/>
|
||||||
|
<rect x="23" y="3" width="6" height="6"/>
|
||||||
|
<rect x="3" y="13" width="6" height="6"/>
|
||||||
|
<rect x="23" y="13" width="6" height="6"/>
|
||||||
|
<rect x="3" y="23" width="6" height="6"/>
|
||||||
|
<rect x="13" y="23" width="6" height="6"/>
|
||||||
|
</g>
|
||||||
|
<rect x="13" y="13" width="6" height="6" fill="#D6F24B"/>
|
||||||
|
<rect x="23" y="23" width="6" height="6" fill="#D6F24B"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 692 B |
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,334 @@
|
|||||||
|
/* ------------------------------------------------------------------
|
||||||
|
Natural Memory v2 — 站点数据层
|
||||||
|
所有数字均直接摘自工程内的正式报告,src 字段标注出处文件。
|
||||||
|
本文件不包含任何推算、外推或未测量的数字。
|
||||||
|
------------------------------------------------------------------ */
|
||||||
|
window.NM_DATA = {
|
||||||
|
|
||||||
|
meta: {
|
||||||
|
name: "Natural Memory v2",
|
||||||
|
version: "v2",
|
||||||
|
base: "Qwen3.5-4B",
|
||||||
|
date: "2026-09",
|
||||||
|
repo: "H:\\Memory",
|
||||||
|
disclaimer:
|
||||||
|
"本文只描述当前实现已经完成并实际测量的内容。它不把系统描述成通用智能,也不把实验室结果表述成线上服务承诺。"
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- 一句话定位 ---------- */
|
||||||
|
positioning: {
|
||||||
|
headline: "模型重启之后,它仍然记得。",
|
||||||
|
latin: "A memory layer inside the model.",
|
||||||
|
body:
|
||||||
|
"Natural Memory v2 是接在本地 Qwen3.5-4B 上的一个模型内记忆层:把适合长期复用的个人事实、项目事实和短对话片段写进带地址的记忆记录," +
|
||||||
|
"当前问题只读取少量相关记录,再把这些记录作为模型内部前缀交给 Qwen 生成答案。",
|
||||||
|
problem:
|
||||||
|
"要解决的具体问题:模型重启后不携带历史聊天记录,仍能访问已经保存的个人或项目事实,同时不把全部历史转换成 GPU 上的长 KV Cache。"
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- 记忆与 KV 的分工 ---------- */
|
||||||
|
division: [
|
||||||
|
{ k: "最近对话", v: "Qwen 热 KV", note: "顺序关系仍由普通上下文负责" },
|
||||||
|
{ k: "长期个人/项目事实", v: "Natural Memory 记录", note: "事实、版本、来源、短证据、语义地址" },
|
||||||
|
{ k: "当前问题", v: "有界路由与 Top-K 读取", note: "不做全量 slot 注意力" },
|
||||||
|
{ k: "原始持久化状态", v: "嵌入式 memory safetensors", note: "无 SQLite、无磁盘分页" }
|
||||||
|
],
|
||||||
|
|
||||||
|
/* ---------- 读取路径(可交互的分步) ---------- */
|
||||||
|
readPath: [
|
||||||
|
{ id: "q", label: "用户问题", detail: "普通自然语言,不要求 /remember 之类的显式指令。", io: "输入 · 一句口语化的问题" },
|
||||||
|
{ id: "hs", label: "Qwen hidden state", detail: "由模型隐状态生成紧凑查询地址,而不是独立的外部 embedding 服务。", io: "问题 → 紧凑查询地址(单条 batch 编码,避免显存瞬时峰值)" },
|
||||||
|
{ id: "lsh", label: "LSH / 地址粗索引", detail: "精确桶 + Hamming-1/2 探针,把候选收敛到少量页面。", io: "查询地址 → 候选页(批次 A 粗索引 730 个桶,最近一次粗筛返回 24 个候选)" },
|
||||||
|
{ id: "pg", label: "候选页", detail: "页容量 32 条记录;默认最多读取 4 页。", io: "候选页 → 少量页面(本次 723 条 active records 分布在 23 个页面上)" },
|
||||||
|
{ id: "rr", label: "页内记录重排", detail: "记录级重排由独立的 text_retriever 完成(6 张量、1,573,377 参数)。", io: "页内记录 → 有序候选(text_retriever 自身 Top-1 只有 23.20%,是当前主要瓶颈)" },
|
||||||
|
{ id: "tk", label: "Top-K 记录", detail: "正式脏数据测试中的读取上限为 2 条。", io: "有序候选 → 少量证据(目标召回:批次 A 166/246,批次 B 228/246)" },
|
||||||
|
{ id: "inj", label: "证据前缀注入 Qwen", detail: "命中的短证据被提升到 GPU,作为模型内部前缀。", io: "证据 → 模型内部前缀(批次 B 96.97% 的题实际注入,平均 410.34 token)" },
|
||||||
|
{ id: "gen", label: "普通生成", detail: "记忆主体留在进程内存,只有热点记录进入有界 GPU cache。", io: "前缀 + 问题 → 回答(读取额外耗时:批次 A 61.10 ms → 批次 B 26.35 ms)" }
|
||||||
|
],
|
||||||
|
readPathCost: { value: 61.1, unit: "ms", label: "读取路径额外耗时", src: "对外技术总结 §4" },
|
||||||
|
|
||||||
|
/* ---------- 记忆记录解剖 ---------- */
|
||||||
|
recordFields: [
|
||||||
|
{ f: "raw_text", d: "原始短文本" },
|
||||||
|
{ f: "semantic_addr", d: "语义地址" },
|
||||||
|
{ f: "entity", d: "实体" },
|
||||||
|
{ f: "attribute", d: "属性" },
|
||||||
|
{ f: "value", d: "值" },
|
||||||
|
{ f: "timestamp", d: "时间" },
|
||||||
|
{ f: "source", d: "来源" },
|
||||||
|
{ f: "confidence", d: "置信度" },
|
||||||
|
{ f: "importance", d: "重要性" },
|
||||||
|
{ f: "access_count", d: "访问次数" },
|
||||||
|
{ f: "status", d: "状态" },
|
||||||
|
{ f: "supersedes", d: "版本关系" },
|
||||||
|
{ f: "related_ids", d: "关联记录" },
|
||||||
|
{ f: "audit", d: "审计信息" }
|
||||||
|
],
|
||||||
|
states: [
|
||||||
|
{ s: "active", d: "当前有效事实,参与正常读取", tone: "ok" },
|
||||||
|
{ s: "superseded", d: "同一实体+属性出现新值,旧值退役", tone: "mute" },
|
||||||
|
{ s: "quarantined", d: "低置信度写入,需显式批准", tone: "warn" },
|
||||||
|
{ s: "retracted", d: "已撤回,但不从审计中消失", tone: "bad" }
|
||||||
|
],
|
||||||
|
|
||||||
|
/* ---------- 主结果:正式脏数据迁移测试 ---------- */
|
||||||
|
dirty: {
|
||||||
|
title: "正式脏数据迁移测试",
|
||||||
|
src: "对外技术总结 §3",
|
||||||
|
subtitle: "真实工程源码 / 文档 + 本项目对话中用户明确说过的短事实",
|
||||||
|
corpus: [
|
||||||
|
{ k: "真实源码与文档", v: "65 个文件 · 1,110,524 字节 · 620 个分片" },
|
||||||
|
{ k: "用户对话事实", v: "15 条记录" },
|
||||||
|
{ k: "由记录派生的问题", v: "44 题(38 可回答 / 6 未知)" },
|
||||||
|
{ k: "来自源码与文档", v: "220 题" },
|
||||||
|
{ k: "题目总数", v: "264 题 · 246 可回答 · 18 未知" }
|
||||||
|
],
|
||||||
|
protocol: "Qwen3.5-4B · 4-bit NF4 · greedy 解码 · 最大新生成 64 token · 进程显存上限 10 GiB · 读取上限 2 条记录 · 同一 tokenizer",
|
||||||
|
batchNote: "同一题集(264 题 / 246 可回答 / 18 未知)、同一协议、同一仓库,先后跑了两个独立批次。批次配置不同,因此两个批次的分数不可合并、不可平均,只能并列读。",
|
||||||
|
headline: [
|
||||||
|
{ metric: "可回答正确率", base: 1.22, a: 62.60, b: 82.52, baseRaw: "3/246", aRaw: "154/246", bRaw: "203/246" },
|
||||||
|
{ metric: "目标记忆召回率", base: 0.00, a: 67.48, b: 92.68, baseRaw: "0/246", aRaw: "166/246", bRaw: "228/246" },
|
||||||
|
{ metric: "总体正确率", base: 7.58, a: 64.39, b: 82.95, baseRaw: "20/264", aRaw: "170/264", bRaw: "219/264" },
|
||||||
|
{ metric: "未知拒答正确率", base: 94.44, a: 88.89, b: 88.89, baseRaw: "17/18", aRaw: "16/18", bRaw: "16/18" }
|
||||||
|
],
|
||||||
|
batches: [
|
||||||
|
{
|
||||||
|
id: "A", label: "批次 A", date: "2026-09-05 23:22", file: "dirty_real_corpus_compare_4b.json",
|
||||||
|
tag: "对外技术总结采用",
|
||||||
|
reader: 61.10, promptTokens: 641.42, prefixRate: 90.91, prefixTokens: 610.67,
|
||||||
|
latencyBase: 2650.4, latencyNm: 2718.9, decodeBase: 24.06, decodeNm: 21.68,
|
||||||
|
allocNm: 3.134, resvNm: 5.021, records: 723, pages: 23, cacheTokens: 15885
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "B", label: "批次 B", date: "2026-09-06 11:36", file: "dirty_real_corpus_compare_4b_router_final.json",
|
||||||
|
tag: "接入记忆路由器后",
|
||||||
|
reader: 26.35, promptTokens: 441.19, prefixRate: 96.97, prefixTokens: 410.34,
|
||||||
|
latencyBase: 2854.9, latencyNm: 2878.3, decodeBase: 22.34, decodeNm: 20.68,
|
||||||
|
allocNm: 3.134, resvNm: 5.180, records: 738, pages: 24, cacheTokens: 17990
|
||||||
|
}
|
||||||
|
],
|
||||||
|
categories: [
|
||||||
|
{ k: "symbol_navigation", label: "符号定位(函数在哪个文件)", n: 192, base: "0/192", a: "129/192", b: "181/192" },
|
||||||
|
{ k: "unknown_refusal", label: "未知拒答", n: 18, base: "17/18", a: "16/18", b: "16/18" },
|
||||||
|
{ k: "constraint", label: "约束类问题", n: 15, base: "0/15", a: "5/15", b: "6/15" },
|
||||||
|
{ k: "paraphrase", label: "自然改写", n: 9, base: "0/9", a: "5/9", b: "5/9" },
|
||||||
|
{ k: "cross_session", label: "跨会话", n: 6, base: "1/6", a: "5/6", b: "5/6" },
|
||||||
|
{ k: "temporal_conflict", label: "时间冲突目录查询", n: 4, base: "0/4", a: "4/4", b: "4/4" },
|
||||||
|
{ k: "reasoning", label: "推理", n: 4, base: "0/4", a: "2/4", b: "0/4" },
|
||||||
|
{ k: "write_safety", label: "写入安全解释", n: 2, base: "0/2", a: "2/2", b: "0/2" },
|
||||||
|
{ k: "baseline_limitation", label: "基线局限说明", n: 2, base: "2/2", a: "2/2", b: "2/2" },
|
||||||
|
{ k: "operational_architecture", label: "操作性架构", n: 2, base: "0/2", a: "0/2", b: "0/2" },
|
||||||
|
{ k: "architecture_tradeoff", label: "架构取舍", n: 2, base: "0/2", a: "0/2", b: "0/2" },
|
||||||
|
{ k: "memory_tiers", label: "记忆分层", n: 2, base: "0/2", a: "0/2", b: "0/2" },
|
||||||
|
{ k: "benchmark_protocol", label: "基准协议", n: 2, base: "0/2", a: "0/2", b: "0/2" },
|
||||||
|
{ k: "control_path", label: "控制路径", n: 2, base: "0/2", a: "0/2", b: "0/2" },
|
||||||
|
{ k: "router_path", label: "路由器路径", n: 2, base: "0/2", a: "0/2", b: "0/2" }
|
||||||
|
],
|
||||||
|
categoryNote: "类别题量差异极大:符号定位 192 题,而 11 个类别各只有 2 题——2 题的类别里错 1 题就是 50 个百分点,不构成结论。批次 B 也并非全面提升:符号定位从 129 升到 181,但写入安全从 2/2 掉到 0/2、推理从 2/4 掉到 0/4。",
|
||||||
|
domains: [
|
||||||
|
{ domain: "用户对话事实", n: 38, base: 2.63, baseRaw: "1/38", a: 55.26, aRaw: "21/38", b: 52.63, bRaw: "20/38" },
|
||||||
|
{ domain: "真实源码/文档", n: 208, base: 0.96, baseRaw: "2/208", a: 63.94, aRaw: "133/208", b: 87.98, bRaw: "183/208" }
|
||||||
|
],
|
||||||
|
gap: {
|
||||||
|
recallA: 67.48, recallARaw: "166/246",
|
||||||
|
answerA: 62.60, answerARaw: "154/246",
|
||||||
|
recallB: 92.68, recallBRaw: "228/246",
|
||||||
|
answerB: 82.52, answerBRaw: "203/246",
|
||||||
|
note: "目标记忆召回与最终回答正确必须分开报告——检索准确率不等于回答准确率。批次 A 的召回 67.48%、回答 62.60%(差 4.88pp);批次 B 召回 92.68%、回答 82.52%(差 10.16pp):路由器把该查的记忆查回来了,但证据到答案的闭环仍有丢失。"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- 实测样例(逐字取自评测原始结果) ---------- */
|
||||||
|
examples: {
|
||||||
|
title: "实测样例",
|
||||||
|
src: "dirty_real_corpus_compare_4b_router_final.json(批次 B 逐条记录)",
|
||||||
|
subtitle: "下面五条题目与回答全部逐字取自评测原始结果,未经改写或润色。包含两条我们判错的样例。",
|
||||||
|
note:
|
||||||
|
"判分规则:可回答题要求 expected_anchors 里的锚点全部出现在回答中(去空白、转小写后做子串匹配);未知题则看模型是否拒答。" +
|
||||||
|
"输出上限为 64 token,标注「达上限截断」的回答是被硬截断的原文,不是完整句——我们保留原样,不做补全。" +
|
||||||
|
"另外:第 1 条命中的记忆记录里写的是「Natural Memory v1」,那是这条记录写入时的项目名,记录内容按原样保留、未做改写;" +
|
||||||
|
"第 5 条则是证据明明已经召回、回答却没能把锚点说全,因此判为未命中——这类「检索对、答案错」正是当前最主要的失分来源。"
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- Stage 5 结构化工程基准 ---------- */
|
||||||
|
stage5: {
|
||||||
|
title: "Stage 5 结构化工程基准",
|
||||||
|
src: "对外技术总结 §5",
|
||||||
|
subtitle: "与脏数据迁移集不是同一题集,不能合并成一个总分",
|
||||||
|
sets: [
|
||||||
|
{
|
||||||
|
name: "通用个人事实",
|
||||||
|
n: 107,
|
||||||
|
rows: [
|
||||||
|
{ sys: "原版 Qwen3.5-4B", acc: 3.74, raw: "4/107", lat: 1233.2, tok: 23.51, abstain: "21/21" },
|
||||||
|
{ sys: "强 RAG 基线", acc: 99.07, raw: "106/107", lat: 885.8, tok: 21.67, abstain: "20/21" },
|
||||||
|
{ sys: "Natural Memory v2", acc: 100.00, raw: "107/107", lat: 994.3, tok: 21.70, abstain: "21/21" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "项目库",
|
||||||
|
n: 64,
|
||||||
|
rows: [
|
||||||
|
{ sys: "原版 Qwen3.5-4B", acc: 70.31, raw: "45/64", lat: 1351.5, tok: 23.70, abstain: null },
|
||||||
|
{ sys: "强 RAG 基线", acc: 100.00, raw: "64/64", lat: 1395.3, tok: 22.94, abstain: null },
|
||||||
|
{ sys: "Natural Memory v2", acc: 100.00, raw: "64/64", lat: 1463.2, tok: 21.85, abstain: null }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
note: "强 RAG 使用本地 CPU bert-base-chinese 向量、稀疏特征和固定规则重排。它不是训练好的公开 cross-encoder,因此可以作为更强的本地基线,但不能代表所有生产 RAG 服务。"
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- 代价账本 ---------- */
|
||||||
|
cost: {
|
||||||
|
title: "代价账本",
|
||||||
|
src: "对外技术总结 §4",
|
||||||
|
subtitle: "以下数字来自同一次正式脏数据测试。显存字段是每次请求结束后的 allocated/reserved 快照,不是 torch.cuda.max_memory_allocated() 记录的严格峰值。",
|
||||||
|
rows: [
|
||||||
|
{ k: "平均总延迟", base: "2650.4 ms", nm2: "2718.9 ms", delta: "+2.58%", tone: "warn" },
|
||||||
|
{ k: "平均解码速度", base: "24.06 tok/s", nm2: "21.68 tok/s", delta: "-9.90%", tone: "bad" },
|
||||||
|
{ k: "平均输入 token", base: "30.8", nm2: "641.4", delta: "证据前缀增加", tone: "mute" },
|
||||||
|
{ k: "读取额外耗时", base: "无", nm2: "61.1 ms", delta: "新增路径", tone: "mute" },
|
||||||
|
{ k: "allocated 快照峰值", base: "3.084 GiB", nm2: "3.134 GiB", delta: "+0.050 GiB", tone: "ok" },
|
||||||
|
{ k: "reserved 快照峰值", base: "3.234 GiB", nm2: "5.021 GiB", delta: "+1.787 GiB", tone: "warn" }
|
||||||
|
],
|
||||||
|
vram: { card: 12, allocBase: 3.084, allocNm2: 3.134, resvBase: 3.234, resvNm2: 5.021, unit: "GiB" },
|
||||||
|
quote: "这个代价来自 Qwen 查询编码、稀疏路由、证据前缀和热点缓存,而不是免费获得的能力。"
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- 容量与存储 ---------- */
|
||||||
|
capacity: {
|
||||||
|
title: "容量与存储",
|
||||||
|
src: "对外技术总结 §4",
|
||||||
|
stats: [
|
||||||
|
{ k: "active records", v: "723", d: "本次运行实际装载" },
|
||||||
|
{ k: "pages", v: "23", d: "页容量 32 records/page" },
|
||||||
|
{ k: "设计容量", v: "1,048,576", d: "地址空间容量,非已装入数量" },
|
||||||
|
{ k: "GPU cache 上限", v: "256 records", d: "且 131,072 token" },
|
||||||
|
{ k: "实际 GPU cache token", v: "15,885", d: "" },
|
||||||
|
{ k: "GPU cache fallback", v: "0", d: "分配失败 0" },
|
||||||
|
{ k: "cold page", v: "0", d: "本次为 embedded / process-RAM 模式" }
|
||||||
|
],
|
||||||
|
storage: {
|
||||||
|
mode: "embedded weight-shard",
|
||||||
|
text: "记忆快照、路由器参数、页面元数据和短文本证据写入模型包的 memory safetensors 切片。启动时加载到进程内存,命中的热点记录才进入有界 GPU cache。",
|
||||||
|
tradeoff: "当前默认路径不使用 SQLite,也不使用磁盘分页。该设计减少了运行时依赖,但意味着模型包会随持久化记忆增长而变大,且需要重新保存权重切片才能固化更新。"
|
||||||
|
},
|
||||||
|
grid: { pagesTotal: 32768, perPage: 32, usedPages: 23 }
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- 记忆路由器工程线 ---------- */
|
||||||
|
router: {
|
||||||
|
title: "记忆路由器工程线",
|
||||||
|
src: "PRODUCTION_ROUTER.md · router_scorecard_final.md · V6_FINAL_REPORT.md · ZERO_OVERLAP_FINDINGS.md · WRITE_PATH_FIX.md",
|
||||||
|
subtitle: "128 维路由器替换原 512 维方案。以下为工程报告中的实测值。",
|
||||||
|
spec: [
|
||||||
|
{ k: "参数量", v: "2,037,774" },
|
||||||
|
{ k: "张量数", v: "16 (float32)" },
|
||||||
|
{ k: "地址字节", v: "512 B" },
|
||||||
|
{ k: "结构", v: "dim=128 · heads=8 · hidden=2560 · max_hops=3" },
|
||||||
|
{ k: "权重摘要", v: "sha256 69f8295e…d189deb · 8,156,921 B" },
|
||||||
|
{ k: "冻结评测集", v: "21,920 episode / 10 类" }
|
||||||
|
],
|
||||||
|
metrics: [
|
||||||
|
{ k: "Top-1 命中", base: "41.12%", nm2: "94.14%", note: "REPLAY-128" },
|
||||||
|
{ k: "Recall@1 / @3 / @5", base: "37.03 / 46.73 / 48.91", nm2: "88.58 / 96.48 / 97.15", note: "" },
|
||||||
|
{ k: "MRR / nDCG@3", base: "47.69 / 44.22", nm2: "95.77 / 95.37", note: "" },
|
||||||
|
{ k: "多跳证据全中 (Top-3)", base: "43.43%", nm2: "96.22%", note: "" },
|
||||||
|
{ k: "hop 正确率", base: "73.23%", nm2: "100.00%", note: "欠预测率 4.68% → 0.00%" },
|
||||||
|
{ k: "未知拒答率", base: "0.00%", nm2: "100.00%", note: "门槛 0.30–0.80 每点均为 100%" },
|
||||||
|
{ k: "单查询延迟", base: "1.0995 ms", nm2: "0.9663 ms", note: "路由 QPS 909.5 → 1034.8" },
|
||||||
|
{ k: "batch256 吞吐", base: "207,287", nm2: "242,759", note: "texts/s 口径" },
|
||||||
|
{ k: "零重叠改写 Top-1", base: "18.40%", nm2: "59.60%", note: "+41.20pp,随机基线 4.17%" },
|
||||||
|
{ k: "写入路径存活记录", base: "12/20", nm2: "20/20", note: "retract 16 → 0;e2e 37.50% → 68.75%" },
|
||||||
|
{ k: "逐轴判定", base: "—", nm2: "99 通过 / 11 未通过", note: "128 维两条线 22/22 全方位超越" }
|
||||||
|
],
|
||||||
|
caveats: [
|
||||||
|
"端到端答案不由路由器决定:93.75% 的读取仍走旧版 16 槽注入路径,地址命中 0/16,记录级排序由 text_retriever 决定(其 Top-1 仅 23.20%)。路由器 +41.20pp 不传递到最终答案。",
|
||||||
|
"512 维方案「全部指标不劣于基线」在数学上不可达(地址存储 ×4 与 batch-256 吞吐两条独立障碍);XL 架构准确率最高,但吞吐真实低 26–52%。",
|
||||||
|
"拒答机制只在域内成立:跨域 A 段可回答 0.00%,集成门已回退为 gate=false;开放词表属性匹配仅 49.20% / AUC 0.6560。",
|
||||||
|
"属性头词表固定 24 类闭集:训练后新写入的属性会被判为 NONE 而误拒。",
|
||||||
|
"同一指标在多份报告中的延迟口径不一致(1.0995→0.9663、0.9549→0.9169 等),本页只列其中一套。",
|
||||||
|
"长上下文:8K 可跑,16K / 32K OOM。不得据此宣称百万级 token 上下文。"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- 边界:不能宣称的内容 ---------- */
|
||||||
|
limits: {
|
||||||
|
title: "我们不宣称的内容",
|
||||||
|
subtitle: "以下说法目前没有足够证据支持。把它们放在这里,是因为它们和上面的数字一样重要。",
|
||||||
|
claims: [
|
||||||
|
"Natural Memory 已经等价于百万 token 的完整 KV",
|
||||||
|
"Natural Memory 已经击败生产级 embedding + reranker RAG",
|
||||||
|
"任何自然语言表达都能稳定召回正确记忆",
|
||||||
|
"记忆写入永远不会出错",
|
||||||
|
"一百万条记录已经完成端到端验证",
|
||||||
|
"当前 4B 结果可以直接外推到 14B、32B 或更大模型",
|
||||||
|
"reserved VRAM 就是实际模型峰值显存",
|
||||||
|
"本次用户事实测试代表大规模真实用户群体"
|
||||||
|
],
|
||||||
|
limitations: [
|
||||||
|
{ t: "训练数据仍不够自然", d: "路由器主体训练仍来自本地构造的实体—属性—值事实和 hard negatives。自然改写仍是人工编写的测试变体,不是大规模脱敏真人会话。" },
|
||||||
|
{ t: "真实仓库的语义索引覆盖有限", d: "620 个真实分片全部进库,但为控制 GPU 压力,只有 96 个符号目标和 8 个操作性事实建立了 Qwen 语义地址。这不等于整个仓库都被高质量索引。" },
|
||||||
|
{ t: "开放式解释弱于明确定位", d: "「某个函数在哪个文件」明显好于「结合多个文件解释系统为什么这样设计」。后者需要多跳证据合并,仍会出现证据已召回但回答不完整。" },
|
||||||
|
{ t: "速度仍有真实代价", d: "平均延迟高约 2.58%,解码速度低约 9.90%,输入前缀显著变长。" },
|
||||||
|
{ t: "生产级基线还不完整", d: "本次对照聚焦原版 Qwen 无记忆基线;要作服务经济学结论,还需加入强 embedding 检索器、cross-encoder、滑动窗口和分页 KV。" }
|
||||||
|
],
|
||||||
|
quotes: [
|
||||||
|
{ q: "Memory Slot 不模拟完整 KV。它只接管 KV 中最昂贵、最适合长期保存、最容易重复利用的部分。", s: "README_NATURAL_MEMORY_V2.md" },
|
||||||
|
{ q: "这些限制是设计边界,不是用一个「无限上下文」数字掩盖的未验证假设。", s: "README_NATURAL_MEMORY_V2.md" },
|
||||||
|
{ q: "任何排序器都救不回一条已经不存在的记录。", s: "WRITE_PATH_FIX.md" },
|
||||||
|
{ q: "这不是调参空间不够,而是这个信号根本不存在。", s: "ABSTENTION_BREAKTHROUGH.md" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- 已解决的问题 ---------- */
|
||||||
|
solved: [
|
||||||
|
"普通自然语言触发自动记忆读取,不要求用户输入 /remember",
|
||||||
|
"模型重启后不回放历史聊天,只加载已保存的 memory shard",
|
||||||
|
"旧值和新值保留版本关系,旧值不会继续作为 active 事实参与正常读取",
|
||||||
|
"记忆读取器、地址索引和证据注入位于模型适配架构内部",
|
||||||
|
"记忆主体留在进程内存,热点记录使用有界 GPU cache",
|
||||||
|
"当前问题只读取 Top-K 记录,不对全量 slot 做注意力",
|
||||||
|
"低置信度写入、撤回和审计状态有独立表示",
|
||||||
|
"在真实工程源码定位任务上,相比无记忆 Qwen 有明显的可回答性提升"
|
||||||
|
],
|
||||||
|
|
||||||
|
/* ---------- 路线图 ---------- */
|
||||||
|
roadmap: [
|
||||||
|
"使用有用户同意的脱敏对话,增加自然省略、指代、错别字、时间间隔、互相矛盾的旧说法和多轮项目协作样本",
|
||||||
|
"重新训练路由器,重点覆盖「同一事实的多种问法」和「相似但错误的记录」",
|
||||||
|
"对「检索正确但回答错误」的样本单独训练证据使用与拒答策略",
|
||||||
|
"将真实仓库的语义地址覆盖从目标记录扩展到完整索引,仍保持单条/小批次编码以保护显存",
|
||||||
|
"加入多跳证据合并和当前版本优先规则",
|
||||||
|
"将写入、冲突解决和摘要从生成热路径移到回合边界或后台线程",
|
||||||
|
"把显存测试改为记录真正的 CUDA high-water mark,并分别报告 live allocated、reserved 和 cache payload",
|
||||||
|
"在同一协议下补齐强 RAG、滑动窗口和分页 KV 的成本—质量曲线"
|
||||||
|
],
|
||||||
|
|
||||||
|
/* ---------- 复现 ---------- */
|
||||||
|
reproduce: {
|
||||||
|
cwd: "H:\\Memory",
|
||||||
|
python: "C:\\Users\\Administrator\\miniconda3\\envs\\LLM\\python.exe",
|
||||||
|
cmd: [
|
||||||
|
"& C:\\Users\\Administrator\\miniconda3\\envs\\LLM\\python.exe `",
|
||||||
|
" -m dynamic_memory_lab.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\\dynamic_memory_lab\\dirty_real_corpus_compare_4b.json"
|
||||||
|
],
|
||||||
|
files: [
|
||||||
|
{ k: "原始结果", v: "H:\\Memory\\dynamic_memory_lab\\dirty_real_corpus_compare_4b.json" },
|
||||||
|
{ k: "评测脚本", v: "H:\\Memory\\dynamic_memory_lab\\benchmark_dirty_real_corpus_4b.py" },
|
||||||
|
{ k: "对外技术说明", v: "H:\\Memory\\dynamic_memory_lab\\Natural_Memory_v2_对外技术总结.md" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- 结论 ---------- */
|
||||||
|
conclusion:
|
||||||
|
"Natural Memory v2 当前已经不是只有构造数据上的演示:在真实工程源码、文档和本项目用户要求组成的脏数据迁移测试中," +
|
||||||
|
"它显著提高了窗口外事实的可回答性,并在 10 GiB GPU 进程上完成了 723 条 active records 的读取运行。" +
|
||||||
|
"同时,62.60% 的可回答正确率、88.89% 的未知拒答正确率和约 10% 的解码速度下降说明它仍处于研究原型到工程验证之间。"
|
||||||
|
};
|
||||||
@@ -0,0 +1,226 @@
|
|||||||
|
/* 本文件由脚本从评测原始结果逐字提取,请勿手改。
|
||||||
|
来源:H:\Memory\dynamic_memory_lab\dirty_real_corpus_compare_4b_router_final.json
|
||||||
|
创建时间:2026-09-06T11:36:26+0800 协议:greedy / max_new_tokens=64 / top_k=2 */
|
||||||
|
window.NM_EXAMPLES = [
|
||||||
|
{
|
||||||
|
"id": "user-004",
|
||||||
|
"domain": "user_dialogue",
|
||||||
|
"category": "paraphrase",
|
||||||
|
"answerable": true,
|
||||||
|
"query": "我不想翻聊天记录,当前这个记忆模型叫什么?",
|
||||||
|
"expected": "Natural Memory v1",
|
||||||
|
"expected_anchors": [
|
||||||
|
"Natural Memory v1"
|
||||||
|
],
|
||||||
|
"nm": {
|
||||||
|
"response": "当前这个记忆模型叫 **Natural Memory v1**。",
|
||||||
|
"correct": true,
|
||||||
|
"tokens": 14,
|
||||||
|
"recall": true,
|
||||||
|
"retrieved_values": [
|
||||||
|
"Natural Memory v1",
|
||||||
|
"重要信息写入,禁止胡编乱造,并学习写入、清理和总结时机"
|
||||||
|
],
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"record_id": "mem_da9418d179467fba",
|
||||||
|
"entity": "user",
|
||||||
|
"attribute": "模型名称",
|
||||||
|
"value": "Natural Memory v1",
|
||||||
|
"status": "active",
|
||||||
|
"version": 0,
|
||||||
|
"source": "user_provided_dialogue",
|
||||||
|
"text_preview": "用户给当前模型定名:Natural Memory v1。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"record_id": "mem_862617d79b828161",
|
||||||
|
"entity": "user",
|
||||||
|
"attribute": "记忆质量要求",
|
||||||
|
"value": "重要信息写入,禁止胡编乱造,并学习写入、清理和总结时机",
|
||||||
|
"status": "active",
|
||||||
|
"version": 0,
|
||||||
|
"source": "user_provided_dialogue",
|
||||||
|
"text_preview": "用户要求:重要信息都要存进去,但不能让模型胡编乱造记忆,还要学会什么时候写入和清理总结。"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"base": {
|
||||||
|
"response": "您提到的“当前这个记忆模型”具体指代什么,取决于您使用的平台或应用。如果您是在使用某个特定的 AI 助手或应用程序,那么该应用可能内置了某种形式的记忆功能,用于记住您的偏好、历史对话或其他相关信息。\n\n不过,从技术角度来看,并没有一个统一的“记忆",
|
||||||
|
"correct": false,
|
||||||
|
"tokens": 64
|
||||||
|
},
|
||||||
|
"note": "actual user-stated fact with a hand-written natural paraphrase"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "code-symbol-010-a",
|
||||||
|
"domain": "real_repository",
|
||||||
|
"category": "symbol_navigation",
|
||||||
|
"answerable": true,
|
||||||
|
"query": "我现在不想翻完整个屎山代码库,_generate_student 这个 def 定义落在哪个文件?",
|
||||||
|
"expected": "benchmark_memory_vs_full_kv.py",
|
||||||
|
"expected_anchors": [
|
||||||
|
"benchmark_memory_vs_full_kv.py",
|
||||||
|
"_generate_student"
|
||||||
|
],
|
||||||
|
"nm": {
|
||||||
|
"response": "根据已保存的长期记忆,`_generate_student` 这个函数定义落在文件 **`benchmark_memory_vs_full_kv.py`** 中(具体在第 171 行)。",
|
||||||
|
"correct": true,
|
||||||
|
"tokens": 43,
|
||||||
|
"recall": true,
|
||||||
|
"retrieved_values": [
|
||||||
|
"benchmark_memory_vs_full_kv.py",
|
||||||
|
"benchmark_compare_baselines_4b.py",
|
||||||
|
"test_restart_memory_dialogue.py"
|
||||||
|
],
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"record_id": "mem_df66c88a7e2ea9da",
|
||||||
|
"entity": "benchmark_memory_vs_full_kv.py",
|
||||||
|
"attribute": "symbol:_generate_student",
|
||||||
|
"value": "benchmark_memory_vs_full_kv.py",
|
||||||
|
"status": "active",
|
||||||
|
"version": 0,
|
||||||
|
"source": "real_repository_symbol_index",
|
||||||
|
"text_preview": "真实代码库事实:文件 benchmark_memory_vs_full_kv.py 的第 171 行定义了 def _generate_student。原始代码行:def _generate_student("
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"record_id": "mem_7fb124c563472b07",
|
||||||
|
"entity": "benchmark_compare_baselines_4b.py",
|
||||||
|
"attribute": "symbol:_base_generate",
|
||||||
|
"value": "benchmark_compare_baselines_4b.py",
|
||||||
|
"status": "active",
|
||||||
|
"version": 0,
|
||||||
|
"source": "real_repository_symbol_index",
|
||||||
|
"text_preview": "真实代码库事实:文件 benchmark_compare_baselines_4b.py 的第 116 行定义了 def _base_generate。原始代码行:def _base_generate("
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"base": {
|
||||||
|
"response": "我无法直接访问您的本地文件系统或代码库,因此无法告诉您 `_generate_student` 这个函数具体落在哪个文件中。\n\n不过,您可以尝试以下几种方法来快速定位:\n\n1. **使用 IDE 的搜索功能**:在您的代码编辑器(如 VS Code、PyCharm 等)中",
|
||||||
|
"correct": false,
|
||||||
|
"tokens": 64
|
||||||
|
},
|
||||||
|
"note": "real symbol extracted from repository source"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "user-unknown-004",
|
||||||
|
"domain": "user_dialogue",
|
||||||
|
"category": "unknown_refusal",
|
||||||
|
"answerable": false,
|
||||||
|
"query": "我在这次对话里有没有说过生日?",
|
||||||
|
"expected": "",
|
||||||
|
"expected_anchors": [],
|
||||||
|
"nm": {
|
||||||
|
"response": "在这次对话中,**您还没有提到过生日**。\n\n截至目前,我们的交流内容中没有任何关于您生日、年龄或庆祝生日的提及。如果您想分享,随时可以告诉我!",
|
||||||
|
"correct": true,
|
||||||
|
"tokens": 41,
|
||||||
|
"recall": false,
|
||||||
|
"retrieved_values": [],
|
||||||
|
"records": []
|
||||||
|
},
|
||||||
|
"base": {
|
||||||
|
"response": "在这次对话中,**您还没有提到过生日**。\n\n截至目前,我们的交流内容中没有任何关于您生日、年龄或庆祝生日的提及。如果您想分享,随时可以告诉我!",
|
||||||
|
"correct": true,
|
||||||
|
"tokens": 41
|
||||||
|
},
|
||||||
|
"note": "unknown or deliberately sensitive field absent from the supplied dialogue slice"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "code-unknown-008",
|
||||||
|
"domain": "real_repository",
|
||||||
|
"category": "unknown_refusal",
|
||||||
|
"answerable": false,
|
||||||
|
"query": "请告诉我没有出现在仓库里的部署区域。",
|
||||||
|
"expected": "",
|
||||||
|
"expected_anchors": [],
|
||||||
|
"nm": {
|
||||||
|
"response": "根据您提供的长期记忆证据(特别是 `README_NATURAL_MEMORY_V2.md` 的内容),**该文档中并没有列出任何具体的“部署区域”(Deployment Regions)**。\n\n文档主要关注的是以下技术架构和逻辑,而非地理或云端的部署位置:\n\n1. **核心设计",
|
||||||
|
"correct": false,
|
||||||
|
"tokens": 64,
|
||||||
|
"recall": false,
|
||||||
|
"retrieved_values": [
|
||||||
|
"README_NATURAL_MEMORY_V2.md",
|
||||||
|
"README_NATURAL_MEMORY_V2.md"
|
||||||
|
],
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"record_id": "mem_796c6e8c86afce71",
|
||||||
|
"entity": "README_NATURAL_MEMORY_V2.md",
|
||||||
|
"attribute": "operational:1",
|
||||||
|
"value": "README_NATURAL_MEMORY_V2.md",
|
||||||
|
"status": "active",
|
||||||
|
"version": 0,
|
||||||
|
"source": "real_repository_snapshot",
|
||||||
|
"text_preview": "真实项目文件:README_NATURAL_MEMORY_V2.md\n## 核心设计\n\n### KV 与 Memory Slot 的分工\n\n```text\n最近 32K token(最多可配置到 128K) -> GPU 热 KV:保留精确顺序和局部连贯性\n长期个人事实 / 项目决策 / 纠错版本 -> Memory Slot:保存压缩、可寻址的证据\n当前问题 -> 稀疏路由:只读取少量相关记录\n```\n\nMemory Slot 不模拟完整 KV。它只接管 KV 中最昂贵、最适合长期保存、最容易重复利用的部分。这里的目标是比长 K"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"record_id": "mem_32331793e07a8a4f",
|
||||||
|
"entity": "README_NATURAL_MEMORY_V2.md",
|
||||||
|
"attribute": "operational:0",
|
||||||
|
"value": "README_NATURAL_MEMORY_V2.md",
|
||||||
|
"status": "active",
|
||||||
|
"version": 0,
|
||||||
|
"source": "real_repository_snapshot",
|
||||||
|
"text_preview": "真实项目文件:README_NATURAL_MEMORY_V2.md\n把一百万个 slot 当作一张巨大的 KV Cache,而是把历史中最适合长期保存的部分压缩成有地址的记忆记录;当前对话仍由 Qwen 的热 KV 负责连续理解。\n\n## 先看结论\n\n当前版本已经完成以下闭环:\n\n```text\n普通用户输入\n -> 自动写入策略\n -> 置信度 / 重要性 / 来源审计\n -> 紧凑地址投影\n -> 分页存储\n -> LSH 粗索引\n -> 候选页重排\n -> 候选记录精排\n -> Top-K 证据注入 Qwen\n -> 版本冲突 / "
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"base": {
|
||||||
|
"response": "您好!由于我无法访问您的仓库系统或具体业务数据,无法直接列出“未出现在仓库里的部署区域”。\n\n为了帮您准确定位,请提供以下信息:\n1. 仓库系统名称(如 GitLab、Jenkins、阿里云容器服务等)\n2. 您关注的部署区域范围",
|
||||||
|
"correct": true,
|
||||||
|
"tokens": 64
|
||||||
|
},
|
||||||
|
"note": "target deliberately absent from the real repository snapshot"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "user-009",
|
||||||
|
"domain": "user_dialogue",
|
||||||
|
"category": "constraint",
|
||||||
|
"answerable": true,
|
||||||
|
"query": "你记得我对持久化文件和分页的限制吗?",
|
||||||
|
"expected": "第三个权重文件",
|
||||||
|
"expected_anchors": [
|
||||||
|
"第三个权重文件",
|
||||||
|
"不使用 SQLite",
|
||||||
|
"不使用磁盘分页"
|
||||||
|
],
|
||||||
|
"nm": {
|
||||||
|
"response": "是的,我记住了。\n\n根据您之前的要求,关于持久化方案和分页的限制如下:\n* **持久化方案**:不使用 SQLite 或磁盘分页,所有信息完全由**第三个权重文件**储存。\n* **实体**:user\n* **属性**:记忆持久化",
|
||||||
|
"correct": false,
|
||||||
|
"tokens": 64,
|
||||||
|
"recall": true,
|
||||||
|
"retrieved_values": [
|
||||||
|
"第三个权重文件,不使用 SQLite 或磁盘分页",
|
||||||
|
"Qwen3.5 4B"
|
||||||
|
],
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"record_id": "mem_c3886345cac35147",
|
||||||
|
"entity": "user",
|
||||||
|
"attribute": "记忆持久化方案",
|
||||||
|
"value": "第三个权重文件,不使用 SQLite 或磁盘分页",
|
||||||
|
"status": "active",
|
||||||
|
"version": 0,
|
||||||
|
"source": "user_provided_dialogue",
|
||||||
|
"text_preview": "用户要求:不使用 SQLite 或磁盘分页,完全由第三个权重文件储存所有信息。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"record_id": "mem_149a0c2ab04c0f56",
|
||||||
|
"entity": "user",
|
||||||
|
"attribute": "对照模型",
|
||||||
|
"value": "Qwen3.5 4B",
|
||||||
|
"status": "active",
|
||||||
|
"version": 0,
|
||||||
|
"source": "user_provided_dialogue",
|
||||||
|
"text_preview": "用户要求和原版 qwen3.5 4b 做跑分对比,并纠正为 4B。"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"base": {
|
||||||
|
"response": "作为一个人工智能模型,我**无法访问您的个人历史对话记录、系统配置或您之前设定的具体规则**(例如具体的持久化文件大小限制、分页数量限制等)。每次对话对我来说都是全新的开始,除非您在当前的对话中明确告知我这些限制。\n\n不过,我可以帮您**重新设定",
|
||||||
|
"correct": false,
|
||||||
|
"tokens": 64
|
||||||
|
},
|
||||||
|
"note": "actual user-stated fact with a hand-written natural paraphrase"
|
||||||
|
}
|
||||||
|
];
|
||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,50 @@
|
|||||||
|
/* ==================================================================
|
||||||
|
Natural Memory v2 — nm21.js
|
||||||
|
「v2.1 之后做了什么」页面上需要交互的那部分数据。
|
||||||
|
|
||||||
|
只放剂量曲线:它们是这一轮唯一需要「拖动/悬停看数值」的东西,
|
||||||
|
其余表格都直接写在正文里并标注了来源文件,便于逐条核对。
|
||||||
|
|
||||||
|
⚠️ 数值逐字取自工程内报告,未做改写或换算:
|
||||||
|
V2_dpskw\NM2_1_FINAL.md 第 3 节(两处改动 + 剂量曲线)
|
||||||
|
V2_dpskw\record_blend_dose_response.md / prior_scale_dose_response.md 原始产物
|
||||||
|
================================================================== */
|
||||||
|
window.NM21 = {
|
||||||
|
/* 改动一:记录排序混合权重(独立进程测量,48 用例,先验保持 1.0)
|
||||||
|
此前的同进程测量因顺序污染已作废,这里用的是独立进程那一版。 */
|
||||||
|
blend: {
|
||||||
|
title: "记录排序混合权重 · 剂量曲线",
|
||||||
|
axis: "memory_record_router_blend",
|
||||||
|
xLabel: "blend 值(0 = 仅 retriever,1 = 仅路由器)",
|
||||||
|
pick: 0.5,
|
||||||
|
metrics: [
|
||||||
|
{ key: "answer", label: "可回答正确率", unit: "%", higherBetter: true,
|
||||||
|
v: [65.00, 70.00, 62.50] },
|
||||||
|
{ key: "wrong", label: "答成别的属性", unit: "%", higherBetter: false,
|
||||||
|
v: [35.00, 27.50, 37.50] },
|
||||||
|
{ key: "leak", label: "未知泄漏率", unit: "%", higherBetter: false,
|
||||||
|
v: [75.00, 75.00, 87.50] }
|
||||||
|
],
|
||||||
|
x: [0, 0.5, 1],
|
||||||
|
note: "两个打分器互补:0.50 是可回答正确率最高、答成别的属性最低的点。" +
|
||||||
|
"blend=1.00 反而全面变差,说明这不是单调关系 —— 单看某一端会得出错的结论。"
|
||||||
|
},
|
||||||
|
|
||||||
|
/* 改动二:把加法先验暴露成参数后测出来「不该动」。
|
||||||
|
这是一个有价值的负面结论:它否定了「先验压过学习打分」这条假设。 */
|
||||||
|
prior: {
|
||||||
|
title: "记录打分先验权重 · 剂量曲线",
|
||||||
|
axis: "加法先验的缩放系数",
|
||||||
|
xLabel: "先验缩放(原值为 1.00)",
|
||||||
|
pick: 1.0,
|
||||||
|
metrics: [
|
||||||
|
{ key: "answer", label: "可回答正确率", unit: "%", higherBetter: true,
|
||||||
|
v: [65.00, 47.50, 42.50, 40.00] }
|
||||||
|
],
|
||||||
|
x: [1, 0.5, 0.25, 0],
|
||||||
|
note: "调小先验只会更差(65.00 → 47.50 → 42.50 → 40.00),所以保持 1.00 不动。" +
|
||||||
|
"这条曲线的作用是排除一个假设,而不是带来增益。"
|
||||||
|
},
|
||||||
|
|
||||||
|
srcLabel: "V2_dpskw\\NM2_1_FINAL.md §3 · 原始产物 prior1_blend_{0.0,0.5,1.0}_proc.json 与 prior_scale_dose_response.json"
|
||||||
|
};
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
/* ==================================================================
|
||||||
|
Natural Memory v2 — restart.js
|
||||||
|
「重启实验」互动装置的数据层。
|
||||||
|
|
||||||
|
⚠️ 本文件的每一个数值都逐字取自工程内的原始 JSON,未做任何改写、
|
||||||
|
换算或估算。两个来源文件:
|
||||||
|
A. dynamic_memory_lab\natural_memory_v2_restart_test_v7.json (修复前)
|
||||||
|
B. dynamic_memory_lab\natural_memory_v2_restart_test_v7_final.json (修复后)
|
||||||
|
两次运行使用同一条事实、同一个问题、同一份协议,唯一差别是
|
||||||
|
「写入是否真的落库」(write_changed: false → true)。
|
||||||
|
|
||||||
|
修改此处等于修改一个「证据」页面,请先核对原始 JSON 再改。
|
||||||
|
================================================================== */
|
||||||
|
window.NM_RESTART = {
|
||||||
|
eyebrow: "Evidence · 重启实验",
|
||||||
|
h2: "把历史扔掉,它还记得吗?",
|
||||||
|
lede: "下面不是示意动画,是工程里两次真实运行的逐字回放。同一条事实、同一个问题、同一份协议;" +
|
||||||
|
"两次之间唯一的差别,是写入有没有真的落库。",
|
||||||
|
|
||||||
|
fact: "我正在开发一个长期项目,项目内部代号是NM-V2-RESTART,使用中文。",
|
||||||
|
query: "我正在开发的长期项目内部代号是什么?只回答代号。",
|
||||||
|
expected: "NM-V2-RESTART",
|
||||||
|
historyPassedToRestart: false,
|
||||||
|
|
||||||
|
/* 读取路径的四个节拍(两次运行共用同一套节拍名) */
|
||||||
|
beats: [
|
||||||
|
{ i: "01", t: "写入", s: "automatic_write: true —— 事实作为一条带地址的记录进入记忆库" },
|
||||||
|
{ i: "02", t: "重启", s: "history_passed_to_restart: false —— 重启不携带任何对话历史" },
|
||||||
|
{ i: "03", t: "召回", s: "路由器在当前问题与有界候选之间定位证据记录" },
|
||||||
|
{ i: "04", t: "作答", s: "命中的短证据作为模型内部前缀注入 Qwen,再由普通生成产出答案" }
|
||||||
|
],
|
||||||
|
|
||||||
|
variants: [
|
||||||
|
{
|
||||||
|
key: "before",
|
||||||
|
label: "修复前",
|
||||||
|
tone: "bad",
|
||||||
|
file: "natural_memory_v2_restart_test_v7.json",
|
||||||
|
/* --- 写入 --- */
|
||||||
|
writeChanged: false,
|
||||||
|
/* --- 重启后模型看到的内部状态 --- */
|
||||||
|
prefixLength: 0,
|
||||||
|
prefixUsed: false,
|
||||||
|
/* --- 路由决策 --- */
|
||||||
|
needMemory: false,
|
||||||
|
pageIds: [],
|
||||||
|
recordIds: [],
|
||||||
|
pageScores: [],
|
||||||
|
recordScores: [],
|
||||||
|
hopCount: 1,
|
||||||
|
confidence: 0.5,
|
||||||
|
stopReason: "below_read_threshold",
|
||||||
|
/* --- 生成结果 --- */
|
||||||
|
response: "Project Phoenix",
|
||||||
|
recalled: false,
|
||||||
|
correct: false,
|
||||||
|
/* --- 存储快照(before_save) --- */
|
||||||
|
store: {
|
||||||
|
records: 0, active_records: 0, pages: 0, resident_records: 0,
|
||||||
|
coarse_index_buckets: 0, gpu_cache_records: 0, gpu_cache_tokens: 0,
|
||||||
|
gpu_cache_bytes: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "after",
|
||||||
|
label: "修复后",
|
||||||
|
tone: "ok",
|
||||||
|
file: "natural_memory_v2_restart_test_v7_final.json",
|
||||||
|
writeChanged: true,
|
||||||
|
prefixLength: 45,
|
||||||
|
prefixUsed: true,
|
||||||
|
needMemory: true,
|
||||||
|
pageIds: ["page_00000001"],
|
||||||
|
recordIds: ["mem_3f5823eb77810b49"],
|
||||||
|
pageScores: [0.48235471503517796],
|
||||||
|
recordScores: [0.5923714575763567],
|
||||||
|
hopCount: 1,
|
||||||
|
confidence: 0.7961857287881784,
|
||||||
|
stopReason: "evidence_found",
|
||||||
|
response: "NM-V2-RESTART",
|
||||||
|
recalled: true,
|
||||||
|
correct: true,
|
||||||
|
store: {
|
||||||
|
records: 1, active_records: 1, pages: 1, resident_records: 1,
|
||||||
|
coarse_index_buckets: 1, gpu_cache_records: 1, gpu_cache_tokens: 45,
|
||||||
|
gpu_cache_bytes: 1429
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
/* 常量:出自同一份 JSON 的存储与预算字段(两次运行相同) */
|
||||||
|
limits: {
|
||||||
|
maxPages: 32768,
|
||||||
|
pageCapacity: 32,
|
||||||
|
capacityRecords: 1048576,
|
||||||
|
kvBudgetTokens: 32768,
|
||||||
|
kvTriggerTokens: 29491,
|
||||||
|
gpuCacheLimitRecords: 256,
|
||||||
|
gpuCacheLimitTokens: 131072,
|
||||||
|
gpuCacheReserveMB: 2048,
|
||||||
|
gpuCacheDevice: "cuda:0"
|
||||||
|
},
|
||||||
|
|
||||||
|
/* 同一个实验的另外两次运行,用于说明「不是每次都成功」 */
|
||||||
|
otherRuns: [
|
||||||
|
{ file: "natural_memory_v2_restart_test.json", date: "2026-09-04 23:16",
|
||||||
|
writeChanged: true, prefixLength: 36, recalled: true, quarantined: 2 },
|
||||||
|
{ file: "restart_memory_natural_v7.json", date: "2026-09-04 09:15",
|
||||||
|
note: "另一条事实(工作地点代号 R7)。复位 token 后 memory_norm 归零,模型随即答不出——" +
|
||||||
|
"这条记录的是「清掉记忆会怎样」的对照组。" }
|
||||||
|
],
|
||||||
|
|
||||||
|
note: "两次运行的判定字段(router_recalled_after_restart / generated_contains_expected)分别为 " +
|
||||||
|
"false / false 与 true / true。我们没有为发布页润色过任何一条模型输出,包括修复前那次编造出来的答案。"
|
||||||
|
};
|
||||||
File diff suppressed because one or more lines are too long
+1188
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,256 @@
|
|||||||
|
/* ==================================================================
|
||||||
|
Natural Memory — space.js
|
||||||
|
「地址空间下降」—— 本页的招牌机制。
|
||||||
|
|
||||||
|
机制来自题材自身的物理(motion-web: design-slop B5):这套系统的读取路径
|
||||||
|
本来就是一次寻址下降 —— 问题 → 128 维地址 → LSH 粗索引 → 候选页 →
|
||||||
|
页内重排 → Top-K → 证据前缀 → 生成。所以镜头一路下降,而不是在旁边飘粒子。
|
||||||
|
|
||||||
|
实现取 case 的**机制**、不取 case 的皮(cases/ 的照搬边界):
|
||||||
|
滚动进度从文档里读回来((scrollY - offsetTop) / 可滚动距离),不用 sticky 累加 ——
|
||||||
|
同 press-stack 的做法;原生滚动完全不动它。
|
||||||
|
|
||||||
|
全部数字都是真的:1,048,576 槽位 / 738 条活跃记录 / 730 个索引桶 /
|
||||||
|
24 页 × 页容量 32 / 最多 2 条记录 / 前缀 45 token。
|
||||||
|
================================================================== */
|
||||||
|
(function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var cv = document.getElementById("spaceCv");
|
||||||
|
if (!cv) return;
|
||||||
|
|
||||||
|
var D = window.NM_DATA;
|
||||||
|
var ctx = cv.getContext("2d");
|
||||||
|
var host = document.getElementById("hero");
|
||||||
|
var pin = cv.parentNode;
|
||||||
|
|
||||||
|
var reduce = !!(window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches);
|
||||||
|
var narrow = window.matchMedia && window.matchMedia("(max-width: 900px)").matches;
|
||||||
|
|
||||||
|
/* ---- 真实的地址空间几何 ---- */
|
||||||
|
var GEO = {
|
||||||
|
slots: 1048576, /* 地址空间设计容量 */
|
||||||
|
records: 738, /* 批次 B 实际装载的 active records */
|
||||||
|
buckets: 730, /* LSH 粗索引桶数 */
|
||||||
|
pages: 24, /* 实际使用的页数 */
|
||||||
|
pageCap: 32, /* 页容量 */
|
||||||
|
topK: 2, /* 单次读取最多记录数 */
|
||||||
|
prefix: 45 /* 注入模型内部的前缀 token 数 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ---- 可复现的伪随机(不用 Math.random:同一张图每次都一样) ---- */
|
||||||
|
function rng(seed) {
|
||||||
|
var s = seed >>> 0;
|
||||||
|
return function () {
|
||||||
|
s = (s * 1664525 + 1013904223) >>> 0;
|
||||||
|
return s / 4294967296;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var N = 128; /* 空间栅格 128×128 = 16,384 格 */
|
||||||
|
var SPACE = 1024; /* 离屏位图边长 */
|
||||||
|
var CELL = SPACE / N;
|
||||||
|
|
||||||
|
/* 738 条记录散布在 16,384 格里 —— 每格代表 64 个真实槽位 */
|
||||||
|
var lit = [];
|
||||||
|
var rand = rng(20260914);
|
||||||
|
var want = Math.round(N * N * (GEO.records / 16384)); /* ≈ 738 格 */
|
||||||
|
var seen = {};
|
||||||
|
while (lit.length < want) {
|
||||||
|
var i = Math.floor(rand() * N * N);
|
||||||
|
if (seen[i]) continue;
|
||||||
|
seen[i] = 1;
|
||||||
|
lit.push(i);
|
||||||
|
}
|
||||||
|
/* 降落的终点:其中一条记录 */
|
||||||
|
var target = lit[Math.floor(lit.length * 0.42)];
|
||||||
|
var tx = (target % N) * CELL + CELL / 2;
|
||||||
|
var ty = Math.floor(target / N) * CELL + CELL / 2;
|
||||||
|
|
||||||
|
/* ---- 离屏烘焙整张地址空间(每秒重画 16k 个点太贵,烘一次然后只做缩放着色) ---- */
|
||||||
|
var off = document.createElement("canvas");
|
||||||
|
off.width = off.height = SPACE;
|
||||||
|
(function bake() {
|
||||||
|
var g = off.getContext("2d");
|
||||||
|
g.fillStyle = "#000";
|
||||||
|
g.fillRect(0, 0, SPACE, SPACE);
|
||||||
|
/* 底噪:整个地址空间的槽位骨架 */
|
||||||
|
g.fillStyle = "rgba(255,254,244,0.10)";
|
||||||
|
for (var y = 0; y < N; y++) {
|
||||||
|
for (var x = 0; x < N; x++) {
|
||||||
|
g.fillRect(x * CELL + CELL * 0.42, y * CELL + CELL * 0.42, 0.9, 0.9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 活跃记录 */
|
||||||
|
g.fillStyle = "#fffef4";
|
||||||
|
lit.forEach(function (i) {
|
||||||
|
g.fillRect((i % N) * CELL + CELL * 0.34, Math.floor(i / N) * CELL + CELL * 0.34, 1.7, 1.7);
|
||||||
|
});
|
||||||
|
/* 目标记录:唯一一个用信号色标出的点,全页只在这里出现 */
|
||||||
|
g.fillStyle = "#00ff6a";
|
||||||
|
g.fillRect(tx - 1.6, ty - 1.6, 3.2, 3.2);
|
||||||
|
})();
|
||||||
|
|
||||||
|
/* ---- 八个环节(标签直接取自 data.js 的读取路径,单一来源) ---- */
|
||||||
|
var path = (D && D.readPath && D.readPath.length) ? D.readPath : [];
|
||||||
|
var STEPS = [
|
||||||
|
{ label: "地址空间", value: "1,048,576 槽位 · 738 条活跃记录", zoom: 1.00 },
|
||||||
|
{ label: path[0] ? path[0].label : "用户问题", value: "自然语言,不接触全量记忆", zoom: 0.62 },
|
||||||
|
{ label: path[1] ? path[1].label : "隐状态地址", value: "128 维紧凑查询地址", zoom: 0.38 },
|
||||||
|
{ label: path[2] ? path[2].label : "LSH 粗索引", value: "730 个桶,只取少量候选", zoom: 0.20 },
|
||||||
|
{ label: path[3] ? path[3].label : "候选页", value: "24 页 × 页容量 32", zoom: 0.105 },
|
||||||
|
{ label: path[4] ? path[4].label : "页内重排", value: "页内逐条打分", zoom: 0.052 },
|
||||||
|
{ label: path[5] ? path[5].label : "Top-K 记录", value: "最多 2 条", zoom: 0.026 },
|
||||||
|
{ label: path[6] ? path[6].label : "证据前缀", value: "45 token 注入模型内部", zoom: 0.014 }
|
||||||
|
];
|
||||||
|
|
||||||
|
var W = 0, H = 0, dpr = 1;
|
||||||
|
function resize() {
|
||||||
|
dpr = Math.min(window.devicePixelRatio || 1, 2);
|
||||||
|
W = pin.clientWidth;
|
||||||
|
H = pin.clientHeight;
|
||||||
|
cv.width = Math.round(W * dpr);
|
||||||
|
cv.height = Math.round(H * dpr);
|
||||||
|
cv.style.width = W + "px";
|
||||||
|
cv.style.height = H + "px";
|
||||||
|
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
||||||
|
ctx.imageSmoothingEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- t ∈ [0,1] → 画一帧 ---- */
|
||||||
|
function draw(t) {
|
||||||
|
if (!W || !H) return;
|
||||||
|
ctx.clearRect(0, 0, W, H);
|
||||||
|
ctx.fillStyle = "#000";
|
||||||
|
ctx.fillRect(0, 0, W, H);
|
||||||
|
|
||||||
|
/* 镜头窗口:从整张空间缩到 32×32(约五个数量级) */
|
||||||
|
var i = Math.min(STEPS.length - 1, Math.max(0, t * STEPS.length));
|
||||||
|
var a = STEPS[Math.floor(i)];
|
||||||
|
var b = STEPS[Math.min(STEPS.length - 1, Math.floor(i) + 1)];
|
||||||
|
var f = i - Math.floor(i);
|
||||||
|
var e = f * f * (3 - 2 * f); /* smoothstep,镜头不做生硬跳变 */
|
||||||
|
var zoom = a.zoom + (b.zoom - a.zoom) * e;
|
||||||
|
|
||||||
|
/* 保持长宽比并保证源矩形始终落在图内 */
|
||||||
|
var sw, sh;
|
||||||
|
if (W >= H) { sw = SPACE * zoom; sh = sw * (H / W); }
|
||||||
|
else { sh = SPACE * zoom; sw = sh * (W / H); }
|
||||||
|
var cx = (1 - e) * (SPACE / 2) + e * tx;
|
||||||
|
var cy = (1 - e) * (SPACE / 2) + e * ty;
|
||||||
|
var sx = Math.max(0, Math.min(SPACE - sw, cx - sw / 2));
|
||||||
|
var sy = Math.max(0, Math.min(SPACE - sh, cy - sh / 2));
|
||||||
|
|
||||||
|
ctx.globalAlpha = 1;
|
||||||
|
ctx.drawImage(off, sx, sy, sw, sh, 0, 0, W, H);
|
||||||
|
|
||||||
|
/* 下降越深,越暗:让叠加的字有安静的地面(page-design §3) */
|
||||||
|
var dim = Math.min(0.84, 0.30 + t * 0.62);
|
||||||
|
ctx.fillStyle = "rgba(0,0,0," + dim.toFixed(3) + ")";
|
||||||
|
ctx.fillRect(0, 0, W, H);
|
||||||
|
|
||||||
|
/* 越深,槽位骨架的网格线越显形 —— 空间「resolved」成结构 */
|
||||||
|
if (t > 0.30) {
|
||||||
|
var ga = Math.min(0.22, (t - 0.30) * 0.5);
|
||||||
|
ctx.strokeStyle = "rgba(255,254,244," + ga.toFixed(3) + ")";
|
||||||
|
ctx.lineWidth = 1;
|
||||||
|
var step = Math.max(18, 46 / (0.4 + t));
|
||||||
|
var ox = ((tx - sx) / sw) * W, oy = ((ty - sy) / sh) * H;
|
||||||
|
ctx.beginPath();
|
||||||
|
for (var x = ox % step; x < W; x += step) { ctx.moveTo(Math.round(x) + .5, 0); ctx.lineTo(Math.round(x) + .5, H); }
|
||||||
|
for (var y = oy % step; y < H; y += step) { ctx.moveTo(0, Math.round(y) + .5); ctx.lineTo(W, Math.round(y) + .5); }
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 终点:目标记录被圈出来(信号色,全页唯一一次) */
|
||||||
|
if (t > 0.62) {
|
||||||
|
var pa = Math.min(1, (t - 0.62) / 0.18);
|
||||||
|
var px = ((tx - sx) / sw) * W, py = ((ty - sy) / sh) * H;
|
||||||
|
var r = 10 + 26 * (1 - pa) + 8 * Math.sin(performance.now() / 620);
|
||||||
|
ctx.strokeStyle = "rgba(0,255,106," + (0.90 * pa).toFixed(3) + ")";
|
||||||
|
ctx.lineWidth = 1.25;
|
||||||
|
ctx.beginPath(); ctx.arc(px, py, r, 0, Math.PI * 2); ctx.stroke();
|
||||||
|
ctx.beginPath(); ctx.arc(px, py, r * 0.34, 0, Math.PI * 2); ctx.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- HUD:把当前环节读出来(同时是这台机器的探针面) ---- */
|
||||||
|
var hudIdx = document.getElementById("hudIdx");
|
||||||
|
var hudName = document.getElementById("hudName");
|
||||||
|
var hudVal = document.getElementById("hudVal");
|
||||||
|
var hudBar = document.getElementById("hudBar");
|
||||||
|
var lastStep = -1;
|
||||||
|
function hud(t) {
|
||||||
|
var s = Math.min(STEPS.length - 1, Math.floor(t * STEPS.length));
|
||||||
|
if (s === lastStep) return;
|
||||||
|
lastStep = s;
|
||||||
|
var st = STEPS[s];
|
||||||
|
if (hudIdx) hudIdx.textContent = String(s + 1).padStart(2, "0") + " / " + String(STEPS.length).padStart(2, "0");
|
||||||
|
if (hudName) hudName.textContent = st.label;
|
||||||
|
if (hudVal) hudVal.textContent = st.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- 一个循环:只在首屏可见时跑,不可见就停(省电,也便于量 FPS) ---- */
|
||||||
|
var t = 0, raf = 0, visible = true, lastFrame = 0;
|
||||||
|
function progress() {
|
||||||
|
var r = host.getBoundingClientRect();
|
||||||
|
var span = host.offsetHeight - pin.offsetHeight;
|
||||||
|
if (span <= 0) return 0;
|
||||||
|
return Math.max(0, Math.min(1, -r.top / span));
|
||||||
|
}
|
||||||
|
function step() {
|
||||||
|
var want = progress();
|
||||||
|
t += (want - t) * 0.12; /* 指数趋近:帧率无关的近似 */
|
||||||
|
if (Math.abs(want - t) < 0.0004) t = want;
|
||||||
|
draw(t);
|
||||||
|
hud(t);
|
||||||
|
if (hudBar) hudBar.style.width = (t * 100).toFixed(1) + "%";
|
||||||
|
lastFrame = (window.performance || Date).now();
|
||||||
|
}
|
||||||
|
function loop() { raf = 0; step(); if (visible) raf = requestAnimationFrame(loop); }
|
||||||
|
/* rAF 会被节流或冻结(后台标签页、无头虚拟时间、低端 WebView)。
|
||||||
|
只有句柄没有帧会让循环永久卡住,所以超时就同步走一帧 ——
|
||||||
|
滚动事件本身就能把画面推着走。 */
|
||||||
|
function kick() {
|
||||||
|
if (!visible) return;
|
||||||
|
var now = (window.performance || Date).now();
|
||||||
|
if (raf && now - lastFrame < 140) return;
|
||||||
|
step();
|
||||||
|
if (!raf) raf = requestAnimationFrame(loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- 静态帧:reduced-motion 与窄屏都走这里 ---- */
|
||||||
|
function still() {
|
||||||
|
document.documentElement.classList.add("space--still");
|
||||||
|
resize();
|
||||||
|
var frozen = narrow ? 0.30 : 0.52;
|
||||||
|
draw(frozen);
|
||||||
|
hud(frozen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- 探针面(verification-harness §1):能被 seek / hold,才好量 ---- */
|
||||||
|
window.__space = {
|
||||||
|
seek: function (v) { t = Math.max(0, Math.min(1, v)); draw(t); hud(t); },
|
||||||
|
hold: function () { if (raf) { cancelAnimationFrame(raf); raf = 0; } },
|
||||||
|
progress: progress,
|
||||||
|
steps: STEPS.length,
|
||||||
|
geo: GEO,
|
||||||
|
t: function () { return t; }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (reduce || narrow) {
|
||||||
|
still();
|
||||||
|
window.addEventListener("resize", function () { resize(); draw(narrow ? 0.30 : 0.52); });
|
||||||
|
} else {
|
||||||
|
resize();
|
||||||
|
if ("IntersectionObserver" in window) {
|
||||||
|
new IntersectionObserver(function (es) {
|
||||||
|
visible = es[0].isIntersecting;
|
||||||
|
if (visible) kick(); else if (raf) { cancelAnimationFrame(raf); raf = 0; }
|
||||||
|
}, { rootMargin: "120px" }).observe(host);
|
||||||
|
}
|
||||||
|
window.addEventListener("scroll", kick, { passive: true });
|
||||||
|
window.addEventListener("resize", function () { resize(); kick(); });
|
||||||
|
kick(); /* 循环常转:静止时目标点的呼吸也要活着 */
|
||||||
|
}
|
||||||
|
})();
|
||||||
@@ -0,0 +1,324 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Natural Memory v2 — 站点构建脚本
|
||||||
|
|
||||||
|
两种版式:
|
||||||
|
release —— 发布页(总览):无侧栏、全宽分段,按研究/模型发布页的通行骨架组织
|
||||||
|
docs —— 文档页(其余 9 页):左侧栏 + 窄栏正文
|
||||||
|
|
||||||
|
把 `src/pages/*.body.html` 的正文片段套进 `templates/base.html` 骨架;
|
||||||
|
正文里可用 `{{include:partials/xxx.html}}` 引入 `src/partials/` 下的共用片段。
|
||||||
|
|
||||||
|
用法:
|
||||||
|
python build.py # 生成全部页面
|
||||||
|
python build.py --check # 只校验,不写文件
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
ROOT = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
SRC = os.path.join(ROOT, "src", "pages")
|
||||||
|
PARTIALS = os.path.join(ROOT, "src", "partials")
|
||||||
|
TPL = os.path.join(ROOT, "templates", "base.html")
|
||||||
|
|
||||||
|
# slug, 序号, 中文标题, 英文小标, 分组, <title>, 摘要
|
||||||
|
PAGES = [
|
||||||
|
("index", "00", "总览", "OVERVIEW", "概览",
|
||||||
|
"Natural Memory v2 — 模型内的记忆层",
|
||||||
|
"接在本地 Qwen3.5-4B 上的模型内记忆层。模型重启后不携带历史聊天记录,仍能访问已保存的个人与项目事实,且不把全部历史转换成 GPU 上的长 KV Cache。"),
|
||||||
|
("division", "01", "记忆与 KV 的分工", "DIVISION OF LABOUR", "原理",
|
||||||
|
"记忆与 KV 的分工 — Natural Memory v2",
|
||||||
|
"为什么不是简单加长上下文:哪些东西该留在 Qwen 的热 KV 里,哪些该写入带地址的记忆记录,各自的边界在哪里。"),
|
||||||
|
("mechanism", "02", "一次读取与一次写入", "MECHANISM", "原理",
|
||||||
|
"机制:读取路径、记录结构与写入状态机 — Natural Memory v2",
|
||||||
|
"从用户问题到证据前缀注入的八个环节,记录包含哪些字段,以及 active / superseded / quarantined / retracted 四个状态如何演化。"),
|
||||||
|
("results", "03", "测量结果", "MEASUREMENTS", "证据",
|
||||||
|
"测量结果 — Natural Memory v2",
|
||||||
|
"同一 264 题题集的两个独立批次、结构化工程基准与记忆路由器工程线的全部实测数字,均标注出处与口径。"),
|
||||||
|
("nm21", "04", "NM2.1 · 之后做了什么", "WHAT CHANGED NEXT", "证据",
|
||||||
|
"NM2.1:之后做了什么 — Natural Memory v2",
|
||||||
|
"三处改动各自的测量依据、把端到端正确率锁死在 50% 的写入缺陷如何定位、75% 未知泄漏如何修到 0%,以及它接上运行时连续失败两次的完整记录。"),
|
||||||
|
("examples", "05", "实测样例", "GROUND TRUTH", "证据",
|
||||||
|
"实测样例 — Natural Memory v2",
|
||||||
|
"五条逐字取自评测原始结果的问答对照,包含两条我们判错的样例。"),
|
||||||
|
("ledger", "06", "真实评测台账", "FULL LEDGER", "证据",
|
||||||
|
"真实评测台账 — Natural Memory v2",
|
||||||
|
"全部 108 条真实评测 episode 的逐条台账:模型逐字回复、判定结果、停止原因、选中记录数与分数,可按来源与判定筛选。"),
|
||||||
|
("cost", "07", "代价账本", "COST", "工程",
|
||||||
|
"代价账本 — Natural Memory v2",
|
||||||
|
"记忆带来的延迟、解码速度、前缀长度与显存开销,以及显存快照的口径说明。"),
|
||||||
|
("capacity", "08", "容量与存储", "CAPACITY & STORAGE", "工程",
|
||||||
|
"容量与存储 — Natural Memory v2",
|
||||||
|
"地址空间、分页结构、有界 GPU cache 与嵌入式 weight-shard 持久化的实际数字与取舍。"),
|
||||||
|
("limits", "09", "我们不宣称的内容", "BOUNDARIES", "工程",
|
||||||
|
"边界:我们不宣称的内容 — Natural Memory v2",
|
||||||
|
"没有足够证据支持的八条说法、五项主要局限,以及来自工程文档的原文引用。"),
|
||||||
|
("roadmap", "10", "已解决的与下一步", "STATUS & NEXT", "工程",
|
||||||
|
"已解决的与下一步 — Natural Memory v2",
|
||||||
|
"在 12 GiB GPU 上已经跑通的闭环,以及按对正确率最有帮助的顺序排出的下一阶段任务。"),
|
||||||
|
("reproduce", "11", "复现实验", "REPRODUCE", "工程",
|
||||||
|
"复现实验 — Natural Memory v2",
|
||||||
|
"正式脏数据迁移测试的完整命令、协议参数与产物路径。"),
|
||||||
|
]
|
||||||
|
|
||||||
|
AUTHOR_SITE = "https://wpyw.site"
|
||||||
|
AUTHOR_MAIL = "[email protected]"
|
||||||
|
|
||||||
|
# 每页的头号数字。文档页的页眉由一个**真实数字**领起,而不是只有标题:
|
||||||
|
# 这些页面本来就是「证据页」,让它自己先把最强的那条数字说出来。
|
||||||
|
# 顺带承担移动端的字阶落差 —— 中文标题在 320px 上推不到 7×,数字可以。
|
||||||
|
KEYS = {
|
||||||
|
"division": ("441.19", "tok", "批次 B 平均输入前缀 token"),
|
||||||
|
"mechanism": ("1,048,576", "", "地址空间设计容量"),
|
||||||
|
"results": ("82.52", "%", "批次 B 可回答正确率 · 批次 A 为 62.60%,两批配置不同、不可合并"),
|
||||||
|
"nm21": ("94.14", "%", "路由器 Top-1(v2 为 41.12%)"),
|
||||||
|
"examples": ("5", "", "逐字原文,其中 2 条是我们主动放进去的判错样例"),
|
||||||
|
"ledger": ("108", "", "条真实评测 episode,含全部失败"),
|
||||||
|
"cost": ("26.35", "ms", "读取路径额外耗时(批次 B;批次 A 为 61.10 ms)"),
|
||||||
|
"capacity": ("512", "B", "每条记录地址字节 · 100 万条约 512 MB"),
|
||||||
|
"limits": ("75.00", "%", "跨域未知泄漏率 —— 仍未解决,覆盖门已回退"),
|
||||||
|
"roadmap": ("52", "", "项单元测试通过"),
|
||||||
|
"reproduce": ("264", "", "题题集 · 246 可回答 / 18 未知"),
|
||||||
|
}
|
||||||
|
|
||||||
|
GROUP_ORDER = ["概览", "原理", "证据", "工程"]
|
||||||
|
RELEASE_SLUG = "index" # 这一页用发布页版式,其余用文档版式
|
||||||
|
|
||||||
|
|
||||||
|
def asset_version() -> str:
|
||||||
|
"""assets 静态资源的短指纹:内容一变 URL 就变,浏览器不会再用到旧资源。"""
|
||||||
|
h = hashlib.md5()
|
||||||
|
files = []
|
||||||
|
for sub in ("css", "js"):
|
||||||
|
d = os.path.join(ROOT, "assets", sub)
|
||||||
|
if os.path.isdir(d):
|
||||||
|
files += [os.path.join(d, f) for f in sorted(os.listdir(d)) if f.endswith((".css", ".js"))]
|
||||||
|
for p in files:
|
||||||
|
with open(p, "rb") as fh:
|
||||||
|
h.update(fh.read())
|
||||||
|
return h.hexdigest()[:10]
|
||||||
|
|
||||||
|
|
||||||
|
def expand_includes(text: str) -> str:
|
||||||
|
"""把 {{include:partials/x.svg}} 展开成 src/partials/x.svg 的内容。"""
|
||||||
|
def repl(m):
|
||||||
|
rel = m.group(1).strip().lstrip("/")
|
||||||
|
p = os.path.join(ROOT, "src", rel)
|
||||||
|
if not os.path.isfile(p):
|
||||||
|
sys.stderr.write("[警告] 找不到 include: %s\n" % rel)
|
||||||
|
return "<!-- include missing: %s -->" % rel
|
||||||
|
with open(p, "r", encoding="utf-8") as fh:
|
||||||
|
return fh.read().rstrip()
|
||||||
|
return re.sub(r"\{\{include:([^}]+)\}\}", repl, text)
|
||||||
|
|
||||||
|
|
||||||
|
def href_for(slug: str) -> str:
|
||||||
|
return "./" if slug == RELEASE_SLUG else "./%s" % slug
|
||||||
|
|
||||||
|
|
||||||
|
def render_sidebar(active: str) -> str:
|
||||||
|
out = ['<a class="side__back" href="./">← 返回发布页</a>']
|
||||||
|
for group in GROUP_ORDER:
|
||||||
|
items = [p for p in PAGES if p[4] == group and p[0] != RELEASE_SLUG]
|
||||||
|
if not items:
|
||||||
|
continue
|
||||||
|
out.append('<p class="side__grp">%s</p>' % group)
|
||||||
|
out.append('<ul class="side__list">')
|
||||||
|
for slug, num, zh, en, _g, _t, _d in items:
|
||||||
|
cls = "side__a is-on" if slug == active else "side__a"
|
||||||
|
cur = ' aria-current="page"' if slug == active else ""
|
||||||
|
out.append('<li><a class="%s" href="%s"%s><span class="side__n">%s</span>'
|
||||||
|
'<span class="side__t">%s</span></a></li>' % (cls, href_for(slug), cur, num, zh))
|
||||||
|
out.append("</ul>")
|
||||||
|
return "\n".join(out)
|
||||||
|
|
||||||
|
|
||||||
|
def render_prevnext(active: str) -> str:
|
||||||
|
"""上一节 / 下一节:只在文档页出现,且把发布页作为首尾的邻页。"""
|
||||||
|
if active == RELEASE_SLUG:
|
||||||
|
return ""
|
||||||
|
order = [p[0] for p in PAGES]
|
||||||
|
idx = order.index(active)
|
||||||
|
prev_p = PAGES[idx - 1] if idx > 0 else None
|
||||||
|
next_p = PAGES[idx + 1] if idx < len(PAGES) - 1 else None
|
||||||
|
|
||||||
|
def link(p, direction):
|
||||||
|
if not p:
|
||||||
|
return '<span class="pn__x"></span>'
|
||||||
|
slug, num, zh = p[0], p[1], p[2]
|
||||||
|
label = "上一节" if direction == "prev" else "下一节"
|
||||||
|
kbd = "←" if direction == "prev" else "→"
|
||||||
|
return ('<a class="pn__a pn__a--%s" href="%s" data-dir="%s">'
|
||||||
|
'<span class="pn__k">%s · %s</span><span class="pn__t">%s</span>'
|
||||||
|
'<span class="kbd">%s</span></a>' % (direction, href_for(slug), direction, label, num, zh, kbd))
|
||||||
|
|
||||||
|
return '<nav class="pn" aria-label="章节切换">%s%s</nav>' % (link(prev_p, "prev"), link(next_p, "next"))
|
||||||
|
|
||||||
|
|
||||||
|
def render_topnav(active: str) -> str:
|
||||||
|
"""顶栏快速导航:发布页与文档页共用,当前页高亮。"""
|
||||||
|
items = [
|
||||||
|
("index", "发布页"),
|
||||||
|
("mechanism", "机制"),
|
||||||
|
("results", "测量"),
|
||||||
|
("nm21", "NM2.1"),
|
||||||
|
("ledger", "台账"),
|
||||||
|
("limits", "边界"),
|
||||||
|
("reproduce", "复现"),
|
||||||
|
]
|
||||||
|
out = []
|
||||||
|
for slug, label in items:
|
||||||
|
cls = "topnav__a is-on" if slug == active else "topnav__a"
|
||||||
|
cur = ' aria-current="page"' if slug == active else ""
|
||||||
|
out.append('<a class="%s" href="%s"%s>%s</a>' % (cls, href_for(slug), cur, label))
|
||||||
|
return " ".join(out)
|
||||||
|
|
||||||
|
|
||||||
|
def render_main(slug: str, num: str, zh: str, en: str, desc: str, content: str) -> str:
|
||||||
|
if slug == RELEASE_SLUG:
|
||||||
|
# 发布页:无侧栏,全宽分段
|
||||||
|
return ('<main class="release" id="doc">\n%s\n</main>' % content)
|
||||||
|
fig = ""
|
||||||
|
if slug in KEYS:
|
||||||
|
k, unit, note = KEYS[slug]
|
||||||
|
fig = (' <p class="doc__figure">\n'
|
||||||
|
' <span class="mega">%s<small>%s</small></span>\n'
|
||||||
|
' <span class="doc__figure-n">%s</span>\n'
|
||||||
|
' </p>\n' % (k, unit, note))
|
||||||
|
return (
|
||||||
|
'<div class="shell">\n'
|
||||||
|
' <aside class="side">\n'
|
||||||
|
' <nav class="side__in" aria-label="章节导航">\n%s\n </nav>\n'
|
||||||
|
' </aside>\n'
|
||||||
|
' <main class="doc" id="doc">\n'
|
||||||
|
' <header class="doc__hd">\n'
|
||||||
|
' <span class="kicker">%s / %s</span>\n'
|
||||||
|
' <h1 class="doc__h">%s</h1>\n'
|
||||||
|
' <p class="doc__lede">%s</p>\n%s'
|
||||||
|
' </header>\n%s\n%s\n </main>\n'
|
||||||
|
'</div>' % (render_sidebar(slug), num, en, zh, desc, fig, content, render_prevnext(slug))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_SVG_RE = re.compile(r"<svg\b.*?</svg>", re.S | re.I)
|
||||||
|
_TAG_RE = re.compile(r"<[^>]+>")
|
||||||
|
_WS_RE = re.compile(r"\s+")
|
||||||
|
_ENT = (("<", "<"), (">", ">"), ("&", "&"), (""", '"'),
|
||||||
|
("'", "'"), ("←", "←"), ("→", "→"), (" ", " "))
|
||||||
|
|
||||||
|
|
||||||
|
def _plain(html: str) -> str:
|
||||||
|
html = _SVG_RE.sub(" ", html)
|
||||||
|
html = _TAG_RE.sub(" ", html)
|
||||||
|
for a, b in _ENT:
|
||||||
|
html = html.replace(a, b)
|
||||||
|
return _WS_RE.sub(" ", html).strip()
|
||||||
|
|
||||||
|
|
||||||
|
def build_search_index() -> int:
|
||||||
|
"""把每页正文按 h2/h3 切成条目,生成顶栏命令面板用的客户端检索索引。
|
||||||
|
|
||||||
|
在 asset_version() 之前调用,这样 search.js 的内容也会进资源指纹。
|
||||||
|
"""
|
||||||
|
entries = []
|
||||||
|
for slug, num, zh, en, group, title, desc in PAGES:
|
||||||
|
body_path = os.path.join(SRC, "%s.body.html" % slug)
|
||||||
|
if not os.path.isfile(body_path):
|
||||||
|
continue
|
||||||
|
with open(body_path, "r", encoding="utf-8") as fh:
|
||||||
|
body = expand_includes(fh.read())
|
||||||
|
|
||||||
|
chunks = []
|
||||||
|
# 以 h2/h3 为锚点切段:parts = [前导, level, 标题, 正文, level, 标题, 正文, ...]
|
||||||
|
parts = re.split(r"<h([23])\b[^>]*>(.*?)</h\1>", body, flags=re.S | re.I)
|
||||||
|
if len(parts) > 1:
|
||||||
|
lead = _plain(parts[0])
|
||||||
|
if lead:
|
||||||
|
chunks.append((zh, lead))
|
||||||
|
for i in range(1, len(parts) - 1, 3):
|
||||||
|
head = _plain(parts[i + 1]) or zh
|
||||||
|
rest = _plain(parts[i + 2]) if i + 2 < len(parts) else ""
|
||||||
|
chunks.append((head, rest))
|
||||||
|
else:
|
||||||
|
chunks.append((zh, _plain(body)))
|
||||||
|
|
||||||
|
entries.append({"s": slug, "p": href_for(slug), "g": group, "n": num,
|
||||||
|
"pg": zh, "h": "", "t": desc, "d": 1})
|
||||||
|
for head, text in chunks:
|
||||||
|
entries.append({"s": slug, "p": href_for(slug), "g": group, "n": num,
|
||||||
|
"pg": zh, "h": head, "t": text[:220]})
|
||||||
|
|
||||||
|
out = os.path.join(ROOT, "assets", "js", "search.js")
|
||||||
|
with open(out, "w", encoding="utf-8", newline="\n") as fh:
|
||||||
|
fh.write("/* 由 build.py 生成:顶栏命令面板的全站检索索引。请勿手改。 */\n")
|
||||||
|
fh.write("window.NM_SEARCH = %s;\n"
|
||||||
|
% json.dumps(entries, ensure_ascii=False, separators=(",", ":")))
|
||||||
|
return len(entries)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
ap = argparse.ArgumentParser()
|
||||||
|
ap.add_argument("--check", action="store_true", help="只校验,不写文件")
|
||||||
|
args = ap.parse_args()
|
||||||
|
|
||||||
|
if not os.path.isfile(TPL):
|
||||||
|
sys.stderr.write("缺少模板 %s\n" % TPL)
|
||||||
|
return 2
|
||||||
|
with open(TPL, "r", encoding="utf-8") as fh:
|
||||||
|
base = fh.read()
|
||||||
|
|
||||||
|
n_idx = 0 if args.check else build_search_index()
|
||||||
|
av = asset_version()
|
||||||
|
missing, written = [], []
|
||||||
|
for slug, num, zh, en, group, title, desc in PAGES:
|
||||||
|
body_path = os.path.join(SRC, "%s.body.html" % slug)
|
||||||
|
if not os.path.isfile(body_path):
|
||||||
|
missing.append("src/pages/%s.body.html" % slug)
|
||||||
|
continue
|
||||||
|
with open(body_path, "r", encoding="utf-8") as fh:
|
||||||
|
body = expand_includes(fh.read()).rstrip() + "\n"
|
||||||
|
|
||||||
|
layout = "release" if slug == RELEASE_SLUG else "docs"
|
||||||
|
html = (base
|
||||||
|
.replace("{{TITLE}}", title)
|
||||||
|
.replace("{{DESC}}", desc)
|
||||||
|
.replace("{{PAGE_ID}}", slug)
|
||||||
|
.replace("{{LAYOUT}}", layout)
|
||||||
|
.replace("{{NUM}}", num)
|
||||||
|
.replace("{{ZH}}", zh)
|
||||||
|
.replace("{{EN}}", en)
|
||||||
|
.replace("{{GROUP}}", group)
|
||||||
|
.replace("{{ASSET_V}}", av)
|
||||||
|
.replace("{{TOPBAR_NAV}}", render_topnav(slug))
|
||||||
|
.replace("{{MAIN}}", render_main(slug, num, zh, en, desc, body))
|
||||||
|
.replace("{{BUILT}}", datetime.now().strftime("%Y-%m-%d %H:%M")))
|
||||||
|
left = re.findall(r"\{\{[A-Z_]+\}\}", html)
|
||||||
|
if left:
|
||||||
|
sys.stderr.write("[警告] %s 仍有未替换占位符: %s\n" % (slug, set(left)))
|
||||||
|
|
||||||
|
if not args.check:
|
||||||
|
out = os.path.join(ROOT, "index.html" if slug == RELEASE_SLUG else "%s.html" % slug)
|
||||||
|
with open(out, "w", encoding="utf-8", newline="\n") as fh:
|
||||||
|
fh.write(html)
|
||||||
|
written.append("index.html" if slug == RELEASE_SLUG else "%s.html" % slug)
|
||||||
|
|
||||||
|
if missing:
|
||||||
|
sys.stderr.write("[缺失正文片段]\n " + "\n ".join(missing) + "\n")
|
||||||
|
print("页面 %d 个%s:" % (len(written), "(校验模式,未写盘)" if args.check else ""))
|
||||||
|
for w in written:
|
||||||
|
print(" " + w)
|
||||||
|
if n_idx:
|
||||||
|
print("检索索引 %d 条 → assets/js/search.js" % n_idx)
|
||||||
|
return 1 if missing else 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
+184
@@ -0,0 +1,184 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>容量与存储 — Natural Memory v2</title>
|
||||||
|
<meta name="description" content="地址空间、分页结构、有界 GPU cache 与嵌入式 weight-shard 持久化的实际数字与取舍。">
|
||||||
|
<meta name="color-scheme" content="dark">
|
||||||
|
<meta name="theme-color" content="#0a0a0a">
|
||||||
|
<!-- 动效的初始隐藏态只在 JS 可用时生效;脚本被禁用时内容照常可见 -->
|
||||||
|
<script>document.documentElement.classList.add("js");</script>
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:title" content="容量与存储 — Natural Memory v2">
|
||||||
|
<meta property="og:description" content="地址空间、分页结构、有界 GPU cache 与嵌入式 weight-shard 持久化的实际数字与取舍。">
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<link rel="icon" href="assets/favicon.svg" type="image/svg+xml">
|
||||||
|
<link rel="apple-touch-icon" href="assets/favicon.svg">
|
||||||
|
<link rel="preload" href="assets/fonts/archivo-latin-wdth-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<link rel="preload" href="assets/fonts/geist-mono-latin-wght-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<!-- 资源带构建指纹:内容一变 URL 就变,浏览器不可能再用到旧 JS/CSS -->
|
||||||
|
<link rel="stylesheet" href="assets/css/site.css?v=a9c21ef3a8">
|
||||||
|
</head>
|
||||||
|
<body data-page="capacity" data-layout="docs">
|
||||||
|
<a class="skip" href="#doc">跳到正文</a>
|
||||||
|
|
||||||
|
<header class="site" id="site">
|
||||||
|
<div class="topbar">
|
||||||
|
<a class="brand" href="./" aria-label="Natural Memory v2 发布页">
|
||||||
|
<svg class="brand__mark" viewBox="0 0 32 32" aria-hidden="true">
|
||||||
|
<rect class="dim" x="2" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="12" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="22" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
</svg>
|
||||||
|
<span class="brand__name">Natural Memory</span>
|
||||||
|
<span class="pill pill--acc">v2</span>
|
||||||
|
</a>
|
||||||
|
<span class="crumb">
|
||||||
|
<span class="crumb__n">08</span>
|
||||||
|
<span class="crumb__t">容量与存储</span>
|
||||||
|
</span>
|
||||||
|
<span class="topbar__spacer"></span>
|
||||||
|
<nav class="topnav" aria-label="快速导航">
|
||||||
|
<a class="topnav__a" href="./">发布页</a> <a class="topnav__a" href="./mechanism">机制</a> <a class="topnav__a" href="./results">测量</a> <a class="topnav__a" href="./nm21">NM2.1</a> <a class="topnav__a" href="./ledger">台账</a> <a class="topnav__a" href="./limits">边界</a> <a class="topnav__a" href="./reproduce">复现</a>
|
||||||
|
</nav>
|
||||||
|
<button class="palbtn" id="palBtn" type="button" aria-label="检索全站内容(快捷键 /)">
|
||||||
|
<span class="palbtn__t">检索</span><span class="kbd">/</span>
|
||||||
|
</button>
|
||||||
|
<span class="pill" id="serverChip" title="本站服务端运行时读数">
|
||||||
|
<i class="dot"></i><span id="serverChipText">读取中</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="progress" id="progress"></div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<aside class="side">
|
||||||
|
<nav class="side__in" aria-label="章节导航">
|
||||||
|
<a class="side__back" href="./">← 返回发布页</a>
|
||||||
|
<p class="side__grp">原理</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./division"><span class="side__n">01</span><span class="side__t">记忆与 KV 的分工</span></a></li>
|
||||||
|
<li><a class="side__a" href="./mechanism"><span class="side__n">02</span><span class="side__t">一次读取与一次写入</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">证据</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./results"><span class="side__n">03</span><span class="side__t">测量结果</span></a></li>
|
||||||
|
<li><a class="side__a" href="./nm21"><span class="side__n">04</span><span class="side__t">NM2.1 · 之后做了什么</span></a></li>
|
||||||
|
<li><a class="side__a" href="./examples"><span class="side__n">05</span><span class="side__t">实测样例</span></a></li>
|
||||||
|
<li><a class="side__a" href="./ledger"><span class="side__n">06</span><span class="side__t">真实评测台账</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">工程</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./cost"><span class="side__n">07</span><span class="side__t">代价账本</span></a></li>
|
||||||
|
<li><a class="side__a is-on" href="./capacity" aria-current="page"><span class="side__n">08</span><span class="side__t">容量与存储</span></a></li>
|
||||||
|
<li><a class="side__a" href="./limits"><span class="side__n">09</span><span class="side__t">我们不宣称的内容</span></a></li>
|
||||||
|
<li><a class="side__a" href="./roadmap"><span class="side__n">10</span><span class="side__t">已解决的与下一步</span></a></li>
|
||||||
|
<li><a class="side__a" href="./reproduce"><span class="side__n">11</span><span class="side__t">复现实验</span></a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
|
<main class="doc" id="doc">
|
||||||
|
<header class="doc__hd">
|
||||||
|
<span class="kicker">08 / CAPACITY & STORAGE</span>
|
||||||
|
<h1 class="doc__h">容量与存储</h1>
|
||||||
|
<p class="doc__lede">地址空间、分页结构、有界 GPU cache 与嵌入式 weight-shard 持久化的实际数字与取舍。</p>
|
||||||
|
<p class="doc__figure">
|
||||||
|
<span class="mega">512<small>B</small></span>
|
||||||
|
<span class="doc__figure-n">每条记录地址字节 · 100 万条约 512 MB</span>
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
<p class="lede2">
|
||||||
|
「一百万记录容量」是<strong>地址空间和分页结构的容量</strong>,不是本次已经装入了一百万条语义记忆,
|
||||||
|
也不是一百万条记录已经通过端到端测试。这一节把容量、实际用量与存储方式分开列清楚。
|
||||||
|
</p>
|
||||||
|
<div class="grid g-2-1" >
|
||||||
|
<div class="card card--flat">
|
||||||
|
<p class="eyebrow" >PAGE MAP · 32768 PAGES × 32 SLOTS</p>
|
||||||
|
<div class="pagemap" id="pageMap" aria-hidden="true"></div>
|
||||||
|
<p class="tiny" >高亮部分为本次运行实际使用的页面(批次 A:23 页 / 723 条 active records;批次 B:24 页 / 738 条)。其余为地址空间余量。</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="cap" id="capList"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="grid g2" >
|
||||||
|
<div class="card">
|
||||||
|
<p class="eyebrow" >PERSISTENCE</p>
|
||||||
|
<h3 class="h3" id="storageMode"></h3>
|
||||||
|
<p class="small" id="storageText"></p>
|
||||||
|
</div>
|
||||||
|
<div class="card card--warn">
|
||||||
|
<p class="eyebrow" style="color:var(--warn)">TRADE-OFF</p>
|
||||||
|
<h3 class="h3" >取舍</h3>
|
||||||
|
<p class="small" id="storageTradeoff"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav class="pn" aria-label="章节切换"><a class="pn__a pn__a--prev" href="./cost" data-dir="prev"><span class="pn__k">上一节 · 07</span><span class="pn__t">代价账本</span><span class="kbd">←</span></a><a class="pn__a pn__a--next" href="./limits" data-dir="next"><span class="pn__k">下一节 · 09</span><span class="pn__t">我们不宣称的内容</span><span class="kbd">→</span></a></nav>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="wrap footer__in">
|
||||||
|
<div class="footer__col">
|
||||||
|
<p class="footer__h">作者</p>
|
||||||
|
<div class="author">
|
||||||
|
<a class="author__a" href="https://wpyw.site" target="_blank" rel="noopener">
|
||||||
|
<span class="author__k">个人网站</span><span class="author__v">wpyw.site</span>
|
||||||
|
</a>
|
||||||
|
<a class="author__a" href="mailto:[email protected]">
|
||||||
|
<span class="author__k">邮箱</span><span class="author__v">[email protected]</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">来源</p>
|
||||||
|
<div class="readout" id="footFiles"></div>
|
||||||
|
<p class="footer__h" style="margin-top:20px">服务端读数</p>
|
||||||
|
<div class="readout mono" id="footServer"><span>读取中…</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">说明</p>
|
||||||
|
<p class="footer__note" id="disclaimer"></p>
|
||||||
|
<p class="footer__meta">构建于 2026-09-16 20:39 · 所有数字取自工程内的正式报告,未做外推或估算。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<!-- 全站检索:客户端索引,无后端、无网络请求 -->
|
||||||
|
<div class="pal" id="pal" hidden>
|
||||||
|
<div class="pal__mask" id="palMask"></div>
|
||||||
|
<div class="pal__box" role="dialog" aria-modal="true" aria-label="检索全站内容">
|
||||||
|
<div class="pal__hd">
|
||||||
|
<span class="pal__ico" aria-hidden="true"></span>
|
||||||
|
<input class="pal__in" id="palInput" type="text" role="combobox" aria-expanded="true"
|
||||||
|
aria-controls="palList" autocomplete="off" spellcheck="false"
|
||||||
|
placeholder="检索全站内容:章节、数字、术语…">
|
||||||
|
<span class="kbd">Esc</span>
|
||||||
|
</div>
|
||||||
|
<div class="pal__list" id="palList" role="listbox" aria-label="检索结果"></div>
|
||||||
|
<div class="pal__ft">
|
||||||
|
<span><span class="kbd">↑</span><span class="kbd">↓</span> 选择</span>
|
||||||
|
<span><span class="kbd">↵</span> 打开</span>
|
||||||
|
<span class="pal__n mono" id="palN"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="assets/js/data.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/examples.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/restart.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/nm21.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/ledger.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/search.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/space.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/site.js?v=a9c21ef3a8"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,173 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>代价账本 — Natural Memory v2</title>
|
||||||
|
<meta name="description" content="记忆带来的延迟、解码速度、前缀长度与显存开销,以及显存快照的口径说明。">
|
||||||
|
<meta name="color-scheme" content="dark">
|
||||||
|
<meta name="theme-color" content="#0a0a0a">
|
||||||
|
<!-- 动效的初始隐藏态只在 JS 可用时生效;脚本被禁用时内容照常可见 -->
|
||||||
|
<script>document.documentElement.classList.add("js");</script>
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:title" content="代价账本 — Natural Memory v2">
|
||||||
|
<meta property="og:description" content="记忆带来的延迟、解码速度、前缀长度与显存开销,以及显存快照的口径说明。">
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<link rel="icon" href="assets/favicon.svg" type="image/svg+xml">
|
||||||
|
<link rel="apple-touch-icon" href="assets/favicon.svg">
|
||||||
|
<link rel="preload" href="assets/fonts/archivo-latin-wdth-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<link rel="preload" href="assets/fonts/geist-mono-latin-wght-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<!-- 资源带构建指纹:内容一变 URL 就变,浏览器不可能再用到旧 JS/CSS -->
|
||||||
|
<link rel="stylesheet" href="assets/css/site.css?v=a9c21ef3a8">
|
||||||
|
</head>
|
||||||
|
<body data-page="cost" data-layout="docs">
|
||||||
|
<a class="skip" href="#doc">跳到正文</a>
|
||||||
|
|
||||||
|
<header class="site" id="site">
|
||||||
|
<div class="topbar">
|
||||||
|
<a class="brand" href="./" aria-label="Natural Memory v2 发布页">
|
||||||
|
<svg class="brand__mark" viewBox="0 0 32 32" aria-hidden="true">
|
||||||
|
<rect class="dim" x="2" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="12" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="22" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
</svg>
|
||||||
|
<span class="brand__name">Natural Memory</span>
|
||||||
|
<span class="pill pill--acc">v2</span>
|
||||||
|
</a>
|
||||||
|
<span class="crumb">
|
||||||
|
<span class="crumb__n">07</span>
|
||||||
|
<span class="crumb__t">代价账本</span>
|
||||||
|
</span>
|
||||||
|
<span class="topbar__spacer"></span>
|
||||||
|
<nav class="topnav" aria-label="快速导航">
|
||||||
|
<a class="topnav__a" href="./">发布页</a> <a class="topnav__a" href="./mechanism">机制</a> <a class="topnav__a" href="./results">测量</a> <a class="topnav__a" href="./nm21">NM2.1</a> <a class="topnav__a" href="./ledger">台账</a> <a class="topnav__a" href="./limits">边界</a> <a class="topnav__a" href="./reproduce">复现</a>
|
||||||
|
</nav>
|
||||||
|
<button class="palbtn" id="palBtn" type="button" aria-label="检索全站内容(快捷键 /)">
|
||||||
|
<span class="palbtn__t">检索</span><span class="kbd">/</span>
|
||||||
|
</button>
|
||||||
|
<span class="pill" id="serverChip" title="本站服务端运行时读数">
|
||||||
|
<i class="dot"></i><span id="serverChipText">读取中</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="progress" id="progress"></div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<aside class="side">
|
||||||
|
<nav class="side__in" aria-label="章节导航">
|
||||||
|
<a class="side__back" href="./">← 返回发布页</a>
|
||||||
|
<p class="side__grp">原理</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./division"><span class="side__n">01</span><span class="side__t">记忆与 KV 的分工</span></a></li>
|
||||||
|
<li><a class="side__a" href="./mechanism"><span class="side__n">02</span><span class="side__t">一次读取与一次写入</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">证据</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./results"><span class="side__n">03</span><span class="side__t">测量结果</span></a></li>
|
||||||
|
<li><a class="side__a" href="./nm21"><span class="side__n">04</span><span class="side__t">NM2.1 · 之后做了什么</span></a></li>
|
||||||
|
<li><a class="side__a" href="./examples"><span class="side__n">05</span><span class="side__t">实测样例</span></a></li>
|
||||||
|
<li><a class="side__a" href="./ledger"><span class="side__n">06</span><span class="side__t">真实评测台账</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">工程</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a is-on" href="./cost" aria-current="page"><span class="side__n">07</span><span class="side__t">代价账本</span></a></li>
|
||||||
|
<li><a class="side__a" href="./capacity"><span class="side__n">08</span><span class="side__t">容量与存储</span></a></li>
|
||||||
|
<li><a class="side__a" href="./limits"><span class="side__n">09</span><span class="side__t">我们不宣称的内容</span></a></li>
|
||||||
|
<li><a class="side__a" href="./roadmap"><span class="side__n">10</span><span class="side__t">已解决的与下一步</span></a></li>
|
||||||
|
<li><a class="side__a" href="./reproduce"><span class="side__n">11</span><span class="side__t">复现实验</span></a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
|
<main class="doc" id="doc">
|
||||||
|
<header class="doc__hd">
|
||||||
|
<span class="kicker">07 / COST</span>
|
||||||
|
<h1 class="doc__h">代价账本</h1>
|
||||||
|
<p class="doc__lede">记忆带来的延迟、解码速度、前缀长度与显存开销,以及显存快照的口径说明。</p>
|
||||||
|
<p class="doc__figure">
|
||||||
|
<span class="mega">26.35<small>ms</small></span>
|
||||||
|
<span class="doc__figure-n">读取路径额外耗时(批次 B;批次 A 为 61.10 ms)</span>
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
<p class="lede2" id="costIntro"></p>
|
||||||
|
<div class="grid g-2-1" >
|
||||||
|
<div>
|
||||||
|
<div class="ledger" id="ledger"></div>
|
||||||
|
<p class="quote" ><q id="costQuote"></q></p>
|
||||||
|
</div>
|
||||||
|
<div class="card card--flat">
|
||||||
|
<p class="eyebrow" >VRAM · 12 GiB CARD</p>
|
||||||
|
<div class="vram" id="vram"></div>
|
||||||
|
<p class="tiny" >
|
||||||
|
allocated 与 reserved 均为每次请求结束后的快照,<strong>不是 CUDA high-water mark</strong>;
|
||||||
|
reserved 还包含 PyTorch 分配器保留的缓存。因此这里不能当作"模型峰值显存"来引用。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav class="pn" aria-label="章节切换"><a class="pn__a pn__a--prev" href="./ledger" data-dir="prev"><span class="pn__k">上一节 · 06</span><span class="pn__t">真实评测台账</span><span class="kbd">←</span></a><a class="pn__a pn__a--next" href="./capacity" data-dir="next"><span class="pn__k">下一节 · 08</span><span class="pn__t">容量与存储</span><span class="kbd">→</span></a></nav>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="wrap footer__in">
|
||||||
|
<div class="footer__col">
|
||||||
|
<p class="footer__h">作者</p>
|
||||||
|
<div class="author">
|
||||||
|
<a class="author__a" href="https://wpyw.site" target="_blank" rel="noopener">
|
||||||
|
<span class="author__k">个人网站</span><span class="author__v">wpyw.site</span>
|
||||||
|
</a>
|
||||||
|
<a class="author__a" href="mailto:[email protected]">
|
||||||
|
<span class="author__k">邮箱</span><span class="author__v">[email protected]</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">来源</p>
|
||||||
|
<div class="readout" id="footFiles"></div>
|
||||||
|
<p class="footer__h" style="margin-top:20px">服务端读数</p>
|
||||||
|
<div class="readout mono" id="footServer"><span>读取中…</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">说明</p>
|
||||||
|
<p class="footer__note" id="disclaimer"></p>
|
||||||
|
<p class="footer__meta">构建于 2026-09-16 20:39 · 所有数字取自工程内的正式报告,未做外推或估算。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<!-- 全站检索:客户端索引,无后端、无网络请求 -->
|
||||||
|
<div class="pal" id="pal" hidden>
|
||||||
|
<div class="pal__mask" id="palMask"></div>
|
||||||
|
<div class="pal__box" role="dialog" aria-modal="true" aria-label="检索全站内容">
|
||||||
|
<div class="pal__hd">
|
||||||
|
<span class="pal__ico" aria-hidden="true"></span>
|
||||||
|
<input class="pal__in" id="palInput" type="text" role="combobox" aria-expanded="true"
|
||||||
|
aria-controls="palList" autocomplete="off" spellcheck="false"
|
||||||
|
placeholder="检索全站内容:章节、数字、术语…">
|
||||||
|
<span class="kbd">Esc</span>
|
||||||
|
</div>
|
||||||
|
<div class="pal__list" id="palList" role="listbox" aria-label="检索结果"></div>
|
||||||
|
<div class="pal__ft">
|
||||||
|
<span><span class="kbd">↑</span><span class="kbd">↓</span> 选择</span>
|
||||||
|
<span><span class="kbd">↵</span> 打开</span>
|
||||||
|
<span class="pal__n mono" id="palN"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="assets/js/data.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/examples.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/restart.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/nm21.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/ledger.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/search.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/space.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/site.js?v=a9c21ef3a8"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+284
@@ -0,0 +1,284 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>记忆与 KV 的分工 — Natural Memory v2</title>
|
||||||
|
<meta name="description" content="为什么不是简单加长上下文:哪些东西该留在 Qwen 的热 KV 里,哪些该写入带地址的记忆记录,各自的边界在哪里。">
|
||||||
|
<meta name="color-scheme" content="dark">
|
||||||
|
<meta name="theme-color" content="#0a0a0a">
|
||||||
|
<!-- 动效的初始隐藏态只在 JS 可用时生效;脚本被禁用时内容照常可见 -->
|
||||||
|
<script>document.documentElement.classList.add("js");</script>
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:title" content="记忆与 KV 的分工 — Natural Memory v2">
|
||||||
|
<meta property="og:description" content="为什么不是简单加长上下文:哪些东西该留在 Qwen 的热 KV 里,哪些该写入带地址的记忆记录,各自的边界在哪里。">
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<link rel="icon" href="assets/favicon.svg" type="image/svg+xml">
|
||||||
|
<link rel="apple-touch-icon" href="assets/favicon.svg">
|
||||||
|
<link rel="preload" href="assets/fonts/archivo-latin-wdth-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<link rel="preload" href="assets/fonts/geist-mono-latin-wght-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<!-- 资源带构建指纹:内容一变 URL 就变,浏览器不可能再用到旧 JS/CSS -->
|
||||||
|
<link rel="stylesheet" href="assets/css/site.css?v=a9c21ef3a8">
|
||||||
|
</head>
|
||||||
|
<body data-page="division" data-layout="docs">
|
||||||
|
<a class="skip" href="#doc">跳到正文</a>
|
||||||
|
|
||||||
|
<header class="site" id="site">
|
||||||
|
<div class="topbar">
|
||||||
|
<a class="brand" href="./" aria-label="Natural Memory v2 发布页">
|
||||||
|
<svg class="brand__mark" viewBox="0 0 32 32" aria-hidden="true">
|
||||||
|
<rect class="dim" x="2" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="12" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="22" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
</svg>
|
||||||
|
<span class="brand__name">Natural Memory</span>
|
||||||
|
<span class="pill pill--acc">v2</span>
|
||||||
|
</a>
|
||||||
|
<span class="crumb">
|
||||||
|
<span class="crumb__n">01</span>
|
||||||
|
<span class="crumb__t">记忆与 KV 的分工</span>
|
||||||
|
</span>
|
||||||
|
<span class="topbar__spacer"></span>
|
||||||
|
<nav class="topnav" aria-label="快速导航">
|
||||||
|
<a class="topnav__a" href="./">发布页</a> <a class="topnav__a" href="./mechanism">机制</a> <a class="topnav__a" href="./results">测量</a> <a class="topnav__a" href="./nm21">NM2.1</a> <a class="topnav__a" href="./ledger">台账</a> <a class="topnav__a" href="./limits">边界</a> <a class="topnav__a" href="./reproduce">复现</a>
|
||||||
|
</nav>
|
||||||
|
<button class="palbtn" id="palBtn" type="button" aria-label="检索全站内容(快捷键 /)">
|
||||||
|
<span class="palbtn__t">检索</span><span class="kbd">/</span>
|
||||||
|
</button>
|
||||||
|
<span class="pill" id="serverChip" title="本站服务端运行时读数">
|
||||||
|
<i class="dot"></i><span id="serverChipText">读取中</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="progress" id="progress"></div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<aside class="side">
|
||||||
|
<nav class="side__in" aria-label="章节导航">
|
||||||
|
<a class="side__back" href="./">← 返回发布页</a>
|
||||||
|
<p class="side__grp">原理</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a is-on" href="./division" aria-current="page"><span class="side__n">01</span><span class="side__t">记忆与 KV 的分工</span></a></li>
|
||||||
|
<li><a class="side__a" href="./mechanism"><span class="side__n">02</span><span class="side__t">一次读取与一次写入</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">证据</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./results"><span class="side__n">03</span><span class="side__t">测量结果</span></a></li>
|
||||||
|
<li><a class="side__a" href="./nm21"><span class="side__n">04</span><span class="side__t">NM2.1 · 之后做了什么</span></a></li>
|
||||||
|
<li><a class="side__a" href="./examples"><span class="side__n">05</span><span class="side__t">实测样例</span></a></li>
|
||||||
|
<li><a class="side__a" href="./ledger"><span class="side__n">06</span><span class="side__t">真实评测台账</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">工程</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./cost"><span class="side__n">07</span><span class="side__t">代价账本</span></a></li>
|
||||||
|
<li><a class="side__a" href="./capacity"><span class="side__n">08</span><span class="side__t">容量与存储</span></a></li>
|
||||||
|
<li><a class="side__a" href="./limits"><span class="side__n">09</span><span class="side__t">我们不宣称的内容</span></a></li>
|
||||||
|
<li><a class="side__a" href="./roadmap"><span class="side__n">10</span><span class="side__t">已解决的与下一步</span></a></li>
|
||||||
|
<li><a class="side__a" href="./reproduce"><span class="side__n">11</span><span class="side__t">复现实验</span></a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
|
<main class="doc" id="doc">
|
||||||
|
<header class="doc__hd">
|
||||||
|
<span class="kicker">01 / DIVISION OF LABOUR</span>
|
||||||
|
<h1 class="doc__h">记忆与 KV 的分工</h1>
|
||||||
|
<p class="doc__lede">为什么不是简单加长上下文:哪些东西该留在 Qwen 的热 KV 里,哪些该写入带地址的记忆记录,各自的边界在哪里。</p>
|
||||||
|
<p class="doc__figure">
|
||||||
|
<span class="mega">441.19<small>tok</small></span>
|
||||||
|
<span class="doc__figure-n">批次 B 平均输入前缀 token</span>
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
<p class="lede2">
|
||||||
|
这一节回答一个问题:<strong>既然模型已经有上下文窗口,为什么还要单独做一层记忆?</strong>
|
||||||
|
答案不是「窗口不够长」,而是<strong>把长期事实塞进上下文,会以线性成本换来极低的复用率</strong>。
|
||||||
|
下面把「哪些东西留在 Qwen 的热 KV 里、哪些写进记忆记录」这条分界线逐层讲清楚。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="h3" >先看没有这层记忆时会发生什么</h2>
|
||||||
|
<p class="small" style="max-width:78ch">
|
||||||
|
同一套题、同一协议下,原版 Qwen3.5-4B 在 246 道<strong>可回答</strong>题上只答对 3 道(1.22%)。
|
||||||
|
它的典型回答不是答错,而是明确表示拿不到信息:
|
||||||
|
</p>
|
||||||
|
<div class="quote" >
|
||||||
|
<q>作为一个人工智能模型,我无法访问您的个人历史对话记录、系统配置或您之前设定的具体规则……每次对话对我来说都是全新的开始。</q>
|
||||||
|
<cite>原版 Qwen3.5-4B · 评测样本 user-009 原始回答</cite>
|
||||||
|
</div>
|
||||||
|
<p class="small" style="max-width:78ch">
|
||||||
|
这句话在事实上完全正确——模型确实没有这些信息。问题出在:这些信息<strong>本来就应该被保存下来</strong>,
|
||||||
|
而它们不属于「当前这轮对话」,所以每轮都重新粘一遍历史是最笨的保存方式。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="h3" >四层分工:谁存什么、为什么</h2>
|
||||||
|
<p class="small" style="max-width:78ch">
|
||||||
|
这是整份设计里最核心的一张表。判断标准只有一条:<strong>这份信息是「这一轮才有意义」还是「跨轮次可复用」</strong>。
|
||||||
|
</p>
|
||||||
|
<div class="scrollx">
|
||||||
|
<div class="gt gt--4">
|
||||||
|
<div class="gt__h"><span>层级</span><span>存放什么</span><span>由谁负责</span><span>为什么放在这一层</span></div>
|
||||||
|
<div class="gt__r">
|
||||||
|
<span class="gt__k">最近对话</span>
|
||||||
|
<span class="gt__v">这一轮前后的原话与顺序</span>
|
||||||
|
<span class="gt__who">Qwen 热 KV</span>
|
||||||
|
<span class="gt__why">指代、省略、语气、"你刚才说的那句"都依赖严格的先后顺序。这类信息复用价值低、时效性强,放 KV 最自然。</span>
|
||||||
|
</div>
|
||||||
|
<div class="gt__r">
|
||||||
|
<span class="gt__k">长期个人 / 项目事实</span>
|
||||||
|
<span class="gt__v">事实、版本、来源、置信度、短文本证据</span>
|
||||||
|
<span class="gt__who gt__who--acc">Natural Memory 记录</span>
|
||||||
|
<span class="gt__why">跨会话反复被问到,且需要保留"哪个版本才是当前有效"的关系。它们不依赖顺序,只依赖地址与内容。</span>
|
||||||
|
</div>
|
||||||
|
<div class="gt__r">
|
||||||
|
<span class="gt__k">当前问题</span>
|
||||||
|
<span class="gt__v">由问题生成的有界读取</span>
|
||||||
|
<span class="gt__who gt__who--acc">路由 + Top-K</span>
|
||||||
|
<span class="gt__why">不是所有记忆都该被读。当前问题只与少量页面和记录交互,避免"记忆越多、噪声越大"。</span>
|
||||||
|
</div>
|
||||||
|
<div class="gt__r">
|
||||||
|
<span class="gt__k">原始持久化状态</span>
|
||||||
|
<span class="gt__v">记忆快照与索引</span>
|
||||||
|
<span class="gt__who gt__who--acc">嵌入式 memory safetensors</span>
|
||||||
|
<span class="gt__why">随模型包一起加载,运行时不需要额外数据库进程,也避免了磁盘分页带来的延迟抖动。</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="callout" >
|
||||||
|
<p class="callout__t">关键判断</p>
|
||||||
|
<p class="callout__b">
|
||||||
|
Memory Slot <strong>不试图逐 token 模拟完整 KV</strong>。它接管的是 KV 里最昂贵、最适合长期保存、
|
||||||
|
也最容易重复利用的那一部分;而当前对话的顺序关系,仍然由 Qwen 的原生上下文负责。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="h3" >分工落到数字上是什么样</h2>
|
||||||
|
<p class="small" style="max-width:78ch">
|
||||||
|
下面这组对照最能说明「不是把历史灌进去,而是把命中的少量证据灌进去」。两组数字分别来自批次 A 与批次 B(同一题集、同一协议)。
|
||||||
|
</p>
|
||||||
|
<div class="statrow">
|
||||||
|
<div class="stat">
|
||||||
|
<span class="stat__k">无记忆时的平均输入</span>
|
||||||
|
<span class="stat__v">30.75<small>token</small></span>
|
||||||
|
<span class="stat__d">批次 A 基线:只有问题本身,没有历史</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat stat--acc">
|
||||||
|
<span class="stat__k">有记忆时的平均输入</span>
|
||||||
|
<span class="stat__v">441.19<small>token</small></span>
|
||||||
|
<span class="stat__d">批次 B:命中的证据前缀(批次 A 为 641.42)</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat">
|
||||||
|
<span class="stat__k">前缀命中率</span>
|
||||||
|
<span class="stat__v">96.97<small>%</small></span>
|
||||||
|
<span class="stat__d">批次 B 实际注入证据的题目占比(批次 A 为 90.91%)</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat">
|
||||||
|
<span class="stat__k">GPU cache 实际用量</span>
|
||||||
|
<span class="stat__v">17,990<small>token</small></span>
|
||||||
|
<span class="stat__d">有界上限 131,072 token,用到约 13.7%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="small" style="max-width:78ch">
|
||||||
|
注意最后一项:<strong>上限是 131,072 token,实际只用了 17,990</strong>。
|
||||||
|
这说明读取路径被"有界"约束住了——不会因为记忆库变大就把显存吃满。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="h3" >这条分工线换来了什么、付出了什么</h2>
|
||||||
|
<div class="grid g2" >
|
||||||
|
<div class="card">
|
||||||
|
<p class="eyebrow" >换来的</p>
|
||||||
|
<div class="mini">
|
||||||
|
<div><span>可回答正确率</span><b>1.22% → 82.52%</b></div>
|
||||||
|
<div><span>目标记忆召回</span><b>0% → 92.68%</b></div>
|
||||||
|
<div><span>符号定位(192 题)</span><b>0/192 → 181/192</b></div>
|
||||||
|
<div><span>跨会话问题</span><b>1/6 → 5/6</b></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card card--warn">
|
||||||
|
<p class="eyebrow" style="color:var(--warn)">付出的</p>
|
||||||
|
<div class="mini">
|
||||||
|
<div><span>平均输入前缀</span><b>30.75 → 441.19 token</b></div>
|
||||||
|
<div><span>平均总延迟(批次 B)</span><b>2854.9 → 2878.3 ms</b></div>
|
||||||
|
<div><span>平均解码速度(批次 B)</span><b>22.34 → 20.68 tok/s</b></div>
|
||||||
|
<div><span>reserved 显存峰值</span><b>3.234 → 5.180 GiB</b></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="h3" >这条线不能推到哪里</h2>
|
||||||
|
<div class="claims claims--loose" >
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">Natural Memory 已经等价于百万 token 的完整 KV</span><span class="claim__s">UNSUPPORTED</span></div>
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">长上下文限制已被解除(实测 8K 可跑,16K / 32K OOM)</span><span class="claim__s">UNSUPPORTED</span></div>
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">设计容量 1,048,576 条记录等于已经装入并验证了这么多</span><span class="claim__s">UNSUPPORTED</span></div>
|
||||||
|
</div>
|
||||||
|
<p class="small" style="max-width:78ch">
|
||||||
|
第三条尤其要注意:<strong>1,048,576 是地址空间与分页结构的容量</strong>,
|
||||||
|
本次两个批次实际装载的是 723 / 738 条 active records,分别是 23 / 24 个页面。
|
||||||
|
容量上限与已装入量是两个概念,我们不在页面上把它们混为一谈。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<nav class="pn" aria-label="章节切换"><a class="pn__a pn__a--prev" href="./" data-dir="prev"><span class="pn__k">上一节 · 00</span><span class="pn__t">总览</span><span class="kbd">←</span></a><a class="pn__a pn__a--next" href="./mechanism" data-dir="next"><span class="pn__k">下一节 · 02</span><span class="pn__t">一次读取与一次写入</span><span class="kbd">→</span></a></nav>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="wrap footer__in">
|
||||||
|
<div class="footer__col">
|
||||||
|
<p class="footer__h">作者</p>
|
||||||
|
<div class="author">
|
||||||
|
<a class="author__a" href="https://wpyw.site" target="_blank" rel="noopener">
|
||||||
|
<span class="author__k">个人网站</span><span class="author__v">wpyw.site</span>
|
||||||
|
</a>
|
||||||
|
<a class="author__a" href="mailto:[email protected]">
|
||||||
|
<span class="author__k">邮箱</span><span class="author__v">[email protected]</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">来源</p>
|
||||||
|
<div class="readout" id="footFiles"></div>
|
||||||
|
<p class="footer__h" style="margin-top:20px">服务端读数</p>
|
||||||
|
<div class="readout mono" id="footServer"><span>读取中…</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">说明</p>
|
||||||
|
<p class="footer__note" id="disclaimer"></p>
|
||||||
|
<p class="footer__meta">构建于 2026-09-16 20:39 · 所有数字取自工程内的正式报告,未做外推或估算。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<!-- 全站检索:客户端索引,无后端、无网络请求 -->
|
||||||
|
<div class="pal" id="pal" hidden>
|
||||||
|
<div class="pal__mask" id="palMask"></div>
|
||||||
|
<div class="pal__box" role="dialog" aria-modal="true" aria-label="检索全站内容">
|
||||||
|
<div class="pal__hd">
|
||||||
|
<span class="pal__ico" aria-hidden="true"></span>
|
||||||
|
<input class="pal__in" id="palInput" type="text" role="combobox" aria-expanded="true"
|
||||||
|
aria-controls="palList" autocomplete="off" spellcheck="false"
|
||||||
|
placeholder="检索全站内容:章节、数字、术语…">
|
||||||
|
<span class="kbd">Esc</span>
|
||||||
|
</div>
|
||||||
|
<div class="pal__list" id="palList" role="listbox" aria-label="检索结果"></div>
|
||||||
|
<div class="pal__ft">
|
||||||
|
<span><span class="kbd">↑</span><span class="kbd">↓</span> 选择</span>
|
||||||
|
<span><span class="kbd">↵</span> 打开</span>
|
||||||
|
<span class="pal__n mono" id="palN"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="assets/js/data.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/examples.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/restart.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/nm21.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/ledger.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/search.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/space.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/site.js?v=a9c21ef3a8"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+161
@@ -0,0 +1,161 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>实测样例 — Natural Memory v2</title>
|
||||||
|
<meta name="description" content="五条逐字取自评测原始结果的问答对照,包含两条我们判错的样例。">
|
||||||
|
<meta name="color-scheme" content="dark">
|
||||||
|
<meta name="theme-color" content="#0a0a0a">
|
||||||
|
<!-- 动效的初始隐藏态只在 JS 可用时生效;脚本被禁用时内容照常可见 -->
|
||||||
|
<script>document.documentElement.classList.add("js");</script>
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:title" content="实测样例 — Natural Memory v2">
|
||||||
|
<meta property="og:description" content="五条逐字取自评测原始结果的问答对照,包含两条我们判错的样例。">
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<link rel="icon" href="assets/favicon.svg" type="image/svg+xml">
|
||||||
|
<link rel="apple-touch-icon" href="assets/favicon.svg">
|
||||||
|
<link rel="preload" href="assets/fonts/archivo-latin-wdth-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<link rel="preload" href="assets/fonts/geist-mono-latin-wght-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<!-- 资源带构建指纹:内容一变 URL 就变,浏览器不可能再用到旧 JS/CSS -->
|
||||||
|
<link rel="stylesheet" href="assets/css/site.css?v=a9c21ef3a8">
|
||||||
|
</head>
|
||||||
|
<body data-page="examples" data-layout="docs">
|
||||||
|
<a class="skip" href="#doc">跳到正文</a>
|
||||||
|
|
||||||
|
<header class="site" id="site">
|
||||||
|
<div class="topbar">
|
||||||
|
<a class="brand" href="./" aria-label="Natural Memory v2 发布页">
|
||||||
|
<svg class="brand__mark" viewBox="0 0 32 32" aria-hidden="true">
|
||||||
|
<rect class="dim" x="2" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="12" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="22" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
</svg>
|
||||||
|
<span class="brand__name">Natural Memory</span>
|
||||||
|
<span class="pill pill--acc">v2</span>
|
||||||
|
</a>
|
||||||
|
<span class="crumb">
|
||||||
|
<span class="crumb__n">05</span>
|
||||||
|
<span class="crumb__t">实测样例</span>
|
||||||
|
</span>
|
||||||
|
<span class="topbar__spacer"></span>
|
||||||
|
<nav class="topnav" aria-label="快速导航">
|
||||||
|
<a class="topnav__a" href="./">发布页</a> <a class="topnav__a" href="./mechanism">机制</a> <a class="topnav__a" href="./results">测量</a> <a class="topnav__a" href="./nm21">NM2.1</a> <a class="topnav__a" href="./ledger">台账</a> <a class="topnav__a" href="./limits">边界</a> <a class="topnav__a" href="./reproduce">复现</a>
|
||||||
|
</nav>
|
||||||
|
<button class="palbtn" id="palBtn" type="button" aria-label="检索全站内容(快捷键 /)">
|
||||||
|
<span class="palbtn__t">检索</span><span class="kbd">/</span>
|
||||||
|
</button>
|
||||||
|
<span class="pill" id="serverChip" title="本站服务端运行时读数">
|
||||||
|
<i class="dot"></i><span id="serverChipText">读取中</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="progress" id="progress"></div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<aside class="side">
|
||||||
|
<nav class="side__in" aria-label="章节导航">
|
||||||
|
<a class="side__back" href="./">← 返回发布页</a>
|
||||||
|
<p class="side__grp">原理</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./division"><span class="side__n">01</span><span class="side__t">记忆与 KV 的分工</span></a></li>
|
||||||
|
<li><a class="side__a" href="./mechanism"><span class="side__n">02</span><span class="side__t">一次读取与一次写入</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">证据</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./results"><span class="side__n">03</span><span class="side__t">测量结果</span></a></li>
|
||||||
|
<li><a class="side__a" href="./nm21"><span class="side__n">04</span><span class="side__t">NM2.1 · 之后做了什么</span></a></li>
|
||||||
|
<li><a class="side__a is-on" href="./examples" aria-current="page"><span class="side__n">05</span><span class="side__t">实测样例</span></a></li>
|
||||||
|
<li><a class="side__a" href="./ledger"><span class="side__n">06</span><span class="side__t">真实评测台账</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">工程</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./cost"><span class="side__n">07</span><span class="side__t">代价账本</span></a></li>
|
||||||
|
<li><a class="side__a" href="./capacity"><span class="side__n">08</span><span class="side__t">容量与存储</span></a></li>
|
||||||
|
<li><a class="side__a" href="./limits"><span class="side__n">09</span><span class="side__t">我们不宣称的内容</span></a></li>
|
||||||
|
<li><a class="side__a" href="./roadmap"><span class="side__n">10</span><span class="side__t">已解决的与下一步</span></a></li>
|
||||||
|
<li><a class="side__a" href="./reproduce"><span class="side__n">11</span><span class="side__t">复现实验</span></a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
|
<main class="doc" id="doc">
|
||||||
|
<header class="doc__hd">
|
||||||
|
<span class="kicker">05 / GROUND TRUTH</span>
|
||||||
|
<h1 class="doc__h">实测样例</h1>
|
||||||
|
<p class="doc__lede">五条逐字取自评测原始结果的问答对照,包含两条我们判错的样例。</p>
|
||||||
|
<p class="doc__figure">
|
||||||
|
<span class="mega">5<small></small></span>
|
||||||
|
<span class="doc__figure-n">逐字原文,其中 2 条是我们主动放进去的判错样例</span>
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
<p class="lede2" id="exampleIntro"></p>
|
||||||
|
<div id="exampleList" class="examples" ></div>
|
||||||
|
<p class="small" style="max-width:86ch" id="exampleNote"></p>
|
||||||
|
|
||||||
|
<nav class="pn" aria-label="章节切换"><a class="pn__a pn__a--prev" href="./nm21" data-dir="prev"><span class="pn__k">上一节 · 04</span><span class="pn__t">NM2.1 · 之后做了什么</span><span class="kbd">←</span></a><a class="pn__a pn__a--next" href="./ledger" data-dir="next"><span class="pn__k">下一节 · 06</span><span class="pn__t">真实评测台账</span><span class="kbd">→</span></a></nav>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="wrap footer__in">
|
||||||
|
<div class="footer__col">
|
||||||
|
<p class="footer__h">作者</p>
|
||||||
|
<div class="author">
|
||||||
|
<a class="author__a" href="https://wpyw.site" target="_blank" rel="noopener">
|
||||||
|
<span class="author__k">个人网站</span><span class="author__v">wpyw.site</span>
|
||||||
|
</a>
|
||||||
|
<a class="author__a" href="mailto:[email protected]">
|
||||||
|
<span class="author__k">邮箱</span><span class="author__v">[email protected]</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">来源</p>
|
||||||
|
<div class="readout" id="footFiles"></div>
|
||||||
|
<p class="footer__h" style="margin-top:20px">服务端读数</p>
|
||||||
|
<div class="readout mono" id="footServer"><span>读取中…</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">说明</p>
|
||||||
|
<p class="footer__note" id="disclaimer"></p>
|
||||||
|
<p class="footer__meta">构建于 2026-09-16 20:39 · 所有数字取自工程内的正式报告,未做外推或估算。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<!-- 全站检索:客户端索引,无后端、无网络请求 -->
|
||||||
|
<div class="pal" id="pal" hidden>
|
||||||
|
<div class="pal__mask" id="palMask"></div>
|
||||||
|
<div class="pal__box" role="dialog" aria-modal="true" aria-label="检索全站内容">
|
||||||
|
<div class="pal__hd">
|
||||||
|
<span class="pal__ico" aria-hidden="true"></span>
|
||||||
|
<input class="pal__in" id="palInput" type="text" role="combobox" aria-expanded="true"
|
||||||
|
aria-controls="palList" autocomplete="off" spellcheck="false"
|
||||||
|
placeholder="检索全站内容:章节、数字、术语…">
|
||||||
|
<span class="kbd">Esc</span>
|
||||||
|
</div>
|
||||||
|
<div class="pal__list" id="palList" role="listbox" aria-label="检索结果"></div>
|
||||||
|
<div class="pal__ft">
|
||||||
|
<span><span class="kbd">↑</span><span class="kbd">↓</span> 选择</span>
|
||||||
|
<span><span class="kbd">↵</span> 打开</span>
|
||||||
|
<span class="pal__n mono" id="palN"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="assets/js/data.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/examples.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/restart.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/nm21.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/ledger.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/search.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/space.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/site.js?v=a9c21ef3a8"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+585
@@ -0,0 +1,585 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Natural Memory v2 — 模型内的记忆层</title>
|
||||||
|
<meta name="description" content="接在本地 Qwen3.5-4B 上的模型内记忆层。模型重启后不携带历史聊天记录,仍能访问已保存的个人与项目事实,且不把全部历史转换成 GPU 上的长 KV Cache。">
|
||||||
|
<meta name="color-scheme" content="dark">
|
||||||
|
<meta name="theme-color" content="#0a0a0a">
|
||||||
|
<!-- 动效的初始隐藏态只在 JS 可用时生效;脚本被禁用时内容照常可见 -->
|
||||||
|
<script>document.documentElement.classList.add("js");</script>
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:title" content="Natural Memory v2 — 模型内的记忆层">
|
||||||
|
<meta property="og:description" content="接在本地 Qwen3.5-4B 上的模型内记忆层。模型重启后不携带历史聊天记录,仍能访问已保存的个人与项目事实,且不把全部历史转换成 GPU 上的长 KV Cache。">
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<link rel="icon" href="assets/favicon.svg" type="image/svg+xml">
|
||||||
|
<link rel="apple-touch-icon" href="assets/favicon.svg">
|
||||||
|
<link rel="preload" href="assets/fonts/archivo-latin-wdth-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<link rel="preload" href="assets/fonts/geist-mono-latin-wght-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<!-- 资源带构建指纹:内容一变 URL 就变,浏览器不可能再用到旧 JS/CSS -->
|
||||||
|
<link rel="stylesheet" href="assets/css/site.css?v=a9c21ef3a8">
|
||||||
|
</head>
|
||||||
|
<body data-page="index" data-layout="release">
|
||||||
|
<a class="skip" href="#doc">跳到正文</a>
|
||||||
|
|
||||||
|
<header class="site" id="site">
|
||||||
|
<div class="topbar">
|
||||||
|
<a class="brand" href="./" aria-label="Natural Memory v2 发布页">
|
||||||
|
<svg class="brand__mark" viewBox="0 0 32 32" aria-hidden="true">
|
||||||
|
<rect class="dim" x="2" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="12" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="22" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
</svg>
|
||||||
|
<span class="brand__name">Natural Memory</span>
|
||||||
|
<span class="pill pill--acc">v2</span>
|
||||||
|
</a>
|
||||||
|
<span class="crumb">
|
||||||
|
<span class="crumb__n">00</span>
|
||||||
|
<span class="crumb__t">总览</span>
|
||||||
|
</span>
|
||||||
|
<span class="topbar__spacer"></span>
|
||||||
|
<nav class="topnav" aria-label="快速导航">
|
||||||
|
<a class="topnav__a is-on" href="./" aria-current="page">发布页</a> <a class="topnav__a" href="./mechanism">机制</a> <a class="topnav__a" href="./results">测量</a> <a class="topnav__a" href="./nm21">NM2.1</a> <a class="topnav__a" href="./ledger">台账</a> <a class="topnav__a" href="./limits">边界</a> <a class="topnav__a" href="./reproduce">复现</a>
|
||||||
|
</nav>
|
||||||
|
<button class="palbtn" id="palBtn" type="button" aria-label="检索全站内容(快捷键 /)">
|
||||||
|
<span class="palbtn__t">检索</span><span class="kbd">/</span>
|
||||||
|
</button>
|
||||||
|
<span class="pill" id="serverChip" title="本站服务端运行时读数">
|
||||||
|
<i class="dot"></i><span id="serverChipText">读取中</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="progress" id="progress"></div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="release" id="doc">
|
||||||
|
<!-- ============ BAND 1 · 地址空间(首屏即机制,不是标题块) ============
|
||||||
|
动效概念:地址空间下降。镜头从 1,048,576 个槽位一路降到一条记录,
|
||||||
|
每个环节的数字都是真的。机制来自题材自身的物理(读取路径本来就是寻址)。 -->
|
||||||
|
<section class="hero" id="hero">
|
||||||
|
<div class="hero__pin">
|
||||||
|
<canvas class="hero__cv" id="spaceCv" aria-hidden="true"></canvas>
|
||||||
|
<div class="hero__layer">
|
||||||
|
<div class="hero__row hero__row--top">
|
||||||
|
<span class="eyebrow">Natural Memory · NM2.1</span>
|
||||||
|
<span class="eyebrow hero__geo">1,048,576 槽位 · 738 条活跃记录 · 730 个索引桶</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hero__row hero__row--mid">
|
||||||
|
<h1 class="hero__h dsp">模型重启之后,<br>它仍然记得。</h1>
|
||||||
|
<!-- 头号数字就在第一屏里:读者不需要滚三屏才知道这页在说什么 -->
|
||||||
|
<p class="hero__fig">
|
||||||
|
<span class="hero__fig-row">
|
||||||
|
<span class="hero__fig-v">1.22<small>%</small></span>
|
||||||
|
<span class="hero__fig-a" aria-hidden="true">→</span>
|
||||||
|
<span class="hero__fig-v">82.52<small>%</small></span>
|
||||||
|
</span>
|
||||||
|
<span class="hero__fig-n">同一 264 题题集的可回答正确率:无记忆基线 → 批次 B。
|
||||||
|
批次 A 为 62.60%,两批配置不同、不可合并。</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hero__row hero__row--bot">
|
||||||
|
<div class="hero__lede-wrap">
|
||||||
|
<p class="hero__lede" id="heroLede"></p>
|
||||||
|
<p class="hero__byline mono">wpyw.site · [email protected] · 本地 Qwen3.5-4B · 4-bit NF4</p>
|
||||||
|
</div>
|
||||||
|
<div class="hero__hud" role="status" aria-live="off">
|
||||||
|
<span class="hero__hud-i mono" id="hudIdx">01 / 08</span>
|
||||||
|
<span class="hero__hud-n" id="hudName">地址空间</span>
|
||||||
|
<span class="hero__hud-v mono" id="hudVal">1,048,576 槽位 · 738 条活跃记录</span>
|
||||||
|
<span class="hero__hud-track"><i id="hudBar"></i></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="hero__cue mono">向下滚动 · 走一遍读取路径</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ============ BAND 2 · 关键数字(紧贴首屏;以前这里空着一屏多) ============ -->
|
||||||
|
<section class="band band--tight">
|
||||||
|
<div class="wrap">
|
||||||
|
<p class="eyebrow band__k">Key numbers</p>
|
||||||
|
<div class="kpis reveal" id="heroKpis"></div>
|
||||||
|
<p class="src" style="display:block;margin-top:16px">出处 · <span id="heroSrc"></span></p>
|
||||||
|
<nav class="linkrow" aria-label="发布资源" style="margin-top:var(--sp-2xl)">
|
||||||
|
<a class="btn btn--pri" href="./reproduce">复现实验</a>
|
||||||
|
<a class="btn" href="./results">测量结果</a>
|
||||||
|
<a class="btn" href="./nm21">NM2.1 技术论证</a>
|
||||||
|
<a class="btn" href="./ledger">108 条真实台账</a>
|
||||||
|
<a class="btn" href="./limits">边界声明</a>
|
||||||
|
<a class="btn" href="https://wpyw.site" target="_blank" rel="noopener">作者网站 ↗</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ============ BAND 2 · 重启实验(真实运行回放装置) ============ -->
|
||||||
|
<section class="band band--alt band--rst" id="restart">
|
||||||
|
<div class="wrap">
|
||||||
|
<p class="eyebrow">Evidence · 重启实验</p>
|
||||||
|
<h2 class="h2">把历史扔掉,它还记得吗?</h2>
|
||||||
|
<p class="lede2 rst__lede">
|
||||||
|
下面不是示意动画,是工程里两次真实运行的逐字回放。同一条事实、同一个问题、同一份协议;
|
||||||
|
两次之间唯一的差别,是写入有没有真的落库。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="rst" id="rst">
|
||||||
|
<div class="rst__head">
|
||||||
|
<div class="seg" role="group" aria-label="选择运行版本">
|
||||||
|
<button class="seg__b" type="button" data-v="before">修复前</button>
|
||||||
|
<button class="seg__b is-on" type="button" data-v="after">修复后</button>
|
||||||
|
</div>
|
||||||
|
<button class="btn rst__play" type="button" id="rstPlay">重放</button>
|
||||||
|
<span class="rst__file mono" id="rstFile"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="rst__grid">
|
||||||
|
<div class="rst__aside">
|
||||||
|
<p class="rst__k">写入的事实</p>
|
||||||
|
<p class="rst__quote" id="rstFact"></p>
|
||||||
|
<p class="rst__k">重启之后问</p>
|
||||||
|
<p class="rst__quote rst__quote--q" id="rstQuery"></p>
|
||||||
|
|
||||||
|
<div class="rst__gauges">
|
||||||
|
<div class="rst__g">
|
||||||
|
<div class="rst__gt"><span>记忆库记录</span><b class="mono" id="rstRec">0</b></div>
|
||||||
|
<div class="rst__track"><span class="rst__fill rst__fill--store" id="rstRecBar"></span></div>
|
||||||
|
</div>
|
||||||
|
<div class="rst__g">
|
||||||
|
<div class="rst__gt"><span>重启时传入的历史</span><b class="mono" id="rstHist">false</b></div>
|
||||||
|
<div class="rst__track"><span class="rst__fill rst__fill--hist" id="rstHistBar"></span></div>
|
||||||
|
</div>
|
||||||
|
<div class="rst__g">
|
||||||
|
<div class="rst__gt"><span>注入模型内部的前缀</span><b class="mono" id="rstPf">0<small> tok</small></b></div>
|
||||||
|
<div class="rst__track"><span class="rst__fill rst__fill--pf" id="rstPfBar"></span></div>
|
||||||
|
<p class="rst__hint" id="rstPfHint"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ol class="rst__beats" id="rstBeats"></ol>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="rst__out" id="rstOut">
|
||||||
|
<div class="rst__outhead">
|
||||||
|
<span class="mono">模型输出 · 逐字</span>
|
||||||
|
<span class="rst__verdict mono" id="rstVerdict"></span>
|
||||||
|
</div>
|
||||||
|
<p class="rst__resp mono" id="rstResp"></p>
|
||||||
|
<div class="rst__kv" id="rstKv"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="tiny rst__note" id="rstNote"></p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ============ BAND 3 · Teaser(全宽读取路径图) ============ -->
|
||||||
|
<section class="band band--teaser">
|
||||||
|
<div class="wrap">
|
||||||
|
<figure class="teaser">
|
||||||
|
<svg class="dgm" viewBox="0 0 1120 250" role="img"
|
||||||
|
aria-label="读取路径示意:问题 → 隐状态地址 → LSH 粗索引 → 候选页 → 页内重排 → Top-K → 证据前缀 → 生成">
|
||||||
|
<!-- 连接线(pathLength=1 让描边可以按 0→1 精确绘制) -->
|
||||||
|
<g class="dgm__a">
|
||||||
|
<path pathLength="1" d="M132 78 L156 78" /><path pathLength="1" d="M270 78 L294 78" /><path pathLength="1" d="M408 78 L432 78" />
|
||||||
|
<path pathLength="1" d="M546 78 L570 78" /><path pathLength="1" d="M684 78 L708 78" /><path pathLength="1" d="M822 78 L846 78" />
|
||||||
|
<path pathLength="1" d="M960 78 L984 78" />
|
||||||
|
</g>
|
||||||
|
<!-- 8 个环节 -->
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box" x="12" y="46" width="120" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="24" y="66">01</text>
|
||||||
|
<text class="dgm__l" x="24" y="86">用户问题</text>
|
||||||
|
<text class="dgm__s" x="24" y="101">自然语言</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box" x="156" y="46" width="114" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="168" y="66">02</text>
|
||||||
|
<text class="dgm__l" x="168" y="86">隐状态地址</text>
|
||||||
|
<text class="dgm__s" x="168" y="101">Qwen hidden</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box" x="294" y="46" width="114" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="306" y="66">03</text>
|
||||||
|
<text class="dgm__l" x="306" y="86">LSH 粗索引</text>
|
||||||
|
<text class="dgm__s" x="306" y="101">730 桶</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box" x="432" y="46" width="114" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="444" y="66">04</text>
|
||||||
|
<text class="dgm__l" x="444" y="86">候选页</text>
|
||||||
|
<text class="dgm__s" x="444" y="101">≤4 页 · 32/页</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box" x="570" y="46" width="114" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="582" y="66">05</text>
|
||||||
|
<text class="dgm__l" x="582" y="86">页内重排</text>
|
||||||
|
<text class="dgm__s" x="582" y="101">text_retriever</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box dgm__box--acc" x="708" y="46" width="114" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="720" y="66">06</text>
|
||||||
|
<text class="dgm__l" x="720" y="86">Top-K 记录</text>
|
||||||
|
<text class="dgm__s" x="720" y="101">≤2 条</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box dgm__box--acc" x="846" y="46" width="114" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="858" y="66">07</text>
|
||||||
|
<text class="dgm__l" x="858" y="86">证据前缀</text>
|
||||||
|
<text class="dgm__s" x="858" y="101">注入 Qwen</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box" x="984" y="46" width="124" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="996" y="66">08</text>
|
||||||
|
<text class="dgm__l" x="996" y="86">普通生成</text>
|
||||||
|
<text class="dgm__s" x="996" y="101">回答</text>
|
||||||
|
</g>
|
||||||
|
<!-- 关键约束注释 -->
|
||||||
|
<line class="dgm__rule" x1="12" y1="146" x2="1108" y2="146"/>
|
||||||
|
<text class="dgm__note" x="12" y="172">无全量注意力</text>
|
||||||
|
<text class="dgm__s" x="1108" y="172" text-anchor="end">BOUNDED READ</text>
|
||||||
|
<text class="dgm__note" x="12" y="190">当前问题不与全部记忆记录做注意力,只与少量页面和记录交互</text>
|
||||||
|
<text class="dgm__note" x="12" y="222">读取额外耗时 61.10 ms → 26.35 ms(批次 A → B) · 前缀命中率 96.97% · GPU cache 实际 17,990 / 上限 131,072 token</text>
|
||||||
|
</svg>
|
||||||
|
<figcaption class="teaser__cap">
|
||||||
|
<span class="teaser__k">图 1 · 读取路径</span>
|
||||||
|
一次问答里记忆层做了什么。用户问题只与少量页面和记录交互,<b>全程没有对全量记忆做注意力</b>;
|
||||||
|
命中的短证据作为模型内部前缀注入 Qwen。图为示意,环节顺序与实现一致。
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ============ BAND 4 · 摘要 ============ -->
|
||||||
|
<section class="band">
|
||||||
|
<div class="wrap wrap--narrow">
|
||||||
|
<p class="eyebrow band__k">Abstract</p>
|
||||||
|
<h2 class="h2 arr-wipe">这是什么东西</h2>
|
||||||
|
<p class="lede2">
|
||||||
|
它接在本地 Qwen3.5-4B 上,是一个<strong>模型内的记忆层</strong>:把适合长期复用的个人事实、项目事实和短对话片段
|
||||||
|
写进<strong>带地址的记忆记录</strong>;当前问题只读取少量相关记录,再把这些记录作为<strong>模型内部前缀</strong>交给 Qwen 生成答案。
|
||||||
|
</p>
|
||||||
|
<p class="lede2" style="margin-top:20px">
|
||||||
|
它要解决的具体问题是:<strong>模型重启后不携带历史聊天记录,仍能访问已经保存的个人或项目事实,
|
||||||
|
同时不把全部历史转换成 GPU 上的长 KV Cache。</strong>
|
||||||
|
</p>
|
||||||
|
<p class="small" style="margin-top:24px">
|
||||||
|
当前状态:研究原型到工程验证之间。同一 264 题题集上,可回答正确率从 1.22% 提升到 62.60%(批次 A)
|
||||||
|
与 82.52%(批次 B);代价是输入前缀变长、解码速度下降约 10%。我们不在页面上把它说成通用智能,
|
||||||
|
也不把实验室结果表述成线上服务承诺。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ============ BAND 5 · 本次发布包含什么 ============ -->
|
||||||
|
<section class="band band--alt">
|
||||||
|
<div class="wrap">
|
||||||
|
<p class="eyebrow band__k">What's in this release</p>
|
||||||
|
<div class="grid g3">
|
||||||
|
<div class="card">
|
||||||
|
<p class="rel__k">记忆层与索引</p>
|
||||||
|
<p class="rel__v">738 <small>active records</small></p>
|
||||||
|
<p class="rel__d">批次 B 实际装载;24 个页面,页容量 32 条。地址空间设计容量 1,048,576。</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<p class="rel__k">记忆路由器</p>
|
||||||
|
<p class="rel__v">2,037,774 <small>参数</small></p>
|
||||||
|
<p class="rel__d">16 张量 / float32 / 512 B 地址;结构 dim=128 · heads=8 · hidden=2560 · max_hops=3。</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<p class="rel__k">有界 GPU cache</p>
|
||||||
|
<p class="rel__v">256 <small>records</small></p>
|
||||||
|
<p class="rel__d">上限 131,072 token;批次 B 实际用到 17,990 token,fallback 与分配失败均为 0。</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<p class="rel__k">评测题集</p>
|
||||||
|
<p class="rel__v">264 <small>题</small></p>
|
||||||
|
<p class="rel__d">246 可回答 / 18 未知;真实仓库 220 题 + 项目对话事实 44 题。</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<p class="rel__k">可复核性</p>
|
||||||
|
<p class="rel__v">逐字原文</p>
|
||||||
|
<p class="rel__d">样例页的问答全部取自评测原始结果、未经润色,并包含两条我们判错的样例。</p>
|
||||||
|
</div>
|
||||||
|
<div class="card card--acc">
|
||||||
|
<p class="rel__k">复现</p>
|
||||||
|
<p class="rel__v">一条命令</p>
|
||||||
|
<p class="rel__d">正式脏数据迁移测试的完整命令、协议参数与产物路径见复现页。</p>
|
||||||
|
<p style="margin:16px 0 0"><a class="btn" href="./reproduce">去复现 →</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ============ BAND 6 · 结果预览 ============ -->
|
||||||
|
<section class="band">
|
||||||
|
<div class="wrap">
|
||||||
|
<p class="eyebrow band__k">Headline result</p>
|
||||||
|
<div class="grid g-2-1">
|
||||||
|
<div class="bars" id="releaseResult">
|
||||||
|
<div class="barset">
|
||||||
|
<div class="barset__top">
|
||||||
|
<span class="barset__t">可回答正确率</span>
|
||||||
|
<span class="barset__n">同一 264 题题集 · 246 可回答</span>
|
||||||
|
</div>
|
||||||
|
<div class="bar bar--base"><span class="bar__l">原版 Qwen</span>
|
||||||
|
<span class="bar__track"><span class="bar__fill" data-fill="1.22"></span></span>
|
||||||
|
<span class="bar__v">1.22%<small>3/246</small></span></div>
|
||||||
|
<div class="bar bar--a"><span class="bar__l">批次 A</span>
|
||||||
|
<span class="bar__track"><span class="bar__fill" data-fill="62.60"></span></span>
|
||||||
|
<span class="bar__v">62.60%<small>154/246</small></span></div>
|
||||||
|
<div class="bar bar--nm2"><span class="bar__l">批次 B</span>
|
||||||
|
<span class="bar__track"><span class="bar__fill" data-fill="82.52"></span></span>
|
||||||
|
<span class="bar__v">82.52%<small>203/246</small></span></div>
|
||||||
|
</div>
|
||||||
|
<div class="legend">
|
||||||
|
<span><i class="l-base"></i>原版 Qwen3.5-4B</span>
|
||||||
|
<span><i class="l-a"></i>批次 A</span>
|
||||||
|
<span><i class="l-nm2"></i>批次 B</span>
|
||||||
|
</div>
|
||||||
|
<p class="small">
|
||||||
|
两个批次同一题集、同一协议,但配置不同,<strong>分数不可合并</strong>,只能并列读。
|
||||||
|
目标记忆召回:批次 A 67.48%、批次 B 92.68%——<strong>检索召回率不等于回答正确率</strong>。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="kv">
|
||||||
|
<div class="kv__r"><span class="kv__k">总体正确率</span><span class="kv__v">7.58% → 64.39% → 82.95%</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">符号定位</span><span class="kv__v">0/192 → 129/192 → 181/192</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">未知拒答</span><span class="kv__v">17/18 → 16/18 → 16/18</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">读取额外耗时</span><span class="kv__v">— → 61.10 → 26.35 ms</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">解码速度</span><span class="kv__v">24.06 → 21.68 → 20.68 tok/s</span></div>
|
||||||
|
</div>
|
||||||
|
<p style="margin:20px 0 0"><a class="btn" href="./results">全部测量结果 →</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ============ BAND 7 · 发布之后(NM2.1) ============ -->
|
||||||
|
<section class="band band--alt">
|
||||||
|
<div class="wrap">
|
||||||
|
<p class="eyebrow">After this release · NM2.1</p>
|
||||||
|
<h2 class="h2">发布之后又做了什么</h2>
|
||||||
|
<p class="lede2" style="margin-top:20px">
|
||||||
|
上面所有数字都来自 v2。之后的 NM2.1 换掉了记忆路由器、修掉写入路径上一个会把事实互相销毁的缺陷,
|
||||||
|
并把「问库里没有的属性时照样编答案」这个 75% 的失败修到 0%。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- 全页的头号数字;也是唯一一个用 .mega 的地方 -->
|
||||||
|
<div class="money">
|
||||||
|
<p class="eyebrow">未知拒答率 · 24 条同形候选</p>
|
||||||
|
<p class="money__row">
|
||||||
|
<span class="mega arr-num">100.00<small>%</small></span>
|
||||||
|
<span class="money__from">从 0.00% 起 —— 修好之前,模型 75% 的情况下照样编一个答案</span>
|
||||||
|
</p>
|
||||||
|
<p class="money__cap">
|
||||||
|
这是整个项目最该被引用的一个数字。它回答的不是「能不能检索到」,而是
|
||||||
|
<strong>「不知道的时候会不会不懂装懂」</strong>。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="nm21grid" style="margin-top:var(--band-tight)">
|
||||||
|
<div>
|
||||||
|
<p class="rel__k">未知拒答率 · 同形候选</p>
|
||||||
|
<p class="rel__v"><em>0.00% →</em>100.00%</p>
|
||||||
|
<p class="rel__d">问库里不存在的属性时,正确说「不知道」的比例。修好之前,模型 75% 的情况下照样编一个答案。</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="rel__k">写 20 条不同属性后存活</p>
|
||||||
|
<p class="rel__v"><em>12/20 →</em>20/20</p>
|
||||||
|
<p class="rel__d">v2 的写入路径会把 8 条<strong>无关</strong>事实互相 retract,让端到端正确率存在 50% 的硬上限——任何排序器都救不回一条已被删掉的记录。</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="rel__k">零字面重叠改写</p>
|
||||||
|
<p class="rel__v"><em>43.75% →</em>68.75%</p>
|
||||||
|
<p class="rel__d">查询与事实之间没有任何独特字重叠时的回答正确率;24 条同句式候选的随机水平是 4.17%。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid g-2-1" style="margin-top:32px">
|
||||||
|
<div>
|
||||||
|
<p class="small">
|
||||||
|
<strong>代价几乎为零:</strong>参数量 2,037,774 不变、每条记录地址 512 字节不变、模型包 8.88 GB 不变;
|
||||||
|
交错基准(7 轮,消除顺序效应)单查询延迟 1.4203 → 1.4242 ms,差 +0.28%,
|
||||||
|
<strong>小于同一轮里原版自身 4.85% 的离散度</strong>。
|
||||||
|
</p>
|
||||||
|
<p class="small">
|
||||||
|
<strong>失败也一并写出来:</strong>那套「先判属性、再查库」的机制在离线实验里是 100.00% 拒答 / 0.00% 误拒,
|
||||||
|
但接上运行时<strong>连续失败两次</strong>——第一次把可回答正确率从 100.00% 压到 6.25%;
|
||||||
|
第二次修好了目标域(泄漏真的到 0.00%、可回答无损)却让另一个域崩到 0.00%。
|
||||||
|
最终该项已回退,原因也定位到了。
|
||||||
|
</p>
|
||||||
|
<p style="margin:22px 0 0; display:flex; flex-wrap:wrap; gap:12px">
|
||||||
|
<a class="btn btn--pri" href="./nm21">完整技术论证 →</a>
|
||||||
|
<a class="btn" href="./ledger">108 条真实台账 →</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="eyebrow" style="margin-bottom:18px">路由器工件本身的提升</p>
|
||||||
|
<div class="kv">
|
||||||
|
<div class="kv__r"><span class="kv__k">Top-1 正确率</span><span class="kv__v">41.12% → 94.14%</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">Recall@3</span><span class="kv__v">46.73% → 96.48%</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">MRR</span><span class="kv__v">47.69% → 95.77%</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">hop 正确率</span><span class="kv__v">73.23% → 100.00%</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">hop 欠预测率</span><span class="kv__v">4.68% → 0.00%</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">替换兼容性</span><span class="kv__v">DROP-IN OK(16/16 键)</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">单元测试</span><span class="kv__v">52 项通过</span></div>
|
||||||
|
</div>
|
||||||
|
<p class="tiny" style="margin-top:16px">
|
||||||
|
这些是路由器工件在冻结评测集上的增益。它<strong>不会</strong>自动传递到最终答案 ——
|
||||||
|
原因见技术论证页的第十节。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ============ BAND 8 · 深入阅读 ============ -->
|
||||||
|
<section class="band">
|
||||||
|
<div class="wrap">
|
||||||
|
<p class="eyebrow band__k">Read further</p>
|
||||||
|
<div class="grid g3">
|
||||||
|
<a class="navcard" href="./division">
|
||||||
|
<span class="navcard__n">01</span>
|
||||||
|
<span class="navcard__t">记忆与 KV 的分工</span>
|
||||||
|
<span class="navcard__d">哪些留在热 KV、哪些写进记忆,判断标准与代价</span>
|
||||||
|
</a>
|
||||||
|
<a class="navcard" href="./mechanism">
|
||||||
|
<span class="navcard__n">02</span>
|
||||||
|
<span class="navcard__t">一次读取与一次写入</span>
|
||||||
|
<span class="navcard__d">八个环节、记录字段、四个状态与四个设计决定</span>
|
||||||
|
</a>
|
||||||
|
<a class="navcard" href="./nm21">
|
||||||
|
<span class="navcard__n">04</span>
|
||||||
|
<span class="navcard__t">NM2.1 · 之后做了什么</span>
|
||||||
|
<span class="navcard__d">根因、两级验证、两处改动的剂量曲线,以及两次失败的集成</span>
|
||||||
|
</a>
|
||||||
|
<a class="navcard" href="./ledger">
|
||||||
|
<span class="navcard__n">06</span>
|
||||||
|
<span class="navcard__t">真实评测台账</span>
|
||||||
|
<span class="navcard__d">108 条逐字原文,可按来源与判定筛选</span>
|
||||||
|
</a>
|
||||||
|
<a class="navcard" href="./examples">
|
||||||
|
<span class="navcard__n">05</span>
|
||||||
|
<span class="navcard__t">实测样例</span>
|
||||||
|
<span class="navcard__d">五条逐字原文,含两条我们判错的</span>
|
||||||
|
</a>
|
||||||
|
<a class="navcard" href="./cost">
|
||||||
|
<span class="navcard__n">07</span>
|
||||||
|
<span class="navcard__t">代价账本</span>
|
||||||
|
<span class="navcard__d">延迟、解码速度、前缀长度、显存</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ============ BAND 8 · 边界(正式章节,不是脚注) ============ -->
|
||||||
|
<section class="band">
|
||||||
|
<div class="wrap">
|
||||||
|
<p class="eyebrow band__k">Boundaries · 我们不宣称的内容</p>
|
||||||
|
<div class="claims claims--loose arr-cards">
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">已经等价于百万 token 的完整 KV</span></div>
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">已经击败生产级 embedding + reranker RAG</span></div>
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">任何自然语言表达都能稳定召回正确记忆</span></div>
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">记忆写入永远不会出错</span></div>
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">一百万条记录已经完成端到端验证</span></div>
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">当前 4B 结果可以直接外推到 14B、32B 或更大模型</span></div>
|
||||||
|
</div>
|
||||||
|
<p class="small" style="margin-top:24px">
|
||||||
|
完整的八条与五项主要局限见 <a href="./limits" class="linku">边界页</a>。
|
||||||
|
把它们放在发布页正面,是因为它们和上面的数字一样重要。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ============ BAND 9 · 引用 ============ -->
|
||||||
|
<section class="band band--alt">
|
||||||
|
<div class="wrap">
|
||||||
|
<p class="eyebrow band__k">Citation</p>
|
||||||
|
<div class="code">
|
||||||
|
<div class="code__bar">
|
||||||
|
<span class="code__t">BibTeX</span>
|
||||||
|
<button class="copy" id="citeCopy" type="button">复制</button>
|
||||||
|
</div>
|
||||||
|
<pre><code id="citeBlock">@misc{naturalmemoryv2,
|
||||||
|
title = {Natural Memory v2: an in-model memory layer for local LLMs},
|
||||||
|
author = {wpy},
|
||||||
|
year = {2026},
|
||||||
|
note = {Research prototype on Qwen3.5-4B. 264-question dirty-corpus
|
||||||
|
transfer test; two independent batches.},
|
||||||
|
url = {https://wpyw.site}
|
||||||
|
}</code></pre>
|
||||||
|
</div>
|
||||||
|
<p class="tiny" style="margin-top:16px">
|
||||||
|
引用时请一并注明「批次 A 与批次 B 配置不同、分数不可合并」,否则单个数字会被误读。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="wrap footer__in">
|
||||||
|
<div class="footer__col">
|
||||||
|
<p class="footer__h">作者</p>
|
||||||
|
<div class="author">
|
||||||
|
<a class="author__a" href="https://wpyw.site" target="_blank" rel="noopener">
|
||||||
|
<span class="author__k">个人网站</span><span class="author__v">wpyw.site</span>
|
||||||
|
</a>
|
||||||
|
<a class="author__a" href="mailto:[email protected]">
|
||||||
|
<span class="author__k">邮箱</span><span class="author__v">[email protected]</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">来源</p>
|
||||||
|
<div class="readout" id="footFiles"></div>
|
||||||
|
<p class="footer__h" style="margin-top:20px">服务端读数</p>
|
||||||
|
<div class="readout mono" id="footServer"><span>读取中…</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">说明</p>
|
||||||
|
<p class="footer__note" id="disclaimer"></p>
|
||||||
|
<p class="footer__meta">构建于 2026-09-16 20:39 · 所有数字取自工程内的正式报告,未做外推或估算。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<!-- 全站检索:客户端索引,无后端、无网络请求 -->
|
||||||
|
<div class="pal" id="pal" hidden>
|
||||||
|
<div class="pal__mask" id="palMask"></div>
|
||||||
|
<div class="pal__box" role="dialog" aria-modal="true" aria-label="检索全站内容">
|
||||||
|
<div class="pal__hd">
|
||||||
|
<span class="pal__ico" aria-hidden="true"></span>
|
||||||
|
<input class="pal__in" id="palInput" type="text" role="combobox" aria-expanded="true"
|
||||||
|
aria-controls="palList" autocomplete="off" spellcheck="false"
|
||||||
|
placeholder="检索全站内容:章节、数字、术语…">
|
||||||
|
<span class="kbd">Esc</span>
|
||||||
|
</div>
|
||||||
|
<div class="pal__list" id="palList" role="listbox" aria-label="检索结果"></div>
|
||||||
|
<div class="pal__ft">
|
||||||
|
<span><span class="kbd">↑</span><span class="kbd">↓</span> 选择</span>
|
||||||
|
<span><span class="kbd">↵</span> 打开</span>
|
||||||
|
<span class="pal__n mono" id="palN"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="assets/js/data.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/examples.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/restart.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/nm21.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/ledger.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/search.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/space.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/site.js?v=a9c21ef3a8"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+183
@@ -0,0 +1,183 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>真实评测台账 — Natural Memory v2</title>
|
||||||
|
<meta name="description" content="全部 108 条真实评测 episode 的逐条台账:模型逐字回复、判定结果、停止原因、选中记录数与分数,可按来源与判定筛选。">
|
||||||
|
<meta name="color-scheme" content="dark">
|
||||||
|
<meta name="theme-color" content="#0a0a0a">
|
||||||
|
<!-- 动效的初始隐藏态只在 JS 可用时生效;脚本被禁用时内容照常可见 -->
|
||||||
|
<script>document.documentElement.classList.add("js");</script>
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:title" content="真实评测台账 — Natural Memory v2">
|
||||||
|
<meta property="og:description" content="全部 108 条真实评测 episode 的逐条台账:模型逐字回复、判定结果、停止原因、选中记录数与分数,可按来源与判定筛选。">
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<link rel="icon" href="assets/favicon.svg" type="image/svg+xml">
|
||||||
|
<link rel="apple-touch-icon" href="assets/favicon.svg">
|
||||||
|
<link rel="preload" href="assets/fonts/archivo-latin-wdth-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<link rel="preload" href="assets/fonts/geist-mono-latin-wght-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<!-- 资源带构建指纹:内容一变 URL 就变,浏览器不可能再用到旧 JS/CSS -->
|
||||||
|
<link rel="stylesheet" href="assets/css/site.css?v=a9c21ef3a8">
|
||||||
|
</head>
|
||||||
|
<body data-page="ledger" data-layout="docs">
|
||||||
|
<a class="skip" href="#doc">跳到正文</a>
|
||||||
|
|
||||||
|
<header class="site" id="site">
|
||||||
|
<div class="topbar">
|
||||||
|
<a class="brand" href="./" aria-label="Natural Memory v2 发布页">
|
||||||
|
<svg class="brand__mark" viewBox="0 0 32 32" aria-hidden="true">
|
||||||
|
<rect class="dim" x="2" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="12" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="22" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
</svg>
|
||||||
|
<span class="brand__name">Natural Memory</span>
|
||||||
|
<span class="pill pill--acc">v2</span>
|
||||||
|
</a>
|
||||||
|
<span class="crumb">
|
||||||
|
<span class="crumb__n">06</span>
|
||||||
|
<span class="crumb__t">真实评测台账</span>
|
||||||
|
</span>
|
||||||
|
<span class="topbar__spacer"></span>
|
||||||
|
<nav class="topnav" aria-label="快速导航">
|
||||||
|
<a class="topnav__a" href="./">发布页</a> <a class="topnav__a" href="./mechanism">机制</a> <a class="topnav__a" href="./results">测量</a> <a class="topnav__a" href="./nm21">NM2.1</a> <a class="topnav__a is-on" href="./ledger" aria-current="page">台账</a> <a class="topnav__a" href="./limits">边界</a> <a class="topnav__a" href="./reproduce">复现</a>
|
||||||
|
</nav>
|
||||||
|
<button class="palbtn" id="palBtn" type="button" aria-label="检索全站内容(快捷键 /)">
|
||||||
|
<span class="palbtn__t">检索</span><span class="kbd">/</span>
|
||||||
|
</button>
|
||||||
|
<span class="pill" id="serverChip" title="本站服务端运行时读数">
|
||||||
|
<i class="dot"></i><span id="serverChipText">读取中</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="progress" id="progress"></div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<aside class="side">
|
||||||
|
<nav class="side__in" aria-label="章节导航">
|
||||||
|
<a class="side__back" href="./">← 返回发布页</a>
|
||||||
|
<p class="side__grp">原理</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./division"><span class="side__n">01</span><span class="side__t">记忆与 KV 的分工</span></a></li>
|
||||||
|
<li><a class="side__a" href="./mechanism"><span class="side__n">02</span><span class="side__t">一次读取与一次写入</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">证据</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./results"><span class="side__n">03</span><span class="side__t">测量结果</span></a></li>
|
||||||
|
<li><a class="side__a" href="./nm21"><span class="side__n">04</span><span class="side__t">NM2.1 · 之后做了什么</span></a></li>
|
||||||
|
<li><a class="side__a" href="./examples"><span class="side__n">05</span><span class="side__t">实测样例</span></a></li>
|
||||||
|
<li><a class="side__a is-on" href="./ledger" aria-current="page"><span class="side__n">06</span><span class="side__t">真实评测台账</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">工程</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./cost"><span class="side__n">07</span><span class="side__t">代价账本</span></a></li>
|
||||||
|
<li><a class="side__a" href="./capacity"><span class="side__n">08</span><span class="side__t">容量与存储</span></a></li>
|
||||||
|
<li><a class="side__a" href="./limits"><span class="side__n">09</span><span class="side__t">我们不宣称的内容</span></a></li>
|
||||||
|
<li><a class="side__a" href="./roadmap"><span class="side__n">10</span><span class="side__t">已解决的与下一步</span></a></li>
|
||||||
|
<li><a class="side__a" href="./reproduce"><span class="side__n">11</span><span class="side__t">复现实验</span></a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
|
<main class="doc" id="doc">
|
||||||
|
<header class="doc__hd">
|
||||||
|
<span class="kicker">06 / FULL LEDGER</span>
|
||||||
|
<h1 class="doc__h">真实评测台账</h1>
|
||||||
|
<p class="doc__lede">全部 108 条真实评测 episode 的逐条台账:模型逐字回复、判定结果、停止原因、选中记录数与分数,可按来源与判定筛选。</p>
|
||||||
|
<p class="doc__figure">
|
||||||
|
<span class="mega">108<small></small></span>
|
||||||
|
<span class="doc__figure-n">条真实评测 episode,含全部失败</span>
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
<p class="lede2">
|
||||||
|
这一页不是挑出来的样例,是<strong>全部 108 条真实评测 episode 的逐条台账</strong>。
|
||||||
|
每条都带模型的逐字回复、判定结果、停止原因、选中记录数与分数。
|
||||||
|
</p>
|
||||||
|
<p class="small" id="ledgerIntro"></p>
|
||||||
|
|
||||||
|
<div class="ledger-bar">
|
||||||
|
<div class="seg" id="ledgerSrc" role="group" aria-label="按来源筛选"></div>
|
||||||
|
<div class="seg" id="ledgerVerdict" role="group" aria-label="按判定筛选"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ledger-count">
|
||||||
|
<span class="mono" id="ledgerCount"></span>
|
||||||
|
<span class="tiny" id="ledgerBreak"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ledger" id="ledgerList"></div>
|
||||||
|
|
||||||
|
<p class="tiny" style="margin-top:var(--sp-2xl)">
|
||||||
|
数据来自 <code>runtime_score_bands.json</code> 与 <code>nm2_1_final_runtime_e2e.json</code>,
|
||||||
|
由 <code>tools/make_ledger.py</code> 生成 <code>assets/js/ledger.js</code>,
|
||||||
|
<strong>字段逐字复制,未做改写、润色或换算</strong>。模型输出里的错字、冗余和编造的内容都按原样保留。
|
||||||
|
期望锚点是评测里的随机码(形如 <code>VAL-XXXXXXX</code>),它只出现在唯一一条候选事实里,
|
||||||
|
因此可以用来检测「证据混用」。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<nav class="pn" aria-label="章节切换"><a class="pn__a pn__a--prev" href="./examples" data-dir="prev"><span class="pn__k">上一节 · 05</span><span class="pn__t">实测样例</span><span class="kbd">←</span></a><a class="pn__a pn__a--next" href="./cost" data-dir="next"><span class="pn__k">下一节 · 07</span><span class="pn__t">代价账本</span><span class="kbd">→</span></a></nav>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="wrap footer__in">
|
||||||
|
<div class="footer__col">
|
||||||
|
<p class="footer__h">作者</p>
|
||||||
|
<div class="author">
|
||||||
|
<a class="author__a" href="https://wpyw.site" target="_blank" rel="noopener">
|
||||||
|
<span class="author__k">个人网站</span><span class="author__v">wpyw.site</span>
|
||||||
|
</a>
|
||||||
|
<a class="author__a" href="mailto:[email protected]">
|
||||||
|
<span class="author__k">邮箱</span><span class="author__v">[email protected]</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">来源</p>
|
||||||
|
<div class="readout" id="footFiles"></div>
|
||||||
|
<p class="footer__h" style="margin-top:20px">服务端读数</p>
|
||||||
|
<div class="readout mono" id="footServer"><span>读取中…</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">说明</p>
|
||||||
|
<p class="footer__note" id="disclaimer"></p>
|
||||||
|
<p class="footer__meta">构建于 2026-09-16 20:39 · 所有数字取自工程内的正式报告,未做外推或估算。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<!-- 全站检索:客户端索引,无后端、无网络请求 -->
|
||||||
|
<div class="pal" id="pal" hidden>
|
||||||
|
<div class="pal__mask" id="palMask"></div>
|
||||||
|
<div class="pal__box" role="dialog" aria-modal="true" aria-label="检索全站内容">
|
||||||
|
<div class="pal__hd">
|
||||||
|
<span class="pal__ico" aria-hidden="true"></span>
|
||||||
|
<input class="pal__in" id="palInput" type="text" role="combobox" aria-expanded="true"
|
||||||
|
aria-controls="palList" autocomplete="off" spellcheck="false"
|
||||||
|
placeholder="检索全站内容:章节、数字、术语…">
|
||||||
|
<span class="kbd">Esc</span>
|
||||||
|
</div>
|
||||||
|
<div class="pal__list" id="palList" role="listbox" aria-label="检索结果"></div>
|
||||||
|
<div class="pal__ft">
|
||||||
|
<span><span class="kbd">↑</span><span class="kbd">↓</span> 选择</span>
|
||||||
|
<span><span class="kbd">↵</span> 打开</span>
|
||||||
|
<span class="pal__n mono" id="palN"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="assets/js/data.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/examples.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/restart.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/nm21.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/ledger.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/search.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/space.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/site.js?v=a9c21ef3a8"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+164
@@ -0,0 +1,164 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>边界:我们不宣称的内容 — Natural Memory v2</title>
|
||||||
|
<meta name="description" content="没有足够证据支持的八条说法、五项主要局限,以及来自工程文档的原文引用。">
|
||||||
|
<meta name="color-scheme" content="dark">
|
||||||
|
<meta name="theme-color" content="#0a0a0a">
|
||||||
|
<!-- 动效的初始隐藏态只在 JS 可用时生效;脚本被禁用时内容照常可见 -->
|
||||||
|
<script>document.documentElement.classList.add("js");</script>
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:title" content="边界:我们不宣称的内容 — Natural Memory v2">
|
||||||
|
<meta property="og:description" content="没有足够证据支持的八条说法、五项主要局限,以及来自工程文档的原文引用。">
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<link rel="icon" href="assets/favicon.svg" type="image/svg+xml">
|
||||||
|
<link rel="apple-touch-icon" href="assets/favicon.svg">
|
||||||
|
<link rel="preload" href="assets/fonts/archivo-latin-wdth-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<link rel="preload" href="assets/fonts/geist-mono-latin-wght-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<!-- 资源带构建指纹:内容一变 URL 就变,浏览器不可能再用到旧 JS/CSS -->
|
||||||
|
<link rel="stylesheet" href="assets/css/site.css?v=a9c21ef3a8">
|
||||||
|
</head>
|
||||||
|
<body data-page="limits" data-layout="docs">
|
||||||
|
<a class="skip" href="#doc">跳到正文</a>
|
||||||
|
|
||||||
|
<header class="site" id="site">
|
||||||
|
<div class="topbar">
|
||||||
|
<a class="brand" href="./" aria-label="Natural Memory v2 发布页">
|
||||||
|
<svg class="brand__mark" viewBox="0 0 32 32" aria-hidden="true">
|
||||||
|
<rect class="dim" x="2" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="12" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="22" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
</svg>
|
||||||
|
<span class="brand__name">Natural Memory</span>
|
||||||
|
<span class="pill pill--acc">v2</span>
|
||||||
|
</a>
|
||||||
|
<span class="crumb">
|
||||||
|
<span class="crumb__n">09</span>
|
||||||
|
<span class="crumb__t">我们不宣称的内容</span>
|
||||||
|
</span>
|
||||||
|
<span class="topbar__spacer"></span>
|
||||||
|
<nav class="topnav" aria-label="快速导航">
|
||||||
|
<a class="topnav__a" href="./">发布页</a> <a class="topnav__a" href="./mechanism">机制</a> <a class="topnav__a" href="./results">测量</a> <a class="topnav__a" href="./nm21">NM2.1</a> <a class="topnav__a" href="./ledger">台账</a> <a class="topnav__a is-on" href="./limits" aria-current="page">边界</a> <a class="topnav__a" href="./reproduce">复现</a>
|
||||||
|
</nav>
|
||||||
|
<button class="palbtn" id="palBtn" type="button" aria-label="检索全站内容(快捷键 /)">
|
||||||
|
<span class="palbtn__t">检索</span><span class="kbd">/</span>
|
||||||
|
</button>
|
||||||
|
<span class="pill" id="serverChip" title="本站服务端运行时读数">
|
||||||
|
<i class="dot"></i><span id="serverChipText">读取中</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="progress" id="progress"></div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<aside class="side">
|
||||||
|
<nav class="side__in" aria-label="章节导航">
|
||||||
|
<a class="side__back" href="./">← 返回发布页</a>
|
||||||
|
<p class="side__grp">原理</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./division"><span class="side__n">01</span><span class="side__t">记忆与 KV 的分工</span></a></li>
|
||||||
|
<li><a class="side__a" href="./mechanism"><span class="side__n">02</span><span class="side__t">一次读取与一次写入</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">证据</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./results"><span class="side__n">03</span><span class="side__t">测量结果</span></a></li>
|
||||||
|
<li><a class="side__a" href="./nm21"><span class="side__n">04</span><span class="side__t">NM2.1 · 之后做了什么</span></a></li>
|
||||||
|
<li><a class="side__a" href="./examples"><span class="side__n">05</span><span class="side__t">实测样例</span></a></li>
|
||||||
|
<li><a class="side__a" href="./ledger"><span class="side__n">06</span><span class="side__t">真实评测台账</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">工程</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./cost"><span class="side__n">07</span><span class="side__t">代价账本</span></a></li>
|
||||||
|
<li><a class="side__a" href="./capacity"><span class="side__n">08</span><span class="side__t">容量与存储</span></a></li>
|
||||||
|
<li><a class="side__a is-on" href="./limits" aria-current="page"><span class="side__n">09</span><span class="side__t">我们不宣称的内容</span></a></li>
|
||||||
|
<li><a class="side__a" href="./roadmap"><span class="side__n">10</span><span class="side__t">已解决的与下一步</span></a></li>
|
||||||
|
<li><a class="side__a" href="./reproduce"><span class="side__n">11</span><span class="side__t">复现实验</span></a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
|
<main class="doc" id="doc">
|
||||||
|
<header class="doc__hd">
|
||||||
|
<span class="kicker">09 / BOUNDARIES</span>
|
||||||
|
<h1 class="doc__h">我们不宣称的内容</h1>
|
||||||
|
<p class="doc__lede">没有足够证据支持的八条说法、五项主要局限,以及来自工程文档的原文引用。</p>
|
||||||
|
<p class="doc__figure">
|
||||||
|
<span class="mega">75.00<small>%</small></span>
|
||||||
|
<span class="doc__figure-n">跨域未知泄漏率 —— 仍未解决,覆盖门已回退</span>
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
<p class="lede2" id="limitsIntro"></p>
|
||||||
|
<div class="claims" id="claims" ></div>
|
||||||
|
<h2 class="h3" >五项主要局限</h2>
|
||||||
|
<div class="lims" id="lims" ></div>
|
||||||
|
<h2 class="h3" >来自工程文档的原文</h2>
|
||||||
|
<div class="lims" id="quotes" ></div>
|
||||||
|
|
||||||
|
<nav class="pn" aria-label="章节切换"><a class="pn__a pn__a--prev" href="./capacity" data-dir="prev"><span class="pn__k">上一节 · 08</span><span class="pn__t">容量与存储</span><span class="kbd">←</span></a><a class="pn__a pn__a--next" href="./roadmap" data-dir="next"><span class="pn__k">下一节 · 10</span><span class="pn__t">已解决的与下一步</span><span class="kbd">→</span></a></nav>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="wrap footer__in">
|
||||||
|
<div class="footer__col">
|
||||||
|
<p class="footer__h">作者</p>
|
||||||
|
<div class="author">
|
||||||
|
<a class="author__a" href="https://wpyw.site" target="_blank" rel="noopener">
|
||||||
|
<span class="author__k">个人网站</span><span class="author__v">wpyw.site</span>
|
||||||
|
</a>
|
||||||
|
<a class="author__a" href="mailto:[email protected]">
|
||||||
|
<span class="author__k">邮箱</span><span class="author__v">[email protected]</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">来源</p>
|
||||||
|
<div class="readout" id="footFiles"></div>
|
||||||
|
<p class="footer__h" style="margin-top:20px">服务端读数</p>
|
||||||
|
<div class="readout mono" id="footServer"><span>读取中…</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">说明</p>
|
||||||
|
<p class="footer__note" id="disclaimer"></p>
|
||||||
|
<p class="footer__meta">构建于 2026-09-16 20:39 · 所有数字取自工程内的正式报告,未做外推或估算。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<!-- 全站检索:客户端索引,无后端、无网络请求 -->
|
||||||
|
<div class="pal" id="pal" hidden>
|
||||||
|
<div class="pal__mask" id="palMask"></div>
|
||||||
|
<div class="pal__box" role="dialog" aria-modal="true" aria-label="检索全站内容">
|
||||||
|
<div class="pal__hd">
|
||||||
|
<span class="pal__ico" aria-hidden="true"></span>
|
||||||
|
<input class="pal__in" id="palInput" type="text" role="combobox" aria-expanded="true"
|
||||||
|
aria-controls="palList" autocomplete="off" spellcheck="false"
|
||||||
|
placeholder="检索全站内容:章节、数字、术语…">
|
||||||
|
<span class="kbd">Esc</span>
|
||||||
|
</div>
|
||||||
|
<div class="pal__list" id="palList" role="listbox" aria-label="检索结果"></div>
|
||||||
|
<div class="pal__ft">
|
||||||
|
<span><span class="kbd">↑</span><span class="kbd">↓</span> 选择</span>
|
||||||
|
<span><span class="kbd">↵</span> 打开</span>
|
||||||
|
<span class="pal__n mono" id="palN"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="assets/js/data.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/examples.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/restart.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/nm21.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/ledger.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/search.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/space.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/site.js?v=a9c21ef3a8"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+335
@@ -0,0 +1,335 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>机制:读取路径、记录结构与写入状态机 — Natural Memory v2</title>
|
||||||
|
<meta name="description" content="从用户问题到证据前缀注入的八个环节,记录包含哪些字段,以及 active / superseded / quarantined / retracted 四个状态如何演化。">
|
||||||
|
<meta name="color-scheme" content="dark">
|
||||||
|
<meta name="theme-color" content="#0a0a0a">
|
||||||
|
<!-- 动效的初始隐藏态只在 JS 可用时生效;脚本被禁用时内容照常可见 -->
|
||||||
|
<script>document.documentElement.classList.add("js");</script>
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:title" content="机制:读取路径、记录结构与写入状态机 — Natural Memory v2">
|
||||||
|
<meta property="og:description" content="从用户问题到证据前缀注入的八个环节,记录包含哪些字段,以及 active / superseded / quarantined / retracted 四个状态如何演化。">
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<link rel="icon" href="assets/favicon.svg" type="image/svg+xml">
|
||||||
|
<link rel="apple-touch-icon" href="assets/favicon.svg">
|
||||||
|
<link rel="preload" href="assets/fonts/archivo-latin-wdth-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<link rel="preload" href="assets/fonts/geist-mono-latin-wght-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<!-- 资源带构建指纹:内容一变 URL 就变,浏览器不可能再用到旧 JS/CSS -->
|
||||||
|
<link rel="stylesheet" href="assets/css/site.css?v=a9c21ef3a8">
|
||||||
|
</head>
|
||||||
|
<body data-page="mechanism" data-layout="docs">
|
||||||
|
<a class="skip" href="#doc">跳到正文</a>
|
||||||
|
|
||||||
|
<header class="site" id="site">
|
||||||
|
<div class="topbar">
|
||||||
|
<a class="brand" href="./" aria-label="Natural Memory v2 发布页">
|
||||||
|
<svg class="brand__mark" viewBox="0 0 32 32" aria-hidden="true">
|
||||||
|
<rect class="dim" x="2" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="12" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="22" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
</svg>
|
||||||
|
<span class="brand__name">Natural Memory</span>
|
||||||
|
<span class="pill pill--acc">v2</span>
|
||||||
|
</a>
|
||||||
|
<span class="crumb">
|
||||||
|
<span class="crumb__n">02</span>
|
||||||
|
<span class="crumb__t">一次读取与一次写入</span>
|
||||||
|
</span>
|
||||||
|
<span class="topbar__spacer"></span>
|
||||||
|
<nav class="topnav" aria-label="快速导航">
|
||||||
|
<a class="topnav__a" href="./">发布页</a> <a class="topnav__a is-on" href="./mechanism" aria-current="page">机制</a> <a class="topnav__a" href="./results">测量</a> <a class="topnav__a" href="./nm21">NM2.1</a> <a class="topnav__a" href="./ledger">台账</a> <a class="topnav__a" href="./limits">边界</a> <a class="topnav__a" href="./reproduce">复现</a>
|
||||||
|
</nav>
|
||||||
|
<button class="palbtn" id="palBtn" type="button" aria-label="检索全站内容(快捷键 /)">
|
||||||
|
<span class="palbtn__t">检索</span><span class="kbd">/</span>
|
||||||
|
</button>
|
||||||
|
<span class="pill" id="serverChip" title="本站服务端运行时读数">
|
||||||
|
<i class="dot"></i><span id="serverChipText">读取中</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="progress" id="progress"></div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<aside class="side">
|
||||||
|
<nav class="side__in" aria-label="章节导航">
|
||||||
|
<a class="side__back" href="./">← 返回发布页</a>
|
||||||
|
<p class="side__grp">原理</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./division"><span class="side__n">01</span><span class="side__t">记忆与 KV 的分工</span></a></li>
|
||||||
|
<li><a class="side__a is-on" href="./mechanism" aria-current="page"><span class="side__n">02</span><span class="side__t">一次读取与一次写入</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">证据</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./results"><span class="side__n">03</span><span class="side__t">测量结果</span></a></li>
|
||||||
|
<li><a class="side__a" href="./nm21"><span class="side__n">04</span><span class="side__t">NM2.1 · 之后做了什么</span></a></li>
|
||||||
|
<li><a class="side__a" href="./examples"><span class="side__n">05</span><span class="side__t">实测样例</span></a></li>
|
||||||
|
<li><a class="side__a" href="./ledger"><span class="side__n">06</span><span class="side__t">真实评测台账</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">工程</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./cost"><span class="side__n">07</span><span class="side__t">代价账本</span></a></li>
|
||||||
|
<li><a class="side__a" href="./capacity"><span class="side__n">08</span><span class="side__t">容量与存储</span></a></li>
|
||||||
|
<li><a class="side__a" href="./limits"><span class="side__n">09</span><span class="side__t">我们不宣称的内容</span></a></li>
|
||||||
|
<li><a class="side__a" href="./roadmap"><span class="side__n">10</span><span class="side__t">已解决的与下一步</span></a></li>
|
||||||
|
<li><a class="side__a" href="./reproduce"><span class="side__n">11</span><span class="side__t">复现实验</span></a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
|
<main class="doc" id="doc">
|
||||||
|
<header class="doc__hd">
|
||||||
|
<span class="kicker">02 / MECHANISM</span>
|
||||||
|
<h1 class="doc__h">一次读取与一次写入</h1>
|
||||||
|
<p class="doc__lede">从用户问题到证据前缀注入的八个环节,记录包含哪些字段,以及 active / superseded / quarantined / retracted 四个状态如何演化。</p>
|
||||||
|
<p class="doc__figure">
|
||||||
|
<span class="mega">1,048,576<small></small></span>
|
||||||
|
<span class="doc__figure-n">地址空间设计容量</span>
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
<p class="lede2">
|
||||||
|
这一节把「<strong>一次读取</strong>」和「<strong>一次写入</strong>」拆开讲透:读取路径有哪八个环节、每一步的输入输出是什么、
|
||||||
|
一条记录里到底存了什么、四个状态如何演化,以及我们为这些决定付出了什么代价。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="h3" >一、读取路径:从提问到证据注入</h2>
|
||||||
|
<div class="scrollx teaser--doc">
|
||||||
|
<svg class="dgm" viewBox="0 0 1120 250" role="img"
|
||||||
|
aria-label="读取路径示意:问题 → 隐状态地址 → LSH 粗索引 → 候选页 → 页内重排 → Top-K → 证据前缀 → 生成">
|
||||||
|
<!-- 连接线(pathLength=1 让描边可以按 0→1 精确绘制) -->
|
||||||
|
<g class="dgm__a">
|
||||||
|
<path pathLength="1" d="M132 78 L156 78" /><path pathLength="1" d="M270 78 L294 78" /><path pathLength="1" d="M408 78 L432 78" />
|
||||||
|
<path pathLength="1" d="M546 78 L570 78" /><path pathLength="1" d="M684 78 L708 78" /><path pathLength="1" d="M822 78 L846 78" />
|
||||||
|
<path pathLength="1" d="M960 78 L984 78" />
|
||||||
|
</g>
|
||||||
|
<!-- 8 个环节 -->
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box" x="12" y="46" width="120" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="24" y="66">01</text>
|
||||||
|
<text class="dgm__l" x="24" y="86">用户问题</text>
|
||||||
|
<text class="dgm__s" x="24" y="101">自然语言</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box" x="156" y="46" width="114" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="168" y="66">02</text>
|
||||||
|
<text class="dgm__l" x="168" y="86">隐状态地址</text>
|
||||||
|
<text class="dgm__s" x="168" y="101">Qwen hidden</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box" x="294" y="46" width="114" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="306" y="66">03</text>
|
||||||
|
<text class="dgm__l" x="306" y="86">LSH 粗索引</text>
|
||||||
|
<text class="dgm__s" x="306" y="101">730 桶</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box" x="432" y="46" width="114" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="444" y="66">04</text>
|
||||||
|
<text class="dgm__l" x="444" y="86">候选页</text>
|
||||||
|
<text class="dgm__s" x="444" y="101">≤4 页 · 32/页</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box" x="570" y="46" width="114" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="582" y="66">05</text>
|
||||||
|
<text class="dgm__l" x="582" y="86">页内重排</text>
|
||||||
|
<text class="dgm__s" x="582" y="101">text_retriever</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box dgm__box--acc" x="708" y="46" width="114" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="720" y="66">06</text>
|
||||||
|
<text class="dgm__l" x="720" y="86">Top-K 记录</text>
|
||||||
|
<text class="dgm__s" x="720" y="101">≤2 条</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box dgm__box--acc" x="846" y="46" width="114" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="858" y="66">07</text>
|
||||||
|
<text class="dgm__l" x="858" y="86">证据前缀</text>
|
||||||
|
<text class="dgm__s" x="858" y="101">注入 Qwen</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box" x="984" y="46" width="124" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="996" y="66">08</text>
|
||||||
|
<text class="dgm__l" x="996" y="86">普通生成</text>
|
||||||
|
<text class="dgm__s" x="996" y="101">回答</text>
|
||||||
|
</g>
|
||||||
|
<!-- 关键约束注释 -->
|
||||||
|
<line class="dgm__rule" x1="12" y1="146" x2="1108" y2="146"/>
|
||||||
|
<text class="dgm__note" x="12" y="172">无全量注意力</text>
|
||||||
|
<text class="dgm__s" x="1108" y="172" text-anchor="end">BOUNDED READ</text>
|
||||||
|
<text class="dgm__note" x="12" y="190">当前问题不与全部记忆记录做注意力,只与少量页面和记录交互</text>
|
||||||
|
<text class="dgm__note" x="12" y="222">读取额外耗时 61.10 ms → 26.35 ms(批次 A → B) · 前缀命中率 96.97% · GPU cache 实际 17,990 / 上限 131,072 token</text>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="small" style="max-width:78ch">
|
||||||
|
点左侧任一环节查看它在做什么,也可以依次点一遍——注意整条链路上<strong>没有一步是「和全部记忆做注意力」</strong>,
|
||||||
|
这是显存可控的根本原因。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="flow">
|
||||||
|
<div class="steps" id="steps" role="tablist" aria-label="记忆读取路径"></div>
|
||||||
|
<div class="flow__detail card card--flat">
|
||||||
|
<p class="flow__stage" id="flowIdx">STAGE 01 / 08</p>
|
||||||
|
<h3 class="flow__title" id="flowTitle"></h3>
|
||||||
|
<p class="flow__body" id="flowBody"></p>
|
||||||
|
<p class="flow__io" id="flowIo"></p>
|
||||||
|
<div class="flow__meta">
|
||||||
|
<div><span>读取上限</span><b>2 records</b></div>
|
||||||
|
<div><span>候选页上限</span><b>4 pages</b></div>
|
||||||
|
<div><span>页容量</span><b>32 / page</b></div>
|
||||||
|
<div><span>全量注意力</span><b>否</b></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="h3" >每一步的输入、输出与约束</h2>
|
||||||
|
<p class="small" style="max-width:78ch">
|
||||||
|
括号里的数字是实测值,不是设计目标。
|
||||||
|
</p>
|
||||||
|
<div class="scrollx">
|
||||||
|
<div class="gt gt--3">
|
||||||
|
<div class="gt__h"><span>环节</span><span>输入 → 输出</span><span>约束或实测</span></div>
|
||||||
|
<div class="gt__r"><span class="gt__k">01 用户问题</span><span class="gt__v">普通自然语言</span><span class="gt__why">不要求任何显式指令,不需要输入 <code>/remember</code> 之类的标记。</span></div>
|
||||||
|
<div class="gt__r"><span class="gt__k">02 Qwen hidden state</span><span class="gt__v">问题 → 紧凑查询地址</span><span class="gt__why">地址由模型隐状态生成,不依赖外部 embedding 服务;语义地址编码用单条 batch 执行,避免编码阶段出现显存瞬时峰值。</span></div>
|
||||||
|
<div class="gt__r"><span class="gt__k">03 LSH / 地址粗索引</span><span class="gt__v">查询地址 → 候选页</span><span class="gt__why">精确桶 + Hamming-1/2 探针;批次 A 的记忆状态里粗索引有 730 个桶、最近一次粗筛返回 24 个候选。</span></div>
|
||||||
|
<div class="gt__r"><span class="gt__k">04 候选页</span><span class="gt__v">候选页 → 少量页面</span><span class="gt__why">页容量 32 条记录,默认最多读取 4 页;本次 active records 723 条落在 23 个页面上。</span></div>
|
||||||
|
<div class="gt__r"><span class="gt__k">05 页内记录重排</span><span class="gt__v">页内记录 → 有序候选</span><span class="gt__why">记录级重排由独立的 text_retriever 完成(6 张量、1,573,377 参数)。它的 Top-1 命中率本身只有 23.20%,是当前的主要瓶颈之一。</span></div>
|
||||||
|
<div class="gt__r"><span class="gt__k">06 Top-K 记录</span><span class="gt__v">有序候选 → 少量证据</span><span class="gt__why">正式测试中的读取上限为 2 条记录。目标记忆召回:批次 A 166/246,<strong>批次 B 228/246</strong>。</span></div>
|
||||||
|
<div class="gt__r"><span class="gt__k">07 证据前缀注入</span><span class="gt__v">证据 → 模型内部前缀</span><span class="gt__why">命中的短证据被提升到 GPU 作为前缀;批次 B 有 96.97% 的题目实际注入了前缀,平均 410.34 token(批次 A 为 610.67)。</span></div>
|
||||||
|
<div class="gt__r"><span class="gt__k">08 普通生成</span><span class="gt__v">前缀 + 问题 → 回答</span><span class="gt__why">记忆主体始终留在进程内存,只有热点记录进入有界 GPU cache。读取路径额外耗时:批次 A 61.10 ms → <strong>批次 B 26.35 ms</strong>。</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="h3" >二、一条记录里到底存了什么</h2>
|
||||||
|
<p class="small" style="max-width:78ch">
|
||||||
|
记录不是一段文本,而是一条带地址、带版本关系、带状态的结构化数据。下面左侧是全部字段,
|
||||||
|
右侧是<strong>一条真实记录</strong>(逐字取自评测结果里的命中记录)。
|
||||||
|
</p>
|
||||||
|
<div class="grid g-2-1">
|
||||||
|
<div>
|
||||||
|
<div class="rec" id="recFields"></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="card card--acc" id="realRecord"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="h3" >三、状态机:旧的答案不会凭空消失</h2>
|
||||||
|
<p class="small" style="max-width:78ch">
|
||||||
|
同一实体和属性出现新值时,<strong>旧值被标记为 superseded,而不是被覆盖或删除</strong>。
|
||||||
|
这是「时间冲突」类问题能答对的前提:既要给出当前有效值,也要能说清旧值去哪了。
|
||||||
|
</p>
|
||||||
|
<div class="states" id="stateList"></div>
|
||||||
|
|
||||||
|
<div class="callout callout--warn" >
|
||||||
|
<p class="callout__t">写入路径的教训:检索救不回不存在的记录</p>
|
||||||
|
<p class="callout__b">
|
||||||
|
早期版本的退役授权完全依赖一个学习打分(阈值 ≥0.95),<strong>没有任何结构校验</strong>。
|
||||||
|
结果是新写入把已有记录误判为旧值并退役:一次 20 条记录的测试里 active 只剩 12 条、retract 高达 16 次、目标记录只存活 8/16。
|
||||||
|
修好之后:<strong>active 12/20 → 20/20,retract 16 → 0,目标记录存活 8/16 → 16/16,端到端 37.50% → 68.75%</strong>。
|
||||||
|
这件事的结论很直白——<span class="serif-it">任何排序器都救不回一条已经不存在的记录。</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="h3" >四、四个设计决定与它们的代价</h2>
|
||||||
|
<div class="grid g2" >
|
||||||
|
<div class="card">
|
||||||
|
<p class="eyebrow" >决定 1 · 两段式读取</p>
|
||||||
|
<p class="small" ><strong>粗索引筛页 → 页内重排</strong>,而不是对全量记录做注意力。</p>
|
||||||
|
<p class="tiny">好处:单次读取的候选规模被压到固定上限(≤4 页 / ≤2 条),成本与记忆总量解耦。
|
||||||
|
代价:两段都可能出错,且错误会叠加——粗索引错了就再没有机会。</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<p class="eyebrow" >决定 2 · 用地址索引而非向量库</p>
|
||||||
|
<p class="small" >语义地址 + LSH 桶放在模型包内,<strong>不引入外部检索服务</strong>。</p>
|
||||||
|
<p class="tiny">好处:部署时没有额外进程与网络依赖,读取耗时稳定(批次 B 26.35 ms)。
|
||||||
|
代价:召回质量受地址质量限制,零字面重叠的改写问法曾只有 18.40% 的 Top-1。</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<p class="eyebrow" >决定 3 · 有界 GPU cache</p>
|
||||||
|
<p class="small" >热点记录进 GPU,上限 <strong>256 条 / 131,072 token</strong>,另有动态保留。</p>
|
||||||
|
<p class="tiny">好处:显存占用可预测,两个批次的实际用量分别是 15,885 / 17,990 token,fallback 与分配失败均为 0。
|
||||||
|
代价:cold page 会带来额外取数路径——不过本次两个批次都是 embedded / process-RAM 模式,cold page 为 0。</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<p class="eyebrow" >决定 4 · 嵌入式 weight-shard 持久化</p>
|
||||||
|
<p class="small" >记忆快照写进模型包的 memory safetensors 切片,<strong>默认不用 SQLite、不用磁盘分页</strong>。</p>
|
||||||
|
<p class="tiny">好处:运行时依赖最少,重启只需加载权重切片、不回放历史聊天。
|
||||||
|
代价:模型包会随记忆增长变大,且<strong>固化更新需要重新保存权重切片</strong>——这是明确的工程负担,不是白拿的。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="h3" >五、这套机制仍然做不到的事</h2>
|
||||||
|
<div class="claims claims--loose" >
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">任何自然语言表达都能稳定召回正确记忆</span><span class="claim__s">UNSUPPORTED</span></div>
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">记忆写入永远不会出错</span><span class="claim__s">UNSUPPORTED</span></div>
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">检索召回率等于回答正确率(批次 B 召回 92.68% / 回答 82.52%,差 10.16pp)</span><span class="claim__s">UNSUPPORTED</span></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav class="pn" aria-label="章节切换"><a class="pn__a pn__a--prev" href="./division" data-dir="prev"><span class="pn__k">上一节 · 01</span><span class="pn__t">记忆与 KV 的分工</span><span class="kbd">←</span></a><a class="pn__a pn__a--next" href="./results" data-dir="next"><span class="pn__k">下一节 · 03</span><span class="pn__t">测量结果</span><span class="kbd">→</span></a></nav>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="wrap footer__in">
|
||||||
|
<div class="footer__col">
|
||||||
|
<p class="footer__h">作者</p>
|
||||||
|
<div class="author">
|
||||||
|
<a class="author__a" href="https://wpyw.site" target="_blank" rel="noopener">
|
||||||
|
<span class="author__k">个人网站</span><span class="author__v">wpyw.site</span>
|
||||||
|
</a>
|
||||||
|
<a class="author__a" href="mailto:[email protected]">
|
||||||
|
<span class="author__k">邮箱</span><span class="author__v">[email protected]</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">来源</p>
|
||||||
|
<div class="readout" id="footFiles"></div>
|
||||||
|
<p class="footer__h" style="margin-top:20px">服务端读数</p>
|
||||||
|
<div class="readout mono" id="footServer"><span>读取中…</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">说明</p>
|
||||||
|
<p class="footer__note" id="disclaimer"></p>
|
||||||
|
<p class="footer__meta">构建于 2026-09-16 20:39 · 所有数字取自工程内的正式报告,未做外推或估算。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<!-- 全站检索:客户端索引,无后端、无网络请求 -->
|
||||||
|
<div class="pal" id="pal" hidden>
|
||||||
|
<div class="pal__mask" id="palMask"></div>
|
||||||
|
<div class="pal__box" role="dialog" aria-modal="true" aria-label="检索全站内容">
|
||||||
|
<div class="pal__hd">
|
||||||
|
<span class="pal__ico" aria-hidden="true"></span>
|
||||||
|
<input class="pal__in" id="palInput" type="text" role="combobox" aria-expanded="true"
|
||||||
|
aria-controls="palList" autocomplete="off" spellcheck="false"
|
||||||
|
placeholder="检索全站内容:章节、数字、术语…">
|
||||||
|
<span class="kbd">Esc</span>
|
||||||
|
</div>
|
||||||
|
<div class="pal__list" id="palList" role="listbox" aria-label="检索结果"></div>
|
||||||
|
<div class="pal__ft">
|
||||||
|
<span><span class="kbd">↑</span><span class="kbd">↓</span> 选择</span>
|
||||||
|
<span><span class="kbd">↵</span> 打开</span>
|
||||||
|
<span class="pal__n mono" id="palN"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="assets/js/data.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/examples.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/restart.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/nm21.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/ledger.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/search.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/space.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/site.js?v=a9c21ef3a8"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,704 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>NM2.1:之后做了什么 — Natural Memory v2</title>
|
||||||
|
<meta name="description" content="三处改动各自的测量依据、把端到端正确率锁死在 50% 的写入缺陷如何定位、75% 未知泄漏如何修到 0%,以及它接上运行时连续失败两次的完整记录。">
|
||||||
|
<meta name="color-scheme" content="dark">
|
||||||
|
<meta name="theme-color" content="#0a0a0a">
|
||||||
|
<!-- 动效的初始隐藏态只在 JS 可用时生效;脚本被禁用时内容照常可见 -->
|
||||||
|
<script>document.documentElement.classList.add("js");</script>
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:title" content="NM2.1:之后做了什么 — Natural Memory v2">
|
||||||
|
<meta property="og:description" content="三处改动各自的测量依据、把端到端正确率锁死在 50% 的写入缺陷如何定位、75% 未知泄漏如何修到 0%,以及它接上运行时连续失败两次的完整记录。">
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<link rel="icon" href="assets/favicon.svg" type="image/svg+xml">
|
||||||
|
<link rel="apple-touch-icon" href="assets/favicon.svg">
|
||||||
|
<link rel="preload" href="assets/fonts/archivo-latin-wdth-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<link rel="preload" href="assets/fonts/geist-mono-latin-wght-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<!-- 资源带构建指纹:内容一变 URL 就变,浏览器不可能再用到旧 JS/CSS -->
|
||||||
|
<link rel="stylesheet" href="assets/css/site.css?v=a9c21ef3a8">
|
||||||
|
</head>
|
||||||
|
<body data-page="nm21" data-layout="docs">
|
||||||
|
<a class="skip" href="#doc">跳到正文</a>
|
||||||
|
|
||||||
|
<header class="site" id="site">
|
||||||
|
<div class="topbar">
|
||||||
|
<a class="brand" href="./" aria-label="Natural Memory v2 发布页">
|
||||||
|
<svg class="brand__mark" viewBox="0 0 32 32" aria-hidden="true">
|
||||||
|
<rect class="dim" x="2" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="12" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="22" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
</svg>
|
||||||
|
<span class="brand__name">Natural Memory</span>
|
||||||
|
<span class="pill pill--acc">v2</span>
|
||||||
|
</a>
|
||||||
|
<span class="crumb">
|
||||||
|
<span class="crumb__n">04</span>
|
||||||
|
<span class="crumb__t">NM2.1 · 之后做了什么</span>
|
||||||
|
</span>
|
||||||
|
<span class="topbar__spacer"></span>
|
||||||
|
<nav class="topnav" aria-label="快速导航">
|
||||||
|
<a class="topnav__a" href="./">发布页</a> <a class="topnav__a" href="./mechanism">机制</a> <a class="topnav__a" href="./results">测量</a> <a class="topnav__a is-on" href="./nm21" aria-current="page">NM2.1</a> <a class="topnav__a" href="./ledger">台账</a> <a class="topnav__a" href="./limits">边界</a> <a class="topnav__a" href="./reproduce">复现</a>
|
||||||
|
</nav>
|
||||||
|
<button class="palbtn" id="palBtn" type="button" aria-label="检索全站内容(快捷键 /)">
|
||||||
|
<span class="palbtn__t">检索</span><span class="kbd">/</span>
|
||||||
|
</button>
|
||||||
|
<span class="pill" id="serverChip" title="本站服务端运行时读数">
|
||||||
|
<i class="dot"></i><span id="serverChipText">读取中</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="progress" id="progress"></div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<aside class="side">
|
||||||
|
<nav class="side__in" aria-label="章节导航">
|
||||||
|
<a class="side__back" href="./">← 返回发布页</a>
|
||||||
|
<p class="side__grp">原理</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./division"><span class="side__n">01</span><span class="side__t">记忆与 KV 的分工</span></a></li>
|
||||||
|
<li><a class="side__a" href="./mechanism"><span class="side__n">02</span><span class="side__t">一次读取与一次写入</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">证据</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./results"><span class="side__n">03</span><span class="side__t">测量结果</span></a></li>
|
||||||
|
<li><a class="side__a is-on" href="./nm21" aria-current="page"><span class="side__n">04</span><span class="side__t">NM2.1 · 之后做了什么</span></a></li>
|
||||||
|
<li><a class="side__a" href="./examples"><span class="side__n">05</span><span class="side__t">实测样例</span></a></li>
|
||||||
|
<li><a class="side__a" href="./ledger"><span class="side__n">06</span><span class="side__t">真实评测台账</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">工程</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./cost"><span class="side__n">07</span><span class="side__t">代价账本</span></a></li>
|
||||||
|
<li><a class="side__a" href="./capacity"><span class="side__n">08</span><span class="side__t">容量与存储</span></a></li>
|
||||||
|
<li><a class="side__a" href="./limits"><span class="side__n">09</span><span class="side__t">我们不宣称的内容</span></a></li>
|
||||||
|
<li><a class="side__a" href="./roadmap"><span class="side__n">10</span><span class="side__t">已解决的与下一步</span></a></li>
|
||||||
|
<li><a class="side__a" href="./reproduce"><span class="side__n">11</span><span class="side__t">复现实验</span></a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
|
<main class="doc" id="doc">
|
||||||
|
<header class="doc__hd">
|
||||||
|
<span class="kicker">04 / WHAT CHANGED NEXT</span>
|
||||||
|
<h1 class="doc__h">NM2.1 · 之后做了什么</h1>
|
||||||
|
<p class="doc__lede">三处改动各自的测量依据、把端到端正确率锁死在 50% 的写入缺陷如何定位、75% 未知泄漏如何修到 0%,以及它接上运行时连续失败两次的完整记录。</p>
|
||||||
|
<p class="doc__figure">
|
||||||
|
<span class="mega">94.14<small>%</small></span>
|
||||||
|
<span class="doc__figure-n">路由器 Top-1(v2 为 41.12%)</span>
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
<p class="lede2">
|
||||||
|
发布页上的数字来自 v2。这一页讲**之后又做了什么**:三处改动各自凭什么、一个把端到端正确率
|
||||||
|
锁死在 50% 的写入缺陷怎么定位的、以及一个 75% 泄漏的失败怎么修到 0%——又怎么在接上运行时之后失败两次。
|
||||||
|
所有数字都来自磁盘上的报告文件,每张表都标了出处;**没有一条是估算或外推**。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="callout callout--warn">
|
||||||
|
<p class="eyebrow" style="color:var(--warn)">先读这一句</p>
|
||||||
|
<p class="small" style="margin:0">
|
||||||
|
这一页里**离线实验最好的数字(未知拒答 100.00%)不等于运行时可用**。它接上运行时之后
|
||||||
|
连续失败两次,最终被回退。把失败过程一起写出来,是因为它比成功更能说明这套机制到底卡在哪。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================= 净变化 ================= -->
|
||||||
|
<h2 class="h3">净变化一览</h2>
|
||||||
|
<p class="small src">出处 · <code>V2_dpskw\NM2_VS_NM2_1.md</code>(该文件自述:所有数字均从磁盘上的评分卡 / JSON 读取,不是手工抄录)</p>
|
||||||
|
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>轴</th><th>v2(原版)</th><th>NM2.1</th><th>净变化</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>路由器 Top-1</td><td class="n">41.12%</td><td class="n acc">94.14%</td><td class="n acc">+53.02 pp</td></tr>
|
||||||
|
<tr><td>路由器 Recall@3</td><td class="n">46.73%</td><td class="n acc">96.48%</td><td class="n acc">+49.75 pp</td></tr>
|
||||||
|
<tr><td>未知拒答率</td><td class="n">0.00%</td><td class="n acc">100.00%</td><td class="n acc">+100.00 pp</td></tr>
|
||||||
|
<tr><td>未知问题泄漏(同形候选)</td><td class="n">75.00%</td><td class="n acc">0.00%</td><td class="n acc">−75.00 pp</td></tr>
|
||||||
|
<tr><td>一次写 20 条不同属性后存活</td><td class="n">12 / 20</td><td class="n acc">20 / 20</td><td class="n acc">+8 条</td></tr>
|
||||||
|
<tr><td>零字面重叠改写正确率</td><td class="n">43.75%</td><td class="n acc">68.75%</td><td class="n acc">+25.00 pp</td></tr>
|
||||||
|
<tr><td>hop 欠预测率</td><td class="n">4.68%</td><td class="n acc">0.00%</td><td class="n acc">−4.68 pp</td></tr>
|
||||||
|
<tr><td>参数量 / 每条记录地址字节</td><td class="n">2,037,774 / 512</td><td class="n">2,037,774 / 512</td><td class="n">不变</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<p class="tiny">
|
||||||
|
「未知拒答率」与「未知泄漏」是同一件事的两面:前者是问库里没有的属性时**正确说不知道**的比例,
|
||||||
|
后者是**照样编一个答案**的比例。v2 在这两轴上是 0% 和 75%,也就是几乎必然硬答。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- ================= §1 检索与排序 ================= -->
|
||||||
|
<h2 class="h3">一 · 路由器工件本身的检索与排序</h2>
|
||||||
|
<p class="small src">出处 · <code>router_scorecard_final.json</code>(判定见 <code>router_verdict_final.json</code>)· 冻结 v6 评测集 21,920 条 / 10 类别</p>
|
||||||
|
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>指标</th><th>v2 · <code>V2-128 deployed(v3)</code></th><th>NM2.1 · <code>REPLAY-128 v7 final</code></th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>Top-1 正确率</td><td class="n">41.12%</td><td class="n acc">94.14%</td></tr>
|
||||||
|
<tr><td>Recall@1</td><td class="n">37.03%</td><td class="n acc">88.58%</td></tr>
|
||||||
|
<tr><td>Recall@3</td><td class="n">46.73%</td><td class="n acc">96.48%</td></tr>
|
||||||
|
<tr><td>Recall@5</td><td class="n">48.91%</td><td class="n acc">97.15%</td></tr>
|
||||||
|
<tr><td>MRR</td><td class="n">47.69%</td><td class="n acc">95.77%</td></tr>
|
||||||
|
<tr><td>nDCG@3</td><td class="n">44.22%</td><td class="n acc">95.37%</td></tr>
|
||||||
|
<tr><td>多跳证据全中(Top-3)</td><td class="n">43.43%</td><td class="n acc">96.22%</td></tr>
|
||||||
|
<tr><td>多跳证据全中(仅多正例)</td><td class="n">37.15%</td><td class="n acc">95.45%</td></tr>
|
||||||
|
<tr><td>hop 正确率</td><td class="n">73.23%</td><td class="n acc">100.00%</td></tr>
|
||||||
|
<tr><td>hop 欠预测率</td><td class="n">4.68%</td><td class="n acc">0.00%</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================= §2 拒答与仲裁 ================= -->
|
||||||
|
<h2 class="h3">二 · 拒答与仲裁策略轴</h2>
|
||||||
|
<p class="small src">出处 · <code>router_scorecard_final.json</code>(门槛 0.50)+ <code>threshold_sweep_check.json</code>(0.30–0.80 全门槛扫描)</p>
|
||||||
|
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>指标</th><th>v2</th><th>NM2.1</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>need F1</td><td class="n">89.58%</td><td class="n acc">100.00%</td></tr>
|
||||||
|
<tr><td>need 召回</td><td class="n">99.82%</td><td class="n acc">100.00%</td></tr>
|
||||||
|
<tr><td>need 精确率</td><td class="n">81.24%</td><td class="n acc">100.00%</td></tr>
|
||||||
|
<tr><td>未知拒答率</td><td class="n">0.00%</td><td class="n acc">100.00%</td></tr>
|
||||||
|
<tr><td>已知问题被误拒率</td><td class="n">0.18%</td><td class="n acc">0.00%</td></tr>
|
||||||
|
<tr><td>未知问题被误读率</td><td class="n">100.00%</td><td class="n acc">0.00%</td></tr>
|
||||||
|
<tr><td>仲裁准确率</td><td class="n">81.12%</td><td class="n acc">100.00%</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<p class="small">
|
||||||
|
<strong>门槛扫描是这里真正的证据。</strong>0.30 / 0.40 / 0.50 / 0.60 / 0.70 / 0.80 六个门槛逐一复核:
|
||||||
|
NM2.1 **全门槛通过**;而原版在**每一个**门槛上未知拒答率都是 0.00%,且门槛越高误拒越差
|
||||||
|
(0.00% → 1.32%)。一个能在整条门槛轴上都成立的结论,和一个只在某个阈值上成立的点,可信度不是一回事。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- ================= §3 端到端 ================= -->
|
||||||
|
<h2 class="h3">三 · 端到端整体记忆能力(同一份运行时,只有模型包不同)</h2>
|
||||||
|
<p class="small src">出处 · <code>nm2_battery_comparison_final.json</code> · A 110 用例 / B 16 / C 48 / D 重启持久化</p>
|
||||||
|
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>指标</th><th>原版 NM2</th><th>NM2.1(仅换路由器)</th><th>NM2.1 最终</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>A 总体正确率</td><td class="n">89.09%</td><td class="n">88.18%</td><td class="n">88.18%</td></tr>
|
||||||
|
<tr><td>A <strong>可回答正确率</strong></td><td class="n">100.00%</td><td class="n">100.00%</td><td class="n acc">100.00%</td></tr>
|
||||||
|
<tr><td>A 未知拒答率</td><td class="n">60.00%</td><td class="n">56.67%</td><td class="n bad">56.67%</td></tr>
|
||||||
|
<tr><td>A 已知问题被误拒率</td><td class="n">0.00%</td><td class="n">0.00%</td><td class="n acc">0.00%</td></tr>
|
||||||
|
<tr><td>B 零字面重叠改写回答正确率</td><td class="n">43.75%</td><td class="n">68.75%</td><td class="n acc">68.75%</td></tr>
|
||||||
|
<tr><td>B 答成别的属性</td><td class="n">18.75%</td><td class="n">18.75%</td><td class="n">18.75%</td></tr>
|
||||||
|
<tr><td>B 触发读取</td><td class="n">56.25%</td><td class="n">93.75%</td><td class="n acc">93.75%</td></tr>
|
||||||
|
<tr><td>C 可回答正确率(24 同形候选)</td><td class="n">65.00%</td><td class="n">65.00%</td><td class="n acc">70.00%</td></tr>
|
||||||
|
<tr><td>C 答成别的属性</td><td class="n">35.00%</td><td class="n">35.00%</td><td class="n acc">27.50%</td></tr>
|
||||||
|
<tr><td>C <strong>未知泄漏率</strong></td><td class="n">75.00%</td><td class="n">75.00%</td><td class="n acc">0.00%</td></tr>
|
||||||
|
<tr><td>C 活跃记录 min / max</td><td class="n">23 / 24</td><td class="n">23 / 24</td><td class="n">23 / 24</td></tr>
|
||||||
|
<tr><td>D 重启后召回 / 作答 / 清理</td><td class="n">通过</td><td class="n">通过</td><td class="n acc">通过</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<p class="small">
|
||||||
|
<strong>运行间波动必须自己讲出来:</strong>B 段只有 16 个用例,1 个用例 = 6.25 pp。所以 B 的 68.75%
|
||||||
|
与另一次测得的 75.00% 属于同一水平的运行间波动,**不作为增益主张**。A / C / D 的结论在多次运行中一致。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- ================= §4 零重叠 ================= -->
|
||||||
|
<h2 class="h3">四 · 零字面重叠改写的泛化</h2>
|
||||||
|
<p class="small src">出处 · <code>replay_check_zov.json</code>(路由器级)与上表 B / C 段(端到端)· 数据集 300 条、24 个<strong>未见过</strong>的问法</p>
|
||||||
|
|
||||||
|
<div class="grid g2">
|
||||||
|
<div>
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>指标</th><th>v2 权重</th><th>NM2.1 权重</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>路由器 Top-1(250 条可回答)</td><td class="n">18.40%</td><td class="n acc">59.60%</td></tr>
|
||||||
|
<tr><td>路由器 Recall@3</td><td class="n">36.00%</td><td class="n acc">83.20%</td></tr>
|
||||||
|
<tr><td>路由器 MRR</td><td class="n">35.07%</td><td class="n acc">73.06%</td></tr>
|
||||||
|
<tr><td>端到端改写正确率(B 段)</td><td class="n">43.75%</td><td class="n acc">68.75%</td></tr>
|
||||||
|
<tr><td>端到端未知泄漏(C 段)</td><td class="n">75.00%</td><td class="n acc">0.00%</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="small" style="margin-top:0">
|
||||||
|
零重叠评测集有 24 条**同句式、不同属性**的候选,随机猜中的概率是 <strong>4.17%</strong>。
|
||||||
|
所以 59.60% 大约是随机水平的 <strong>14 倍</strong>。
|
||||||
|
</p>
|
||||||
|
<div class="kv">
|
||||||
|
<div class="kv__r"><span class="kv__k">数据集规模</span><span class="kv__v">300 条评测 / 24 个未见问法</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">训练 / 留出划分</span><span class="kv__v">前 2 个改写训练(48)/ 第 3 个留出(24)</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">两个划分共享的查询字符串</span><span class="kv__v">0</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">查询与自身目标的重叠</span><span class="kv__v">0</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">含「陷阱」候选的 episode</span><span class="kv__v">54.53%(生成器统计)</span></div>
|
||||||
|
</div>
|
||||||
|
<p class="tiny">
|
||||||
|
<strong>关键设计判断:</strong>改写与**无关**属性的字符重叠被刻意保留(命中错误候选只会得到错误答案,
|
||||||
|
让任务更难,不提供捷径);真正必须为 0 的是与**自身**目标的重叠。最初把二者混为一谈时,
|
||||||
|
24 个属性里有 7 个因为「起床时间」的「时」、「办公城市」的「公」这类高频字被判为「无可用的改写」。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================= §5 成本 ================= -->
|
||||||
|
<h2 class="h3">五 · 代价:几乎没有</h2>
|
||||||
|
<p class="small src">出处 · <code>router_scorecard_final.json</code>、<code>router_latency_bench_prod.json</code>(7 轮交错取中位数)</p>
|
||||||
|
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>指标</th><th>v2</th><th>NM2.1</th><th>说明</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>参数量</td><td class="n">2,037,774</td><td class="n">2,037,774</td><td class="small">未增加</td></tr>
|
||||||
|
<tr><td>每条记录地址字节</td><td class="n">512</td><td class="n">512</td><td class="small">存储几何未变</td></tr>
|
||||||
|
<tr><td>单查询延迟中位数(GPU)</td><td class="n">0.9549 ms</td><td class="n">0.9169 ms</td><td class="small">略快</td></tr>
|
||||||
|
<tr><td>批量 QPS(batch=64)</td><td class="n">66,037</td><td class="n acc">69,378</td><td class="small">+5.1%</td></tr>
|
||||||
|
<tr><td>批量 QPS(batch=256)</td><td class="n">207,287</td><td class="n acc">242,759</td><td class="small">+17.1%</td></tr>
|
||||||
|
<tr><td>模型包大小</td><td class="n">8.88 GB / 22 文件</td><td class="n">8.88 GB / 23 文件</td><td class="small">多出属性头 ~0.25 MB</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<p class="small">
|
||||||
|
<strong>交错基准(7 轮,消除顺序效应):</strong>单查询中位数 1.4203 ms → 1.4242 ms,差 <strong>+0.28%</strong>。
|
||||||
|
同一轮里原版自身离散度就有 4.85% —— 也就是说这个差值小于测量噪声。
|
||||||
|
<strong>零重叠那一轮里 batch=64 的读数低 9.2%,但该轮离散度是 17.4%,且同架构同参数同 FLOPs 下 batch=256 反而更快,
|
||||||
|
方向不一致,判为测量噪声而非回归</strong>;这条也写在这里,因为把噪声当结论是这个领域最常见的错误。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- ================= §6 鲁棒性 ================= -->
|
||||||
|
<h2 class="h3">六 · 工程鲁棒性</h2>
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>项目</th><th>v2</th><th>NM2.1</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>一次写 20 条不同属性事实后存活</td><td class="n">12 / 20(8 条查询前被误删)</td><td class="n acc">20 / 20</td></tr>
|
||||||
|
<tr><td>端到端(写入修复前后,16 用例)</td><td class="n">37.50%</td><td class="n acc">68.75%</td></tr>
|
||||||
|
<tr><td>替换兼容性</td><td class="n">基线</td><td class="n acc">DROP-IN OK(16 / 16 键)</td></tr>
|
||||||
|
<tr><td>单元测试</td><td class="n">—</td><td class="n acc">52 项通过</td></tr>
|
||||||
|
<tr><td>未知问题泄漏(同形候选)</td><td class="n">75.00%</td><td class="n acc">0.00%</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================= 三处改动 ================= -->
|
||||||
|
<h2 class="h3">七 · 三处改动,每处都有测量依据</h2>
|
||||||
|
|
||||||
|
<h3>改动 1 · 记录排序混合权重取 0.5</h3>
|
||||||
|
<p class="small">
|
||||||
|
<code>memory_record_router_blend</code> 控制「打包的词面重排器」与「学习出的路由器」各占多少。
|
||||||
|
调这个之前先测了剂量曲线 —— 而且**此前的同进程测量因顺序污染已作废**,下面这版是独立进程测的。
|
||||||
|
</p>
|
||||||
|
<div id="nmBlend" class="dose"></div>
|
||||||
|
|
||||||
|
<h3>改动 2 · 把加法先验参数化,然后测出「不该动」</h3>
|
||||||
|
<p class="small">
|
||||||
|
假设是「加法先验压过了学习打分」。把它暴露成可调再测,结果**调小只会更差**:
|
||||||
|
</p>
|
||||||
|
<div id="nmPrior" class="dose"></div>
|
||||||
|
<p class="small">
|
||||||
|
这是一个<strong>有价值的负面结论</strong>:它否定了原来的假设。项目里这类结论和增益一样被保留下来,
|
||||||
|
因为它们决定了后面不再往哪个方向投入。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>改动 3 · 覆盖门 —— 以及为了让它真正生效必须一起修的两处</h3>
|
||||||
|
<p class="small">
|
||||||
|
覆盖门本身很简单:先判断「这个提问在问哪个属性」,再查库里有没有这个属性。但单独加门是不生效的,
|
||||||
|
有两处**必须同时修**,否则门会被静默绕过:
|
||||||
|
</p>
|
||||||
|
<div class="lims">
|
||||||
|
<div class="lim"><span class="lim__i">01</span><div>
|
||||||
|
<h3 class="lim__t"><code>_build_text_prefix</code> 短路</h3>
|
||||||
|
<p class="lim__d">门拒绝之后如果继续往下回落,会走**旧版 16 槽注入路径**,把记忆又塞回去。
|
||||||
|
实测:不修这一处,泄漏只从 75.00% 降到 62.50%。</p></div></div>
|
||||||
|
<div class="lim"><span class="lim__i">02</span><div>
|
||||||
|
<h3 class="lim__t">闭包要动态解析 bank</h3>
|
||||||
|
<p class="lim__d"><code>reset_memory()</code> 每次都会新建 <code>memory_os_v2</code>;闭包捕获了旧引用的话,
|
||||||
|
门会永远看到一个空 bank,于是**静默旁路** —— 实测诊断输出 <code>applicable:0 / bypassed:1</code>。</p></div></div>
|
||||||
|
<div class="lim"><span class="lim__i">03</span><div>
|
||||||
|
<h3 class="lim__t">门必须自门控</h3>
|
||||||
|
<p class="lim__d">只有当库的属性集合填充了头部词表的 <strong>≥ 90%</strong> 时才让门生效。
|
||||||
|
这条阈值是必需的:放宽成「子集即可」会让门在通用套件上误判,
|
||||||
|
把 A 段可回答正确率从 100.00% 压到 92.50%、已知误拒升到 2.50%;收紧到 90% 后 A 段完全恢复,
|
||||||
|
C 段泄漏仍为 0.00%。</p></div></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================= 写入路径 ================= -->
|
||||||
|
<h2 class="h3">八 · 写入路径:为什么 20 条事实会互相销毁</h2>
|
||||||
|
<p class="small src">出处 · <code>V2_dpskw\WRITE_PATH_FIX.md</code>(根因由栈追踪确证,非推断)</p>
|
||||||
|
|
||||||
|
<div class="callout callout--warn">
|
||||||
|
<p class="eyebrow" style="color:var(--warn)">症状</p>
|
||||||
|
<p class="small" style="margin:0">
|
||||||
|
一次写入 20 条<strong>不同属性</strong>的事实后,库里有 20 条记录但只剩 <strong>12 条 active</strong>,
|
||||||
|
8 条在查询前就被 retract。16 个关键零重叠用例里有 8 个的目标记录已经不存在 ——
|
||||||
|
因此端到端正确率存在 <strong>50% 的硬上限</strong>。**任何排序器都救不回一条已经被删掉的记录。**
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="small">16 次 retract 的调用栈完全一致:</p>
|
||||||
|
<div class="code">
|
||||||
|
<div class="code__bar"><span class="code__t">call stack</span></div>
|
||||||
|
<pre><code>eval_end_to_end_memory.py:106 write_fact
|
||||||
|
-> qwen_integration.py:3807 forward
|
||||||
|
-> qwen_integration.py:2195 _write_text_memory <-- retract 调用点
|
||||||
|
-> memory_os_v2.py:2578 MemoryOSV2.retract_record
|
||||||
|
-> memory_os_v2.py:1959 PagedMemoryBankV2.retract (status = retracted)</code></pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="small">
|
||||||
|
<code>status_transition_summary == {"active->retracted": 16}</code>,无 superseded、无 quarantined,
|
||||||
|
20 次 <code>bank.write</code> 全部返回 <code>inserted</code> —— 写入路径的<strong>唯一</strong>销毁机制就是 2195 行的 retract。
|
||||||
|
授权条件 <code>confirmed_update</code> 在 20 次写入中为真 <strong>5 次</strong>,且全部只走「学习重排器
|
||||||
|
<code>learned_best >= 0.95</code>」这一条:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>写入序号</th><th>事实</th><th>learned_best</th><th>结果</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td class="n">2</td><td>出生城市</td><td class="n">0.998959</td><td>confirmed_update = True</td></tr>
|
||||||
|
<tr><td class="n">3</td><td>办公城市</td><td class="n">0.992638</td><td>confirmed_update = True</td></tr>
|
||||||
|
<tr><td class="n">9</td><td>工位楼层</td><td class="n">0.964987</td><td>confirmed_update = True</td></tr>
|
||||||
|
<tr><td class="n">12</td><td>手机尾号</td><td class="n">0.998516</td><td>confirmed_update = True</td></tr>
|
||||||
|
<tr><td class="n">15</td><td>办公楼层</td><td class="n">0.997487</td><td>confirmed_update = True</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="small">
|
||||||
|
随后 2187–2197 的循环退掉 8 条:3 条走 <code>record.slot_index == slot</code>,5 条走
|
||||||
|
<code>score >= 0.95 and shared >= 2</code>;2196 行的 <code>break</code>(仅当 <code>score < 0.98</code> 才停)
|
||||||
|
让写 #12 一次级联退掉 3 条、写 #15 退掉 2 条。被退掉的正是写 1/2/3/4/9/10/11/14 —— 16 条关键事实中的 8 条。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="grid g3">
|
||||||
|
<div class="card">
|
||||||
|
<p class="rel__k">辅助事实 1</p>
|
||||||
|
<p class="rel__v">0 / 20</p>
|
||||||
|
<p class="rel__d"><code>exact_slots.numel() > 0</code>(token 完全相同)一次都没命中 —— 精确重复路径与此无关。</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<p class="rel__k">辅助事实 2</p>
|
||||||
|
<p class="rel__v">{2,3,5,6,7}</p>
|
||||||
|
<p class="rel__d"><code>shared >= 2</code> 毫无区分力:19 个候选的 shared 全落在这个区间,因为每条事实都含「我的 / 是」模板词元。</p>
|
||||||
|
</div>
|
||||||
|
<div class="card card--warn">
|
||||||
|
<p class="rel__k">辅助事实 3</p>
|
||||||
|
<p class="rel__v">0.9985</p>
|
||||||
|
<p class="rel__d">190 个<strong>不相关</strong>属性对里有 10 个 ≥ 0.95,最高 0.9985(「常住城市」vs「出生城市」)。<strong>调阈值不可行</strong>:假阳性高达 0.9989,没有任何标量切点能分开「不相关属性」与「真更新」。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="small">
|
||||||
|
<strong>根因:</strong>retire 一条已存在记录的授权完全来自学习打分加一个固定 0.95 阈值,
|
||||||
|
没有任何「新文本与在位记录共享 <code>(entity, attribute)</code>」的<strong>结构性校验</strong>。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>修复(两处,都是结构性的)</h3>
|
||||||
|
<div class="lims">
|
||||||
|
<div class="lim"><span class="lim__i">01</span><div>
|
||||||
|
<h3 class="lim__t"><code>confirmed_update</code> 的两条打分类分支改为结构优先</h3>
|
||||||
|
<p class="lim__d">仅当候选文本的 <code>entity::attribute</code> 已经在库的
|
||||||
|
<code>active_by_conflict</code> 账本里存在(即确实是同一条事实的更新)才允许由打分授权;
|
||||||
|
<code>exact_slots</code> 这条结构安全的分支保持不变,以保留「重复写入幂等」的既有语义。</p></div></div>
|
||||||
|
<div class="lim"><span class="lim__i">02</span><div>
|
||||||
|
<h3 class="lim__t">retract 循环加冲突键守卫</h3>
|
||||||
|
<p class="lim__d"><code>if record.conflict_key() != candidate_conflict_key: continue</code> ——
|
||||||
|
循环只能退掉<strong>描述同一属性</strong>的记录,不再因「共享热槽」或「词面重叠高」销毁无关事实。</p></div></div>
|
||||||
|
</div>
|
||||||
|
<p class="small">
|
||||||
|
语义不受损:真·同属性更新本来就已经由 <code>PagedMemoryBankV2.write</code> 通过
|
||||||
|
<code>active_by_conflict</code> 做版本化(旧版本保留为 superseded、<code>version+1</code>),
|
||||||
|
修复只是移除了那条<strong>额外的、无监督的销毁路径</strong>。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>四级验证</h3>
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>级</th><th>检验</th><th>修复前</th><th>修复后</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td class="n">①</td><td><code>status_transition_summary</code></td><td class="n">{"active->retracted": 16}</td><td class="n acc">{}</td></tr>
|
||||||
|
<tr><td class="n">①</td><td><code>retraction_calls</code> / <code>status_counts</code></td><td class="n">16 次 / {retracted: 8, active: 12}</td><td class="n acc">[] / {active: 20}</td></tr>
|
||||||
|
<tr><td class="n">②</td><td>正对照:同属性改值</td><td class="n">—</td><td class="n acc">旧值 superseded + 新值 active,其余 19 属性不受影响,0 retract</td></tr>
|
||||||
|
<tr><td class="n">③</td><td>重排器缺席对照</td><td class="n">会踩死代码分支</td><td class="n acc">20 条全 active、0 retract</td></tr>
|
||||||
|
<tr><td class="n">④</td><td><code>target_record_active</code></td><td class="n">8 / 16</td><td class="n acc">16 / 16</td></tr>
|
||||||
|
<tr><td class="n">④</td><td><code>target_record_retracted_or_absent</code></td><td class="n">8</td><td class="n acc">0</td></tr>
|
||||||
|
<tr><td class="n">④</td><td><code>active_records_min / max</code></td><td class="n">12 / 12</td><td class="n acc">20 / 20</td></tr>
|
||||||
|
<tr><td class="n">④</td><td>probe 口径回答正确率</td><td class="n">25.00%(4 / 16)</td><td class="n acc">43.75%(7 / 16)</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="small"><strong>端到端效果</strong>(官方 harness,16 个零重叠用例):</p>
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>路由器</th><th>修复前</th><th>修复后</th><th>答成别的属性</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>deployed(原版 NM2)</td><td class="n">25.00%</td><td class="n acc">50.00%(+25.00 pp)</td><td class="n">18.75% → 12.50%</td></tr>
|
||||||
|
<tr><td>V2-128-v6</td><td class="n">37.50%</td><td class="n acc">68.75%(+31.25 pp)</td><td class="n">25.00% → 18.75%</td></tr>
|
||||||
|
<tr><td>REPLAY-128</td><td class="n">37.50%</td><td class="n acc">68.75%(+31.25 pp)</td><td class="n">25.00% → 18.75%</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<p class="tiny">
|
||||||
|
<strong>一个诚实的补充:</strong>这 16 个用例里 <strong>93.75% 的读取仍走旧版 16 槽路径</strong>而非 V2 库记录,
|
||||||
|
地址命中 0 / 16。写入路径的修复解除了 50% 的硬上限,但「V2 库记录真正参与读取」这一项仍未解决。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- ================= 未知拒答 ================= -->
|
||||||
|
<h2 class="h3">九 · 未知拒答:从 75% 泄漏到 100% 拒答</h2>
|
||||||
|
<p class="small src">出处 · <code>V2_dpskw\ABSTENTION_BREAKTHROUGH.md</code></p>
|
||||||
|
|
||||||
|
<p class="lede2">
|
||||||
|
这是整个项目最差的一个数字:问库里不存在的属性时,75% 的情况下模型照样编一个答案。
|
||||||
|
下面按「先排除一整类无效修法 → 再给出有效机制 → 最后如实记录接上运行时的两次失败」来写。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>9.1 先排除掉一整类无效修法(有测量支撑)</h3>
|
||||||
|
<p class="small">
|
||||||
|
最直觉的修法是「检索分数不够高就拒答」。用<strong>只在训练集拟合、评测集算 AUC</strong> 的口径,
|
||||||
|
测了四种打分器的分数几何(top1 / margin / top-k 均值 / 离散度 / 熵 / 近邻数,共 9 个特征):
|
||||||
|
</p>
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>打分器</th><th>最佳单特征 AUC</th><th>拟合头 AUC(评测集)</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>cosine(冻结键余弦)</td><td class="n">0.6257(margin)</td><td class="n">0.6086</td></tr>
|
||||||
|
<tr><td>打包 <code>text_retriever</code></td><td class="n">0.6076(margin)</td><td class="n bad">0.4752</td></tr>
|
||||||
|
<tr><td>50/50 混合</td><td class="n">0.5446</td><td class="n">0.5062</td></tr>
|
||||||
|
<tr><td>训练过的路由器</td><td class="n">0.5711</td><td class="n">0.5130</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<p class="small">
|
||||||
|
操作点同样不可用:混合打分器想标出 22% 的未知要误拒 <strong>28.40%</strong> 的可回答问题;
|
||||||
|
cosine 想标出 46% 要误拒 <strong>30.00%</strong>。
|
||||||
|
<strong>结论:75% 的泄漏不可能靠分数阈值或分数上的分类头修好。</strong>
|
||||||
|
这不是调参空间不够,而是这个信号根本不存在 —— 24 条同句式候选对任何提问都「一样像」。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>9.2 有效的机制:先判「问的是哪个属性」,再查库里有没有</h3>
|
||||||
|
<p class="small">
|
||||||
|
换一个问题问就成立了:不是「有没有候选匹配得好」,而是「这个提问在问哪个属性,这个属性在库里吗」。
|
||||||
|
</p>
|
||||||
|
<div class="grid g2">
|
||||||
|
<div>
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>封闭词表</th><th>值</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>可回答 episode 中「预测属性在候选集内」</td><td class="n acc">100.00%(250 条)</td></tr>
|
||||||
|
<tr><td>未知 episode 中「预测属性在候选集内」</td><td class="n acc">0.00%(50 条)</td></tr>
|
||||||
|
<tr><td><strong>未知拒答率</strong></td><td class="n acc">100.00%</td></tr>
|
||||||
|
<tr><td><strong>已知问题被误拒率</strong></td><td class="n acc">0.00%</td></tr>
|
||||||
|
<tr><td>混淆矩阵</td><td class="n">tp=50 fn=0 fp=0 tn=250</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="small" style="margin-top:0">
|
||||||
|
<strong>开放集:</strong>真实用户会问模型没见过的属性。只靠最大概率调阈值不够 ——
|
||||||
|
实测<strong>没有拒绝选项时,从未见过的属性 100.00% 会被认成某个存在的属性</strong>。
|
||||||
|
所以改成<strong>显式训练一个 NONE 类</strong>:词表取 12 个属性,另取 6 个词表外属性的真实提问作为 NONE 的负样本,
|
||||||
|
最后用<strong>第三组、与两者都不相交的 6 个全新属性</strong>做测试。
|
||||||
|
</p>
|
||||||
|
<div class="kv">
|
||||||
|
<div class="kv__r"><span class="kv__k">词表内属性识别(133 条未见改写)</span><span class="kv__v">100.00%</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">从未见过的属性被拒绝(52 条)</span><span class="kv__v">100.00%</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">已知问题被误拒率</span><span class="kv__v">0.00%</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">随机基线(13 类)</span><span class="kv__v">7.69%</span></div>
|
||||||
|
</div>
|
||||||
|
<p class="tiny">
|
||||||
|
运行时规则只有三步,全部可审计、无阈值调参:① 属性分类头读提问的冻结键 → 输出某个属性或 NONE;
|
||||||
|
② 若为 NONE → 拒绝;③ 若为某属性 → 查库的活跃属性集合是否包含它,不含 → 拒绝。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>9.3 接上运行时:连续失败两次(如实记录)</h3>
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>指标</th><th>NM2.1(无门)</th><th>+ 覆盖门(第一轮)</th><th>+ 门 + 短路(第二轮)</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>A 可回答正确率</td><td class="n acc">100.00%</td><td class="n bad">6.25%</td><td class="n bad">0.00%</td></tr>
|
||||||
|
<tr><td>A 已知问题被误拒率</td><td class="n acc">0.00%</td><td class="n bad">7.50%</td><td class="n bad">7.50%</td></tr>
|
||||||
|
<tr><td>A 未知拒答率</td><td class="n">56.67%</td><td class="n">43.33%</td><td class="n">—</td></tr>
|
||||||
|
<tr><td>C 未知泄漏率</td><td class="n bad">75.00%</td><td class="n">62.50%</td><td class="n acc">0.00%</td></tr>
|
||||||
|
<tr><td>C 可回答正确率</td><td class="n">65.00%</td><td class="n">65.00%</td><td class="n">65.00%</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<p class="small">
|
||||||
|
第一轮:<strong>门把几乎全部可回答问题都拒掉了</strong>(100.00% → 6.25%),而它本该修好的 C 段泄漏只从 75.00% 降到 62.50%。
|
||||||
|
第二轮定位到真正的机制缺口 —— <code>read()</code> 返回空记录后不会停止,<code>_build_text_prefix</code>
|
||||||
|
会继续落到旧版 16 槽注入路径把无关记忆又塞回去。加了短路之后,<strong>C 段泄漏真的到了 0.00%、可回答正确率无损</strong>,
|
||||||
|
但 A 段崩到 0.00%。
|
||||||
|
</p>
|
||||||
|
<p class="small">
|
||||||
|
<strong>A 段崩掉的原因已测定:</strong>段事实里 94.03% 是「这是普通对话噪声…不需要长期保存」,
|
||||||
|
只有 5.97%(63 / 1056)能解析出属性;更关键的是 <strong>A 段的属性空间完全不在属性头训练的 24 个属性之内</strong>,
|
||||||
|
头对 A 的提问只能输出那 24 个之一 → 必然不在库里 → 门把一切都拒掉。
|
||||||
|
<strong>也就是说:这个机制目前是「域内可用、跨域不可用」。</strong>
|
||||||
|
</p>
|
||||||
|
<p class="small">
|
||||||
|
结论:已把 NM2.1 的 <code>memory_coverage_gate</code> 改回 <code>false</code>,恢复为已验证的可用状态。
|
||||||
|
属性头工件保留在 <code>checkpoints/memory_attribute_head/</code>,<strong>未随包启用</strong>。
|
||||||
|
正确的最终形态是<strong>开放词表的属性匹配</strong>(把提问与库里真实存在的属性名做匹配,词表随写入动态变化),
|
||||||
|
而不是 24 类闭集分类头。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="callout callout--warn">
|
||||||
|
<p class="eyebrow" style="color:var(--warn)">这一节最该记住的一句</p>
|
||||||
|
<p class="small" style="margin:0">
|
||||||
|
离线 100.00% / 0.00% 是真实的,但它只证明了机制在「裸提问键 + 24 个可解析属性」这个条件下成立,
|
||||||
|
<strong>并不等于接上运行时就能用</strong>。这一点必须在任何对外表述里讲清楚。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================= 负面结论 ================= -->
|
||||||
|
<h2 class="h3">十 · 关键负面结论:路由器排序不影响端到端答案</h2>
|
||||||
|
<p class="small src">出处 · <code>V2_dpskw\ZERO_OVERLAP_FINDINGS.md</code> §5</p>
|
||||||
|
|
||||||
|
<p class="small">
|
||||||
|
NM2.1 的路由器在零重叠集合上 Top-1 提升了 <strong>41.20 pp</strong>,但在
|
||||||
|
<code>eval_router_critical_e2e.py</code>(16 个零重叠用例)上,REPLAY-128 与 V2-128-v6 的结果
|
||||||
|
<strong>逐位相同</strong>(默认 Top-K:37.50% / 37.50%,答成别的属性 25.00% / 25.00%,平均选中记录 5.88 / 5.88)。
|
||||||
|
</p>
|
||||||
|
<p class="small">
|
||||||
|
于是做了一个<strong>判决性实验</strong>:保留 <code>need_memory</code> / <code>hop_controller</code> / <code>head_gate</code>
|
||||||
|
全部原权重,只把排序通路(<code>query_projection</code>、<code>key_projection</code>、<code>pair_scorer</code>)
|
||||||
|
替换为同形状<strong>随机权重</strong>。结果在默认 Top-K 与 Top-K=1 下<strong>都完全不变</strong>。
|
||||||
|
</p>
|
||||||
|
<div class="lims">
|
||||||
|
<div class="lim"><span class="lim__i">01</span><div>
|
||||||
|
<h3 class="lim__t"><code>memory_os_v2.py:1671</code>:路由器分数被逐位置覆盖</h3>
|
||||||
|
<p class="lim__d">带 <code>semantic_key</code> 的记录,其 <code>_score_candidates()</code> 分数会被
|
||||||
|
<code>self.record_scorer</code> 覆盖。实测残差与 <code>text_retriever</code> 匹配 18 / 18,
|
||||||
|
与 <code>memory_router_v2</code> 匹配 0 / 18。</p></div></div>
|
||||||
|
<div class="lim"><span class="lim__i">02</span><div>
|
||||||
|
<h3 class="lim__t">「部署目录没有 <code>text_retriever.pt</code> 所以走余弦兜底」是错的</h3>
|
||||||
|
<p class="lim__d">重排器被烘焙进合并包(safetensors 内有 6 个
|
||||||
|
<code>dynamic_memory.text_retriever.*</code> 张量,1,573,377 参数),<code>_text_retriever_ready</code>
|
||||||
|
实测为 <strong>True</strong>,余弦兜底分支根本不执行。</p></div></div>
|
||||||
|
<div class="lim"><span class="lim__i">03</span><div>
|
||||||
|
<h3 class="lim__t">路由器在此配置下唯一实际生效的杠杆是 <code>need_memory</code> 门</h3>
|
||||||
|
<p class="lim__d">部署权重下门开启率 <strong>68.75%</strong>(11 / 16),而三份随机初始化的路由器只有
|
||||||
|
<strong>37.5%</strong>(6 / 16)。判决性探针只随机化了排序通路、保留了门控头,所以「端到端零变化」
|
||||||
|
是由构造保证的,不是巧合。</p></div></div>
|
||||||
|
</div>
|
||||||
|
<p class="small">
|
||||||
|
<strong>结论分两层,不要混为一谈:</strong>① 路由器记分卡上 22 / 22 的统治性和 +41.20 pp 的零重叠提升,
|
||||||
|
都是路由器工件<strong>真实</strong>的增益;② 但在这套运行时里,记录级顺序由打包的 <code>text_retriever</code> 决定,
|
||||||
|
路由器分数被覆盖,且相当比例的读取根本不走 V2 库、目标记录还会被写入路径删除。
|
||||||
|
所以<strong>路由器增益不会传递到最终答案</strong>。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- ================= 仍未解决 ================= -->
|
||||||
|
<h2 class="h3">十一 · 仍未解决(不粉饰)</h2>
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>短板</th><th>现状</th><th>说明</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>跨域未知拒答</td><td class="n bad">未解决</td><td class="small">覆盖头是 24 类闭集,只在其词表被库填充 ≥ 90% 时生效;开放词表的属性匹配实测仅 <strong>49.20% Top-1 / AUC 0.6560</strong>(零训练),不足</td></tr>
|
||||||
|
<tr><td>答成别的属性</td><td class="n">27.50%</td><td class="small">同形候选间排序仍不理想;已排除先验重加权(更差)与单纯替换打分器(更差)</td></tr>
|
||||||
|
<tr><td>A 段未知拒答率</td><td class="n">56.67%</td><td class="small">未见改善</td></tr>
|
||||||
|
<tr><td>规模验证</td><td class="n bad">未做</td><td class="small">仅 24 属性 / 300 条评测;生产需上千属性、上万改写问法</td></tr>
|
||||||
|
<tr><td>V2 库记录真正参与读取</td><td class="n bad">未解决</td><td class="small">16 个关键用例里 93.75% 仍走旧版 16 槽路径,地址命中 0 / 16</td></tr>
|
||||||
|
<tr><td>通用能力回归套件</td><td class="n bad">未跑</td><td class="small"><code>eval_general_capability.py</code> 依赖的 <code>comprehensive_general.jsonl</code> 不存在</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================= 复现 ================= -->
|
||||||
|
<h2 class="h3">十二 · 复现</h2>
|
||||||
|
<div class="code">
|
||||||
|
<div class="code__bar">
|
||||||
|
<span class="code__t">PowerShell · 整体电池(A / B / C / D 四段)</span>
|
||||||
|
<button class="copy" id="nmCopy" type="button">复制</button>
|
||||||
|
</div>
|
||||||
|
<pre><code id="nmCmd">$env:PYTHONPATH='H:\Memory'; $env:PYTHONIOENCODING='utf-8'; cd H:\Memory\V2_dpskw
|
||||||
|
|
||||||
|
# 整体电池(A/B/C/D 四段)
|
||||||
|
pwsh -NoProfile -File .\run_nm2_battery.ps1 -Package qwen3_5_4b_natural_memory_v2_1 `
|
||||||
|
-Label 'NM2.1 最终' -Tag 'nm2_1_final' -PerCategory 10 -OverlapCases 48 -Blends '0.5'
|
||||||
|
|
||||||
|
# 三代对照表
|
||||||
|
& 'C:\Users\Administrator\miniconda3\envs\LLM\python.exe' -m V2_dpskw.compare_nm2_batteries `
|
||||||
|
--tag "原版NM2=nm2_orig" --tag "NM2.1=nm2_1" --tag "NM2.1最终=nm2_1_final"
|
||||||
|
|
||||||
|
# 门的适用性诊断(确认 applicable/bypassed,避免静默旁路)
|
||||||
|
& 'C:\Users\Administrator\miniconda3\envs\LLM\python.exe' -m V2_dpskw.diagnose_coverage_gate `
|
||||||
|
--package qwen3_5_4b_natural_memory_v2_1</code></pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="small" style="margin-top:var(--sp-2xl)">
|
||||||
|
台账式的逐条原文在 <a class="linku" href="./ledger">真实评测台账</a>;
|
||||||
|
v2 的正式脏数据迁移测试在 <a class="linku" href="./results">测量结果</a>。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<nav class="pn" aria-label="章节切换"><a class="pn__a pn__a--prev" href="./results" data-dir="prev"><span class="pn__k">上一节 · 03</span><span class="pn__t">测量结果</span><span class="kbd">←</span></a><a class="pn__a pn__a--next" href="./examples" data-dir="next"><span class="pn__k">下一节 · 05</span><span class="pn__t">实测样例</span><span class="kbd">→</span></a></nav>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="wrap footer__in">
|
||||||
|
<div class="footer__col">
|
||||||
|
<p class="footer__h">作者</p>
|
||||||
|
<div class="author">
|
||||||
|
<a class="author__a" href="https://wpyw.site" target="_blank" rel="noopener">
|
||||||
|
<span class="author__k">个人网站</span><span class="author__v">wpyw.site</span>
|
||||||
|
</a>
|
||||||
|
<a class="author__a" href="mailto:[email protected]">
|
||||||
|
<span class="author__k">邮箱</span><span class="author__v">[email protected]</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">来源</p>
|
||||||
|
<div class="readout" id="footFiles"></div>
|
||||||
|
<p class="footer__h" style="margin-top:20px">服务端读数</p>
|
||||||
|
<div class="readout mono" id="footServer"><span>读取中…</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">说明</p>
|
||||||
|
<p class="footer__note" id="disclaimer"></p>
|
||||||
|
<p class="footer__meta">构建于 2026-09-16 20:39 · 所有数字取自工程内的正式报告,未做外推或估算。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<!-- 全站检索:客户端索引,无后端、无网络请求 -->
|
||||||
|
<div class="pal" id="pal" hidden>
|
||||||
|
<div class="pal__mask" id="palMask"></div>
|
||||||
|
<div class="pal__box" role="dialog" aria-modal="true" aria-label="检索全站内容">
|
||||||
|
<div class="pal__hd">
|
||||||
|
<span class="pal__ico" aria-hidden="true"></span>
|
||||||
|
<input class="pal__in" id="palInput" type="text" role="combobox" aria-expanded="true"
|
||||||
|
aria-controls="palList" autocomplete="off" spellcheck="false"
|
||||||
|
placeholder="检索全站内容:章节、数字、术语…">
|
||||||
|
<span class="kbd">Esc</span>
|
||||||
|
</div>
|
||||||
|
<div class="pal__list" id="palList" role="listbox" aria-label="检索结果"></div>
|
||||||
|
<div class="pal__ft">
|
||||||
|
<span><span class="kbd">↑</span><span class="kbd">↓</span> 选择</span>
|
||||||
|
<span><span class="kbd">↵</span> 打开</span>
|
||||||
|
<span class="pal__n mono" id="palN"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="assets/js/data.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/examples.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/restart.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/nm21.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/ledger.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/search.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/space.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/site.js?v=a9c21ef3a8"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+195
@@ -0,0 +1,195 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>复现实验 — Natural Memory v2</title>
|
||||||
|
<meta name="description" content="正式脏数据迁移测试的完整命令、协议参数与产物路径。">
|
||||||
|
<meta name="color-scheme" content="dark">
|
||||||
|
<meta name="theme-color" content="#0a0a0a">
|
||||||
|
<!-- 动效的初始隐藏态只在 JS 可用时生效;脚本被禁用时内容照常可见 -->
|
||||||
|
<script>document.documentElement.classList.add("js");</script>
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:title" content="复现实验 — Natural Memory v2">
|
||||||
|
<meta property="og:description" content="正式脏数据迁移测试的完整命令、协议参数与产物路径。">
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<link rel="icon" href="assets/favicon.svg" type="image/svg+xml">
|
||||||
|
<link rel="apple-touch-icon" href="assets/favicon.svg">
|
||||||
|
<link rel="preload" href="assets/fonts/archivo-latin-wdth-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<link rel="preload" href="assets/fonts/geist-mono-latin-wght-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<!-- 资源带构建指纹:内容一变 URL 就变,浏览器不可能再用到旧 JS/CSS -->
|
||||||
|
<link rel="stylesheet" href="assets/css/site.css?v=a9c21ef3a8">
|
||||||
|
</head>
|
||||||
|
<body data-page="reproduce" data-layout="docs">
|
||||||
|
<a class="skip" href="#doc">跳到正文</a>
|
||||||
|
|
||||||
|
<header class="site" id="site">
|
||||||
|
<div class="topbar">
|
||||||
|
<a class="brand" href="./" aria-label="Natural Memory v2 发布页">
|
||||||
|
<svg class="brand__mark" viewBox="0 0 32 32" aria-hidden="true">
|
||||||
|
<rect class="dim" x="2" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="12" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="22" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
</svg>
|
||||||
|
<span class="brand__name">Natural Memory</span>
|
||||||
|
<span class="pill pill--acc">v2</span>
|
||||||
|
</a>
|
||||||
|
<span class="crumb">
|
||||||
|
<span class="crumb__n">11</span>
|
||||||
|
<span class="crumb__t">复现实验</span>
|
||||||
|
</span>
|
||||||
|
<span class="topbar__spacer"></span>
|
||||||
|
<nav class="topnav" aria-label="快速导航">
|
||||||
|
<a class="topnav__a" href="./">发布页</a> <a class="topnav__a" href="./mechanism">机制</a> <a class="topnav__a" href="./results">测量</a> <a class="topnav__a" href="./nm21">NM2.1</a> <a class="topnav__a" href="./ledger">台账</a> <a class="topnav__a" href="./limits">边界</a> <a class="topnav__a is-on" href="./reproduce" aria-current="page">复现</a>
|
||||||
|
</nav>
|
||||||
|
<button class="palbtn" id="palBtn" type="button" aria-label="检索全站内容(快捷键 /)">
|
||||||
|
<span class="palbtn__t">检索</span><span class="kbd">/</span>
|
||||||
|
</button>
|
||||||
|
<span class="pill" id="serverChip" title="本站服务端运行时读数">
|
||||||
|
<i class="dot"></i><span id="serverChipText">读取中</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="progress" id="progress"></div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<aside class="side">
|
||||||
|
<nav class="side__in" aria-label="章节导航">
|
||||||
|
<a class="side__back" href="./">← 返回发布页</a>
|
||||||
|
<p class="side__grp">原理</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./division"><span class="side__n">01</span><span class="side__t">记忆与 KV 的分工</span></a></li>
|
||||||
|
<li><a class="side__a" href="./mechanism"><span class="side__n">02</span><span class="side__t">一次读取与一次写入</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">证据</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./results"><span class="side__n">03</span><span class="side__t">测量结果</span></a></li>
|
||||||
|
<li><a class="side__a" href="./nm21"><span class="side__n">04</span><span class="side__t">NM2.1 · 之后做了什么</span></a></li>
|
||||||
|
<li><a class="side__a" href="./examples"><span class="side__n">05</span><span class="side__t">实测样例</span></a></li>
|
||||||
|
<li><a class="side__a" href="./ledger"><span class="side__n">06</span><span class="side__t">真实评测台账</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">工程</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./cost"><span class="side__n">07</span><span class="side__t">代价账本</span></a></li>
|
||||||
|
<li><a class="side__a" href="./capacity"><span class="side__n">08</span><span class="side__t">容量与存储</span></a></li>
|
||||||
|
<li><a class="side__a" href="./limits"><span class="side__n">09</span><span class="side__t">我们不宣称的内容</span></a></li>
|
||||||
|
<li><a class="side__a" href="./roadmap"><span class="side__n">10</span><span class="side__t">已解决的与下一步</span></a></li>
|
||||||
|
<li><a class="side__a is-on" href="./reproduce" aria-current="page"><span class="side__n">11</span><span class="side__t">复现实验</span></a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
|
<main class="doc" id="doc">
|
||||||
|
<header class="doc__hd">
|
||||||
|
<span class="kicker">11 / REPRODUCE</span>
|
||||||
|
<h1 class="doc__h">复现实验</h1>
|
||||||
|
<p class="doc__lede">正式脏数据迁移测试的完整命令、协议参数与产物路径。</p>
|
||||||
|
<p class="doc__figure">
|
||||||
|
<span class="mega">264<small></small></span>
|
||||||
|
<span class="doc__figure-n">题题集 · 246 可回答 / 18 未知</span>
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
<p class="lede2">
|
||||||
|
正式脏数据迁移测试的完整命令与产物路径。协议参数与批次之间的差异见下方说明——
|
||||||
|
<strong>复现同一批次才能得到同一组数字</strong>。
|
||||||
|
</p>
|
||||||
|
<div class="grid g-2-1" >
|
||||||
|
<div class="code">
|
||||||
|
<div class="code__bar">
|
||||||
|
<span class="code__t">PowerShell · 工作目录 <span id="cwd"></span></span>
|
||||||
|
<button class="copy" id="copyBtn" type="button">复制命令</button>
|
||||||
|
</div>
|
||||||
|
<pre><code id="cmdBlock"></code></pre>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="kv" id="files"></div>
|
||||||
|
<div class="card card--flat" >
|
||||||
|
<p class="eyebrow" >PROTOCOL</p>
|
||||||
|
<div class="flow__meta" style="padding:0; border:0">
|
||||||
|
<div><span>基座模型</span><b id="pBase"></b></div>
|
||||||
|
<div><span>量化</span><b>4-bit NF4</b></div>
|
||||||
|
<div><span>解码</span><b>greedy</b></div>
|
||||||
|
<div><span>最大新生成</span><b>64 token</b></div>
|
||||||
|
<div><span>进程显存上限</span><b>10 GiB</b></div>
|
||||||
|
<div><span>记忆读取上限</span><b>2 records</b></div>
|
||||||
|
<div><span>地址编码</span><b>batch size 1</b></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="callout" >
|
||||||
|
<p class="callout__t">两个批次的差别</p>
|
||||||
|
<p class="callout__b">
|
||||||
|
上面的命令复现的是批次 A(对外技术总结采用的口径,可答题 154/246)。
|
||||||
|
批次 B 来自同目录的 <code>dirty_real_corpus_compare_4b_router_final.json</code>,
|
||||||
|
是接入记忆路由器之后的另一次运行(可答题 203/246)。两次运行的配置不同,
|
||||||
|
<strong>因此它们的分数不能平均、不能合并,也不能互相替代</strong>。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav class="pn" aria-label="章节切换"><a class="pn__a pn__a--prev" href="./roadmap" data-dir="prev"><span class="pn__k">上一节 · 10</span><span class="pn__t">已解决的与下一步</span><span class="kbd">←</span></a><span class="pn__x"></span></nav>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="wrap footer__in">
|
||||||
|
<div class="footer__col">
|
||||||
|
<p class="footer__h">作者</p>
|
||||||
|
<div class="author">
|
||||||
|
<a class="author__a" href="https://wpyw.site" target="_blank" rel="noopener">
|
||||||
|
<span class="author__k">个人网站</span><span class="author__v">wpyw.site</span>
|
||||||
|
</a>
|
||||||
|
<a class="author__a" href="mailto:[email protected]">
|
||||||
|
<span class="author__k">邮箱</span><span class="author__v">[email protected]</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">来源</p>
|
||||||
|
<div class="readout" id="footFiles"></div>
|
||||||
|
<p class="footer__h" style="margin-top:20px">服务端读数</p>
|
||||||
|
<div class="readout mono" id="footServer"><span>读取中…</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">说明</p>
|
||||||
|
<p class="footer__note" id="disclaimer"></p>
|
||||||
|
<p class="footer__meta">构建于 2026-09-16 20:39 · 所有数字取自工程内的正式报告,未做外推或估算。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<!-- 全站检索:客户端索引,无后端、无网络请求 -->
|
||||||
|
<div class="pal" id="pal" hidden>
|
||||||
|
<div class="pal__mask" id="palMask"></div>
|
||||||
|
<div class="pal__box" role="dialog" aria-modal="true" aria-label="检索全站内容">
|
||||||
|
<div class="pal__hd">
|
||||||
|
<span class="pal__ico" aria-hidden="true"></span>
|
||||||
|
<input class="pal__in" id="palInput" type="text" role="combobox" aria-expanded="true"
|
||||||
|
aria-controls="palList" autocomplete="off" spellcheck="false"
|
||||||
|
placeholder="检索全站内容:章节、数字、术语…">
|
||||||
|
<span class="kbd">Esc</span>
|
||||||
|
</div>
|
||||||
|
<div class="pal__list" id="palList" role="listbox" aria-label="检索结果"></div>
|
||||||
|
<div class="pal__ft">
|
||||||
|
<span><span class="kbd">↑</span><span class="kbd">↓</span> 选择</span>
|
||||||
|
<span><span class="kbd">↵</span> 打开</span>
|
||||||
|
<span class="pal__n mono" id="palN"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="assets/js/data.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/examples.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/restart.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/nm21.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/ledger.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/search.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/space.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/site.js?v=a9c21ef3a8"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+170
@@ -0,0 +1,170 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>测量结果 — Natural Memory v2</title>
|
||||||
|
<meta name="description" content="同一 264 题题集的两个独立批次、结构化工程基准与记忆路由器工程线的全部实测数字,均标注出处与口径。">
|
||||||
|
<meta name="color-scheme" content="dark">
|
||||||
|
<meta name="theme-color" content="#0a0a0a">
|
||||||
|
<!-- 动效的初始隐藏态只在 JS 可用时生效;脚本被禁用时内容照常可见 -->
|
||||||
|
<script>document.documentElement.classList.add("js");</script>
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:title" content="测量结果 — Natural Memory v2">
|
||||||
|
<meta property="og:description" content="同一 264 题题集的两个独立批次、结构化工程基准与记忆路由器工程线的全部实测数字,均标注出处与口径。">
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<link rel="icon" href="assets/favicon.svg" type="image/svg+xml">
|
||||||
|
<link rel="apple-touch-icon" href="assets/favicon.svg">
|
||||||
|
<link rel="preload" href="assets/fonts/archivo-latin-wdth-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<link rel="preload" href="assets/fonts/geist-mono-latin-wght-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<!-- 资源带构建指纹:内容一变 URL 就变,浏览器不可能再用到旧 JS/CSS -->
|
||||||
|
<link rel="stylesheet" href="assets/css/site.css?v=a9c21ef3a8">
|
||||||
|
</head>
|
||||||
|
<body data-page="results" data-layout="docs">
|
||||||
|
<a class="skip" href="#doc">跳到正文</a>
|
||||||
|
|
||||||
|
<header class="site" id="site">
|
||||||
|
<div class="topbar">
|
||||||
|
<a class="brand" href="./" aria-label="Natural Memory v2 发布页">
|
||||||
|
<svg class="brand__mark" viewBox="0 0 32 32" aria-hidden="true">
|
||||||
|
<rect class="dim" x="2" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="12" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="22" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
</svg>
|
||||||
|
<span class="brand__name">Natural Memory</span>
|
||||||
|
<span class="pill pill--acc">v2</span>
|
||||||
|
</a>
|
||||||
|
<span class="crumb">
|
||||||
|
<span class="crumb__n">03</span>
|
||||||
|
<span class="crumb__t">测量结果</span>
|
||||||
|
</span>
|
||||||
|
<span class="topbar__spacer"></span>
|
||||||
|
<nav class="topnav" aria-label="快速导航">
|
||||||
|
<a class="topnav__a" href="./">发布页</a> <a class="topnav__a" href="./mechanism">机制</a> <a class="topnav__a is-on" href="./results" aria-current="page">测量</a> <a class="topnav__a" href="./nm21">NM2.1</a> <a class="topnav__a" href="./ledger">台账</a> <a class="topnav__a" href="./limits">边界</a> <a class="topnav__a" href="./reproduce">复现</a>
|
||||||
|
</nav>
|
||||||
|
<button class="palbtn" id="palBtn" type="button" aria-label="检索全站内容(快捷键 /)">
|
||||||
|
<span class="palbtn__t">检索</span><span class="kbd">/</span>
|
||||||
|
</button>
|
||||||
|
<span class="pill" id="serverChip" title="本站服务端运行时读数">
|
||||||
|
<i class="dot"></i><span id="serverChipText">读取中</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="progress" id="progress"></div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<aside class="side">
|
||||||
|
<nav class="side__in" aria-label="章节导航">
|
||||||
|
<a class="side__back" href="./">← 返回发布页</a>
|
||||||
|
<p class="side__grp">原理</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./division"><span class="side__n">01</span><span class="side__t">记忆与 KV 的分工</span></a></li>
|
||||||
|
<li><a class="side__a" href="./mechanism"><span class="side__n">02</span><span class="side__t">一次读取与一次写入</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">证据</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a is-on" href="./results" aria-current="page"><span class="side__n">03</span><span class="side__t">测量结果</span></a></li>
|
||||||
|
<li><a class="side__a" href="./nm21"><span class="side__n">04</span><span class="side__t">NM2.1 · 之后做了什么</span></a></li>
|
||||||
|
<li><a class="side__a" href="./examples"><span class="side__n">05</span><span class="side__t">实测样例</span></a></li>
|
||||||
|
<li><a class="side__a" href="./ledger"><span class="side__n">06</span><span class="side__t">真实评测台账</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">工程</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./cost"><span class="side__n">07</span><span class="side__t">代价账本</span></a></li>
|
||||||
|
<li><a class="side__a" href="./capacity"><span class="side__n">08</span><span class="side__t">容量与存储</span></a></li>
|
||||||
|
<li><a class="side__a" href="./limits"><span class="side__n">09</span><span class="side__t">我们不宣称的内容</span></a></li>
|
||||||
|
<li><a class="side__a" href="./roadmap"><span class="side__n">10</span><span class="side__t">已解决的与下一步</span></a></li>
|
||||||
|
<li><a class="side__a" href="./reproduce"><span class="side__n">11</span><span class="side__t">复现实验</span></a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
|
<main class="doc" id="doc">
|
||||||
|
<header class="doc__hd">
|
||||||
|
<span class="kicker">03 / MEASUREMENTS</span>
|
||||||
|
<h1 class="doc__h">测量结果</h1>
|
||||||
|
<p class="doc__lede">同一 264 题题集的两个独立批次、结构化工程基准与记忆路由器工程线的全部实测数字,均标注出处与口径。</p>
|
||||||
|
<p class="doc__figure">
|
||||||
|
<span class="mega">82.52<small>%</small></span>
|
||||||
|
<span class="doc__figure-n">批次 B 可回答正确率 · 批次 A 为 62.60%,两批配置不同、不可合并</span>
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
<p class="lede2">
|
||||||
|
三个面板对应三组不同的题集与口径,<strong>不能合并成一个总分</strong>。
|
||||||
|
面板一是同一题集先后跑的两个独立批次(配置不同、分数不可合并,只能并列读);
|
||||||
|
面板二是结构化工程基准;面板三是记忆路由器工程线。每组数据都标注了出处、日期与口径。
|
||||||
|
</p>
|
||||||
|
<p class="small" style="max-width:80ch">
|
||||||
|
读这些数字时请留意两件事:<strong>所有对照都使用同一 tokenizer、同一 greedy 解码、同一 64 token 输出上限</strong>;
|
||||||
|
而<strong>检索召回率与回答正确率是两个必须分开报告的量</strong>——这一点在面板一里体现得最清楚。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="tabs reveal" id="resultTabs" role="tablist" ></div>
|
||||||
|
<div id="resultPanels" ></div>
|
||||||
|
|
||||||
|
<nav class="pn" aria-label="章节切换"><a class="pn__a pn__a--prev" href="./mechanism" data-dir="prev"><span class="pn__k">上一节 · 02</span><span class="pn__t">一次读取与一次写入</span><span class="kbd">←</span></a><a class="pn__a pn__a--next" href="./nm21" data-dir="next"><span class="pn__k">下一节 · 04</span><span class="pn__t">NM2.1 · 之后做了什么</span><span class="kbd">→</span></a></nav>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="wrap footer__in">
|
||||||
|
<div class="footer__col">
|
||||||
|
<p class="footer__h">作者</p>
|
||||||
|
<div class="author">
|
||||||
|
<a class="author__a" href="https://wpyw.site" target="_blank" rel="noopener">
|
||||||
|
<span class="author__k">个人网站</span><span class="author__v">wpyw.site</span>
|
||||||
|
</a>
|
||||||
|
<a class="author__a" href="mailto:[email protected]">
|
||||||
|
<span class="author__k">邮箱</span><span class="author__v">[email protected]</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">来源</p>
|
||||||
|
<div class="readout" id="footFiles"></div>
|
||||||
|
<p class="footer__h" style="margin-top:20px">服务端读数</p>
|
||||||
|
<div class="readout mono" id="footServer"><span>读取中…</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">说明</p>
|
||||||
|
<p class="footer__note" id="disclaimer"></p>
|
||||||
|
<p class="footer__meta">构建于 2026-09-16 20:39 · 所有数字取自工程内的正式报告,未做外推或估算。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<!-- 全站检索:客户端索引,无后端、无网络请求 -->
|
||||||
|
<div class="pal" id="pal" hidden>
|
||||||
|
<div class="pal__mask" id="palMask"></div>
|
||||||
|
<div class="pal__box" role="dialog" aria-modal="true" aria-label="检索全站内容">
|
||||||
|
<div class="pal__hd">
|
||||||
|
<span class="pal__ico" aria-hidden="true"></span>
|
||||||
|
<input class="pal__in" id="palInput" type="text" role="combobox" aria-expanded="true"
|
||||||
|
aria-controls="palList" autocomplete="off" spellcheck="false"
|
||||||
|
placeholder="检索全站内容:章节、数字、术语…">
|
||||||
|
<span class="kbd">Esc</span>
|
||||||
|
</div>
|
||||||
|
<div class="pal__list" id="palList" role="listbox" aria-label="检索结果"></div>
|
||||||
|
<div class="pal__ft">
|
||||||
|
<span><span class="kbd">↑</span><span class="kbd">↓</span> 选择</span>
|
||||||
|
<span><span class="kbd">↵</span> 打开</span>
|
||||||
|
<span class="pal__n mono" id="palN"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="assets/js/data.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/examples.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/restart.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/nm21.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/ledger.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/search.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/space.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/site.js?v=a9c21ef3a8"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+166
@@ -0,0 +1,166 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>已解决的与下一步 — Natural Memory v2</title>
|
||||||
|
<meta name="description" content="在 12 GiB GPU 上已经跑通的闭环,以及按对正确率最有帮助的顺序排出的下一阶段任务。">
|
||||||
|
<meta name="color-scheme" content="dark">
|
||||||
|
<meta name="theme-color" content="#0a0a0a">
|
||||||
|
<!-- 动效的初始隐藏态只在 JS 可用时生效;脚本被禁用时内容照常可见 -->
|
||||||
|
<script>document.documentElement.classList.add("js");</script>
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:title" content="已解决的与下一步 — Natural Memory v2">
|
||||||
|
<meta property="og:description" content="在 12 GiB GPU 上已经跑通的闭环,以及按对正确率最有帮助的顺序排出的下一阶段任务。">
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<link rel="icon" href="assets/favicon.svg" type="image/svg+xml">
|
||||||
|
<link rel="apple-touch-icon" href="assets/favicon.svg">
|
||||||
|
<link rel="preload" href="assets/fonts/archivo-latin-wdth-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<link rel="preload" href="assets/fonts/geist-mono-latin-wght-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<!-- 资源带构建指纹:内容一变 URL 就变,浏览器不可能再用到旧 JS/CSS -->
|
||||||
|
<link rel="stylesheet" href="assets/css/site.css?v=a9c21ef3a8">
|
||||||
|
</head>
|
||||||
|
<body data-page="roadmap" data-layout="docs">
|
||||||
|
<a class="skip" href="#doc">跳到正文</a>
|
||||||
|
|
||||||
|
<header class="site" id="site">
|
||||||
|
<div class="topbar">
|
||||||
|
<a class="brand" href="./" aria-label="Natural Memory v2 发布页">
|
||||||
|
<svg class="brand__mark" viewBox="0 0 32 32" aria-hidden="true">
|
||||||
|
<rect class="dim" x="2" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="12" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="22" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
</svg>
|
||||||
|
<span class="brand__name">Natural Memory</span>
|
||||||
|
<span class="pill pill--acc">v2</span>
|
||||||
|
</a>
|
||||||
|
<span class="crumb">
|
||||||
|
<span class="crumb__n">10</span>
|
||||||
|
<span class="crumb__t">已解决的与下一步</span>
|
||||||
|
</span>
|
||||||
|
<span class="topbar__spacer"></span>
|
||||||
|
<nav class="topnav" aria-label="快速导航">
|
||||||
|
<a class="topnav__a" href="./">发布页</a> <a class="topnav__a" href="./mechanism">机制</a> <a class="topnav__a" href="./results">测量</a> <a class="topnav__a" href="./nm21">NM2.1</a> <a class="topnav__a" href="./ledger">台账</a> <a class="topnav__a" href="./limits">边界</a> <a class="topnav__a" href="./reproduce">复现</a>
|
||||||
|
</nav>
|
||||||
|
<button class="palbtn" id="palBtn" type="button" aria-label="检索全站内容(快捷键 /)">
|
||||||
|
<span class="palbtn__t">检索</span><span class="kbd">/</span>
|
||||||
|
</button>
|
||||||
|
<span class="pill" id="serverChip" title="本站服务端运行时读数">
|
||||||
|
<i class="dot"></i><span id="serverChipText">读取中</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="progress" id="progress"></div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<aside class="side">
|
||||||
|
<nav class="side__in" aria-label="章节导航">
|
||||||
|
<a class="side__back" href="./">← 返回发布页</a>
|
||||||
|
<p class="side__grp">原理</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./division"><span class="side__n">01</span><span class="side__t">记忆与 KV 的分工</span></a></li>
|
||||||
|
<li><a class="side__a" href="./mechanism"><span class="side__n">02</span><span class="side__t">一次读取与一次写入</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">证据</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./results"><span class="side__n">03</span><span class="side__t">测量结果</span></a></li>
|
||||||
|
<li><a class="side__a" href="./nm21"><span class="side__n">04</span><span class="side__t">NM2.1 · 之后做了什么</span></a></li>
|
||||||
|
<li><a class="side__a" href="./examples"><span class="side__n">05</span><span class="side__t">实测样例</span></a></li>
|
||||||
|
<li><a class="side__a" href="./ledger"><span class="side__n">06</span><span class="side__t">真实评测台账</span></a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="side__grp">工程</p>
|
||||||
|
<ul class="side__list">
|
||||||
|
<li><a class="side__a" href="./cost"><span class="side__n">07</span><span class="side__t">代价账本</span></a></li>
|
||||||
|
<li><a class="side__a" href="./capacity"><span class="side__n">08</span><span class="side__t">容量与存储</span></a></li>
|
||||||
|
<li><a class="side__a" href="./limits"><span class="side__n">09</span><span class="side__t">我们不宣称的内容</span></a></li>
|
||||||
|
<li><a class="side__a is-on" href="./roadmap" aria-current="page"><span class="side__n">10</span><span class="side__t">已解决的与下一步</span></a></li>
|
||||||
|
<li><a class="side__a" href="./reproduce"><span class="side__n">11</span><span class="side__t">复现实验</span></a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
|
<main class="doc" id="doc">
|
||||||
|
<header class="doc__hd">
|
||||||
|
<span class="kicker">10 / STATUS & NEXT</span>
|
||||||
|
<h1 class="doc__h">已解决的与下一步</h1>
|
||||||
|
<p class="doc__lede">在 12 GiB GPU 上已经跑通的闭环,以及按对正确率最有帮助的顺序排出的下一阶段任务。</p>
|
||||||
|
<p class="doc__figure">
|
||||||
|
<span class="mega">52<small></small></span>
|
||||||
|
<span class="doc__figure-n">项单元测试通过</span>
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
<p class="lede2">
|
||||||
|
左侧是在 12 GiB GPU 上已经跑通的闭环;右侧是按<strong>对正确率最有帮助的顺序</strong>排出的下一阶段工程任务。
|
||||||
|
这里刻意不写时间表——顺序比日期更可信。
|
||||||
|
</p>
|
||||||
|
<h2 class="h3" >已经解决的问题</h2>
|
||||||
|
<div class="checks" id="solved" ></div>
|
||||||
|
<h2 class="h3" >下一阶段的工程任务</h2>
|
||||||
|
<div class="road" id="roadmap-list" ></div>
|
||||||
|
|
||||||
|
<nav class="pn" aria-label="章节切换"><a class="pn__a pn__a--prev" href="./limits" data-dir="prev"><span class="pn__k">上一节 · 09</span><span class="pn__t">我们不宣称的内容</span><span class="kbd">←</span></a><a class="pn__a pn__a--next" href="./reproduce" data-dir="next"><span class="pn__k">下一节 · 11</span><span class="pn__t">复现实验</span><span class="kbd">→</span></a></nav>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="wrap footer__in">
|
||||||
|
<div class="footer__col">
|
||||||
|
<p class="footer__h">作者</p>
|
||||||
|
<div class="author">
|
||||||
|
<a class="author__a" href="https://wpyw.site" target="_blank" rel="noopener">
|
||||||
|
<span class="author__k">个人网站</span><span class="author__v">wpyw.site</span>
|
||||||
|
</a>
|
||||||
|
<a class="author__a" href="mailto:[email protected]">
|
||||||
|
<span class="author__k">邮箱</span><span class="author__v">[email protected]</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">来源</p>
|
||||||
|
<div class="readout" id="footFiles"></div>
|
||||||
|
<p class="footer__h" style="margin-top:20px">服务端读数</p>
|
||||||
|
<div class="readout mono" id="footServer"><span>读取中…</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">说明</p>
|
||||||
|
<p class="footer__note" id="disclaimer"></p>
|
||||||
|
<p class="footer__meta">构建于 2026-09-16 20:39 · 所有数字取自工程内的正式报告,未做外推或估算。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<!-- 全站检索:客户端索引,无后端、无网络请求 -->
|
||||||
|
<div class="pal" id="pal" hidden>
|
||||||
|
<div class="pal__mask" id="palMask"></div>
|
||||||
|
<div class="pal__box" role="dialog" aria-modal="true" aria-label="检索全站内容">
|
||||||
|
<div class="pal__hd">
|
||||||
|
<span class="pal__ico" aria-hidden="true"></span>
|
||||||
|
<input class="pal__in" id="palInput" type="text" role="combobox" aria-expanded="true"
|
||||||
|
aria-controls="palList" autocomplete="off" spellcheck="false"
|
||||||
|
placeholder="检索全站内容:章节、数字、术语…">
|
||||||
|
<span class="kbd">Esc</span>
|
||||||
|
</div>
|
||||||
|
<div class="pal__list" id="palList" role="listbox" aria-label="检索结果"></div>
|
||||||
|
<div class="pal__ft">
|
||||||
|
<span><span class="kbd">↑</span><span class="kbd">↓</span> 选择</span>
|
||||||
|
<span><span class="kbd">↵</span> 打开</span>
|
||||||
|
<span class="pal__n mono" id="palN"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="assets/js/data.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/examples.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/restart.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/nm21.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/ledger.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/search.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/space.js?v=a9c21ef3a8"></script>
|
||||||
|
<script src="assets/js/site.js?v=a9c21ef3a8"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,229 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Natural Memory v2 — 站点服务端
|
||||||
|
|
||||||
|
纯标准库实现,无第三方依赖(目标环境 Python 3.8+)。
|
||||||
|
|
||||||
|
默认监听 127.0.0.1:7443(仅本机可达,供 Cloudflare Tunnel 等反向代理使用)。
|
||||||
|
如需对外直接监听,显式指定 --host 0.0.0.0。
|
||||||
|
|
||||||
|
用法:
|
||||||
|
python server.py
|
||||||
|
python server.py --host 0.0.0.0 --port 7443
|
||||||
|
set NM_PORT=8443 && python server.py
|
||||||
|
|
||||||
|
设计约定(安全默认):
|
||||||
|
只放行 index.html 与 assets/ 下白名单扩展名的文件,其余全部 404。
|
||||||
|
server.py、启动脚本、说明文档等一律不通过 HTTP 暴露;目录列表关闭。
|
||||||
|
任何包含 .. / . / 反斜杠 / NUL 的路径直接拒绝。
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import mimetypes
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
|
||||||
|
from urllib.parse import unquote, urlparse
|
||||||
|
|
||||||
|
ROOT = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
SITE_VERSION = "v2"
|
||||||
|
STARTED = time.time()
|
||||||
|
|
||||||
|
# Python 3.8 的 mimetypes 不认 woff2,需要显式登记
|
||||||
|
mimetypes.add_type("font/woff2", ".woff2")
|
||||||
|
mimetypes.add_type("font/woff", ".woff")
|
||||||
|
mimetypes.add_type("application/javascript", ".js")
|
||||||
|
mimetypes.add_type("image/svg+xml", ".svg")
|
||||||
|
|
||||||
|
ALLOWED_EXT = {
|
||||||
|
".html", ".css", ".js", ".mjs", ".json",
|
||||||
|
".woff2", ".woff", ".ttf",
|
||||||
|
".svg", ".png", ".jpg", ".jpeg", ".webp", ".avif", ".ico",
|
||||||
|
}
|
||||||
|
ALLOWED_ROOT_FILES = {"index.html", "favicon.ico", "robots.txt"}
|
||||||
|
|
||||||
|
# 生成出来的分页(build.py 的 PAGES 列表)。支持 /division 与 /division.html 两种写法。
|
||||||
|
PAGE_SLUGS = {
|
||||||
|
"index", "division", "mechanism", "results", "nm21", "examples",
|
||||||
|
"ledger", "cost", "capacity", "limits", "roadmap", "reproduce",
|
||||||
|
}
|
||||||
|
|
||||||
|
LONG_CACHE = (".woff2", ".woff", ".ttf", ".png", ".jpg", ".jpeg", ".webp", ".avif", ".svg", ".ico")
|
||||||
|
NO_CACHE = (".html", ".css", ".js", ".json")
|
||||||
|
|
||||||
|
|
||||||
|
def human_uptime(seconds: float) -> str:
|
||||||
|
seconds = int(seconds)
|
||||||
|
d, rem = divmod(seconds, 86400)
|
||||||
|
h, rem = divmod(rem, 3600)
|
||||||
|
m, s = divmod(rem, 60)
|
||||||
|
if d:
|
||||||
|
return "%dd %dh" % (d, h)
|
||||||
|
if h:
|
||||||
|
return "%dh %dm" % (h, m)
|
||||||
|
if m:
|
||||||
|
return "%dm %ds" % (m, s)
|
||||||
|
return "%ds" % s
|
||||||
|
|
||||||
|
|
||||||
|
class Handler(SimpleHTTPRequestHandler):
|
||||||
|
server_version = "NaturalMemorySite/" + SITE_VERSION
|
||||||
|
protocol_version = "HTTP/1.1"
|
||||||
|
|
||||||
|
# ---------------- 路径安全 ----------------
|
||||||
|
@staticmethod
|
||||||
|
def _safe_rel(path: str):
|
||||||
|
"""把请求路径解析为站点内的相对路径;不合规返回 None。"""
|
||||||
|
raw = unquote(path or "")
|
||||||
|
if "\x00" in raw or "\\" in raw:
|
||||||
|
return None
|
||||||
|
segs = raw.split("/")
|
||||||
|
if any(s in (".", "..") for s in segs):
|
||||||
|
return None
|
||||||
|
segs = [s for s in segs if s]
|
||||||
|
if not segs:
|
||||||
|
return "index.html"
|
||||||
|
if len(segs) == 1:
|
||||||
|
name = segs[0]
|
||||||
|
if name in ALLOWED_ROOT_FILES:
|
||||||
|
return name
|
||||||
|
# 干净 URL:/division → division.html
|
||||||
|
if name in PAGE_SLUGS:
|
||||||
|
return "index.html" if name == "index" else "%s.html" % name
|
||||||
|
if name.endswith(".html") and name[:-5] in PAGE_SLUGS:
|
||||||
|
return name
|
||||||
|
return None
|
||||||
|
if segs[0] == "assets" and os.path.splitext(segs[-1])[1].lower() in ALLOWED_EXT:
|
||||||
|
return "/".join(segs)
|
||||||
|
return None
|
||||||
|
|
||||||
|
# ---------------- 运行时读数 ----------------
|
||||||
|
def _status_payload(self) -> bytes:
|
||||||
|
host, port = self.server.server_address[0], self.server.server_address[1]
|
||||||
|
payload = {
|
||||||
|
"site": "Natural Memory " + SITE_VERSION,
|
||||||
|
"note": "以下为本站 Web 服务进程的读数,不是模型运行时的指标。",
|
||||||
|
"host": getattr(self.server, "display_host", host),
|
||||||
|
"bind": "%s:%d" % (host, port),
|
||||||
|
"python": "%d.%d.%d" % sys.version_info[:3],
|
||||||
|
"uptime": human_uptime(time.time() - STARTED),
|
||||||
|
"uptime_seconds": round(time.time() - STARTED, 1),
|
||||||
|
"requests": getattr(self.server, "request_count", 0),
|
||||||
|
"started": datetime.fromtimestamp(STARTED).astimezone().isoformat(timespec="seconds"),
|
||||||
|
"now": datetime.now(timezone.utc).astimezone().isoformat(timespec="seconds"),
|
||||||
|
}
|
||||||
|
return json.dumps(payload, ensure_ascii=False).encode("utf-8")
|
||||||
|
|
||||||
|
def _send_json(self, body: bytes, status: int = 200) -> None:
|
||||||
|
self.send_response(status)
|
||||||
|
self.send_header("Content-Type", "application/json; charset=utf-8")
|
||||||
|
self.send_header("Content-Length", str(len(body)))
|
||||||
|
self.send_header("Cache-Control", "no-store")
|
||||||
|
self.end_headers()
|
||||||
|
if self.command != "HEAD":
|
||||||
|
self.wfile.write(body)
|
||||||
|
|
||||||
|
# ---------------- 路由 ----------------
|
||||||
|
def _dispatch(self, with_body: bool) -> None:
|
||||||
|
self.server.request_count = getattr(self.server, "request_count", 0) + 1
|
||||||
|
path = urlparse(self.path).path
|
||||||
|
|
||||||
|
if path.rstrip("/") == "/api/status":
|
||||||
|
self._send_json(self._status_payload())
|
||||||
|
return
|
||||||
|
|
||||||
|
if path == "/healthz":
|
||||||
|
self._send_json(b'{"ok":true}')
|
||||||
|
return
|
||||||
|
|
||||||
|
rel = self._safe_rel(path)
|
||||||
|
if rel is None:
|
||||||
|
# 不区分「不存在」与「不允许」,避免泄露文件是否存在
|
||||||
|
self.send_error(404, "Not Found")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.path = "/" + rel
|
||||||
|
if with_body:
|
||||||
|
SimpleHTTPRequestHandler.do_GET(self)
|
||||||
|
else:
|
||||||
|
SimpleHTTPRequestHandler.do_HEAD(self)
|
||||||
|
|
||||||
|
def do_GET(self): # noqa: N802
|
||||||
|
self._dispatch(True)
|
||||||
|
|
||||||
|
def do_HEAD(self): # noqa: N802
|
||||||
|
self._dispatch(False)
|
||||||
|
|
||||||
|
# ---------------- 缓存与安全响应头 ----------------
|
||||||
|
def end_headers(self):
|
||||||
|
path = urlparse(self.path).path.lower()
|
||||||
|
if path.endswith(".html"):
|
||||||
|
# 页面本体永不缓存:模板一变立刻生效
|
||||||
|
self.send_header("Cache-Control", "no-store")
|
||||||
|
elif path.endswith(LONG_CACHE):
|
||||||
|
# 静态资源走构建指纹(?v=hash),可长期不可变缓存
|
||||||
|
self.send_header("Cache-Control", "public, max-age=604800, immutable")
|
||||||
|
elif path.endswith(NO_CACHE):
|
||||||
|
self.send_header("Cache-Control", "no-cache")
|
||||||
|
self.send_header("X-Content-Type-Options", "nosniff")
|
||||||
|
self.send_header("Referrer-Policy", "same-origin")
|
||||||
|
self.send_header("X-Frame-Options", "SAMEORIGIN")
|
||||||
|
super().end_headers()
|
||||||
|
|
||||||
|
# ---------------- 关闭目录列表 ----------------
|
||||||
|
def list_directory(self, path):
|
||||||
|
self.send_error(404, "Not Found")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def log_message(self, fmt, *args):
|
||||||
|
sys.stderr.write("[%s] %s %s\n" % (
|
||||||
|
datetime.now().strftime("%H:%M:%S"), self.address_string(), fmt % args,
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
class Server(ThreadingHTTPServer):
|
||||||
|
"""ThreadingHTTPServer 已含 ThreadingMixIn,这里只补充运行时读数字段。"""
|
||||||
|
daemon_threads = True
|
||||||
|
allow_reuse_address = True
|
||||||
|
request_count = 0
|
||||||
|
display_host = "127.0.0.1"
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
ap = argparse.ArgumentParser(description="Natural Memory v2 site server")
|
||||||
|
ap.add_argument("--host", default=os.environ.get("NM_HOST", "127.0.0.1"),
|
||||||
|
help="监听地址(默认 127.0.0.1,仅本机可达)")
|
||||||
|
ap.add_argument("--port", type=int, default=int(os.environ.get("NM_PORT", "7443")),
|
||||||
|
help="监听端口(默认 7443)")
|
||||||
|
args = ap.parse_args()
|
||||||
|
|
||||||
|
if not os.path.isfile(os.path.join(ROOT, "index.html")):
|
||||||
|
sys.stderr.write("index.html 不在 %s,请从站点根目录启动。\n" % ROOT)
|
||||||
|
return 2
|
||||||
|
|
||||||
|
httpd = Server((args.host, args.port), lambda *a, **kw: Handler(*a, directory=ROOT, **kw))
|
||||||
|
httpd.display_host = args.host
|
||||||
|
|
||||||
|
print("Natural Memory %s — site server" % SITE_VERSION)
|
||||||
|
print(" 根目录 : %s" % ROOT)
|
||||||
|
print(" 监听 : http://%s:%d/" % (args.host, args.port))
|
||||||
|
print(" 读数 : http://%s:%d/api/status" % (args.host, args.port))
|
||||||
|
if args.host in ("127.0.0.1", "localhost"):
|
||||||
|
print(" 提示 : 当前仅本机可达;需要对外请用反向代理,或显式 --host 0.0.0.0")
|
||||||
|
print(" Ctrl+C 退出")
|
||||||
|
try:
|
||||||
|
httpd.serve_forever()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\n已停止。")
|
||||||
|
finally:
|
||||||
|
httpd.server_close()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<p class="lede2">
|
||||||
|
「一百万记录容量」是<strong>地址空间和分页结构的容量</strong>,不是本次已经装入了一百万条语义记忆,
|
||||||
|
也不是一百万条记录已经通过端到端测试。这一节把容量、实际用量与存储方式分开列清楚。
|
||||||
|
</p>
|
||||||
|
<div class="grid g-2-1" >
|
||||||
|
<div class="card card--flat">
|
||||||
|
<p class="eyebrow" >PAGE MAP · 32768 PAGES × 32 SLOTS</p>
|
||||||
|
<div class="pagemap" id="pageMap" aria-hidden="true"></div>
|
||||||
|
<p class="tiny" >高亮部分为本次运行实际使用的页面(批次 A:23 页 / 723 条 active records;批次 B:24 页 / 738 条)。其余为地址空间余量。</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="cap" id="capList"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="grid g2" >
|
||||||
|
<div class="card">
|
||||||
|
<p class="eyebrow" >PERSISTENCE</p>
|
||||||
|
<h3 class="h3" id="storageMode"></h3>
|
||||||
|
<p class="small" id="storageText"></p>
|
||||||
|
</div>
|
||||||
|
<div class="card card--warn">
|
||||||
|
<p class="eyebrow" style="color:var(--warn)">TRADE-OFF</p>
|
||||||
|
<h3 class="h3" >取舍</h3>
|
||||||
|
<p class="small" id="storageTradeoff"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<p class="lede2" id="costIntro"></p>
|
||||||
|
<div class="grid g-2-1" >
|
||||||
|
<div>
|
||||||
|
<div class="ledger" id="ledger"></div>
|
||||||
|
<p class="quote" ><q id="costQuote"></q></p>
|
||||||
|
</div>
|
||||||
|
<div class="card card--flat">
|
||||||
|
<p class="eyebrow" >VRAM · 12 GiB CARD</p>
|
||||||
|
<div class="vram" id="vram"></div>
|
||||||
|
<p class="tiny" >
|
||||||
|
allocated 与 reserved 均为每次请求结束后的快照,<strong>不是 CUDA high-water mark</strong>;
|
||||||
|
reserved 还包含 PyTorch 分配器保留的缓存。因此这里不能当作"模型峰值显存"来引用。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
<p class="lede2">
|
||||||
|
这一节回答一个问题:<strong>既然模型已经有上下文窗口,为什么还要单独做一层记忆?</strong>
|
||||||
|
答案不是「窗口不够长」,而是<strong>把长期事实塞进上下文,会以线性成本换来极低的复用率</strong>。
|
||||||
|
下面把「哪些东西留在 Qwen 的热 KV 里、哪些写进记忆记录」这条分界线逐层讲清楚。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="h3" >先看没有这层记忆时会发生什么</h2>
|
||||||
|
<p class="small" style="max-width:78ch">
|
||||||
|
同一套题、同一协议下,原版 Qwen3.5-4B 在 246 道<strong>可回答</strong>题上只答对 3 道(1.22%)。
|
||||||
|
它的典型回答不是答错,而是明确表示拿不到信息:
|
||||||
|
</p>
|
||||||
|
<div class="quote" >
|
||||||
|
<q>作为一个人工智能模型,我无法访问您的个人历史对话记录、系统配置或您之前设定的具体规则……每次对话对我来说都是全新的开始。</q>
|
||||||
|
<cite>原版 Qwen3.5-4B · 评测样本 user-009 原始回答</cite>
|
||||||
|
</div>
|
||||||
|
<p class="small" style="max-width:78ch">
|
||||||
|
这句话在事实上完全正确——模型确实没有这些信息。问题出在:这些信息<strong>本来就应该被保存下来</strong>,
|
||||||
|
而它们不属于「当前这轮对话」,所以每轮都重新粘一遍历史是最笨的保存方式。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="h3" >四层分工:谁存什么、为什么</h2>
|
||||||
|
<p class="small" style="max-width:78ch">
|
||||||
|
这是整份设计里最核心的一张表。判断标准只有一条:<strong>这份信息是「这一轮才有意义」还是「跨轮次可复用」</strong>。
|
||||||
|
</p>
|
||||||
|
<div class="scrollx">
|
||||||
|
<div class="gt gt--4">
|
||||||
|
<div class="gt__h"><span>层级</span><span>存放什么</span><span>由谁负责</span><span>为什么放在这一层</span></div>
|
||||||
|
<div class="gt__r">
|
||||||
|
<span class="gt__k">最近对话</span>
|
||||||
|
<span class="gt__v">这一轮前后的原话与顺序</span>
|
||||||
|
<span class="gt__who">Qwen 热 KV</span>
|
||||||
|
<span class="gt__why">指代、省略、语气、"你刚才说的那句"都依赖严格的先后顺序。这类信息复用价值低、时效性强,放 KV 最自然。</span>
|
||||||
|
</div>
|
||||||
|
<div class="gt__r">
|
||||||
|
<span class="gt__k">长期个人 / 项目事实</span>
|
||||||
|
<span class="gt__v">事实、版本、来源、置信度、短文本证据</span>
|
||||||
|
<span class="gt__who gt__who--acc">Natural Memory 记录</span>
|
||||||
|
<span class="gt__why">跨会话反复被问到,且需要保留"哪个版本才是当前有效"的关系。它们不依赖顺序,只依赖地址与内容。</span>
|
||||||
|
</div>
|
||||||
|
<div class="gt__r">
|
||||||
|
<span class="gt__k">当前问题</span>
|
||||||
|
<span class="gt__v">由问题生成的有界读取</span>
|
||||||
|
<span class="gt__who gt__who--acc">路由 + Top-K</span>
|
||||||
|
<span class="gt__why">不是所有记忆都该被读。当前问题只与少量页面和记录交互,避免"记忆越多、噪声越大"。</span>
|
||||||
|
</div>
|
||||||
|
<div class="gt__r">
|
||||||
|
<span class="gt__k">原始持久化状态</span>
|
||||||
|
<span class="gt__v">记忆快照与索引</span>
|
||||||
|
<span class="gt__who gt__who--acc">嵌入式 memory safetensors</span>
|
||||||
|
<span class="gt__why">随模型包一起加载,运行时不需要额外数据库进程,也避免了磁盘分页带来的延迟抖动。</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="callout" >
|
||||||
|
<p class="callout__t">关键判断</p>
|
||||||
|
<p class="callout__b">
|
||||||
|
Memory Slot <strong>不试图逐 token 模拟完整 KV</strong>。它接管的是 KV 里最昂贵、最适合长期保存、
|
||||||
|
也最容易重复利用的那一部分;而当前对话的顺序关系,仍然由 Qwen 的原生上下文负责。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="h3" >分工落到数字上是什么样</h2>
|
||||||
|
<p class="small" style="max-width:78ch">
|
||||||
|
下面这组对照最能说明「不是把历史灌进去,而是把命中的少量证据灌进去」。两组数字分别来自批次 A 与批次 B(同一题集、同一协议)。
|
||||||
|
</p>
|
||||||
|
<div class="statrow">
|
||||||
|
<div class="stat">
|
||||||
|
<span class="stat__k">无记忆时的平均输入</span>
|
||||||
|
<span class="stat__v">30.75<small>token</small></span>
|
||||||
|
<span class="stat__d">批次 A 基线:只有问题本身,没有历史</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat stat--acc">
|
||||||
|
<span class="stat__k">有记忆时的平均输入</span>
|
||||||
|
<span class="stat__v">441.19<small>token</small></span>
|
||||||
|
<span class="stat__d">批次 B:命中的证据前缀(批次 A 为 641.42)</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat">
|
||||||
|
<span class="stat__k">前缀命中率</span>
|
||||||
|
<span class="stat__v">96.97<small>%</small></span>
|
||||||
|
<span class="stat__d">批次 B 实际注入证据的题目占比(批次 A 为 90.91%)</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat">
|
||||||
|
<span class="stat__k">GPU cache 实际用量</span>
|
||||||
|
<span class="stat__v">17,990<small>token</small></span>
|
||||||
|
<span class="stat__d">有界上限 131,072 token,用到约 13.7%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="small" style="max-width:78ch">
|
||||||
|
注意最后一项:<strong>上限是 131,072 token,实际只用了 17,990</strong>。
|
||||||
|
这说明读取路径被"有界"约束住了——不会因为记忆库变大就把显存吃满。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="h3" >这条分工线换来了什么、付出了什么</h2>
|
||||||
|
<div class="grid g2" >
|
||||||
|
<div class="card">
|
||||||
|
<p class="eyebrow" >换来的</p>
|
||||||
|
<div class="mini">
|
||||||
|
<div><span>可回答正确率</span><b>1.22% → 82.52%</b></div>
|
||||||
|
<div><span>目标记忆召回</span><b>0% → 92.68%</b></div>
|
||||||
|
<div><span>符号定位(192 题)</span><b>0/192 → 181/192</b></div>
|
||||||
|
<div><span>跨会话问题</span><b>1/6 → 5/6</b></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card card--warn">
|
||||||
|
<p class="eyebrow" style="color:var(--warn)">付出的</p>
|
||||||
|
<div class="mini">
|
||||||
|
<div><span>平均输入前缀</span><b>30.75 → 441.19 token</b></div>
|
||||||
|
<div><span>平均总延迟(批次 B)</span><b>2854.9 → 2878.3 ms</b></div>
|
||||||
|
<div><span>平均解码速度(批次 B)</span><b>22.34 → 20.68 tok/s</b></div>
|
||||||
|
<div><span>reserved 显存峰值</span><b>3.234 → 5.180 GiB</b></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="h3" >这条线不能推到哪里</h2>
|
||||||
|
<div class="claims claims--loose" >
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">Natural Memory 已经等价于百万 token 的完整 KV</span><span class="claim__s">UNSUPPORTED</span></div>
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">长上下文限制已被解除(实测 8K 可跑,16K / 32K OOM)</span><span class="claim__s">UNSUPPORTED</span></div>
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">设计容量 1,048,576 条记录等于已经装入并验证了这么多</span><span class="claim__s">UNSUPPORTED</span></div>
|
||||||
|
</div>
|
||||||
|
<p class="small" style="max-width:78ch">
|
||||||
|
第三条尤其要注意:<strong>1,048,576 是地址空间与分页结构的容量</strong>,
|
||||||
|
本次两个批次实际装载的是 723 / 738 条 active records,分别是 23 / 24 个页面。
|
||||||
|
容量上限与已装入量是两个概念,我们不在页面上把它们混为一谈。
|
||||||
|
</p>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<p class="lede2" id="exampleIntro"></p>
|
||||||
|
<div id="exampleList" class="examples" ></div>
|
||||||
|
<p class="small" style="max-width:86ch" id="exampleNote"></p>
|
||||||
@@ -0,0 +1,401 @@
|
|||||||
|
<!-- ============ BAND 1 · 地址空间(首屏即机制,不是标题块) ============
|
||||||
|
动效概念:地址空间下降。镜头从 1,048,576 个槽位一路降到一条记录,
|
||||||
|
每个环节的数字都是真的。机制来自题材自身的物理(读取路径本来就是寻址)。 -->
|
||||||
|
<section class="hero" id="hero">
|
||||||
|
<div class="hero__pin">
|
||||||
|
<canvas class="hero__cv" id="spaceCv" aria-hidden="true"></canvas>
|
||||||
|
<div class="hero__layer">
|
||||||
|
<div class="hero__row hero__row--top">
|
||||||
|
<span class="eyebrow">Natural Memory · NM2.1</span>
|
||||||
|
<span class="eyebrow hero__geo">1,048,576 槽位 · 738 条活跃记录 · 730 个索引桶</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hero__row hero__row--mid">
|
||||||
|
<h1 class="hero__h dsp">模型重启之后,<br>它仍然记得。</h1>
|
||||||
|
<!-- 头号数字就在第一屏里:读者不需要滚三屏才知道这页在说什么 -->
|
||||||
|
<p class="hero__fig">
|
||||||
|
<span class="hero__fig-row">
|
||||||
|
<span class="hero__fig-v">1.22<small>%</small></span>
|
||||||
|
<span class="hero__fig-a" aria-hidden="true">→</span>
|
||||||
|
<span class="hero__fig-v">82.52<small>%</small></span>
|
||||||
|
</span>
|
||||||
|
<span class="hero__fig-n">同一 264 题题集的可回答正确率:无记忆基线 → 批次 B。
|
||||||
|
批次 A 为 62.60%,两批配置不同、不可合并。</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hero__row hero__row--bot">
|
||||||
|
<div class="hero__lede-wrap">
|
||||||
|
<p class="hero__lede" id="heroLede"></p>
|
||||||
|
<p class="hero__byline mono">wpyw.site · [email protected] · 本地 Qwen3.5-4B · 4-bit NF4</p>
|
||||||
|
</div>
|
||||||
|
<div class="hero__hud" role="status" aria-live="off">
|
||||||
|
<span class="hero__hud-i mono" id="hudIdx">01 / 08</span>
|
||||||
|
<span class="hero__hud-n" id="hudName">地址空间</span>
|
||||||
|
<span class="hero__hud-v mono" id="hudVal">1,048,576 槽位 · 738 条活跃记录</span>
|
||||||
|
<span class="hero__hud-track"><i id="hudBar"></i></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="hero__cue mono">向下滚动 · 走一遍读取路径</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ============ BAND 2 · 关键数字(紧贴首屏;以前这里空着一屏多) ============ -->
|
||||||
|
<section class="band band--tight">
|
||||||
|
<div class="wrap">
|
||||||
|
<p class="eyebrow band__k">Key numbers</p>
|
||||||
|
<div class="kpis reveal" id="heroKpis"></div>
|
||||||
|
<p class="src" style="display:block;margin-top:16px">出处 · <span id="heroSrc"></span></p>
|
||||||
|
<nav class="linkrow" aria-label="发布资源" style="margin-top:var(--sp-2xl)">
|
||||||
|
<a class="btn btn--pri" href="./reproduce">复现实验</a>
|
||||||
|
<a class="btn" href="./results">测量结果</a>
|
||||||
|
<a class="btn" href="./nm21">NM2.1 技术论证</a>
|
||||||
|
<a class="btn" href="./ledger">108 条真实台账</a>
|
||||||
|
<a class="btn" href="./limits">边界声明</a>
|
||||||
|
<a class="btn" href="https://wpyw.site" target="_blank" rel="noopener">作者网站 ↗</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ============ BAND 2 · 重启实验(真实运行回放装置) ============ -->
|
||||||
|
<section class="band band--alt band--rst" id="restart">
|
||||||
|
<div class="wrap">
|
||||||
|
<p class="eyebrow">Evidence · 重启实验</p>
|
||||||
|
<h2 class="h2">把历史扔掉,它还记得吗?</h2>
|
||||||
|
<p class="lede2 rst__lede">
|
||||||
|
下面不是示意动画,是工程里两次真实运行的逐字回放。同一条事实、同一个问题、同一份协议;
|
||||||
|
两次之间唯一的差别,是写入有没有真的落库。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="rst" id="rst">
|
||||||
|
<div class="rst__head">
|
||||||
|
<div class="seg" role="group" aria-label="选择运行版本">
|
||||||
|
<button class="seg__b" type="button" data-v="before">修复前</button>
|
||||||
|
<button class="seg__b is-on" type="button" data-v="after">修复后</button>
|
||||||
|
</div>
|
||||||
|
<button class="btn rst__play" type="button" id="rstPlay">重放</button>
|
||||||
|
<span class="rst__file mono" id="rstFile"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="rst__grid">
|
||||||
|
<div class="rst__aside">
|
||||||
|
<p class="rst__k">写入的事实</p>
|
||||||
|
<p class="rst__quote" id="rstFact"></p>
|
||||||
|
<p class="rst__k">重启之后问</p>
|
||||||
|
<p class="rst__quote rst__quote--q" id="rstQuery"></p>
|
||||||
|
|
||||||
|
<div class="rst__gauges">
|
||||||
|
<div class="rst__g">
|
||||||
|
<div class="rst__gt"><span>记忆库记录</span><b class="mono" id="rstRec">0</b></div>
|
||||||
|
<div class="rst__track"><span class="rst__fill rst__fill--store" id="rstRecBar"></span></div>
|
||||||
|
</div>
|
||||||
|
<div class="rst__g">
|
||||||
|
<div class="rst__gt"><span>重启时传入的历史</span><b class="mono" id="rstHist">false</b></div>
|
||||||
|
<div class="rst__track"><span class="rst__fill rst__fill--hist" id="rstHistBar"></span></div>
|
||||||
|
</div>
|
||||||
|
<div class="rst__g">
|
||||||
|
<div class="rst__gt"><span>注入模型内部的前缀</span><b class="mono" id="rstPf">0<small> tok</small></b></div>
|
||||||
|
<div class="rst__track"><span class="rst__fill rst__fill--pf" id="rstPfBar"></span></div>
|
||||||
|
<p class="rst__hint" id="rstPfHint"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ol class="rst__beats" id="rstBeats"></ol>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="rst__out" id="rstOut">
|
||||||
|
<div class="rst__outhead">
|
||||||
|
<span class="mono">模型输出 · 逐字</span>
|
||||||
|
<span class="rst__verdict mono" id="rstVerdict"></span>
|
||||||
|
</div>
|
||||||
|
<p class="rst__resp mono" id="rstResp"></p>
|
||||||
|
<div class="rst__kv" id="rstKv"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="tiny rst__note" id="rstNote"></p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ============ BAND 3 · Teaser(全宽读取路径图) ============ -->
|
||||||
|
<section class="band band--teaser">
|
||||||
|
<div class="wrap">
|
||||||
|
<figure class="teaser">
|
||||||
|
{{include:partials/readpath.svg}}
|
||||||
|
<figcaption class="teaser__cap">
|
||||||
|
<span class="teaser__k">图 1 · 读取路径</span>
|
||||||
|
一次问答里记忆层做了什么。用户问题只与少量页面和记录交互,<b>全程没有对全量记忆做注意力</b>;
|
||||||
|
命中的短证据作为模型内部前缀注入 Qwen。图为示意,环节顺序与实现一致。
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ============ BAND 4 · 摘要 ============ -->
|
||||||
|
<section class="band">
|
||||||
|
<div class="wrap wrap--narrow">
|
||||||
|
<p class="eyebrow band__k">Abstract</p>
|
||||||
|
<h2 class="h2 arr-wipe">这是什么东西</h2>
|
||||||
|
<p class="lede2">
|
||||||
|
它接在本地 Qwen3.5-4B 上,是一个<strong>模型内的记忆层</strong>:把适合长期复用的个人事实、项目事实和短对话片段
|
||||||
|
写进<strong>带地址的记忆记录</strong>;当前问题只读取少量相关记录,再把这些记录作为<strong>模型内部前缀</strong>交给 Qwen 生成答案。
|
||||||
|
</p>
|
||||||
|
<p class="lede2" style="margin-top:20px">
|
||||||
|
它要解决的具体问题是:<strong>模型重启后不携带历史聊天记录,仍能访问已经保存的个人或项目事实,
|
||||||
|
同时不把全部历史转换成 GPU 上的长 KV Cache。</strong>
|
||||||
|
</p>
|
||||||
|
<p class="small" style="margin-top:24px">
|
||||||
|
当前状态:研究原型到工程验证之间。同一 264 题题集上,可回答正确率从 1.22% 提升到 62.60%(批次 A)
|
||||||
|
与 82.52%(批次 B);代价是输入前缀变长、解码速度下降约 10%。我们不在页面上把它说成通用智能,
|
||||||
|
也不把实验室结果表述成线上服务承诺。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ============ BAND 5 · 本次发布包含什么 ============ -->
|
||||||
|
<section class="band band--alt">
|
||||||
|
<div class="wrap">
|
||||||
|
<p class="eyebrow band__k">What's in this release</p>
|
||||||
|
<div class="grid g3">
|
||||||
|
<div class="card">
|
||||||
|
<p class="rel__k">记忆层与索引</p>
|
||||||
|
<p class="rel__v">738 <small>active records</small></p>
|
||||||
|
<p class="rel__d">批次 B 实际装载;24 个页面,页容量 32 条。地址空间设计容量 1,048,576。</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<p class="rel__k">记忆路由器</p>
|
||||||
|
<p class="rel__v">2,037,774 <small>参数</small></p>
|
||||||
|
<p class="rel__d">16 张量 / float32 / 512 B 地址;结构 dim=128 · heads=8 · hidden=2560 · max_hops=3。</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<p class="rel__k">有界 GPU cache</p>
|
||||||
|
<p class="rel__v">256 <small>records</small></p>
|
||||||
|
<p class="rel__d">上限 131,072 token;批次 B 实际用到 17,990 token,fallback 与分配失败均为 0。</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<p class="rel__k">评测题集</p>
|
||||||
|
<p class="rel__v">264 <small>题</small></p>
|
||||||
|
<p class="rel__d">246 可回答 / 18 未知;真实仓库 220 题 + 项目对话事实 44 题。</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<p class="rel__k">可复核性</p>
|
||||||
|
<p class="rel__v">逐字原文</p>
|
||||||
|
<p class="rel__d">样例页的问答全部取自评测原始结果、未经润色,并包含两条我们判错的样例。</p>
|
||||||
|
</div>
|
||||||
|
<div class="card card--acc">
|
||||||
|
<p class="rel__k">复现</p>
|
||||||
|
<p class="rel__v">一条命令</p>
|
||||||
|
<p class="rel__d">正式脏数据迁移测试的完整命令、协议参数与产物路径见复现页。</p>
|
||||||
|
<p style="margin:16px 0 0"><a class="btn" href="./reproduce">去复现 →</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ============ BAND 6 · 结果预览 ============ -->
|
||||||
|
<section class="band">
|
||||||
|
<div class="wrap">
|
||||||
|
<p class="eyebrow band__k">Headline result</p>
|
||||||
|
<div class="grid g-2-1">
|
||||||
|
<div class="bars" id="releaseResult">
|
||||||
|
<div class="barset">
|
||||||
|
<div class="barset__top">
|
||||||
|
<span class="barset__t">可回答正确率</span>
|
||||||
|
<span class="barset__n">同一 264 题题集 · 246 可回答</span>
|
||||||
|
</div>
|
||||||
|
<div class="bar bar--base"><span class="bar__l">原版 Qwen</span>
|
||||||
|
<span class="bar__track"><span class="bar__fill" data-fill="1.22"></span></span>
|
||||||
|
<span class="bar__v">1.22%<small>3/246</small></span></div>
|
||||||
|
<div class="bar bar--a"><span class="bar__l">批次 A</span>
|
||||||
|
<span class="bar__track"><span class="bar__fill" data-fill="62.60"></span></span>
|
||||||
|
<span class="bar__v">62.60%<small>154/246</small></span></div>
|
||||||
|
<div class="bar bar--nm2"><span class="bar__l">批次 B</span>
|
||||||
|
<span class="bar__track"><span class="bar__fill" data-fill="82.52"></span></span>
|
||||||
|
<span class="bar__v">82.52%<small>203/246</small></span></div>
|
||||||
|
</div>
|
||||||
|
<div class="legend">
|
||||||
|
<span><i class="l-base"></i>原版 Qwen3.5-4B</span>
|
||||||
|
<span><i class="l-a"></i>批次 A</span>
|
||||||
|
<span><i class="l-nm2"></i>批次 B</span>
|
||||||
|
</div>
|
||||||
|
<p class="small">
|
||||||
|
两个批次同一题集、同一协议,但配置不同,<strong>分数不可合并</strong>,只能并列读。
|
||||||
|
目标记忆召回:批次 A 67.48%、批次 B 92.68%——<strong>检索召回率不等于回答正确率</strong>。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="kv">
|
||||||
|
<div class="kv__r"><span class="kv__k">总体正确率</span><span class="kv__v">7.58% → 64.39% → 82.95%</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">符号定位</span><span class="kv__v">0/192 → 129/192 → 181/192</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">未知拒答</span><span class="kv__v">17/18 → 16/18 → 16/18</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">读取额外耗时</span><span class="kv__v">— → 61.10 → 26.35 ms</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">解码速度</span><span class="kv__v">24.06 → 21.68 → 20.68 tok/s</span></div>
|
||||||
|
</div>
|
||||||
|
<p style="margin:20px 0 0"><a class="btn" href="./results">全部测量结果 →</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ============ BAND 7 · 发布之后(NM2.1) ============ -->
|
||||||
|
<section class="band band--alt">
|
||||||
|
<div class="wrap">
|
||||||
|
<p class="eyebrow">After this release · NM2.1</p>
|
||||||
|
<h2 class="h2">发布之后又做了什么</h2>
|
||||||
|
<p class="lede2" style="margin-top:20px">
|
||||||
|
上面所有数字都来自 v2。之后的 NM2.1 换掉了记忆路由器、修掉写入路径上一个会把事实互相销毁的缺陷,
|
||||||
|
并把「问库里没有的属性时照样编答案」这个 75% 的失败修到 0%。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- 全页的头号数字;也是唯一一个用 .mega 的地方 -->
|
||||||
|
<div class="money">
|
||||||
|
<p class="eyebrow">未知拒答率 · 24 条同形候选</p>
|
||||||
|
<p class="money__row">
|
||||||
|
<span class="mega arr-num">100.00<small>%</small></span>
|
||||||
|
<span class="money__from">从 0.00% 起 —— 修好之前,模型 75% 的情况下照样编一个答案</span>
|
||||||
|
</p>
|
||||||
|
<p class="money__cap">
|
||||||
|
这是整个项目最该被引用的一个数字。它回答的不是「能不能检索到」,而是
|
||||||
|
<strong>「不知道的时候会不会不懂装懂」</strong>。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="nm21grid" style="margin-top:var(--band-tight)">
|
||||||
|
<div>
|
||||||
|
<p class="rel__k">未知拒答率 · 同形候选</p>
|
||||||
|
<p class="rel__v"><em>0.00% →</em>100.00%</p>
|
||||||
|
<p class="rel__d">问库里不存在的属性时,正确说「不知道」的比例。修好之前,模型 75% 的情况下照样编一个答案。</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="rel__k">写 20 条不同属性后存活</p>
|
||||||
|
<p class="rel__v"><em>12/20 →</em>20/20</p>
|
||||||
|
<p class="rel__d">v2 的写入路径会把 8 条<strong>无关</strong>事实互相 retract,让端到端正确率存在 50% 的硬上限——任何排序器都救不回一条已被删掉的记录。</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="rel__k">零字面重叠改写</p>
|
||||||
|
<p class="rel__v"><em>43.75% →</em>68.75%</p>
|
||||||
|
<p class="rel__d">查询与事实之间没有任何独特字重叠时的回答正确率;24 条同句式候选的随机水平是 4.17%。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid g-2-1" style="margin-top:32px">
|
||||||
|
<div>
|
||||||
|
<p class="small">
|
||||||
|
<strong>代价几乎为零:</strong>参数量 2,037,774 不变、每条记录地址 512 字节不变、模型包 8.88 GB 不变;
|
||||||
|
交错基准(7 轮,消除顺序效应)单查询延迟 1.4203 → 1.4242 ms,差 +0.28%,
|
||||||
|
<strong>小于同一轮里原版自身 4.85% 的离散度</strong>。
|
||||||
|
</p>
|
||||||
|
<p class="small">
|
||||||
|
<strong>失败也一并写出来:</strong>那套「先判属性、再查库」的机制在离线实验里是 100.00% 拒答 / 0.00% 误拒,
|
||||||
|
但接上运行时<strong>连续失败两次</strong>——第一次把可回答正确率从 100.00% 压到 6.25%;
|
||||||
|
第二次修好了目标域(泄漏真的到 0.00%、可回答无损)却让另一个域崩到 0.00%。
|
||||||
|
最终该项已回退,原因也定位到了。
|
||||||
|
</p>
|
||||||
|
<p style="margin:22px 0 0; display:flex; flex-wrap:wrap; gap:12px">
|
||||||
|
<a class="btn btn--pri" href="./nm21">完整技术论证 →</a>
|
||||||
|
<a class="btn" href="./ledger">108 条真实台账 →</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="eyebrow" style="margin-bottom:18px">路由器工件本身的提升</p>
|
||||||
|
<div class="kv">
|
||||||
|
<div class="kv__r"><span class="kv__k">Top-1 正确率</span><span class="kv__v">41.12% → 94.14%</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">Recall@3</span><span class="kv__v">46.73% → 96.48%</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">MRR</span><span class="kv__v">47.69% → 95.77%</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">hop 正确率</span><span class="kv__v">73.23% → 100.00%</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">hop 欠预测率</span><span class="kv__v">4.68% → 0.00%</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">替换兼容性</span><span class="kv__v">DROP-IN OK(16/16 键)</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">单元测试</span><span class="kv__v">52 项通过</span></div>
|
||||||
|
</div>
|
||||||
|
<p class="tiny" style="margin-top:16px">
|
||||||
|
这些是路由器工件在冻结评测集上的增益。它<strong>不会</strong>自动传递到最终答案 ——
|
||||||
|
原因见技术论证页的第十节。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ============ BAND 8 · 深入阅读 ============ -->
|
||||||
|
<section class="band">
|
||||||
|
<div class="wrap">
|
||||||
|
<p class="eyebrow band__k">Read further</p>
|
||||||
|
<div class="grid g3">
|
||||||
|
<a class="navcard" href="./division">
|
||||||
|
<span class="navcard__n">01</span>
|
||||||
|
<span class="navcard__t">记忆与 KV 的分工</span>
|
||||||
|
<span class="navcard__d">哪些留在热 KV、哪些写进记忆,判断标准与代价</span>
|
||||||
|
</a>
|
||||||
|
<a class="navcard" href="./mechanism">
|
||||||
|
<span class="navcard__n">02</span>
|
||||||
|
<span class="navcard__t">一次读取与一次写入</span>
|
||||||
|
<span class="navcard__d">八个环节、记录字段、四个状态与四个设计决定</span>
|
||||||
|
</a>
|
||||||
|
<a class="navcard" href="./nm21">
|
||||||
|
<span class="navcard__n">04</span>
|
||||||
|
<span class="navcard__t">NM2.1 · 之后做了什么</span>
|
||||||
|
<span class="navcard__d">根因、两级验证、两处改动的剂量曲线,以及两次失败的集成</span>
|
||||||
|
</a>
|
||||||
|
<a class="navcard" href="./ledger">
|
||||||
|
<span class="navcard__n">06</span>
|
||||||
|
<span class="navcard__t">真实评测台账</span>
|
||||||
|
<span class="navcard__d">108 条逐字原文,可按来源与判定筛选</span>
|
||||||
|
</a>
|
||||||
|
<a class="navcard" href="./examples">
|
||||||
|
<span class="navcard__n">05</span>
|
||||||
|
<span class="navcard__t">实测样例</span>
|
||||||
|
<span class="navcard__d">五条逐字原文,含两条我们判错的</span>
|
||||||
|
</a>
|
||||||
|
<a class="navcard" href="./cost">
|
||||||
|
<span class="navcard__n">07</span>
|
||||||
|
<span class="navcard__t">代价账本</span>
|
||||||
|
<span class="navcard__d">延迟、解码速度、前缀长度、显存</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ============ BAND 8 · 边界(正式章节,不是脚注) ============ -->
|
||||||
|
<section class="band">
|
||||||
|
<div class="wrap">
|
||||||
|
<p class="eyebrow band__k">Boundaries · 我们不宣称的内容</p>
|
||||||
|
<div class="claims claims--loose arr-cards">
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">已经等价于百万 token 的完整 KV</span></div>
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">已经击败生产级 embedding + reranker RAG</span></div>
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">任何自然语言表达都能稳定召回正确记忆</span></div>
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">记忆写入永远不会出错</span></div>
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">一百万条记录已经完成端到端验证</span></div>
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">当前 4B 结果可以直接外推到 14B、32B 或更大模型</span></div>
|
||||||
|
</div>
|
||||||
|
<p class="small" style="margin-top:24px">
|
||||||
|
完整的八条与五项主要局限见 <a href="./limits" class="linku">边界页</a>。
|
||||||
|
把它们放在发布页正面,是因为它们和上面的数字一样重要。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ============ BAND 9 · 引用 ============ -->
|
||||||
|
<section class="band band--alt">
|
||||||
|
<div class="wrap">
|
||||||
|
<p class="eyebrow band__k">Citation</p>
|
||||||
|
<div class="code">
|
||||||
|
<div class="code__bar">
|
||||||
|
<span class="code__t">BibTeX</span>
|
||||||
|
<button class="copy" id="citeCopy" type="button">复制</button>
|
||||||
|
</div>
|
||||||
|
<pre><code id="citeBlock">@misc{naturalmemoryv2,
|
||||||
|
title = {Natural Memory v2: an in-model memory layer for local LLMs},
|
||||||
|
author = {wpy},
|
||||||
|
year = {2026},
|
||||||
|
note = {Research prototype on Qwen3.5-4B. 264-question dirty-corpus
|
||||||
|
transfer test; two independent batches.},
|
||||||
|
url = {https://wpyw.site}
|
||||||
|
}</code></pre>
|
||||||
|
</div>
|
||||||
|
<p class="tiny" style="margin-top:16px">
|
||||||
|
引用时请一并注明「批次 A 与批次 B 配置不同、分数不可合并」,否则单个数字会被误读。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<p class="lede2">
|
||||||
|
这一页不是挑出来的样例,是<strong>全部 108 条真实评测 episode 的逐条台账</strong>。
|
||||||
|
每条都带模型的逐字回复、判定结果、停止原因、选中记录数与分数。
|
||||||
|
</p>
|
||||||
|
<p class="small" id="ledgerIntro"></p>
|
||||||
|
|
||||||
|
<div class="ledger-bar">
|
||||||
|
<div class="seg" id="ledgerSrc" role="group" aria-label="按来源筛选"></div>
|
||||||
|
<div class="seg" id="ledgerVerdict" role="group" aria-label="按判定筛选"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ledger-count">
|
||||||
|
<span class="mono" id="ledgerCount"></span>
|
||||||
|
<span class="tiny" id="ledgerBreak"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ledger" id="ledgerList"></div>
|
||||||
|
|
||||||
|
<p class="tiny" style="margin-top:var(--sp-2xl)">
|
||||||
|
数据来自 <code>runtime_score_bands.json</code> 与 <code>nm2_1_final_runtime_e2e.json</code>,
|
||||||
|
由 <code>tools/make_ledger.py</code> 生成 <code>assets/js/ledger.js</code>,
|
||||||
|
<strong>字段逐字复制,未做改写、润色或换算</strong>。模型输出里的错字、冗余和编造的内容都按原样保留。
|
||||||
|
期望锚点是评测里的随机码(形如 <code>VAL-XXXXXXX</code>),它只出现在唯一一条候选事实里,
|
||||||
|
因此可以用来检测「证据混用」。
|
||||||
|
</p>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<p class="lede2" id="limitsIntro"></p>
|
||||||
|
<div class="claims" id="claims" ></div>
|
||||||
|
<h2 class="h3" >五项主要局限</h2>
|
||||||
|
<div class="lims" id="lims" ></div>
|
||||||
|
<h2 class="h3" >来自工程文档的原文</h2>
|
||||||
|
<div class="lims" id="quotes" ></div>
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
<p class="lede2">
|
||||||
|
这一节把「<strong>一次读取</strong>」和「<strong>一次写入</strong>」拆开讲透:读取路径有哪八个环节、每一步的输入输出是什么、
|
||||||
|
一条记录里到底存了什么、四个状态如何演化,以及我们为这些决定付出了什么代价。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="h3" >一、读取路径:从提问到证据注入</h2>
|
||||||
|
<div class="scrollx teaser--doc">
|
||||||
|
{{include:partials/readpath.svg}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="small" style="max-width:78ch">
|
||||||
|
点左侧任一环节查看它在做什么,也可以依次点一遍——注意整条链路上<strong>没有一步是「和全部记忆做注意力」</strong>,
|
||||||
|
这是显存可控的根本原因。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="flow">
|
||||||
|
<div class="steps" id="steps" role="tablist" aria-label="记忆读取路径"></div>
|
||||||
|
<div class="flow__detail card card--flat">
|
||||||
|
<p class="flow__stage" id="flowIdx">STAGE 01 / 08</p>
|
||||||
|
<h3 class="flow__title" id="flowTitle"></h3>
|
||||||
|
<p class="flow__body" id="flowBody"></p>
|
||||||
|
<p class="flow__io" id="flowIo"></p>
|
||||||
|
<div class="flow__meta">
|
||||||
|
<div><span>读取上限</span><b>2 records</b></div>
|
||||||
|
<div><span>候选页上限</span><b>4 pages</b></div>
|
||||||
|
<div><span>页容量</span><b>32 / page</b></div>
|
||||||
|
<div><span>全量注意力</span><b>否</b></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="h3" >每一步的输入、输出与约束</h2>
|
||||||
|
<p class="small" style="max-width:78ch">
|
||||||
|
括号里的数字是实测值,不是设计目标。
|
||||||
|
</p>
|
||||||
|
<div class="scrollx">
|
||||||
|
<div class="gt gt--3">
|
||||||
|
<div class="gt__h"><span>环节</span><span>输入 → 输出</span><span>约束或实测</span></div>
|
||||||
|
<div class="gt__r"><span class="gt__k">01 用户问题</span><span class="gt__v">普通自然语言</span><span class="gt__why">不要求任何显式指令,不需要输入 <code>/remember</code> 之类的标记。</span></div>
|
||||||
|
<div class="gt__r"><span class="gt__k">02 Qwen hidden state</span><span class="gt__v">问题 → 紧凑查询地址</span><span class="gt__why">地址由模型隐状态生成,不依赖外部 embedding 服务;语义地址编码用单条 batch 执行,避免编码阶段出现显存瞬时峰值。</span></div>
|
||||||
|
<div class="gt__r"><span class="gt__k">03 LSH / 地址粗索引</span><span class="gt__v">查询地址 → 候选页</span><span class="gt__why">精确桶 + Hamming-1/2 探针;批次 A 的记忆状态里粗索引有 730 个桶、最近一次粗筛返回 24 个候选。</span></div>
|
||||||
|
<div class="gt__r"><span class="gt__k">04 候选页</span><span class="gt__v">候选页 → 少量页面</span><span class="gt__why">页容量 32 条记录,默认最多读取 4 页;本次 active records 723 条落在 23 个页面上。</span></div>
|
||||||
|
<div class="gt__r"><span class="gt__k">05 页内记录重排</span><span class="gt__v">页内记录 → 有序候选</span><span class="gt__why">记录级重排由独立的 text_retriever 完成(6 张量、1,573,377 参数)。它的 Top-1 命中率本身只有 23.20%,是当前的主要瓶颈之一。</span></div>
|
||||||
|
<div class="gt__r"><span class="gt__k">06 Top-K 记录</span><span class="gt__v">有序候选 → 少量证据</span><span class="gt__why">正式测试中的读取上限为 2 条记录。目标记忆召回:批次 A 166/246,<strong>批次 B 228/246</strong>。</span></div>
|
||||||
|
<div class="gt__r"><span class="gt__k">07 证据前缀注入</span><span class="gt__v">证据 → 模型内部前缀</span><span class="gt__why">命中的短证据被提升到 GPU 作为前缀;批次 B 有 96.97% 的题目实际注入了前缀,平均 410.34 token(批次 A 为 610.67)。</span></div>
|
||||||
|
<div class="gt__r"><span class="gt__k">08 普通生成</span><span class="gt__v">前缀 + 问题 → 回答</span><span class="gt__why">记忆主体始终留在进程内存,只有热点记录进入有界 GPU cache。读取路径额外耗时:批次 A 61.10 ms → <strong>批次 B 26.35 ms</strong>。</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="h3" >二、一条记录里到底存了什么</h2>
|
||||||
|
<p class="small" style="max-width:78ch">
|
||||||
|
记录不是一段文本,而是一条带地址、带版本关系、带状态的结构化数据。下面左侧是全部字段,
|
||||||
|
右侧是<strong>一条真实记录</strong>(逐字取自评测结果里的命中记录)。
|
||||||
|
</p>
|
||||||
|
<div class="grid g-2-1">
|
||||||
|
<div>
|
||||||
|
<div class="rec" id="recFields"></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="card card--acc" id="realRecord"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="h3" >三、状态机:旧的答案不会凭空消失</h2>
|
||||||
|
<p class="small" style="max-width:78ch">
|
||||||
|
同一实体和属性出现新值时,<strong>旧值被标记为 superseded,而不是被覆盖或删除</strong>。
|
||||||
|
这是「时间冲突」类问题能答对的前提:既要给出当前有效值,也要能说清旧值去哪了。
|
||||||
|
</p>
|
||||||
|
<div class="states" id="stateList"></div>
|
||||||
|
|
||||||
|
<div class="callout callout--warn" >
|
||||||
|
<p class="callout__t">写入路径的教训:检索救不回不存在的记录</p>
|
||||||
|
<p class="callout__b">
|
||||||
|
早期版本的退役授权完全依赖一个学习打分(阈值 ≥0.95),<strong>没有任何结构校验</strong>。
|
||||||
|
结果是新写入把已有记录误判为旧值并退役:一次 20 条记录的测试里 active 只剩 12 条、retract 高达 16 次、目标记录只存活 8/16。
|
||||||
|
修好之后:<strong>active 12/20 → 20/20,retract 16 → 0,目标记录存活 8/16 → 16/16,端到端 37.50% → 68.75%</strong>。
|
||||||
|
这件事的结论很直白——<span class="serif-it">任何排序器都救不回一条已经不存在的记录。</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="h3" >四、四个设计决定与它们的代价</h2>
|
||||||
|
<div class="grid g2" >
|
||||||
|
<div class="card">
|
||||||
|
<p class="eyebrow" >决定 1 · 两段式读取</p>
|
||||||
|
<p class="small" ><strong>粗索引筛页 → 页内重排</strong>,而不是对全量记录做注意力。</p>
|
||||||
|
<p class="tiny">好处:单次读取的候选规模被压到固定上限(≤4 页 / ≤2 条),成本与记忆总量解耦。
|
||||||
|
代价:两段都可能出错,且错误会叠加——粗索引错了就再没有机会。</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<p class="eyebrow" >决定 2 · 用地址索引而非向量库</p>
|
||||||
|
<p class="small" >语义地址 + LSH 桶放在模型包内,<strong>不引入外部检索服务</strong>。</p>
|
||||||
|
<p class="tiny">好处:部署时没有额外进程与网络依赖,读取耗时稳定(批次 B 26.35 ms)。
|
||||||
|
代价:召回质量受地址质量限制,零字面重叠的改写问法曾只有 18.40% 的 Top-1。</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<p class="eyebrow" >决定 3 · 有界 GPU cache</p>
|
||||||
|
<p class="small" >热点记录进 GPU,上限 <strong>256 条 / 131,072 token</strong>,另有动态保留。</p>
|
||||||
|
<p class="tiny">好处:显存占用可预测,两个批次的实际用量分别是 15,885 / 17,990 token,fallback 与分配失败均为 0。
|
||||||
|
代价:cold page 会带来额外取数路径——不过本次两个批次都是 embedded / process-RAM 模式,cold page 为 0。</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<p class="eyebrow" >决定 4 · 嵌入式 weight-shard 持久化</p>
|
||||||
|
<p class="small" >记忆快照写进模型包的 memory safetensors 切片,<strong>默认不用 SQLite、不用磁盘分页</strong>。</p>
|
||||||
|
<p class="tiny">好处:运行时依赖最少,重启只需加载权重切片、不回放历史聊天。
|
||||||
|
代价:模型包会随记忆增长变大,且<strong>固化更新需要重新保存权重切片</strong>——这是明确的工程负担,不是白拿的。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="h3" >五、这套机制仍然做不到的事</h2>
|
||||||
|
<div class="claims claims--loose" >
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">任何自然语言表达都能稳定召回正确记忆</span><span class="claim__s">UNSUPPORTED</span></div>
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">记忆写入永远不会出错</span><span class="claim__s">UNSUPPORTED</span></div>
|
||||||
|
<div class="claim"><span class="claim__x">✕</span><span class="claim__t">检索召回率等于回答正确率(批次 B 召回 92.68% / 回答 82.52%,差 10.16pp)</span><span class="claim__s">UNSUPPORTED</span></div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,546 @@
|
|||||||
|
<p class="lede2">
|
||||||
|
发布页上的数字来自 v2。这一页讲**之后又做了什么**:三处改动各自凭什么、一个把端到端正确率
|
||||||
|
锁死在 50% 的写入缺陷怎么定位的、以及一个 75% 泄漏的失败怎么修到 0%——又怎么在接上运行时之后失败两次。
|
||||||
|
所有数字都来自磁盘上的报告文件,每张表都标了出处;**没有一条是估算或外推**。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="callout callout--warn">
|
||||||
|
<p class="eyebrow" style="color:var(--warn)">先读这一句</p>
|
||||||
|
<p class="small" style="margin:0">
|
||||||
|
这一页里**离线实验最好的数字(未知拒答 100.00%)不等于运行时可用**。它接上运行时之后
|
||||||
|
连续失败两次,最终被回退。把失败过程一起写出来,是因为它比成功更能说明这套机制到底卡在哪。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================= 净变化 ================= -->
|
||||||
|
<h2 class="h3">净变化一览</h2>
|
||||||
|
<p class="small src">出处 · <code>V2_dpskw\NM2_VS_NM2_1.md</code>(该文件自述:所有数字均从磁盘上的评分卡 / JSON 读取,不是手工抄录)</p>
|
||||||
|
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>轴</th><th>v2(原版)</th><th>NM2.1</th><th>净变化</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>路由器 Top-1</td><td class="n">41.12%</td><td class="n acc">94.14%</td><td class="n acc">+53.02 pp</td></tr>
|
||||||
|
<tr><td>路由器 Recall@3</td><td class="n">46.73%</td><td class="n acc">96.48%</td><td class="n acc">+49.75 pp</td></tr>
|
||||||
|
<tr><td>未知拒答率</td><td class="n">0.00%</td><td class="n acc">100.00%</td><td class="n acc">+100.00 pp</td></tr>
|
||||||
|
<tr><td>未知问题泄漏(同形候选)</td><td class="n">75.00%</td><td class="n acc">0.00%</td><td class="n acc">−75.00 pp</td></tr>
|
||||||
|
<tr><td>一次写 20 条不同属性后存活</td><td class="n">12 / 20</td><td class="n acc">20 / 20</td><td class="n acc">+8 条</td></tr>
|
||||||
|
<tr><td>零字面重叠改写正确率</td><td class="n">43.75%</td><td class="n acc">68.75%</td><td class="n acc">+25.00 pp</td></tr>
|
||||||
|
<tr><td>hop 欠预测率</td><td class="n">4.68%</td><td class="n acc">0.00%</td><td class="n acc">−4.68 pp</td></tr>
|
||||||
|
<tr><td>参数量 / 每条记录地址字节</td><td class="n">2,037,774 / 512</td><td class="n">2,037,774 / 512</td><td class="n">不变</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<p class="tiny">
|
||||||
|
「未知拒答率」与「未知泄漏」是同一件事的两面:前者是问库里没有的属性时**正确说不知道**的比例,
|
||||||
|
后者是**照样编一个答案**的比例。v2 在这两轴上是 0% 和 75%,也就是几乎必然硬答。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- ================= §1 检索与排序 ================= -->
|
||||||
|
<h2 class="h3">一 · 路由器工件本身的检索与排序</h2>
|
||||||
|
<p class="small src">出处 · <code>router_scorecard_final.json</code>(判定见 <code>router_verdict_final.json</code>)· 冻结 v6 评测集 21,920 条 / 10 类别</p>
|
||||||
|
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>指标</th><th>v2 · <code>V2-128 deployed(v3)</code></th><th>NM2.1 · <code>REPLAY-128 v7 final</code></th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>Top-1 正确率</td><td class="n">41.12%</td><td class="n acc">94.14%</td></tr>
|
||||||
|
<tr><td>Recall@1</td><td class="n">37.03%</td><td class="n acc">88.58%</td></tr>
|
||||||
|
<tr><td>Recall@3</td><td class="n">46.73%</td><td class="n acc">96.48%</td></tr>
|
||||||
|
<tr><td>Recall@5</td><td class="n">48.91%</td><td class="n acc">97.15%</td></tr>
|
||||||
|
<tr><td>MRR</td><td class="n">47.69%</td><td class="n acc">95.77%</td></tr>
|
||||||
|
<tr><td>nDCG@3</td><td class="n">44.22%</td><td class="n acc">95.37%</td></tr>
|
||||||
|
<tr><td>多跳证据全中(Top-3)</td><td class="n">43.43%</td><td class="n acc">96.22%</td></tr>
|
||||||
|
<tr><td>多跳证据全中(仅多正例)</td><td class="n">37.15%</td><td class="n acc">95.45%</td></tr>
|
||||||
|
<tr><td>hop 正确率</td><td class="n">73.23%</td><td class="n acc">100.00%</td></tr>
|
||||||
|
<tr><td>hop 欠预测率</td><td class="n">4.68%</td><td class="n acc">0.00%</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================= §2 拒答与仲裁 ================= -->
|
||||||
|
<h2 class="h3">二 · 拒答与仲裁策略轴</h2>
|
||||||
|
<p class="small src">出处 · <code>router_scorecard_final.json</code>(门槛 0.50)+ <code>threshold_sweep_check.json</code>(0.30–0.80 全门槛扫描)</p>
|
||||||
|
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>指标</th><th>v2</th><th>NM2.1</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>need F1</td><td class="n">89.58%</td><td class="n acc">100.00%</td></tr>
|
||||||
|
<tr><td>need 召回</td><td class="n">99.82%</td><td class="n acc">100.00%</td></tr>
|
||||||
|
<tr><td>need 精确率</td><td class="n">81.24%</td><td class="n acc">100.00%</td></tr>
|
||||||
|
<tr><td>未知拒答率</td><td class="n">0.00%</td><td class="n acc">100.00%</td></tr>
|
||||||
|
<tr><td>已知问题被误拒率</td><td class="n">0.18%</td><td class="n acc">0.00%</td></tr>
|
||||||
|
<tr><td>未知问题被误读率</td><td class="n">100.00%</td><td class="n acc">0.00%</td></tr>
|
||||||
|
<tr><td>仲裁准确率</td><td class="n">81.12%</td><td class="n acc">100.00%</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<p class="small">
|
||||||
|
<strong>门槛扫描是这里真正的证据。</strong>0.30 / 0.40 / 0.50 / 0.60 / 0.70 / 0.80 六个门槛逐一复核:
|
||||||
|
NM2.1 **全门槛通过**;而原版在**每一个**门槛上未知拒答率都是 0.00%,且门槛越高误拒越差
|
||||||
|
(0.00% → 1.32%)。一个能在整条门槛轴上都成立的结论,和一个只在某个阈值上成立的点,可信度不是一回事。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- ================= §3 端到端 ================= -->
|
||||||
|
<h2 class="h3">三 · 端到端整体记忆能力(同一份运行时,只有模型包不同)</h2>
|
||||||
|
<p class="small src">出处 · <code>nm2_battery_comparison_final.json</code> · A 110 用例 / B 16 / C 48 / D 重启持久化</p>
|
||||||
|
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>指标</th><th>原版 NM2</th><th>NM2.1(仅换路由器)</th><th>NM2.1 最终</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>A 总体正确率</td><td class="n">89.09%</td><td class="n">88.18%</td><td class="n">88.18%</td></tr>
|
||||||
|
<tr><td>A <strong>可回答正确率</strong></td><td class="n">100.00%</td><td class="n">100.00%</td><td class="n acc">100.00%</td></tr>
|
||||||
|
<tr><td>A 未知拒答率</td><td class="n">60.00%</td><td class="n">56.67%</td><td class="n bad">56.67%</td></tr>
|
||||||
|
<tr><td>A 已知问题被误拒率</td><td class="n">0.00%</td><td class="n">0.00%</td><td class="n acc">0.00%</td></tr>
|
||||||
|
<tr><td>B 零字面重叠改写回答正确率</td><td class="n">43.75%</td><td class="n">68.75%</td><td class="n acc">68.75%</td></tr>
|
||||||
|
<tr><td>B 答成别的属性</td><td class="n">18.75%</td><td class="n">18.75%</td><td class="n">18.75%</td></tr>
|
||||||
|
<tr><td>B 触发读取</td><td class="n">56.25%</td><td class="n">93.75%</td><td class="n acc">93.75%</td></tr>
|
||||||
|
<tr><td>C 可回答正确率(24 同形候选)</td><td class="n">65.00%</td><td class="n">65.00%</td><td class="n acc">70.00%</td></tr>
|
||||||
|
<tr><td>C 答成别的属性</td><td class="n">35.00%</td><td class="n">35.00%</td><td class="n acc">27.50%</td></tr>
|
||||||
|
<tr><td>C <strong>未知泄漏率</strong></td><td class="n">75.00%</td><td class="n">75.00%</td><td class="n acc">0.00%</td></tr>
|
||||||
|
<tr><td>C 活跃记录 min / max</td><td class="n">23 / 24</td><td class="n">23 / 24</td><td class="n">23 / 24</td></tr>
|
||||||
|
<tr><td>D 重启后召回 / 作答 / 清理</td><td class="n">通过</td><td class="n">通过</td><td class="n acc">通过</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<p class="small">
|
||||||
|
<strong>运行间波动必须自己讲出来:</strong>B 段只有 16 个用例,1 个用例 = 6.25 pp。所以 B 的 68.75%
|
||||||
|
与另一次测得的 75.00% 属于同一水平的运行间波动,**不作为增益主张**。A / C / D 的结论在多次运行中一致。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- ================= §4 零重叠 ================= -->
|
||||||
|
<h2 class="h3">四 · 零字面重叠改写的泛化</h2>
|
||||||
|
<p class="small src">出处 · <code>replay_check_zov.json</code>(路由器级)与上表 B / C 段(端到端)· 数据集 300 条、24 个<strong>未见过</strong>的问法</p>
|
||||||
|
|
||||||
|
<div class="grid g2">
|
||||||
|
<div>
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>指标</th><th>v2 权重</th><th>NM2.1 权重</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>路由器 Top-1(250 条可回答)</td><td class="n">18.40%</td><td class="n acc">59.60%</td></tr>
|
||||||
|
<tr><td>路由器 Recall@3</td><td class="n">36.00%</td><td class="n acc">83.20%</td></tr>
|
||||||
|
<tr><td>路由器 MRR</td><td class="n">35.07%</td><td class="n acc">73.06%</td></tr>
|
||||||
|
<tr><td>端到端改写正确率(B 段)</td><td class="n">43.75%</td><td class="n acc">68.75%</td></tr>
|
||||||
|
<tr><td>端到端未知泄漏(C 段)</td><td class="n">75.00%</td><td class="n acc">0.00%</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="small" style="margin-top:0">
|
||||||
|
零重叠评测集有 24 条**同句式、不同属性**的候选,随机猜中的概率是 <strong>4.17%</strong>。
|
||||||
|
所以 59.60% 大约是随机水平的 <strong>14 倍</strong>。
|
||||||
|
</p>
|
||||||
|
<div class="kv">
|
||||||
|
<div class="kv__r"><span class="kv__k">数据集规模</span><span class="kv__v">300 条评测 / 24 个未见问法</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">训练 / 留出划分</span><span class="kv__v">前 2 个改写训练(48)/ 第 3 个留出(24)</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">两个划分共享的查询字符串</span><span class="kv__v">0</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">查询与自身目标的重叠</span><span class="kv__v">0</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">含「陷阱」候选的 episode</span><span class="kv__v">54.53%(生成器统计)</span></div>
|
||||||
|
</div>
|
||||||
|
<p class="tiny">
|
||||||
|
<strong>关键设计判断:</strong>改写与**无关**属性的字符重叠被刻意保留(命中错误候选只会得到错误答案,
|
||||||
|
让任务更难,不提供捷径);真正必须为 0 的是与**自身**目标的重叠。最初把二者混为一谈时,
|
||||||
|
24 个属性里有 7 个因为「起床时间」的「时」、「办公城市」的「公」这类高频字被判为「无可用的改写」。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================= §5 成本 ================= -->
|
||||||
|
<h2 class="h3">五 · 代价:几乎没有</h2>
|
||||||
|
<p class="small src">出处 · <code>router_scorecard_final.json</code>、<code>router_latency_bench_prod.json</code>(7 轮交错取中位数)</p>
|
||||||
|
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>指标</th><th>v2</th><th>NM2.1</th><th>说明</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>参数量</td><td class="n">2,037,774</td><td class="n">2,037,774</td><td class="small">未增加</td></tr>
|
||||||
|
<tr><td>每条记录地址字节</td><td class="n">512</td><td class="n">512</td><td class="small">存储几何未变</td></tr>
|
||||||
|
<tr><td>单查询延迟中位数(GPU)</td><td class="n">0.9549 ms</td><td class="n">0.9169 ms</td><td class="small">略快</td></tr>
|
||||||
|
<tr><td>批量 QPS(batch=64)</td><td class="n">66,037</td><td class="n acc">69,378</td><td class="small">+5.1%</td></tr>
|
||||||
|
<tr><td>批量 QPS(batch=256)</td><td class="n">207,287</td><td class="n acc">242,759</td><td class="small">+17.1%</td></tr>
|
||||||
|
<tr><td>模型包大小</td><td class="n">8.88 GB / 22 文件</td><td class="n">8.88 GB / 23 文件</td><td class="small">多出属性头 ~0.25 MB</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<p class="small">
|
||||||
|
<strong>交错基准(7 轮,消除顺序效应):</strong>单查询中位数 1.4203 ms → 1.4242 ms,差 <strong>+0.28%</strong>。
|
||||||
|
同一轮里原版自身离散度就有 4.85% —— 也就是说这个差值小于测量噪声。
|
||||||
|
<strong>零重叠那一轮里 batch=64 的读数低 9.2%,但该轮离散度是 17.4%,且同架构同参数同 FLOPs 下 batch=256 反而更快,
|
||||||
|
方向不一致,判为测量噪声而非回归</strong>;这条也写在这里,因为把噪声当结论是这个领域最常见的错误。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- ================= §6 鲁棒性 ================= -->
|
||||||
|
<h2 class="h3">六 · 工程鲁棒性</h2>
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>项目</th><th>v2</th><th>NM2.1</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>一次写 20 条不同属性事实后存活</td><td class="n">12 / 20(8 条查询前被误删)</td><td class="n acc">20 / 20</td></tr>
|
||||||
|
<tr><td>端到端(写入修复前后,16 用例)</td><td class="n">37.50%</td><td class="n acc">68.75%</td></tr>
|
||||||
|
<tr><td>替换兼容性</td><td class="n">基线</td><td class="n acc">DROP-IN OK(16 / 16 键)</td></tr>
|
||||||
|
<tr><td>单元测试</td><td class="n">—</td><td class="n acc">52 项通过</td></tr>
|
||||||
|
<tr><td>未知问题泄漏(同形候选)</td><td class="n">75.00%</td><td class="n acc">0.00%</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================= 三处改动 ================= -->
|
||||||
|
<h2 class="h3">七 · 三处改动,每处都有测量依据</h2>
|
||||||
|
|
||||||
|
<h3>改动 1 · 记录排序混合权重取 0.5</h3>
|
||||||
|
<p class="small">
|
||||||
|
<code>memory_record_router_blend</code> 控制「打包的词面重排器」与「学习出的路由器」各占多少。
|
||||||
|
调这个之前先测了剂量曲线 —— 而且**此前的同进程测量因顺序污染已作废**,下面这版是独立进程测的。
|
||||||
|
</p>
|
||||||
|
<div id="nmBlend" class="dose"></div>
|
||||||
|
|
||||||
|
<h3>改动 2 · 把加法先验参数化,然后测出「不该动」</h3>
|
||||||
|
<p class="small">
|
||||||
|
假设是「加法先验压过了学习打分」。把它暴露成可调再测,结果**调小只会更差**:
|
||||||
|
</p>
|
||||||
|
<div id="nmPrior" class="dose"></div>
|
||||||
|
<p class="small">
|
||||||
|
这是一个<strong>有价值的负面结论</strong>:它否定了原来的假设。项目里这类结论和增益一样被保留下来,
|
||||||
|
因为它们决定了后面不再往哪个方向投入。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>改动 3 · 覆盖门 —— 以及为了让它真正生效必须一起修的两处</h3>
|
||||||
|
<p class="small">
|
||||||
|
覆盖门本身很简单:先判断「这个提问在问哪个属性」,再查库里有没有这个属性。但单独加门是不生效的,
|
||||||
|
有两处**必须同时修**,否则门会被静默绕过:
|
||||||
|
</p>
|
||||||
|
<div class="lims">
|
||||||
|
<div class="lim"><span class="lim__i">01</span><div>
|
||||||
|
<h3 class="lim__t"><code>_build_text_prefix</code> 短路</h3>
|
||||||
|
<p class="lim__d">门拒绝之后如果继续往下回落,会走**旧版 16 槽注入路径**,把记忆又塞回去。
|
||||||
|
实测:不修这一处,泄漏只从 75.00% 降到 62.50%。</p></div></div>
|
||||||
|
<div class="lim"><span class="lim__i">02</span><div>
|
||||||
|
<h3 class="lim__t">闭包要动态解析 bank</h3>
|
||||||
|
<p class="lim__d"><code>reset_memory()</code> 每次都会新建 <code>memory_os_v2</code>;闭包捕获了旧引用的话,
|
||||||
|
门会永远看到一个空 bank,于是**静默旁路** —— 实测诊断输出 <code>applicable:0 / bypassed:1</code>。</p></div></div>
|
||||||
|
<div class="lim"><span class="lim__i">03</span><div>
|
||||||
|
<h3 class="lim__t">门必须自门控</h3>
|
||||||
|
<p class="lim__d">只有当库的属性集合填充了头部词表的 <strong>≥ 90%</strong> 时才让门生效。
|
||||||
|
这条阈值是必需的:放宽成「子集即可」会让门在通用套件上误判,
|
||||||
|
把 A 段可回答正确率从 100.00% 压到 92.50%、已知误拒升到 2.50%;收紧到 90% 后 A 段完全恢复,
|
||||||
|
C 段泄漏仍为 0.00%。</p></div></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================= 写入路径 ================= -->
|
||||||
|
<h2 class="h3">八 · 写入路径:为什么 20 条事实会互相销毁</h2>
|
||||||
|
<p class="small src">出处 · <code>V2_dpskw\WRITE_PATH_FIX.md</code>(根因由栈追踪确证,非推断)</p>
|
||||||
|
|
||||||
|
<div class="callout callout--warn">
|
||||||
|
<p class="eyebrow" style="color:var(--warn)">症状</p>
|
||||||
|
<p class="small" style="margin:0">
|
||||||
|
一次写入 20 条<strong>不同属性</strong>的事实后,库里有 20 条记录但只剩 <strong>12 条 active</strong>,
|
||||||
|
8 条在查询前就被 retract。16 个关键零重叠用例里有 8 个的目标记录已经不存在 ——
|
||||||
|
因此端到端正确率存在 <strong>50% 的硬上限</strong>。**任何排序器都救不回一条已经被删掉的记录。**
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="small">16 次 retract 的调用栈完全一致:</p>
|
||||||
|
<div class="code">
|
||||||
|
<div class="code__bar"><span class="code__t">call stack</span></div>
|
||||||
|
<pre><code>eval_end_to_end_memory.py:106 write_fact
|
||||||
|
-> qwen_integration.py:3807 forward
|
||||||
|
-> qwen_integration.py:2195 _write_text_memory <-- retract 调用点
|
||||||
|
-> memory_os_v2.py:2578 MemoryOSV2.retract_record
|
||||||
|
-> memory_os_v2.py:1959 PagedMemoryBankV2.retract (status = retracted)</code></pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="small">
|
||||||
|
<code>status_transition_summary == {"active->retracted": 16}</code>,无 superseded、无 quarantined,
|
||||||
|
20 次 <code>bank.write</code> 全部返回 <code>inserted</code> —— 写入路径的<strong>唯一</strong>销毁机制就是 2195 行的 retract。
|
||||||
|
授权条件 <code>confirmed_update</code> 在 20 次写入中为真 <strong>5 次</strong>,且全部只走「学习重排器
|
||||||
|
<code>learned_best >= 0.95</code>」这一条:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>写入序号</th><th>事实</th><th>learned_best</th><th>结果</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td class="n">2</td><td>出生城市</td><td class="n">0.998959</td><td>confirmed_update = True</td></tr>
|
||||||
|
<tr><td class="n">3</td><td>办公城市</td><td class="n">0.992638</td><td>confirmed_update = True</td></tr>
|
||||||
|
<tr><td class="n">9</td><td>工位楼层</td><td class="n">0.964987</td><td>confirmed_update = True</td></tr>
|
||||||
|
<tr><td class="n">12</td><td>手机尾号</td><td class="n">0.998516</td><td>confirmed_update = True</td></tr>
|
||||||
|
<tr><td class="n">15</td><td>办公楼层</td><td class="n">0.997487</td><td>confirmed_update = True</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="small">
|
||||||
|
随后 2187–2197 的循环退掉 8 条:3 条走 <code>record.slot_index == slot</code>,5 条走
|
||||||
|
<code>score >= 0.95 and shared >= 2</code>;2196 行的 <code>break</code>(仅当 <code>score < 0.98</code> 才停)
|
||||||
|
让写 #12 一次级联退掉 3 条、写 #15 退掉 2 条。被退掉的正是写 1/2/3/4/9/10/11/14 —— 16 条关键事实中的 8 条。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="grid g3">
|
||||||
|
<div class="card">
|
||||||
|
<p class="rel__k">辅助事实 1</p>
|
||||||
|
<p class="rel__v">0 / 20</p>
|
||||||
|
<p class="rel__d"><code>exact_slots.numel() > 0</code>(token 完全相同)一次都没命中 —— 精确重复路径与此无关。</p>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<p class="rel__k">辅助事实 2</p>
|
||||||
|
<p class="rel__v">{2,3,5,6,7}</p>
|
||||||
|
<p class="rel__d"><code>shared >= 2</code> 毫无区分力:19 个候选的 shared 全落在这个区间,因为每条事实都含「我的 / 是」模板词元。</p>
|
||||||
|
</div>
|
||||||
|
<div class="card card--warn">
|
||||||
|
<p class="rel__k">辅助事实 3</p>
|
||||||
|
<p class="rel__v">0.9985</p>
|
||||||
|
<p class="rel__d">190 个<strong>不相关</strong>属性对里有 10 个 ≥ 0.95,最高 0.9985(「常住城市」vs「出生城市」)。<strong>调阈值不可行</strong>:假阳性高达 0.9989,没有任何标量切点能分开「不相关属性」与「真更新」。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="small">
|
||||||
|
<strong>根因:</strong>retire 一条已存在记录的授权完全来自学习打分加一个固定 0.95 阈值,
|
||||||
|
没有任何「新文本与在位记录共享 <code>(entity, attribute)</code>」的<strong>结构性校验</strong>。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>修复(两处,都是结构性的)</h3>
|
||||||
|
<div class="lims">
|
||||||
|
<div class="lim"><span class="lim__i">01</span><div>
|
||||||
|
<h3 class="lim__t"><code>confirmed_update</code> 的两条打分类分支改为结构优先</h3>
|
||||||
|
<p class="lim__d">仅当候选文本的 <code>entity::attribute</code> 已经在库的
|
||||||
|
<code>active_by_conflict</code> 账本里存在(即确实是同一条事实的更新)才允许由打分授权;
|
||||||
|
<code>exact_slots</code> 这条结构安全的分支保持不变,以保留「重复写入幂等」的既有语义。</p></div></div>
|
||||||
|
<div class="lim"><span class="lim__i">02</span><div>
|
||||||
|
<h3 class="lim__t">retract 循环加冲突键守卫</h3>
|
||||||
|
<p class="lim__d"><code>if record.conflict_key() != candidate_conflict_key: continue</code> ——
|
||||||
|
循环只能退掉<strong>描述同一属性</strong>的记录,不再因「共享热槽」或「词面重叠高」销毁无关事实。</p></div></div>
|
||||||
|
</div>
|
||||||
|
<p class="small">
|
||||||
|
语义不受损:真·同属性更新本来就已经由 <code>PagedMemoryBankV2.write</code> 通过
|
||||||
|
<code>active_by_conflict</code> 做版本化(旧版本保留为 superseded、<code>version+1</code>),
|
||||||
|
修复只是移除了那条<strong>额外的、无监督的销毁路径</strong>。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>四级验证</h3>
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>级</th><th>检验</th><th>修复前</th><th>修复后</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td class="n">①</td><td><code>status_transition_summary</code></td><td class="n">{"active->retracted": 16}</td><td class="n acc">{}</td></tr>
|
||||||
|
<tr><td class="n">①</td><td><code>retraction_calls</code> / <code>status_counts</code></td><td class="n">16 次 / {retracted: 8, active: 12}</td><td class="n acc">[] / {active: 20}</td></tr>
|
||||||
|
<tr><td class="n">②</td><td>正对照:同属性改值</td><td class="n">—</td><td class="n acc">旧值 superseded + 新值 active,其余 19 属性不受影响,0 retract</td></tr>
|
||||||
|
<tr><td class="n">③</td><td>重排器缺席对照</td><td class="n">会踩死代码分支</td><td class="n acc">20 条全 active、0 retract</td></tr>
|
||||||
|
<tr><td class="n">④</td><td><code>target_record_active</code></td><td class="n">8 / 16</td><td class="n acc">16 / 16</td></tr>
|
||||||
|
<tr><td class="n">④</td><td><code>target_record_retracted_or_absent</code></td><td class="n">8</td><td class="n acc">0</td></tr>
|
||||||
|
<tr><td class="n">④</td><td><code>active_records_min / max</code></td><td class="n">12 / 12</td><td class="n acc">20 / 20</td></tr>
|
||||||
|
<tr><td class="n">④</td><td>probe 口径回答正确率</td><td class="n">25.00%(4 / 16)</td><td class="n acc">43.75%(7 / 16)</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="small"><strong>端到端效果</strong>(官方 harness,16 个零重叠用例):</p>
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>路由器</th><th>修复前</th><th>修复后</th><th>答成别的属性</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>deployed(原版 NM2)</td><td class="n">25.00%</td><td class="n acc">50.00%(+25.00 pp)</td><td class="n">18.75% → 12.50%</td></tr>
|
||||||
|
<tr><td>V2-128-v6</td><td class="n">37.50%</td><td class="n acc">68.75%(+31.25 pp)</td><td class="n">25.00% → 18.75%</td></tr>
|
||||||
|
<tr><td>REPLAY-128</td><td class="n">37.50%</td><td class="n acc">68.75%(+31.25 pp)</td><td class="n">25.00% → 18.75%</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<p class="tiny">
|
||||||
|
<strong>一个诚实的补充:</strong>这 16 个用例里 <strong>93.75% 的读取仍走旧版 16 槽路径</strong>而非 V2 库记录,
|
||||||
|
地址命中 0 / 16。写入路径的修复解除了 50% 的硬上限,但「V2 库记录真正参与读取」这一项仍未解决。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- ================= 未知拒答 ================= -->
|
||||||
|
<h2 class="h3">九 · 未知拒答:从 75% 泄漏到 100% 拒答</h2>
|
||||||
|
<p class="small src">出处 · <code>V2_dpskw\ABSTENTION_BREAKTHROUGH.md</code></p>
|
||||||
|
|
||||||
|
<p class="lede2">
|
||||||
|
这是整个项目最差的一个数字:问库里不存在的属性时,75% 的情况下模型照样编一个答案。
|
||||||
|
下面按「先排除一整类无效修法 → 再给出有效机制 → 最后如实记录接上运行时的两次失败」来写。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>9.1 先排除掉一整类无效修法(有测量支撑)</h3>
|
||||||
|
<p class="small">
|
||||||
|
最直觉的修法是「检索分数不够高就拒答」。用<strong>只在训练集拟合、评测集算 AUC</strong> 的口径,
|
||||||
|
测了四种打分器的分数几何(top1 / margin / top-k 均值 / 离散度 / 熵 / 近邻数,共 9 个特征):
|
||||||
|
</p>
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>打分器</th><th>最佳单特征 AUC</th><th>拟合头 AUC(评测集)</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>cosine(冻结键余弦)</td><td class="n">0.6257(margin)</td><td class="n">0.6086</td></tr>
|
||||||
|
<tr><td>打包 <code>text_retriever</code></td><td class="n">0.6076(margin)</td><td class="n bad">0.4752</td></tr>
|
||||||
|
<tr><td>50/50 混合</td><td class="n">0.5446</td><td class="n">0.5062</td></tr>
|
||||||
|
<tr><td>训练过的路由器</td><td class="n">0.5711</td><td class="n">0.5130</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<p class="small">
|
||||||
|
操作点同样不可用:混合打分器想标出 22% 的未知要误拒 <strong>28.40%</strong> 的可回答问题;
|
||||||
|
cosine 想标出 46% 要误拒 <strong>30.00%</strong>。
|
||||||
|
<strong>结论:75% 的泄漏不可能靠分数阈值或分数上的分类头修好。</strong>
|
||||||
|
这不是调参空间不够,而是这个信号根本不存在 —— 24 条同句式候选对任何提问都「一样像」。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>9.2 有效的机制:先判「问的是哪个属性」,再查库里有没有</h3>
|
||||||
|
<p class="small">
|
||||||
|
换一个问题问就成立了:不是「有没有候选匹配得好」,而是「这个提问在问哪个属性,这个属性在库里吗」。
|
||||||
|
</p>
|
||||||
|
<div class="grid g2">
|
||||||
|
<div>
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>封闭词表</th><th>值</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>可回答 episode 中「预测属性在候选集内」</td><td class="n acc">100.00%(250 条)</td></tr>
|
||||||
|
<tr><td>未知 episode 中「预测属性在候选集内」</td><td class="n acc">0.00%(50 条)</td></tr>
|
||||||
|
<tr><td><strong>未知拒答率</strong></td><td class="n acc">100.00%</td></tr>
|
||||||
|
<tr><td><strong>已知问题被误拒率</strong></td><td class="n acc">0.00%</td></tr>
|
||||||
|
<tr><td>混淆矩阵</td><td class="n">tp=50 fn=0 fp=0 tn=250</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="small" style="margin-top:0">
|
||||||
|
<strong>开放集:</strong>真实用户会问模型没见过的属性。只靠最大概率调阈值不够 ——
|
||||||
|
实测<strong>没有拒绝选项时,从未见过的属性 100.00% 会被认成某个存在的属性</strong>。
|
||||||
|
所以改成<strong>显式训练一个 NONE 类</strong>:词表取 12 个属性,另取 6 个词表外属性的真实提问作为 NONE 的负样本,
|
||||||
|
最后用<strong>第三组、与两者都不相交的 6 个全新属性</strong>做测试。
|
||||||
|
</p>
|
||||||
|
<div class="kv">
|
||||||
|
<div class="kv__r"><span class="kv__k">词表内属性识别(133 条未见改写)</span><span class="kv__v">100.00%</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">从未见过的属性被拒绝(52 条)</span><span class="kv__v">100.00%</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">已知问题被误拒率</span><span class="kv__v">0.00%</span></div>
|
||||||
|
<div class="kv__r"><span class="kv__k">随机基线(13 类)</span><span class="kv__v">7.69%</span></div>
|
||||||
|
</div>
|
||||||
|
<p class="tiny">
|
||||||
|
运行时规则只有三步,全部可审计、无阈值调参:① 属性分类头读提问的冻结键 → 输出某个属性或 NONE;
|
||||||
|
② 若为 NONE → 拒绝;③ 若为某属性 → 查库的活跃属性集合是否包含它,不含 → 拒绝。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>9.3 接上运行时:连续失败两次(如实记录)</h3>
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>指标</th><th>NM2.1(无门)</th><th>+ 覆盖门(第一轮)</th><th>+ 门 + 短路(第二轮)</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>A 可回答正确率</td><td class="n acc">100.00%</td><td class="n bad">6.25%</td><td class="n bad">0.00%</td></tr>
|
||||||
|
<tr><td>A 已知问题被误拒率</td><td class="n acc">0.00%</td><td class="n bad">7.50%</td><td class="n bad">7.50%</td></tr>
|
||||||
|
<tr><td>A 未知拒答率</td><td class="n">56.67%</td><td class="n">43.33%</td><td class="n">—</td></tr>
|
||||||
|
<tr><td>C 未知泄漏率</td><td class="n bad">75.00%</td><td class="n">62.50%</td><td class="n acc">0.00%</td></tr>
|
||||||
|
<tr><td>C 可回答正确率</td><td class="n">65.00%</td><td class="n">65.00%</td><td class="n">65.00%</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<p class="small">
|
||||||
|
第一轮:<strong>门把几乎全部可回答问题都拒掉了</strong>(100.00% → 6.25%),而它本该修好的 C 段泄漏只从 75.00% 降到 62.50%。
|
||||||
|
第二轮定位到真正的机制缺口 —— <code>read()</code> 返回空记录后不会停止,<code>_build_text_prefix</code>
|
||||||
|
会继续落到旧版 16 槽注入路径把无关记忆又塞回去。加了短路之后,<strong>C 段泄漏真的到了 0.00%、可回答正确率无损</strong>,
|
||||||
|
但 A 段崩到 0.00%。
|
||||||
|
</p>
|
||||||
|
<p class="small">
|
||||||
|
<strong>A 段崩掉的原因已测定:</strong>段事实里 94.03% 是「这是普通对话噪声…不需要长期保存」,
|
||||||
|
只有 5.97%(63 / 1056)能解析出属性;更关键的是 <strong>A 段的属性空间完全不在属性头训练的 24 个属性之内</strong>,
|
||||||
|
头对 A 的提问只能输出那 24 个之一 → 必然不在库里 → 门把一切都拒掉。
|
||||||
|
<strong>也就是说:这个机制目前是「域内可用、跨域不可用」。</strong>
|
||||||
|
</p>
|
||||||
|
<p class="small">
|
||||||
|
结论:已把 NM2.1 的 <code>memory_coverage_gate</code> 改回 <code>false</code>,恢复为已验证的可用状态。
|
||||||
|
属性头工件保留在 <code>checkpoints/memory_attribute_head/</code>,<strong>未随包启用</strong>。
|
||||||
|
正确的最终形态是<strong>开放词表的属性匹配</strong>(把提问与库里真实存在的属性名做匹配,词表随写入动态变化),
|
||||||
|
而不是 24 类闭集分类头。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="callout callout--warn">
|
||||||
|
<p class="eyebrow" style="color:var(--warn)">这一节最该记住的一句</p>
|
||||||
|
<p class="small" style="margin:0">
|
||||||
|
离线 100.00% / 0.00% 是真实的,但它只证明了机制在「裸提问键 + 24 个可解析属性」这个条件下成立,
|
||||||
|
<strong>并不等于接上运行时就能用</strong>。这一点必须在任何对外表述里讲清楚。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================= 负面结论 ================= -->
|
||||||
|
<h2 class="h3">十 · 关键负面结论:路由器排序不影响端到端答案</h2>
|
||||||
|
<p class="small src">出处 · <code>V2_dpskw\ZERO_OVERLAP_FINDINGS.md</code> §5</p>
|
||||||
|
|
||||||
|
<p class="small">
|
||||||
|
NM2.1 的路由器在零重叠集合上 Top-1 提升了 <strong>41.20 pp</strong>,但在
|
||||||
|
<code>eval_router_critical_e2e.py</code>(16 个零重叠用例)上,REPLAY-128 与 V2-128-v6 的结果
|
||||||
|
<strong>逐位相同</strong>(默认 Top-K:37.50% / 37.50%,答成别的属性 25.00% / 25.00%,平均选中记录 5.88 / 5.88)。
|
||||||
|
</p>
|
||||||
|
<p class="small">
|
||||||
|
于是做了一个<strong>判决性实验</strong>:保留 <code>need_memory</code> / <code>hop_controller</code> / <code>head_gate</code>
|
||||||
|
全部原权重,只把排序通路(<code>query_projection</code>、<code>key_projection</code>、<code>pair_scorer</code>)
|
||||||
|
替换为同形状<strong>随机权重</strong>。结果在默认 Top-K 与 Top-K=1 下<strong>都完全不变</strong>。
|
||||||
|
</p>
|
||||||
|
<div class="lims">
|
||||||
|
<div class="lim"><span class="lim__i">01</span><div>
|
||||||
|
<h3 class="lim__t"><code>memory_os_v2.py:1671</code>:路由器分数被逐位置覆盖</h3>
|
||||||
|
<p class="lim__d">带 <code>semantic_key</code> 的记录,其 <code>_score_candidates()</code> 分数会被
|
||||||
|
<code>self.record_scorer</code> 覆盖。实测残差与 <code>text_retriever</code> 匹配 18 / 18,
|
||||||
|
与 <code>memory_router_v2</code> 匹配 0 / 18。</p></div></div>
|
||||||
|
<div class="lim"><span class="lim__i">02</span><div>
|
||||||
|
<h3 class="lim__t">「部署目录没有 <code>text_retriever.pt</code> 所以走余弦兜底」是错的</h3>
|
||||||
|
<p class="lim__d">重排器被烘焙进合并包(safetensors 内有 6 个
|
||||||
|
<code>dynamic_memory.text_retriever.*</code> 张量,1,573,377 参数),<code>_text_retriever_ready</code>
|
||||||
|
实测为 <strong>True</strong>,余弦兜底分支根本不执行。</p></div></div>
|
||||||
|
<div class="lim"><span class="lim__i">03</span><div>
|
||||||
|
<h3 class="lim__t">路由器在此配置下唯一实际生效的杠杆是 <code>need_memory</code> 门</h3>
|
||||||
|
<p class="lim__d">部署权重下门开启率 <strong>68.75%</strong>(11 / 16),而三份随机初始化的路由器只有
|
||||||
|
<strong>37.5%</strong>(6 / 16)。判决性探针只随机化了排序通路、保留了门控头,所以「端到端零变化」
|
||||||
|
是由构造保证的,不是巧合。</p></div></div>
|
||||||
|
</div>
|
||||||
|
<p class="small">
|
||||||
|
<strong>结论分两层,不要混为一谈:</strong>① 路由器记分卡上 22 / 22 的统治性和 +41.20 pp 的零重叠提升,
|
||||||
|
都是路由器工件<strong>真实</strong>的增益;② 但在这套运行时里,记录级顺序由打包的 <code>text_retriever</code> 决定,
|
||||||
|
路由器分数被覆盖,且相当比例的读取根本不走 V2 库、目标记录还会被写入路径删除。
|
||||||
|
所以<strong>路由器增益不会传递到最终答案</strong>。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- ================= 仍未解决 ================= -->
|
||||||
|
<h2 class="h3">十一 · 仍未解决(不粉饰)</h2>
|
||||||
|
<div class="tbl-wrap">
|
||||||
|
<table class="dtable">
|
||||||
|
<thead><tr><th>短板</th><th>现状</th><th>说明</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>跨域未知拒答</td><td class="n bad">未解决</td><td class="small">覆盖头是 24 类闭集,只在其词表被库填充 ≥ 90% 时生效;开放词表的属性匹配实测仅 <strong>49.20% Top-1 / AUC 0.6560</strong>(零训练),不足</td></tr>
|
||||||
|
<tr><td>答成别的属性</td><td class="n">27.50%</td><td class="small">同形候选间排序仍不理想;已排除先验重加权(更差)与单纯替换打分器(更差)</td></tr>
|
||||||
|
<tr><td>A 段未知拒答率</td><td class="n">56.67%</td><td class="small">未见改善</td></tr>
|
||||||
|
<tr><td>规模验证</td><td class="n bad">未做</td><td class="small">仅 24 属性 / 300 条评测;生产需上千属性、上万改写问法</td></tr>
|
||||||
|
<tr><td>V2 库记录真正参与读取</td><td class="n bad">未解决</td><td class="small">16 个关键用例里 93.75% 仍走旧版 16 槽路径,地址命中 0 / 16</td></tr>
|
||||||
|
<tr><td>通用能力回归套件</td><td class="n bad">未跑</td><td class="small"><code>eval_general_capability.py</code> 依赖的 <code>comprehensive_general.jsonl</code> 不存在</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================= 复现 ================= -->
|
||||||
|
<h2 class="h3">十二 · 复现</h2>
|
||||||
|
<div class="code">
|
||||||
|
<div class="code__bar">
|
||||||
|
<span class="code__t">PowerShell · 整体电池(A / B / C / D 四段)</span>
|
||||||
|
<button class="copy" id="nmCopy" type="button">复制</button>
|
||||||
|
</div>
|
||||||
|
<pre><code id="nmCmd">$env:PYTHONPATH='H:\Memory'; $env:PYTHONIOENCODING='utf-8'; cd H:\Memory\V2_dpskw
|
||||||
|
|
||||||
|
# 整体电池(A/B/C/D 四段)
|
||||||
|
pwsh -NoProfile -File .\run_nm2_battery.ps1 -Package qwen3_5_4b_natural_memory_v2_1 `
|
||||||
|
-Label 'NM2.1 最终' -Tag 'nm2_1_final' -PerCategory 10 -OverlapCases 48 -Blends '0.5'
|
||||||
|
|
||||||
|
# 三代对照表
|
||||||
|
& 'C:\Users\Administrator\miniconda3\envs\LLM\python.exe' -m V2_dpskw.compare_nm2_batteries `
|
||||||
|
--tag "原版NM2=nm2_orig" --tag "NM2.1=nm2_1" --tag "NM2.1最终=nm2_1_final"
|
||||||
|
|
||||||
|
# 门的适用性诊断(确认 applicable/bypassed,避免静默旁路)
|
||||||
|
& 'C:\Users\Administrator\miniconda3\envs\LLM\python.exe' -m V2_dpskw.diagnose_coverage_gate `
|
||||||
|
--package qwen3_5_4b_natural_memory_v2_1</code></pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="small" style="margin-top:var(--sp-2xl)">
|
||||||
|
台账式的逐条原文在 <a class="linku" href="./ledger">真实评测台账</a>;
|
||||||
|
v2 的正式脏数据迁移测试在 <a class="linku" href="./results">测量结果</a>。
|
||||||
|
</p>
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<p class="lede2">
|
||||||
|
正式脏数据迁移测试的完整命令与产物路径。协议参数与批次之间的差异见下方说明——
|
||||||
|
<strong>复现同一批次才能得到同一组数字</strong>。
|
||||||
|
</p>
|
||||||
|
<div class="grid g-2-1" >
|
||||||
|
<div class="code">
|
||||||
|
<div class="code__bar">
|
||||||
|
<span class="code__t">PowerShell · 工作目录 <span id="cwd"></span></span>
|
||||||
|
<button class="copy" id="copyBtn" type="button">复制命令</button>
|
||||||
|
</div>
|
||||||
|
<pre><code id="cmdBlock"></code></pre>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="kv" id="files"></div>
|
||||||
|
<div class="card card--flat" >
|
||||||
|
<p class="eyebrow" >PROTOCOL</p>
|
||||||
|
<div class="flow__meta" style="padding:0; border:0">
|
||||||
|
<div><span>基座模型</span><b id="pBase"></b></div>
|
||||||
|
<div><span>量化</span><b>4-bit NF4</b></div>
|
||||||
|
<div><span>解码</span><b>greedy</b></div>
|
||||||
|
<div><span>最大新生成</span><b>64 token</b></div>
|
||||||
|
<div><span>进程显存上限</span><b>10 GiB</b></div>
|
||||||
|
<div><span>记忆读取上限</span><b>2 records</b></div>
|
||||||
|
<div><span>地址编码</span><b>batch size 1</b></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="callout" >
|
||||||
|
<p class="callout__t">两个批次的差别</p>
|
||||||
|
<p class="callout__b">
|
||||||
|
上面的命令复现的是批次 A(对外技术总结采用的口径,可答题 154/246)。
|
||||||
|
批次 B 来自同目录的 <code>dirty_real_corpus_compare_4b_router_final.json</code>,
|
||||||
|
是接入记忆路由器之后的另一次运行(可答题 203/246)。两次运行的配置不同,
|
||||||
|
<strong>因此它们的分数不能平均、不能合并,也不能互相替代</strong>。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<p class="lede2">
|
||||||
|
三个面板对应三组不同的题集与口径,<strong>不能合并成一个总分</strong>。
|
||||||
|
面板一是同一题集先后跑的两个独立批次(配置不同、分数不可合并,只能并列读);
|
||||||
|
面板二是结构化工程基准;面板三是记忆路由器工程线。每组数据都标注了出处、日期与口径。
|
||||||
|
</p>
|
||||||
|
<p class="small" style="max-width:80ch">
|
||||||
|
读这些数字时请留意两件事:<strong>所有对照都使用同一 tokenizer、同一 greedy 解码、同一 64 token 输出上限</strong>;
|
||||||
|
而<strong>检索召回率与回答正确率是两个必须分开报告的量</strong>——这一点在面板一里体现得最清楚。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="tabs reveal" id="resultTabs" role="tablist" ></div>
|
||||||
|
<div id="resultPanels" ></div>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<p class="lede2">
|
||||||
|
左侧是在 12 GiB GPU 上已经跑通的闭环;右侧是按<strong>对正确率最有帮助的顺序</strong>排出的下一阶段工程任务。
|
||||||
|
这里刻意不写时间表——顺序比日期更可信。
|
||||||
|
</p>
|
||||||
|
<h2 class="h3" >已经解决的问题</h2>
|
||||||
|
<div class="checks" id="solved" ></div>
|
||||||
|
<h2 class="h3" >下一阶段的工程任务</h2>
|
||||||
|
<div class="road" id="roadmap-list" ></div>
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<svg class="dgm" viewBox="0 0 1120 250" role="img"
|
||||||
|
aria-label="读取路径示意:问题 → 隐状态地址 → LSH 粗索引 → 候选页 → 页内重排 → Top-K → 证据前缀 → 生成">
|
||||||
|
<!-- 连接线(pathLength=1 让描边可以按 0→1 精确绘制) -->
|
||||||
|
<g class="dgm__a">
|
||||||
|
<path pathLength="1" d="M132 78 L156 78" /><path pathLength="1" d="M270 78 L294 78" /><path pathLength="1" d="M408 78 L432 78" />
|
||||||
|
<path pathLength="1" d="M546 78 L570 78" /><path pathLength="1" d="M684 78 L708 78" /><path pathLength="1" d="M822 78 L846 78" />
|
||||||
|
<path pathLength="1" d="M960 78 L984 78" />
|
||||||
|
</g>
|
||||||
|
<!-- 8 个环节 -->
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box" x="12" y="46" width="120" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="24" y="66">01</text>
|
||||||
|
<text class="dgm__l" x="24" y="86">用户问题</text>
|
||||||
|
<text class="dgm__s" x="24" y="101">自然语言</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box" x="156" y="46" width="114" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="168" y="66">02</text>
|
||||||
|
<text class="dgm__l" x="168" y="86">隐状态地址</text>
|
||||||
|
<text class="dgm__s" x="168" y="101">Qwen hidden</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box" x="294" y="46" width="114" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="306" y="66">03</text>
|
||||||
|
<text class="dgm__l" x="306" y="86">LSH 粗索引</text>
|
||||||
|
<text class="dgm__s" x="306" y="101">730 桶</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box" x="432" y="46" width="114" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="444" y="66">04</text>
|
||||||
|
<text class="dgm__l" x="444" y="86">候选页</text>
|
||||||
|
<text class="dgm__s" x="444" y="101">≤4 页 · 32/页</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box" x="570" y="46" width="114" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="582" y="66">05</text>
|
||||||
|
<text class="dgm__l" x="582" y="86">页内重排</text>
|
||||||
|
<text class="dgm__s" x="582" y="101">text_retriever</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box dgm__box--acc" x="708" y="46" width="114" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="720" y="66">06</text>
|
||||||
|
<text class="dgm__l" x="720" y="86">Top-K 记录</text>
|
||||||
|
<text class="dgm__s" x="720" y="101">≤2 条</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box dgm__box--acc" x="846" y="46" width="114" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="858" y="66">07</text>
|
||||||
|
<text class="dgm__l" x="858" y="86">证据前缀</text>
|
||||||
|
<text class="dgm__s" x="858" y="101">注入 Qwen</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect class="dgm__box" x="984" y="46" width="124" height="64" rx="8"/>
|
||||||
|
<text class="dgm__n" x="996" y="66">08</text>
|
||||||
|
<text class="dgm__l" x="996" y="86">普通生成</text>
|
||||||
|
<text class="dgm__s" x="996" y="101">回答</text>
|
||||||
|
</g>
|
||||||
|
<!-- 关键约束注释 -->
|
||||||
|
<line class="dgm__rule" x1="12" y1="146" x2="1108" y2="146"/>
|
||||||
|
<text class="dgm__note" x="12" y="172">无全量注意力</text>
|
||||||
|
<text class="dgm__s" x="1108" y="172" text-anchor="end">BOUNDED READ</text>
|
||||||
|
<text class="dgm__note" x="12" y="190">当前问题不与全部记忆记录做注意力,只与少量页面和记录交互</text>
|
||||||
|
<text class="dgm__note" x="12" y="222">读取额外耗时 61.10 ms → 26.35 ms(批次 A → B) · 前缀命中率 96.97% · GPU cache 实际 17,990 / 上限 131,072 token</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.2 KiB |
@@ -0,0 +1,19 @@
|
|||||||
|
@echo off
|
||||||
|
rem ============================================================
|
||||||
|
rem Natural Memory v2 — 站点启动脚本(Windows)
|
||||||
|
rem 默认监听 127.0.0.1:7443,仅本机可达,供反向代理使用
|
||||||
|
rem ============================================================
|
||||||
|
setlocal
|
||||||
|
cd /d "%~dp0"
|
||||||
|
|
||||||
|
set NM_HOST=%NM_HOST%
|
||||||
|
if "%NM_HOST%"=="" set NM_HOST=127.0.0.1
|
||||||
|
set NM_PORT=%NM_PORT%
|
||||||
|
if "%NM_PORT%"=="" set NM_PORT=7443
|
||||||
|
|
||||||
|
rem 优先使用项目常用的 conda 环境,其次退回 PATH 里的 python
|
||||||
|
set PYBIN=C:\Program Files\python\python.exe
|
||||||
|
if not exist "%PYBIN%" set PYBIN=python
|
||||||
|
|
||||||
|
echo Starting Natural Memory v2 site on http://%NM_HOST%:%NM_PORT%/
|
||||||
|
"%PYBIN%" server.py --host %NM_HOST% --port %NM_PORT%
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>{{TITLE}}</title>
|
||||||
|
<meta name="description" content="{{DESC}}">
|
||||||
|
<meta name="color-scheme" content="dark">
|
||||||
|
<meta name="theme-color" content="#0a0a0a">
|
||||||
|
<!-- 动效的初始隐藏态只在 JS 可用时生效;脚本被禁用时内容照常可见 -->
|
||||||
|
<script>document.documentElement.classList.add("js");</script>
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:title" content="{{TITLE}}">
|
||||||
|
<meta property="og:description" content="{{DESC}}">
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<link rel="icon" href="assets/favicon.svg" type="image/svg+xml">
|
||||||
|
<link rel="apple-touch-icon" href="assets/favicon.svg">
|
||||||
|
<link rel="preload" href="assets/fonts/archivo-latin-wdth-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<link rel="preload" href="assets/fonts/geist-mono-latin-wght-normal.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<!-- 资源带构建指纹:内容一变 URL 就变,浏览器不可能再用到旧 JS/CSS -->
|
||||||
|
<link rel="stylesheet" href="assets/css/site.css?v={{ASSET_V}}">
|
||||||
|
</head>
|
||||||
|
<body data-page="{{PAGE_ID}}" data-layout="{{LAYOUT}}">
|
||||||
|
<a class="skip" href="#doc">跳到正文</a>
|
||||||
|
|
||||||
|
<header class="site" id="site">
|
||||||
|
<div class="topbar">
|
||||||
|
<a class="brand" href="./" aria-label="Natural Memory v2 发布页">
|
||||||
|
<svg class="brand__mark" viewBox="0 0 32 32" aria-hidden="true">
|
||||||
|
<rect class="dim" x="2" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="2" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="12" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="22" y="12" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="2" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="dim" x="12" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
<rect class="on" x="22" y="22" width="7" height="7" rx="1.5"/>
|
||||||
|
</svg>
|
||||||
|
<span class="brand__name">Natural Memory</span>
|
||||||
|
<span class="pill pill--acc">v2</span>
|
||||||
|
</a>
|
||||||
|
<span class="crumb">
|
||||||
|
<span class="crumb__n">{{NUM}}</span>
|
||||||
|
<span class="crumb__t">{{ZH}}</span>
|
||||||
|
</span>
|
||||||
|
<span class="topbar__spacer"></span>
|
||||||
|
<nav class="topnav" aria-label="快速导航">
|
||||||
|
{{TOPBAR_NAV}}
|
||||||
|
</nav>
|
||||||
|
<button class="palbtn" id="palBtn" type="button" aria-label="检索全站内容(快捷键 /)">
|
||||||
|
<span class="palbtn__t">检索</span><span class="kbd">/</span>
|
||||||
|
</button>
|
||||||
|
<span class="pill" id="serverChip" title="本站服务端运行时读数">
|
||||||
|
<i class="dot"></i><span id="serverChipText">读取中</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="progress" id="progress"></div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{{MAIN}}
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="wrap footer__in">
|
||||||
|
<div class="footer__col">
|
||||||
|
<p class="footer__h">作者</p>
|
||||||
|
<div class="author">
|
||||||
|
<a class="author__a" href="https://wpyw.site" target="_blank" rel="noopener">
|
||||||
|
<span class="author__k">个人网站</span><span class="author__v">wpyw.site</span>
|
||||||
|
</a>
|
||||||
|
<a class="author__a" href="mailto:[email protected]">
|
||||||
|
<span class="author__k">邮箱</span><span class="author__v">[email protected]</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">来源</p>
|
||||||
|
<div class="readout" id="footFiles"></div>
|
||||||
|
<p class="footer__h" style="margin-top:20px">服务端读数</p>
|
||||||
|
<div class="readout mono" id="footServer"><span>读取中…</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col footer__col--wide">
|
||||||
|
<p class="footer__h">说明</p>
|
||||||
|
<p class="footer__note" id="disclaimer"></p>
|
||||||
|
<p class="footer__meta">构建于 {{BUILT}} · 所有数字取自工程内的正式报告,未做外推或估算。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<!-- 全站检索:客户端索引,无后端、无网络请求 -->
|
||||||
|
<div class="pal" id="pal" hidden>
|
||||||
|
<div class="pal__mask" id="palMask"></div>
|
||||||
|
<div class="pal__box" role="dialog" aria-modal="true" aria-label="检索全站内容">
|
||||||
|
<div class="pal__hd">
|
||||||
|
<span class="pal__ico" aria-hidden="true"></span>
|
||||||
|
<input class="pal__in" id="palInput" type="text" role="combobox" aria-expanded="true"
|
||||||
|
aria-controls="palList" autocomplete="off" spellcheck="false"
|
||||||
|
placeholder="检索全站内容:章节、数字、术语…">
|
||||||
|
<span class="kbd">Esc</span>
|
||||||
|
</div>
|
||||||
|
<div class="pal__list" id="palList" role="listbox" aria-label="检索结果"></div>
|
||||||
|
<div class="pal__ft">
|
||||||
|
<span><span class="kbd">↑</span><span class="kbd">↓</span> 选择</span>
|
||||||
|
<span><span class="kbd">↵</span> 打开</span>
|
||||||
|
<span class="pal__n mono" id="palN"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="assets/js/data.js?v={{ASSET_V}}"></script>
|
||||||
|
<script src="assets/js/examples.js?v={{ASSET_V}}"></script>
|
||||||
|
<script src="assets/js/restart.js?v={{ASSET_V}}"></script>
|
||||||
|
<script src="assets/js/nm21.js?v={{ASSET_V}}"></script>
|
||||||
|
<script src="assets/js/ledger.js?v={{ASSET_V}}"></script>
|
||||||
|
<script src="assets/js/search.js?v={{ASSET_V}}"></script>
|
||||||
|
<script src="assets/js/space.js?v={{ASSET_V}}"></script>
|
||||||
|
<script src="assets/js/site.js?v={{ASSET_V}}"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,271 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head><meta charset="utf-8"><title>gate</title>
|
||||||
|
<style>html,body{margin:0;background:#111}iframe{width:100%;height:100vh;border:0;visibility:hidden;position:absolute;inset:0}</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- 临时闸门检查页,跑完即删,不随站点部署 -->
|
||||||
|
<iframe id="f"></iframe>
|
||||||
|
<script>
|
||||||
|
var W = (location.search.match(/w=(\d+)/) || [0, "1576"])[1];
|
||||||
|
var LIST = (location.search.match(/p=([^&]+)/) || [0, ""])[1];
|
||||||
|
var PAGES = LIST ? decodeURIComponent(LIST).split(",") : ["/"];
|
||||||
|
var out = ["W" + W, "N" + PAGES.length];
|
||||||
|
function log(k, v) { out.push(k + "=" + v); }
|
||||||
|
function q(s, r) { return (r || document).querySelector(s); }
|
||||||
|
function qa(s, r) { return Array.prototype.slice.call((r || document).querySelectorAll(s)); }
|
||||||
|
var f = document.getElementById("f");
|
||||||
|
var steps = [];
|
||||||
|
function run(fn, wait) { steps.push([fn, wait]); }
|
||||||
|
function next() {
|
||||||
|
if (!steps.length) { (new Image()).src = "/__gate?d=" + encodeURIComponent(out.join(" ; ")); return; }
|
||||||
|
var s = steps.shift();
|
||||||
|
try { s[0](); } catch (e) { log("STEPERR", e.message); }
|
||||||
|
setTimeout(next, s[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function rgb2key(s) {
|
||||||
|
var m = String(s).match(/rgba?\(([^)]+)\)/);
|
||||||
|
if (!m) return null;
|
||||||
|
var p = m[1].split(",").map(function (x) { return parseFloat(x); });
|
||||||
|
if (p.length > 3 && p[3] === 0) return null;
|
||||||
|
return Math.round(p[0] / 16) + "," + Math.round(p[1] / 16) + "," + Math.round(p[2] / 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gatePage(slug) {
|
||||||
|
var d = f.contentDocument, w = f.contentWindow;
|
||||||
|
var VW = w.innerWidth, VH = w.innerHeight;
|
||||||
|
var all = qa("body *", d);
|
||||||
|
|
||||||
|
/* --- 字号刻度:最大渲染字号 vs 正文众数 --- */
|
||||||
|
var dispMax = 0, dispEl = "-", sizes = {};
|
||||||
|
/* 只看「自己直接带的文字」,不能因为元素有子元素就跳过 ——
|
||||||
|
否则 <h1>字<br>字</h1> 和 <span class="mega">100.00<small>%</small></span>
|
||||||
|
都会被漏掉,最大的字号就量错了。 */
|
||||||
|
var ownText = function (el) {
|
||||||
|
var s = "";
|
||||||
|
for (var i = 0; i < el.childNodes.length; i++) {
|
||||||
|
if (el.childNodes[i].nodeType === 3) s += el.childNodes[i].nodeValue;
|
||||||
|
}
|
||||||
|
return s.trim();
|
||||||
|
};
|
||||||
|
all.forEach(function (el) {
|
||||||
|
var cs = w.getComputedStyle(el);
|
||||||
|
var txt = ownText(el);
|
||||||
|
if (!txt) return;
|
||||||
|
var fs = parseFloat(cs.fontSize);
|
||||||
|
if (fs > dispMax) { dispMax = fs; dispEl = el.tagName.toLowerCase() + (el.className ? "." + String(el.className).split(/\s+/)[0] : ""); }
|
||||||
|
if (el.tagName === "P" && (el.textContent || "").trim().length > 40) sizes[fs] = (sizes[fs] || 0) + 1;
|
||||||
|
});
|
||||||
|
var bodyPx = 0, best = 0;
|
||||||
|
Object.keys(sizes).forEach(function (k) { if (sizes[k] > best) { best = sizes[k]; bodyPx = parseFloat(k); } });
|
||||||
|
if (!bodyPx) bodyPx = parseFloat(w.getComputedStyle(d.body).fontSize);
|
||||||
|
|
||||||
|
/* --- 字体家族 --- */
|
||||||
|
var fams = {};
|
||||||
|
all.forEach(function (el) {
|
||||||
|
var ff = w.getComputedStyle(el).fontFamily || "";
|
||||||
|
var first = ff.split(",")[0].replace(/["']/g, "").trim();
|
||||||
|
if (first) fams[first] = 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
/* --- 主色数量(背景 + 文字) --- */
|
||||||
|
var cols = {};
|
||||||
|
all.forEach(function (el) {
|
||||||
|
var cs = w.getComputedStyle(el);
|
||||||
|
var a = rgb2key(cs.backgroundColor); if (a) cols[a] = (cols[a] || 0) + 1;
|
||||||
|
var b = rgb2key(cs.color); if (b) cols[b] = (cols[b] || 0) + 1;
|
||||||
|
});
|
||||||
|
var colN = Object.keys(cols).length;
|
||||||
|
|
||||||
|
/* --- 渐变 --- */
|
||||||
|
var grad = 0;
|
||||||
|
all.forEach(function (el) {
|
||||||
|
var bi = w.getComputedStyle(el).backgroundImage || "";
|
||||||
|
if (/gradient/.test(bi)) grad++;
|
||||||
|
});
|
||||||
|
|
||||||
|
/* --- 章节形状多样性 --- */
|
||||||
|
var secs = qa("#doc > section, #doc > .band, .release > section", d);
|
||||||
|
var shapes = {};
|
||||||
|
secs.forEach(function (s) {
|
||||||
|
var sig = [];
|
||||||
|
sig.push(s.querySelector("table") ? "T" : "-");
|
||||||
|
sig.push(s.querySelector("pre") ? "C" : "-");
|
||||||
|
sig.push(s.querySelector("svg") ? "V" : "-");
|
||||||
|
var g = s.querySelector(".grid, .kpis, .claims, .lims, .ledger, .dose, .nm21grid, .rst");
|
||||||
|
sig.push(g ? (g.className.split(/\s+/).filter(function (x) { return /^g\d|kpis|claims|lims|ledger|dose|nm21grid|rst/.test(x); })[0] || "G") : "-");
|
||||||
|
sig.push(s.querySelectorAll("h3").length > 1 ? "M" : "-");
|
||||||
|
shapes[sig.join("")] = 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
/* --- 首屏是否居中标题 + 双按钮 --- */
|
||||||
|
var first = q("#doc > section, #doc > .band", d) || q("#doc", d) || d.body;
|
||||||
|
var cs1 = w.getComputedStyle(first);
|
||||||
|
var centred = cs1.textAlign === "center" ||
|
||||||
|
!!qa("h1, h2, .h1, .h2", first).filter(function (h) {
|
||||||
|
return w.getComputedStyle(h).textAlign === "center";
|
||||||
|
}).length;
|
||||||
|
var btns = qa("a.btn, button.btn, .linkrow a, .linkrow button", first).length;
|
||||||
|
|
||||||
|
/* --- 页面高度 / 视口 --- */
|
||||||
|
var vhPage = d.documentElement.scrollHeight / VH;
|
||||||
|
|
||||||
|
/* --- body 全局 max-width --- */
|
||||||
|
var bmw = w.getComputedStyle(d.body).maxWidth;
|
||||||
|
|
||||||
|
/* --- h1 数量 / 段落宽度 --- */
|
||||||
|
var h1n = qa("h1", d).length;
|
||||||
|
var meas = 0, measN = 0;
|
||||||
|
qa("p", d).forEach(function (p) {
|
||||||
|
if ((p.textContent || "").trim().length < 60) return;
|
||||||
|
var cw = p.clientWidth, fs = parseFloat(w.getComputedStyle(p).fontSize);
|
||||||
|
// 粗略估算一行字符数:中文按 1 个字宽=fs,英文按 0.5
|
||||||
|
if (cw > 0) { meas += cw / fs; measN++; }
|
||||||
|
});
|
||||||
|
var avgCh = measN ? (meas / measN) : 0;
|
||||||
|
|
||||||
|
log(slug + ".disp", Math.round(dispMax) + "px " + dispEl);
|
||||||
|
log(slug + ".body", Math.round(bodyPx) + "px");
|
||||||
|
log(slug + ".ratio", (dispMax / bodyPx).toFixed(1));
|
||||||
|
log(slug + ".fam", Object.keys(fams).length + " [" + Object.keys(fams).join("|").slice(0, 60) + "]");
|
||||||
|
log(slug + ".cols", colN);
|
||||||
|
log(slug + ".grad", grad);
|
||||||
|
log(slug + ".secs", secs.length);
|
||||||
|
log(slug + ".shapes", Object.keys(shapes).length);
|
||||||
|
log(slug + ".centredHero", centred);
|
||||||
|
log(slug + ".heroBtns", btns);
|
||||||
|
log(slug + ".vh", vhPage.toFixed(1));
|
||||||
|
log(slug + ".bodyMaxW", bmw);
|
||||||
|
log(slug + ".h1", h1n);
|
||||||
|
log(slug + ".avgCh", avgCh.toFixed(0));
|
||||||
|
log(slug + ".midGrey", (function () {
|
||||||
|
// A6 辅助:有多少「中间尺寸」的文字(16–48px 之间)——中间带扎堆是典型的没做字阶
|
||||||
|
var mid = 0, tot = 0;
|
||||||
|
all.forEach(function (el) {
|
||||||
|
if (el.children.length) return;
|
||||||
|
if (!(el.textContent || "").trim()) return;
|
||||||
|
var fs = parseFloat(w.getComputedStyle(el).fontSize);
|
||||||
|
tot++;
|
||||||
|
if (fs >= 16 && fs <= 48) mid++;
|
||||||
|
});
|
||||||
|
return (100 * mid / (tot || 1)).toFixed(0) + "%";
|
||||||
|
})());
|
||||||
|
|
||||||
|
/* --- 溢出与截断 --- */
|
||||||
|
var ov = [], clip = [];
|
||||||
|
all.forEach(function (el) {
|
||||||
|
var r = el.getBoundingClientRect();
|
||||||
|
if (r.width && r.height && r.right > VW + 2 &&
|
||||||
|
!el.closest(".topnav") && !el.closest(".tbl-wrap") && !el.closest(".scrollx") &&
|
||||||
|
!el.closest(".side") && !el.closest("pre") && !el.closest(".pal") &&
|
||||||
|
!el.classList.contains("skip")) ov.push(idOf(el));
|
||||||
|
if (!el.children.length && el.clientWidth > 0 && el.scrollWidth > el.clientWidth + 2 &&
|
||||||
|
/^(P|H1|H2|H3|TD|SPAN|A|B|I|CODE)$/.test(el.tagName)) {
|
||||||
|
clip.push(idOf(el) + "[" + (el.textContent || "").slice(0, 16) + "]");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
log(slug + ".ov", d.documentElement.scrollWidth - VW);
|
||||||
|
log(slug + ".ovEls", ov.slice(0, 3).join("|") || "-");
|
||||||
|
log(slug + ".clip", clip.length);
|
||||||
|
log(slug + ".clipEls", clip.slice(0, 3).join("|") || "-");
|
||||||
|
log(slug + ".undef", ((txt2(d)) .match(/undefined/g) || []).length);
|
||||||
|
log(slug + ".nan", ((txt2(d)).match(/\bNaN\b/g) || []).length);
|
||||||
|
|
||||||
|
/* --- 首屏装置探针 --- */
|
||||||
|
var cv = d.getElementById("spaceCv");
|
||||||
|
if (cv) {
|
||||||
|
log(slug + ".cv", cv.width + "x" + cv.height);
|
||||||
|
var probe = w.__space;
|
||||||
|
log(slug + ".probe", probe ? ("steps=" + probe.steps + " t=" + probe.t().toFixed(2) + " prog=" + probe.progress().toFixed(2)) : "MISSING");
|
||||||
|
try {
|
||||||
|
var g = cv.getContext("2d");
|
||||||
|
var rx = Math.round(cv.width * 0.06), ry = Math.round(cv.height * 0.06);
|
||||||
|
var rw = Math.min(700, cv.width - rx), rh = Math.min(420, cv.height - ry);
|
||||||
|
var px = g.getImageData(rx, ry, rw, rh).data;
|
||||||
|
var ink = 0, maxv = 0;
|
||||||
|
for (var i = 0; i < px.length; i += 4 * 7) {
|
||||||
|
var v = px[i] + px[i + 1] + px[i + 2];
|
||||||
|
if (v > 24) ink++;
|
||||||
|
if (v > maxv) maxv = v;
|
||||||
|
}
|
||||||
|
log(slug + ".cvInk", ink + " maxv=" + maxv + " of " + Math.round(px.length / 28));
|
||||||
|
} catch (e) { log(slug + ".cvInk", "ERR " + e.message); }
|
||||||
|
log(slug + ".hud0", (q("#hudIdx", d) || {}).textContent + " " + (q("#hudName", d) || {}).textContent);
|
||||||
|
if (probe && probe.seek) {
|
||||||
|
probe.seek(0.92); probe.hold();
|
||||||
|
log(slug + ".hud92", (q("#hudName", d) || {}).textContent + " · " + (q("#hudVal", d) || {}).textContent);
|
||||||
|
probe.seek(0);
|
||||||
|
}
|
||||||
|
log(slug + ".still", d.documentElement.classList.contains("space--still"));
|
||||||
|
log(slug + ".heroH", Math.round(d.getElementById("hero").getBoundingClientRect().height));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function txt2(d) { return d.body.innerText || ""; }
|
||||||
|
function idOf(el) {
|
||||||
|
if (!el) return "?";
|
||||||
|
var s = el.tagName.toLowerCase();
|
||||||
|
if (el.className && typeof el.className === "string") s += "." + el.className.trim().split(/\s+/)[0];
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
PAGES.forEach(function (u) {
|
||||||
|
var slug = u.replace(/\W/g, "") || "home";
|
||||||
|
run(function () { f.src = u; }, 1100);
|
||||||
|
run(function () { gatePage(slug); }, 300);
|
||||||
|
});
|
||||||
|
|
||||||
|
/* --- B2/B8:滚完一整页之后,不允许还有「没抵达」的元素卡在隐藏态 --- */
|
||||||
|
run(function () { f.src = "/"; }, 1300);
|
||||||
|
run(function () {
|
||||||
|
var d = f.contentDocument, w = f.contentWindow;
|
||||||
|
var H = d.documentElement.scrollHeight;
|
||||||
|
var step = Math.max(320, Math.round(w.innerHeight * 0.62));
|
||||||
|
var y = 0;
|
||||||
|
(function sweep() {
|
||||||
|
y += step;
|
||||||
|
d.documentElement.scrollTop = y;
|
||||||
|
try { w.scrollTo({ top: y, behavior: "instant" }); } catch (e) { w.scrollTo(0, y); }
|
||||||
|
try { w.dispatchEvent(new w.Event("scroll")); } catch (e) { w.dispatchEvent(new Event("scroll")); }
|
||||||
|
if (y < H) setTimeout(sweep, 70);
|
||||||
|
})();
|
||||||
|
}, 14000);
|
||||||
|
run(function () {
|
||||||
|
var d = f.contentDocument, w = f.contentWindow;
|
||||||
|
var sel = ".arr-wipe, .arr-num, .arr-cards, .teaser, .reveal";
|
||||||
|
var all = qa(sel, d);
|
||||||
|
var off = all.filter(function (e) { return !e.classList.contains("is-in"); });
|
||||||
|
log("RV_total", all.length);
|
||||||
|
log("RV_unresolved", off.length);
|
||||||
|
log("RV_offEls", off.slice(0, 4).map(function (e) { return idOf(e); }).join("|") || "-");
|
||||||
|
log("RV_arrN", qa(".arr-wipe, .arr-num, .arr-cards", d).length);
|
||||||
|
log("RV_oldRv", qa(".rv, .rv-group", d).length);
|
||||||
|
var wip = q(".arr-wipe", d);
|
||||||
|
if (wip) {
|
||||||
|
log("RV_wipeClip", w.getComputedStyle(wip).clipPath);
|
||||||
|
log("RV_wipeH", Math.round(wip.getBoundingClientRect().height));
|
||||||
|
}
|
||||||
|
var probe = w.__space;
|
||||||
|
if (probe) log("RV_spaceT", probe.t().toFixed(2) + " prog=" + probe.progress().toFixed(2));
|
||||||
|
log("RV_pageH", d.documentElement.scrollHeight);
|
||||||
|
|
||||||
|
/* 虚拟时间下过渡不推进,读到的永远是起始值。
|
||||||
|
关掉过渡再读一次,验的是「CSS 目标值」而不是「过渡当前值」。 */
|
||||||
|
var st = d.createElement("style");
|
||||||
|
st.textContent = "*,*::before,*::after{transition:none !important}";
|
||||||
|
d.head.appendChild(st);
|
||||||
|
var wip2 = q(".arr-wipe", d);
|
||||||
|
if (wip2) log("RV_wipeTarget", w.getComputedStyle(wip2).clipPath);
|
||||||
|
var num2 = q(".arr-num", d);
|
||||||
|
if (num2) log("RV_numTarget", w.getComputedStyle(num2).opacity + " / " + w.getComputedStyle(num2).transform);
|
||||||
|
var card2 = q(".arr-cards > *", d);
|
||||||
|
if (card2) log("RV_cardTarget", w.getComputedStyle(card2).opacity + " / " + w.getComputedStyle(card2).transform);
|
||||||
|
var kick = q(".band__k + .h2", d);
|
||||||
|
if (kick) log("RV_bandHead", Math.round(parseFloat(w.getComputedStyle(kick).fontSize)) + "px");
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
next();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
从磁盘上的真实评测 JSON 生成站点用的台账数据 assets/js/ledger.js。
|
||||||
|
|
||||||
|
⚠️ 生成物不要手改;改数据请改上游 JSON 后重跑本脚本。
|
||||||
|
|
||||||
|
来源(两份都是工程里保存的正式运行结果,逐字复制,不做任何改写或换算):
|
||||||
|
A. H:\\Memory\\V2_dpskw\\runtime_score_bands.json 60 episodes
|
||||||
|
B. H:\\Memory\\V2_dpskw\\nm2_1_final_runtime_e2e.json 48 episodes
|
||||||
|
|
||||||
|
用法:
|
||||||
|
python tools/make_ledger.py
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import io
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
SOURCES = [
|
||||||
|
{
|
||||||
|
"key": "bands",
|
||||||
|
"label": "运行时评分带扫描",
|
||||||
|
"path": r"H:\Memory\V2_dpskw\runtime_score_bands.json",
|
||||||
|
"config": "0.00",
|
||||||
|
"note": "60 用例 · 24 同形候选 · prior=1.00 blend=0.00",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "e2e",
|
||||||
|
"label": "NM2.1 最终运行时",
|
||||||
|
"path": r"H:\Memory\V2_dpskw\nm2_1_final_runtime_e2e.json",
|
||||||
|
"config": "prior=1.00 blend=0.50",
|
||||||
|
"note": "48 用例 · 24 同形候选 · prior=1.00 blend=0.50",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
OUT = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
|
||||||
|
"assets", "js", "ledger.js")
|
||||||
|
|
||||||
|
|
||||||
|
def rows_of(path: str, key: str):
|
||||||
|
with open(path, encoding="utf-8") as fh:
|
||||||
|
j = json.load(fh)
|
||||||
|
rows = j.get("rows") or {}
|
||||||
|
if key not in rows:
|
||||||
|
raise SystemExit("在 %s 里找不到 rows[%r]" % (path, key))
|
||||||
|
return rows[key]
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
out, total = [], 0
|
||||||
|
for src in SOURCES:
|
||||||
|
rows = rows_of(src["path"], src["config"])
|
||||||
|
total += len(rows)
|
||||||
|
out.append({
|
||||||
|
"key": src["key"],
|
||||||
|
"label": src["label"],
|
||||||
|
"note": src["note"],
|
||||||
|
"n": len(rows),
|
||||||
|
"items": [{
|
||||||
|
"id": r.get("id"),
|
||||||
|
"attr": r.get("attribute"),
|
||||||
|
"ans": bool(r.get("answerable")),
|
||||||
|
"exp": r.get("expected"),
|
||||||
|
"reply": r.get("reply"),
|
||||||
|
"ok": bool(r.get("correct")),
|
||||||
|
"wrong": bool(r.get("wrong_attribute")),
|
||||||
|
"leak": bool(r.get("leaked")),
|
||||||
|
"stop": r.get("stop_reason"),
|
||||||
|
"sel": r.get("records_selected"),
|
||||||
|
"score": r.get("top_score"),
|
||||||
|
"active": r.get("records_active"),
|
||||||
|
"need": r.get("need_memory"),
|
||||||
|
} for r in rows],
|
||||||
|
})
|
||||||
|
|
||||||
|
body = io.StringIO()
|
||||||
|
body.write("/* ==================================================================\n")
|
||||||
|
body.write(" Natural Memory v2 — ledger.js\n")
|
||||||
|
body.write(" 「真实评测台账」的数据层。\n\n")
|
||||||
|
body.write(" ⚠️ 本文件由 tools/make_ledger.py 从磁盘上的原始评测 JSON 生成,\n")
|
||||||
|
body.write(" 请勿手改。下面是全部 %d 条 episode,字段逐字复制、未做改写或换算。\n\n" % total)
|
||||||
|
for s in SOURCES:
|
||||||
|
body.write(" %s\n" % os.path.basename(s["path"]))
|
||||||
|
body.write(" ================================================================== */\n")
|
||||||
|
body.write("window.NM_LEDGER = ")
|
||||||
|
body.write(json.dumps(out, ensure_ascii=False, separators=(",", ":"), indent=0)
|
||||||
|
.replace("\n", ""))
|
||||||
|
body.write(";\n")
|
||||||
|
|
||||||
|
os.makedirs(os.path.dirname(OUT), exist_ok=True)
|
||||||
|
with open(OUT, "w", encoding="utf-8", newline="\n") as fh:
|
||||||
|
fh.write(body.getvalue())
|
||||||
|
print("写出 %s(%d 条 episode / %d 字节)" % (OUT, total, os.path.getsize(OUT)))
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
Reference in New Issue
Block a user