Browse this library

Chinese source article

2.3.2 · 容量边界与状态治理

分析固定容量、写入读取辨识性、隔离遗忘和证据距离等失败边界。

View original Markdown ↗

1. 固定容量到底固定了什么

LiveMem 的状态大小与历史 token 数无关,但会随层数、头数、key/value 维度和数据类型增长。若每层有 hh 个头,每头状态矩阵为 dk×dvd_k\times d_v,模型有 LL 层,元素字节数为 bb,单请求状态量级为

Mstate=Lhdkdvb.(24)M_{state}=Lhd_kd_vb. \tag{24}

若采用 BF16,b=2b=2。这个公式还未计入门控缓存、对齐和框架对象,但能看出它对序列长度是常数,对并发请求数则线性增长。服务一千个长会话时,固定容量并不等于免费,只是把增长轴从历史长度换成了活跃请求数。 注意力窗口仍保存 KV。设窗口长度为 WW,每 token 每层 KV 宽度为 dkvd_{kv},主路径缓存约为

Mwindow=2LWdkvb.(25)M_{window}=2LWd_{kv}b. \tag{25}

总请求状态为两者之和。将窗口从 32K 减到 8K 会显著降低 KV,却不改变循环状态;若任务依赖精确近期文本,缩窗可能损害性能。论文同时评测 8K 与 32K,正是在观察固定状态能否补偿更窄工作窗口。 固定状态还不受「位置长度」无限扩展保证。官方仓库明确说明单次输入仍受 262,144 token 的位置范围约束,状态在一个请求生命周期内持续,请求结束后释放,当前 OpenAI 兼容接口也不会自动跨独立请求复用。把它描述成无限上下文或永久用户记忆都会超出实现证据。

容量上限可以用碰撞任务测试。构造 nn 个互不相关键值对,逐渐增大 nn,并让查询发生在键退出注意力窗口之后。若状态维度固定,准确率最终会下降。改变头数或状态宽度,观察拐点是否移动,可以区分容量瓶颈与训练不足。 另一种测试要求保存连续更新的少量变量。即使历史很长,只要充分统计量维度小,固定状态应保持稳定。若这类任务也随长度快速退化,问题更可能在递推稳定性、训练分布或服务状态丢失,而非理论容量不足。

Context turnover 的可见性协议,轮转不是在送入模型前截掉前缀。被驱逐 token 必须先经过模型并写入循环状态,随后才从注意力可见集合和 KV 页面中释放。truncate 模式把旧历史丢掉并从零状态处理后缀,state 模式则保留从完整历史累积出的状态;两者输入窗口看起来同样短,内部计算历史完全不同。 设系统 prompt 长度为 SS,近期窗口为 WW,当前查询位置为 tt。注意力可见集合可写成

\mathcal V_t={1,\ldots,S\} \cup\{\max(S+1,t-W+1),\ldots,t\}. \tag{26}

系统 sink 始终保留,普通历史随窗口滑动。循环状态则已经扫描 11 到 tt。若训练 mask 允许注意力偷看本应驱逐的 token,模型不会学会依赖状态;部署真正释放 KV 后,性能会突然下降。 动态 mask 需要处理 packed sequence。一个训练批次可能打包多个样本,状态和注意力都不能跨样本泄漏。segment ID、sequence ID、chunk ID 与 eviction step 共同决定可见关系;任何一个边界错误,模型可能利用前一条样本的答案,离线 loss 还会显得更低。 轮转发生在 token 边界,工具消息或文档段落却有语义边界。若窗口恰好切在 JSON 或公式中间,注意力只看到后半段,状态需要承担前半段信息。训练若总在整段边界驱逐,部署的任意 token 轮转会形成分布偏移。压力测试应随机改变驱逐位置。

位置编码也没有因 KV 释放而重置。近期窗口中的 token 仍携带原请求里的绝对或旋转位置;把后缀重新编码成从零开始的 truncate 基线,会改变模型看到的位置分布。比较两种模式时必须区分「是否有状态」与「是否重新编号」。

为什么要冻结主干,官方训练默认冻结 Qwen3 的注意力和 FFN 主路径,只训练新增循环记忆分支。这样可以把变化集中在记忆能力,减少对原有短上下文能力的破坏,也显著降低训练参数量。输出采用逐层相加:

oℓ=oℓattn+oℓmem.(27)o_\ell=o_{\ell}^{attn}+o_{\ell}^{mem}. \tag{27}

初始记忆分支若输出接近零,模型行为接近原主干;训练逐渐学会在注意力缺失证据时提供修正。这比替换全部注意力层更容易从现有 checkpoint 起步。 冻结也限制了协同适配。主干查询表示原本没有为 GDN2 状态设计,新增分支只能学习如何读取既有 hidden state 并把结果加回去。若两个分支尺度不匹配,记忆输出可能被残差流淹没,或过强地扰动近期推理。归一化、门控和训练阶段需要控制这个尺度。

两阶段 SFT 的意义由数据职责决定。第一阶段用长数据让分支学会基本写入与跨窗口读取;第二阶段混合 QA、分类、多问题和长文本,使状态服务于不同输出形式。仓库给出的 100 步与 500 步属于具体复现配方,不能推广成普遍最优阶段长度。 RL 继续优化「何种记忆最终有用」。仓库开发配置使用 GRPO、每组八个响应、无 KL、非对称裁剪 0.20/0.28 和 token-mean loss。终局奖励可以推动状态保留支持答案的信息,但也可能学习 judge 偏好;若奖励只关心回答,不检查权限和事实来源,记忆分支没有梯度去保存这些边界。

冻结主干让 RL 的可调空间更窄,可能降低灾难性漂移,也可能把所有纠错压力压在小分支上。对照实验应包含只训分支、分支加少量主干 LoRA、全量训练,并分别测短窗口基准、状态任务与安全约束,而非只看长记忆平均分。

1.1. 状态连续性如何获得训练信号

只把长文送进模型并不足以训练记忆。若支持证据仍在活动窗口,注意力路径可以直接回答,循环分支即使完全无用也能降低 loss。训练样本必须让关键证据在回答时退出窗口,使记忆成为 load-bearing 路径。 可以把一条样本拆成证据 EE、干扰历史 DD 和查询 QQ。选择窗口 WW 使

dist⁡(E,Q)>W,(28)\operatorname{dist}(E,Q)>W, \tag{28}

同时保证 EE 在早期确实经过状态更新。若直接截掉 EE 再从零状态推理,任务不可解;若保留连续状态,则答案仍可能恢复。这对照隔离了状态贡献。 困难负例同样重要。放入早期陈述「项目代号是 Aurora」,后来明确改成 Borealis,查询当前代号。状态若只会累积关联,可能吐出旧值;GDN2 的擦除门需要学会覆盖。再加入两个相似实体,测试 key 碰撞和作用域绑定。 多问题样本检查状态是否能反复读取。第一次查询不应耗尽记忆,后续问题仍要访问不同早期事实。若训练每条轨迹只在末尾问一次,模型可能形成针对单个终点的压缩,而非可持续状态。

证据距离分析要控制混杂。距离增大通常也意味着干扰 token 更多,性能下降可能来自容量竞争,也可能来自梯度路径变长。固定写入数量只插入无写掩码的空白,和增加真实干扰写入是两种实验;前者测时间衰减,后者测容量干扰。

换入换出、失效模式与训练信号,循环状态属于请求,服务端必须保证下一段 token 读取同一请求的上一版状态。若批处理重排后把状态行错配,模型会出现跨用户污染。状态对象需要稳定 request ID、层级结构版本和已处理 token 位置。 抢占时,KV 页面与循环状态可能一起从 GPU 换出。恢复必须原子地装回匹配版本;只恢复 KV、忘记循环状态,会让近期对话正常而远期记忆消失,这类错误很难从单轮健康检查发现。只恢复状态、KV 窗口错位,则近期精确文本和位置关系异常。

并发调度的容量约束为

Nactive(Mstate+Mwindow)+Mweights+Mworkspace≤MGPU.(29)N_{active}(M_{state}+M_{window})+M_{weights}+M_{workspace} \le M_{GPU}. \tag{29}

固定状态提高了单请求常驻成本,但释放远期 KV 又降低历史相关成本。短请求占比高时,新增状态可能净增显存;长请求占比高时,窗口上界带来可预测容量。吞吐比较必须按真实长度分布进行。 请求结束后状态释放,重新发起相同用户的 API 请求不会自动继承。若产品需要跨会话记忆,必须显式序列化状态或将关键信息写入外部存储。直接持久化模型内部矩阵还涉及 checkpoint 兼容、隐私删除和跨版本迁移,官方当前接口没有承诺这些能力。

故障恢复也需要边界。状态只在 GPU 内存中,进程崩溃后无法重建;定期 checkpoint 能恢复,却增加复制成本。若原始事件日志仍在,可以重新 prefill 全历史生成状态,代价随历史增长。系统需要按会话价值选择不恢复、周期快照或事件重放。

一组容量与延迟手算,假设一层每个请求的循环状态是 16 个头,每头 128×128128\times128,模型 36 层,使用 BF16。按式 (24),状态约为

36×16×128×128×2=18,874,368 bytes,(30)36\times16\times128\times128\times2 =18{,}874{,}368\text{ bytes}, \tag{30}

约 18 MiB。若还需要双缓冲或临时 scan workspace,实际峰值会更高。100 个并发长请求仅状态就约 1.8 GiB。 再假设每层每 token 的 K 和 V 合计宽度为 2048 个 BF16 元素,32K 窗口的缓存为

36×32768×2048×2≈4.5 GiB/request.(31)36\times32768\times2048\times2 \approx4.5\text{ GiB/request}. \tag{31}

这个示例参数未必等于论文模型的真实 GQA 配置,只展示量级关系:窗口 KV 往往远大于固定状态。缩到 8K 后约 1.125 GiB,节省量远超 18 MiB 状态,但准确率能否接受要由任务决定。 计算方面,GDN2 每个新 token 都做状态读写,单步成本与 dkdvd_kd_v 成正比,不随历史长度增长。主注意力 decode 仍需读取 WW 个 KV,成本随窗口长度线性。缩小 WW 会降低注意力带宽,新增分支提供常数开销,因此历史足够长时总成本可能下降。 prefill 使用并行 scan 可以减少递推串行深度,但常数和内存流量不能忽略。对短输入,新增分支只增加工作;对超过窗口的长输入,释放 KV 的服务收益逐步出现。延迟曲线应该随长度绘制,单一平均值会混淆两种区域。

2. 失败模式与可证伪实验

第一类失败是状态根本没有被使用。将循环状态在证据退出窗口后清零,若答案几乎不变,可能存在数据泄漏、注意力仍能看到证据或任务可由先验猜中。清零实验应逐层、逐时间进行,定位哪些状态真正承载信息。 第二类失败是状态污染。插入大量与目标实体相似的键值,再比较准确率随干扰数量变化;交换实体名称,检查模型是否依赖位置或表面频率;后来撤销旧事实,观察擦除是否完成。只测单一事实的长距离回忆无法暴露这类问题。

第三类失败是服务连续性中断。主动触发批次重排、GPU 抢占、KV 页面驱逐和请求暂停,比较中断前后同一状态校验和与输出。若离线 Hugging Face 推理正常、vLLM 服务失败,问题在状态生命周期,而非模型权重。 第四类失败是训练与部署 mask 不一致。用相同轨迹分别在训练式完整张量 mask 和真实逐块 serving 中运行,比较每层状态与 logits。误差应在数值容忍范围内;随着块数累积扩大的差异说明并行 scan、位置或驱逐边界不一致。

第五类失败是短上下文能力受损。在证据完全位于活动窗口内,LiveMem 应接近原主干;若明显下降,记忆分支正在对无需记忆的情况过度干预。可以关闭分支读出但保留写入,判断问题来自训练改变的输出还是服务缓存。 最终实验矩阵至少包含窗口内、窗口外、覆盖更新、多实体碰撞、多问题复用、进程暂停恢复和跨模式一致性。每组同时报告任务成功、状态显存、KV 显存、prefill/decode 延迟与并发吞吐。这样才能判断连续状态带来的能力是否值得额外常驻成本。

应当保留的结论,LiveMem 的贡献可以落在一条清楚的链上: 历史 token 先经过正常模型并写入 GDN2 状态, 注意力只保留系统 sink 与近期窗口, 旧 KV 页面随后释放; 新增支路在每一层把固定状态读出并加回主路径; SFT 与 RL 通过窗口外证据任务迫使这条支路承担预测责任; 服务系统则让状态与请求生命周期一起迁移.

这套设计提供固定历史相关显存和持续在线计算, 但不提供任意历史的无损访问, 也不会自动跨请求持久化. 状态矩阵容量有限, 远期影响受到递推稳定性和写入干扰约束, 精确证据仍适合外部存储. 这些边界也划分了 LiveMem 与 RAG、摘要、长窗口和 Harness 状态各自承担的职责.

从状态空间模型看 LiveMem,把 GDN2 放在每层注意力旁边,可以视为输入依赖的状态空间模型。传统线性状态空间写成

st=Ast−1+Bxt,yt=Cst+Dxt.(32)s_t=As_{t-1}+Bx_t,\qquad y_t=Cs_t+Dx_t. \tag{32}

LiveMem 的 At,Bt,CtA_t,B_t,C_t 都由当前 hidden state 动态生成,并且状态是矩阵而非单一向量。输入依赖让模型可以在事件边界快速遗忘、在稳定阶段缓慢更新,也让稳定性分析比固定矩阵更难。 若把状态矩阵向量化,式 (20) 仍可写成

vec⁡(St)=Atvec⁡(St−1)+ut.(33)\operatorname{vec}(S_t)=A_t\operatorname{vec}(S_{t-1})+u_t. \tag{33}

远期信息的保留由转移乘积 AT⋯At+1A_T\cdots A_{t+1} 决定。不同输入会选择不同子空间的收缩、擦除与写入,因此不存在一个全局固定半衰期。论文里的证据距离曲线测到的是数据分布下的平均行为,不能证明每种信息都能维持同样距离。 每层都有独立状态,使记忆形成层级。低层可能保留词形、实体和局部模式,高层更接近任务语义,但这只是可检验假设。可以训练线性 probe 或执行层级清零:只清低层、只清高层、清连续层段,观察事实回忆、顺序判断和聚合任务分别受何影响。

逐层相加意味着记忆分支通过残差路径影响后续所有层。第 ℓ\ell 层状态读出 rℓ,tr_{\ell,t} 不只改变当前 logits,还改变第 ℓ+1\ell+1 层生成 key、query 与写门的输入。因此单层错误可能被后层放大或修正。只查看最终一层状态无法解释全部记忆路径。 状态空间视角也说明为什么固定状态擅长充分统计量。若任务只需要累计计数、最近一次值、有限状态机位置或低维信念,存在小状态递推精确求解;若任务要求任意内容寻址,状态维度必须随可区分项目数增长,或接受碰撞。这条界线比「能记多少 token」更准确。

2.1. 写入、读取与覆盖的可辨识性

观察最终答案,很难知道失败发生在写入、保存还是读取。证据可能从未进入状态,可能写入后被干扰覆盖,也可能仍在状态中却没有被当前 query 读出。三种故障需要不同修复。 写入测试在证据 token 之后立即冻结状态,并用多个标准查询读取。若此时已经无法恢复,问题在写门或表示。保存测试把同一冻结快照复制到不同长度的干扰序列,比较状态变化;读取测试固定状态,只改变查询措辞和位置,观察信息是否可访问。

可将准确率粗略分解为

P(correct)=P(W)P(P∣W)P(R∣W,P)P(O∣W,P,R),(34)P(\text{correct}) =P(W)P(P\mid W)P(R\mid W,P)P(O\mid W,P,R), \tag{34}

WW 表示正确写入,PP 表示保持,RR 表示正确读取,OO 表示读出后完成输出。终局分数只观察四项乘积。通过中间 probe、状态替换和受控查询,才能近似定位哪一项下降。 覆盖更新尤其能区分简单累加与可修改记忆。先写「A 的值为 3」,退出窗口后再写「A 改成 7」,最终既询问当前值,也询问历史值。如果任务只要求当前状态,旧值应被抑制;若同时要求审计历史,固定状态需要保留两个时间版本,容量与表示要求更高。

状态交换实验也很有用。两条前缀只在一个事实不同,运行到相同边界后交换其循环状态,保持近期窗口不变。若回答随状态交换,证明信息确实位于循环分支;若回答仍跟随窗口,可能有残留证据或模型先验。交换必须在每层全部状态上一致进行,漏一层会得到混合结果。

RL 奖励怎样塑造记忆,在 LiveMem 中,早期写门动作与很久之后的答案奖励相连。某个 token 是否写入、写多强、覆盖哪个方向,都没有直接标签。GRPO 比较同一问题的多条响应,但这些响应可能共享相同前缀状态,也可能在 rollout 中产生不同中间文本并继续写状态。 若一组八个响应从同一冻结前缀状态开始,组内优势主要训练读取、推理和生成;前缀写入已经完成,无法从这次差异获得反事实信用。若完整轨迹分别 rollout,状态更新也变化,奖励能影响写入策略,但方差更高。训练实现需要明确状态在哪个边界复制。

无 KL 配置让记忆分支有更大更新自由,同时主干冻结限制行为漂移来源。非对称裁剪 0.20/0.28 对负、正更新提供不同边界,具体方向要按实现定义确认;它不能自动解决长延迟信用。奖励若只在答案末端给出,所有参与 token 共享粗粒度信号。 可以加入不改变最终目标的诊断奖励,例如窗口外证据一致性、更新后旧值抑制和状态清零敏感度。但辅助奖励必须防止捷径。奖励状态中可线性解码某个实体,模型可能保存表面标识而忽略真正任务;奖励逐字回忆会挤占聚合状态容量。

一个可证伪的 RL 对照是固定 SFT checkpoint,只改变 rollout 是否让证据退出窗口。若 RL 收益主要出现在窗口内问题,它更可能优化一般回答风格;若只在窗口外提升且清零状态后收益消失,才有较强证据说明奖励塑造了记忆支路。 还要防 judge 泄漏。judge 根据参考答案打分时,模型可能从问题分布猜答案,不依赖历史。构造实体随机化、答案均衡和不可由世界知识推断的键值,可以降低这种捷径。论文分数要结合这类任务构造理解。

不确定性、安全与信息上限,递推状态容易把多次观测混成一个确定表示,但长程 Agent 经常处理互相冲突或尚未确认的信息。若状态只保存最可能值,后续模型可能忘记它原本是猜测,也不知道何时应复核。 从贝叶斯滤波看,状态应近似历史下的信念分布

bt(z)=p(z∣x1:t),(35)b_t(z)=p(z\mid x_{1:t}), \tag{35}

新观测到来后按似然更新。神经状态未必显式表示概率,却可以通过多个方向编码候选、置信度和来源可靠性。训练数据若所有陈述都无冲突,模型没有机会学到这类更新。 可以设计三步任务:早期弱来源说答案 A,中期强来源说 B,末尾询问答案与置信理由。再交换来源可靠性,正确选择应改变。只按最近值覆盖会忽略来源,按频率累计又可能被多个弱来源淹没。

不确定状态与擦除门有关。新证据并非总要完全删除旧值:互相矛盾时应保留冲突,明确纠正时才覆盖。GDN2 提供连续擦写能力,但其语义需要数据学习,架构本身没有内置「事实」「猜测」或「授权」类型。 外部 Harness 可以保存显式置信与来源,循环状态负责让这些信息持续影响生成。若两者冲突,应以可审计外部状态为准,并重新注入当前窗口。把内部状态视为权威数据库,会让不可解释向量承担它无法证明的责任。

2.2. 安全、隔离与遗忘

循环状态能跨越窗口保留信息,也意味着从可见 prompt 删除文本未必让影响消失。用户要求遗忘某段内容时,释放 KV 页面还不够;已经写入 GDN2 的表示可能继续改变输出。当前请求若必须彻底清除,只能重建一个未扫描该内容的状态,或结束请求并从合规历史重新开始。 选择性擦除单个事实更困难。状态是叠加的连续表示,没有稳定地址保证某个用户字段独占一个方向。对某个 key 施加擦除可能伤及相似记忆,也无法证明所有层都不再编码该信息。产品不能把一次负向写入宣称为可验证删除。

租户隔离要求状态永不跨请求错配。批处理张量中的一个索引错误就可能把另一用户的历史注入当前回答。测试应使用高辨识度 canary,在大量请求抢占、重排和恢复后检查是否泄漏;日志则避免打印原始状态或可逆的用户信息。 模型升级会改变状态语义。旧 checkpoint 产生的矩阵不能假设由新权重正确读取,即使形状相同。跨模型版本的请求需要固定模型到结束、重放历史生成新状态,或提供经过验证的状态迁移器。直接加载会让新权重读取未经验证的旧状态。

内部状态也会受到提示注入影响。外部文档中的恶意指令一旦写入,原文退出窗口后仍可能持续。来源标签在神经状态里没有强隔离,关键权限和指令层级仍应由外部控制面每轮提供,不能依赖循环分支自己长期记住。

固定状态的信息上限,连续矩阵使用浮点数,看起来可以编码无限多信息;实际可用容量受到精度、噪声、可训练性和鲁棒间隔限制。把每个 BF16 元素机械地按 16 bit 计算,只能得到存储上界,无法代表模型能可靠写入并读出的语义容量。 设状态包含 DD 个数值元素,每个元素在噪声和量化下可稳定区分 KK 个水平,粗略信息上界为

I(S)≤Dlog⁡2K.(36)I(S)\le D\log_2K. \tag{36}

KK 远小于浮点格式的全部码字,因为递推乘法会压缩动态范围,相邻表示还需留出分类间隔。训练也未必找到接近编码上界的方案。这个式子只说明容量有限,不能用来精确换算「一个状态等于多少 token」。 随机键值任务提供经验容量曲线。令每个 value 从大小为 VV 的集合均匀采样,正确恢复 nn 个独立值至少需要约 nlog⁡2Vn\log_2V bit。逐渐增大 nn,准确率从平台进入下降区,拐点给出特定训练和读取协议下的有效容量。改变状态宽度 DD,若拐点近似线性移动,容量解释更可信。

自然语言历史具有高度冗余,所需充分状态可能远小于 token 数。十万 token 都在围绕五个实体更新,固定状态可以压得很好;一万 token 包含数千个随机编号,反而更难。因此证据距离和历史长度都不能单独代表容量压力,需要同时报告独立状态项数量。 容量还会在层与头之间重复。每层都扫描相似输入,不意味着容量简单相加,因为后层状态依赖已混合的 hidden state,多个头也可能学到冗余特征。消融一部分头或层,再观察能力是否平滑下降,可以估计冗余与专门化。

Chunk 并行与逐 token 递推必须一致,训练长序列时逐 token Python 循环不可接受,GDN2 通常用 chunk 或并行 scan。数学上它们都应实现相同递推,数值上却可能因运算顺序、精度和边界初始化产生差异。部署若使用另一种 kernel,微小偏差会在长轨迹里累积。 对仿射递推 st=Atst−1+uts_t=A_ts_{t-1}+u_t,一个块 [a,b][a,b] 可以合成为

sb=Aˉa:bsa−1+uˉa:b,(37)s_b=\bar A_{a:b}s_{a-1}+\bar u_{a:b}, \tag{37}

其中

Aˉa:b=AbAb−1⋯Aa,uˉa:b=∑i=abAb⋯Ai+1ui.(38)\bar A_{a:b}=A_bA_{b-1}\cdots A_a, \qquad \bar u_{a:b}=\sum_{i=a}^{b} A_b\cdots A_{i+1}u_i. \tag{38}

块之间继续使用同一结合结构。理论上的结合律允许并行前缀扫描;浮点加法和矩阵乘法不严格结合,不同树形顺序会得到略有差异的结果。 一致性测试应固定输入和权重,比较 naive recurrent、chunk scan、训练 kernel 与 serving kernel 的每层末状态和 logits。误差随 token 数、块大小和数据类型绘图。如果误差只在单块内有界,通常可接受;若跨块呈系统漂移,需要检查门值范围、累积精度和状态重载。 边界状态最容易出错。第一个块应从零状态或传入 checkpoint 开始,后续块必须使用上一个块的最终状态;packed batch 中每个新样本要重置。把 padding token 误当真实写入,即使 attention mask 正确,也会污染循环状态。

写掩码与 scan 的组合还要验证。当一个 token 只读不写时,转移必须精确等于恒等映射,不能仍应用衰减。官方实现通过同时置零 g,b,wg,b,w 实现冻结;kernel 若把门值经过额外非线性或默认偏置,零输入未必得到恒等,需要针对实现检查。

Checkpoint 保存的对象,长请求暂停后要继续,保存普通 KV cache 还不够。LiveMem checkpoint 至少包含每层 GDN2 状态、仍在活动窗口内的 KV 页面、当前位置、请求配置、模型版本和 mask/轮转参数。缺少任一项,都可能恢复成另一条计算轨迹。 checkpoint 可以表示为

Ct=(St,Kt,Vt,pt,c,vm,h),(39)C_t=(S_t,K_t,V_t,p_t,c,v_m,h), \tag{39}

cc 是窗口和状态模式配置,vmv_m 是模型及实现版本,hh 是已处理前缀的校验值。恢复时先验证版本和前缀,再把状态与 KV 原子装载。若只成功装入其中一部分,应回退而非继续生成。 保存频率存在成本权衡。每 KK 个 token 快照一次,崩溃后最多重放 KK 个 token;快照写入量则与 1/K1/K 成正比。对状态约 18 MiB、KV 数 GiB 的请求,完整频繁复制成本很高。可以让 KV 依赖可重建前缀,只持久化小得多的循环状态与窗口边界,但恢复时仍需重算近期 KV。

增量快照对矩阵状态不天然友好。每步都会更新大量元素,块级差分未必稀疏;压缩或量化快照又引入额外数值误差。真正收益要以写入带宽、恢复延迟和输出一致性衡量,不能只看文件大小。 checkpoint 还涉及隐私。它是历史的不可读压缩表示,却可能泄露训练或用户信息;不能因为人眼看不懂就当作非敏感数据。访问控制、保留期和删除范围应与原始会话一致。请求结束后若声明释放,磁盘快照与备份也需纳入清理。

3. 证据距离曲线怎样读

论文用 evidence distance 观察支持信息离开活动窗口后能保持多远。距离增加时准确率下降,可能来自状态衰减、更多干扰写入、位置分布偏移或问题本身变难。把所有因素一起变化,只能得到总体鲁棒性,无法直接估计记忆半衰期。 更干净的实验固定证据与问题,在中间插入三类内容:不更新状态的 padding、语义无关但会写入的自然文本、与目标 key 相似的干扰事实。第一类主要增加递推步数,第二类增加一般写入竞争,第三类专门测试地址碰撞。三条曲线的差异帮助定位机制。

对于距离桶 dd,准确率估计为

p^d=1nd∑i=1ndyi,SE⁡(p^d)≈p^d(1−p^d)nd.(40)\hat p_d=\frac{1}{n_d}\sum_{i=1}^{n_d}y_i, \qquad \operatorname{SE}(\hat p_d)\approx \sqrt{\frac{\hat p_d(1-\hat p_d)}{n_d}}. \tag{40}

远距离桶往往样本更少,误差条更宽。只看平滑折线容易把抽样波动当成趋势。若同一问题在多个距离重复,使用配对差异或分层模型会比把样本当独立 Bernoulli 更合适。 曲线还应与 truncate、RAG 和完整窗口对照。完整窗口衡量骨干在仍可访问证据时的上限,truncate 衡量没有连续状态的下限,RAG 衡量精确回取路线。LiveMem 超过 truncate 证明状态有用;接近完整窗口说明损失小;是否优于 RAG 取决于任务可检索性,不能预设。

对多跳问题,证据距离应分别记录最早、最晚和跨度。两个证据都很远但彼此相邻,与一个早期一个近期的组合,对状态提出不同要求。平均距离会掩盖这种结构。

与 Context2LoRA、Recurrent 和 Delta-Mem 的比较边界。 几种内生记忆方案都把历史影响压进有限对象,但更新对象不同。Recurrent 类方法在块之间传递 hidden state 或记忆 token;Context2LoRA 把上下文信息写进低秩参数适配;Delta-Mem 使用在线状态更新;LiveMem 在每层加入并行 GDN2 分支并配合真实 KV 轮转。 比较时要固定骨干、活动窗口、训练数据和历史可见性。某方法若允许 32K 窗口,另一方法只有 8K,最终分数同时反映短期注意力差异。某方法全量微调主干,另一方法冻结主干,训练参数和短上下文保持能力也不同。

状态尺寸需统一换算成字节。记忆 token 还会进入每层注意力计算,成本随 token 数和生成步增长;LoRA 权重在每步参与线性层,参数量固定但可能为每请求保存独立 adapter;GDN2 矩阵每步递推。只报告「固定容量」没有揭示每 token 计算。 更新延迟也是区别。循环状态随 token 在线更新,适合流式;从整块上下文生成 adapter 可能需要额外优化或前向;检索系统在查询时付费。系统应按首 token 延迟、持续 decode 延迟和请求切换成本拆开比较。

能力上,参数式或连续状态都难提供精确来源。RAG 能返回原文,代价是检索失败和额外上下文。一个系统可以用 LiveMem 维持隐含任务态,再用外部检索提供证据;实验中的竞争基线不代表产品里只能二选一。

数据捷径、消融与复现,记忆数据若格式固定,模型可能利用位置和模板。支持句总在开头、答案总是收尾阶段出现的实体,循环分支只需保存一个固定位置特征。随机化证据位置、问题顺序和实体表面形式,才能迫使模型学习内容相关写入。 答案也可能由世界知识猜出。「巴黎属于哪个国家」无需历史;把实体替换成随机代号,或使用每条样本新生成的映射,能隔离记忆。随机数据过多又会偏离自然语言,需要将可控诊断集与真实会话集一起报告。

长文本中的重复证据降低任务难度。若同一事实在窗口外和窗口内各出现一次,模型可以忽略状态。数据预处理要检查近重复与答案泄漏,评测时记录最近支持证据的距离,而非最早证据距离。 多问题训练还可能让前一个回答泄漏后一个答案。回答文本留在近期窗口后,第二问测到的是读取上一回答,不是读取早期状态。可以在问题间清除答案、使用独立分支,或专门报告带回答历史和不带回答历史两种设置。

RL 数据的 reward model 也可能偏爱详细措辞而非事实正确。状态分支学会生成看似自信的长回答,分数上涨却没有改善记忆。客观键值任务用精确匹配,开放回答再由 judge 评分,两者结合更能区分能力与风格。

3.1. 消融实验应该拆哪些因果

最基础的对照是同一权重下的 state 与 truncate。前者扫描全历史并保留循环状态,后者只处理后缀且从零状态开始。两者窗口相同,差异主要来自连续状态。不过,如果前处理、位置编号或系统 prompt 保留方式不同,仍会混入实现差异。 第二组对照关闭记忆分支的写入或读出。关闭写入但保留读出,状态保持初始值,测试新增分支的静态偏置;保留写入但将读出置零,检查主路径是否仍正常;只在证据离窗后关闭读出,能定位远期答案对状态的依赖。

第三组改变状态容量。头数、dkd_k、dvd_v 分别影响地址空间、写入内容和计算量。若扩大状态只提升随机键值、不提升聚合任务,说明前者受容量限制;若两者都不变,训练或读取可能成为瓶颈。参数量变化需要用等参数 FFN 或 adapter 对照,排除单纯增加容量的收益。 第四组改变活动窗口 WW。性能随 WW 增长通常会上升,显存和 decode 成本也增加。应绘制 Pareto 前沿,而非只挑 8K 或 32K 两个点。LiveMem 的价值在于相同成本下更强,或相同能力下使用更小窗口;单点优胜无法说明这个权衡。

第五组拆 SFT 与 RL。Base+分支随机初始化、SFT、RL 三个阶段分别评测窗口内和窗口外任务。如果 SFT 已获得主要收益,RL 只改善开放回答,结论应限定;若 RL 明显提升随机化远期事实,才说明奖励改变了记忆使用。 第六组改变写入策略。连续扫描所有 token 与只扫描驱逐区域可能在冗余、延迟和污染上不同。相同窗口与训练数据下比较,才能判断近期内容同时存在于注意力和状态是否有帮助。部署模式必须与训练匹配。

指标要覆盖能力和系统成本,任务准确率只描述输出。LiveMem 还改变每请求显存、prefill 吞吐、decode 延迟、状态切换成本和可支持并发。一个方法在离线单请求准确率更高,若状态常驻使并发减半,产品取舍可能不同。 能力指标至少分为窗口内准确率 AinA_{in}、窗口外准确率 AoutA_{out}、覆盖更新准确率 AupdA_{upd} 和碰撞压力准确率 AcolA_{col}. 可定义记忆增益

Gmem=Aoutstate−Aouttruncate,(41)G_{mem}=A_{out}^{state}-A_{out}^{truncate}, \tag{41}

同时报告窗口内损失

Lshort=Ainbase−Ainstate.(42)L_{short}=A_{in}^{base}-A_{in}^{state}. \tag{42}

只有 GmemG_{mem} 为正且 LshortL_{short} 可接受,才说明新增分支带来净能力收益。 系统指标按长度分桶。短请求阶段状态分支纯增开销,超过窗口后释放 KV 的收益出现。报告 P50 会掩盖长请求尾部,P95/P99 又可能被少数异常工具调用主导;最好同时给请求长度、输入输出 token 和批量。 状态切换要单测。连续 decode 不换请求、每 token 轮转请求、抢占后恢复三种调度产生不同缓存局部性。循环矩阵虽小于长 KV,层数多时仍需大量读写。其实际带宽和 kernel 融合决定延迟,不能仅按 FLOPs 推断。

成本归一可以报告每个成功任务的 GPU 秒、峰值显存和总生成 token。若 LiveMem 减少因遗忘导致的重复搜索,终局成本可能下降;若回答质量相同却每 token 都多跑分支,成本会上升。端到端指标能容纳两种效应。

跨请求持久化为何是另一项研究问题,当前实现把状态生命周期绑定单次请求。将状态跨请求保存看似只需序列化矩阵,实际会改变身份、权限、版本和训练分布。单请求内所有 token 共享明确顺序,跨请求则可能由多个设备、会话或并发分支产生。 第一步要定义合并。用户同时打开两个会话,各自从同一旧状态出发并产生新状态 Sa,SbS_a,S_b。连续矩阵没有通用三方合并算子,直接平均会破坏非线性编码,按时间选择又丢掉另一分支。事件重放或外部结构化记忆更适合解决并发。

第二步是模型版本。状态只在生成它的权重下有语义;更新模型后读取旧矩阵没有保证。长期记忆系统通常保存可迁移的文本、结构化事实或向量索引,模型升级后可以重新编码。内部状态若要长期存在,需要版本固定和迁移验证。 隐私删除也更严格。请求内结束即释放,边界清楚;长期保存后要按用户、字段和来源删除。矩阵表示难以证明单项信息已清除,整状态删除又会牺牲其他记忆。可审计事实仍应放在外部存储。

训练上,模型只见过单请求连续流,跨天时间间隔、身份切换和新旧权限都属于分布外。产品可以在新请求开始时把外部摘要重新送入 LiveMem,让它在本次请求内维持连续,而不直接复用旧内部矩阵。这样牺牲一些 prefill,换来清晰的数据边界。

3.2. 状态生命周期与实现约束

第一,Hugging Face 示例显式传入 GDN2 cache,适合功能检查,却没有 vLLM 插件的分页 KV 驱逐。能连续生成不等于已经复现 state-32k 服务语义。评测 context turnover 必须使用真实窗口 mask 和释放路径。 第二,模型、代码和配置要成套。基础 Qwen3 版本、LiveMem checkpoint、vendored FLA、vLLM 插件与 kernel 任一不匹配,都可能改变层结构或状态格式。记录提交哈希比只记包名可靠。 第三,state 和 truncate 的 window_size 含义不同。前者是注意力保留的活动 token,完整历史仍写入状态;后者由客户端删除旧记忆,并从零状态处理保留后缀。把两者都理解成服务端滑窗,会构造错误基线。

第四,评测生成参数要一致。temperature、top-p、top-k 与采样次数都会改变开放回答分数。记忆任务常有 judge 评分,judge checkpoint、prompt 和服务版本也属于实验条件。只复现主模型而更换 judge,数字不可直接比较。 第五,训练使用固定 64K pack 和两阶段数据。缩短 pack 会减少真实跨窗依赖,改变 batch 与梯度累积又会影响优化。资源不足时可以调整,但应重新统计每条样本的证据距离和有效 token,而非声称严格复现。 第六,状态正确性先于最终分数。用短随机序列对齐 naive 与 kernel 输出,检查 packed 边界、暂停恢复与 KV 驱逐,再跑昂贵 benchmark。否则一处状态串线可能在平均分里表现成普通噪声,直到真实多租户服务才暴露。

怎样证明收益确实来自状态连续性,一项长记忆评测上涨,可能同时受到更多参数、训练数据、回答风格和服务窗口影响。要把因果归到状态连续性,需要沿干预链逐步排除替代解释。最强的证据来自同一 checkpoint、同一窗口和同一输入,只改变循环状态是否从早期历史延续。 设完整状态运行得分为 Y(S)Y(S),清零状态得分为 Y(0)Y(0),保留近期窗口不变,平均处理效应可写成

ATE⁡state=E[Y(S)−Y(0)].(43)\operatorname{ATE}_{state} =\mathbb E[Y(S)-Y(0)]. \tag{43}

清零可能产生分布外状态,因此还应加入「来自另一条前缀的状态」和「正确状态加小扰动」对照。若模型只对完全清零敏感,却无法区分正确与错误状态,变化可能来自数值尺度而非语义记忆。 状态替换要与问题内容配对。两条轨迹近期窗口完全相同,早期事实分别为 A 与 B;交换状态后答案也交换,是较直接的语义证据。若只在一条轨迹上清零,模型可能从问题先验猜对,低估状态贡献。

参数量对照则给原主干添加相近规模的静态 adapter,但不跨 token 维护状态。若两者都提升窗口内任务,参数增加解释一部分收益;只有 LiveMem 在证据离窗后继续提升,才支持递推连续性。训练 token 和优化步数也应匹配。 数据对照固定架构,分别用普通长文本和强制 turnover 数据训练。若只有后者学会在 KV 释放后回答,说明 load-bearing 训练条件不可省略。再把训练窗口和评测窗口交叉组合,可以观察策略是否只记住某个固定边界。

服务对照在离线 mask 与真实 vLLM 驱逐上运行同一轨迹。结果一致证明状态语义跨实现保持;离线好、在线差则指向生命周期或 kernel 问题。能力论文若不验证真实释放,只能说明模型能在一种 mask 下利用支路。 收尾阶段检查收益是否伴随代价转移。减少远期 KV 却新增固定状态和每 token 递推,任务成功提高却降低并发,或者省下 prompt token 却增加训练与 judge 成本,都属于真实权衡。状态连续性成立与系统是否值得部署是两个判断,分别需要机制证据和端到端成本证据。

LiveMem 在长程系统中的位置,长程 Agent 至少有四层状态:模型内部递推状态、活动注意力窗口、外部可审计任务状态和原始证据存储。LiveMem 加强第一层,并为第二层设置固定上界;它没有替代后两层。目标版本、权限、文件哈希和验收结果仍需要外部结构保存,论文原文和工具日志仍需要可回源存储。 一次可靠执行可以这样流动:新观测进入注意力与 GDN2,Harness 同时提取可审计事件;窗口轮转后,模型内部状态维持语义连续,外部状态维持事实与义务;遇到精确问题时,Harness 根据索引回源,把证据重新放入近期窗口;请求结束时释放内部状态,需长期保存的内容已经落到可迁移表示。

这套分工避免两个极端。若所有记忆都塞进 prompt,成本随历史增长;若所有历史都压进不可解释矩阵,精确回溯、删除和版本迁移无法证明。内部状态承担「继续思考」,外部系统承担「知道事实从哪里来」。 因此判断 LiveMem 时,核心问题是它能否在有限工作窗口下维持同一条计算轨迹,以及这种连续性在状态清零、交换、长距离干扰和真实服务抢占下能否被反复验证。「无限上下文」反而会遮住这些真正可检验的机制。

参考资料