336 lines
20 KiB
HTML
336 lines
20 KiB
HTML
<!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>
|