Browse this library

Chinese source article

2.3.1 · LiveMem 架构与训练

拆解 LiveMem 的状态更新、服务生命周期、训练日程与消融证据。

View original Markdown ↗

长时间运行的 Agent 会遇到一个很具体的系统问题:当前上下文不可能无限增长。最近 token 可以留在 KV cache 里,较早内容迟早要被压缩、检索或直接逐出。普通滑动窗口一旦释放旧 KV,模型内部就不再保留那段计算状态;以后突然需要早期约束,只能依赖外部系统重新把文本放回窗口。 LiveMem 把缺失能力称为「上下文轮转下的状态连续性」(state continuity under context turnover):主注意力路径只保留有界工作窗口,同时另有一个固定容量的循环状态,从第一段输入一直延续到请求生命周期结束。早期 token 离开注意力窗口后,模型仍可能通过这个状态使用它们留下的信息。

这条路线与 RAG、文件记忆和知识图谱不冲突。外部记忆保存可定位、可审计的条目,查询时再取回;LiveMem 的内生状态更像一段持续更新的压缩计算。前者适合精确找回“用户在某天说过什么”,后者希望模型在历史文本已经离开窗口后仍保持对会话的整体认识。固定容量状态不是原文档案,也不提供逐字回放保证。

1. 架构、状态更新与服务生命周期

LiveMem 用主注意力路径保存精确的近期上下文, 用循环支路保存跨窗口的固定容量状态. 两条路径处理不同时间尺度.

理解 LiveMem 需要把双路径、矩阵写入和记忆的因果验证连在一起. 仅看到固定状态的结构, 还不能证明窗口外信息真的经由该状态影响了输出.

双路径怎样工作,论文在预训练全注意力模型的注意力层旁增加循环记忆支路。以第 ℓ\ell 层、第 tt 个 token 为例,归一化后的隐藏表示为 htℓ∈Rdh_t^\ell\in\mathbb R^d,有界注意力路径输出

atℓ=Attn⁡ℓ(h≤tℓ;Ct),(1)a_t^\ell=\operatorname{Attn}^\ell(h_{\le t}^\ell;C_t), \tag{1}

CtC_t 表示当前仍在工作的上下文窗口。循环支路读取上一状态 St−1ℓS_{t-1}^\ell,返回记忆输出和新状态:

(rtℓ,Stℓ)=GDN2⁡ℓ(htℓ,St−1ℓ).(2)(r_t^\ell,S_t^\ell) =\operatorname{GDN2}^\ell(h_t^\ell,S_{t-1}^\ell). \tag{2}

两路输出相加:

otℓ=atℓ+rtℓ.(3)o_t^\ell=a_t^\ell+r_t^\ell. \tag{3}

注意力路径负责最近上下文的精确 token 访问;Gated DeltaNet-2(GDN2)支路把历史不断压入固定大小状态。每层都有自己的 StℓS_t^\ell,这里的“记忆”是进入每层后续计算的隐状态,并不以文末追加文本的形式存在。 LiveMem 的公开实现以 Qwen3 为基座,将记忆支路挂到注意力层,并保留主注意力与 FFN 路径。仓库提供 SFT、RL checkpoint 和 vLLM serving 集成;因此早期“尚未开源”的记录已经过时,不能继续保留。

固定矩阵状态的写入,省略层和 head 下标,一条循环 head 的状态可写成

St∈Rdk×dv.S_t\in\mathbb R^{d_k\times d_v}.

输入产生 key kt∈Rdkk_t\in\mathbb R^{d_k}、value vt∈Rdvv_t\in\mathbb R^{d_v},以及衰减、擦除和写入门。直观更新分三步:先让旧状态按门控衰减;再检查当前 key 从状态中会读出什么;收尾阶段把预测残差写回与 key 对应的方向。这类 delta-rule 更新可以写成简化形式

S~t=DtSt−1,(4)\tilde S_t=D_tS_{t-1}, \tag{4}
et=vt−S~tTkt,(5)e_t=v_t-\tilde S_t^T k_t, \tag{5}
St=S~t+βtktetT,(6)S_t=\tilde S_t+\beta_t k_t e_t^T, \tag{6}

DtD_t 是衰减门,βt\beta_t 是写入强度。论文实际 GDN2 的门控更细,式 (4)–(6) 用来说明计算含义,不能替代实现公式。 假设 dk=dv=2d_k=d_v=2,初始 S0=0S_0=0,不衰减且 β=1\beta=1。第一条记忆 k1=(1,0)T,v1=(0,1)Tk_1=(1,0)^T,v_1=(0,1)^T 写入后

S1=k1v1T=[0100].S_1=k_1v_1^T= \begin{bmatrix}0&1\\0&0\end{bmatrix}.

再用相同 key 写入 v2=(1,0)Tv_2=(1,0)^T。旧状态读取为 S1Tk2=(0,1)TS_1^Tk_2=(0,1)^T,残差是 (1,−1)T(1,-1)^T,更新得到

S2=S1+k2(1,−1)=[1000].S_2=S_1+k_2(1,-1) =\begin{bmatrix}1&0\\0&0\end{bmatrix}.

新 value 覆盖了同一 key 方向上的旧 value。如果两个 key 不正交,新写入还会改变旧 key 的读取结果,这就是固定容量状态的干扰来源。门控可以学习何时保留、擦除和写入,却无法让有限矩阵无损保存无限历史。

1.1. 为什么只加结构还不够

一个随机初始化的循环支路很容易被主注意力忽略。只要支撑答案的文本仍在窗口中,最省力的训练策略就是继续走原来的 attention path。LiveMem 因此把三部分一起设计:上下文轮转、面向记忆的后训练和状态感知 serving。 训练时要模拟真实轮转,让早期证据离开主注意力可见范围,而循环状态仍从头更新。此后再要求模型回答依赖早期证据的问题,梯度才会迫使模型把记忆支路变成「承重结构」。如果训练始终保留完整注意力,测试时突然裁掉旧 KV,记忆支路没有学会独立承接历史。

SFT 可以给出“证据已移出窗口但仍需回答”的监督;RL 则能用最终回答奖励继续调整写入和读取行为。训练要求状态保存以后决策仍需要的信息,无须重建所有旧 token。哪些信息被保留由训练分布决定:长期身份与约束被频繁考查,模型会倾向保留;训练中从未追问的细节更容易丢失。

上下文轮转与服务生命周期,上下文轮转是训练和推理共同遵守的状态迁移规则,不是任意截掉输入。旧 KV 被释放以前,信息已经经过循环支路更新状态。 要让这套机制在长运行服务中成立,还需保存和迁移会话状态,并明确它与外部记忆的职责边界。

Context turnover 不是截断输入. LiveMem 需要区分两种基线。truncate 直接删除过早历史,只把保留后缀作为一次新输入处理,循环状态从零开始;state 从完整历史连续更新记忆状态,但注意力只保留系统提示与最近窗口。两种设置看到的当前 token 可以相同,前者没有逐出历史留下的状态,后者有。 假设历史共 100k token,活动窗口为收尾阶段 8k。truncate 模式只处理 8k,早期 92k 对模型没有任何影响;state 模式让 100k token 依次更新 StS_t,随后释放旧 KV,回答时精确注意力仍只覆盖最近 8k。两者的差值可以确认收益是否经过循环状态,并排除证据仍然留在窗口中的干扰。

论文在 LongMemEval 上专门检查支撑证据已经完全离开当前上下文的情况,并通过证据距离分析观察信息能否跨过活动窗口继续影响答案。这类实验支持“状态确实承载了部分有用历史”,却不能推出任意事实都能精确召回,更不能推出状态容量等价于多少 token。

Serving 生命周期是方法的一部分. 内生状态必须被 serving 系统当成请求资产。prefill 时,token 一边进入主注意力,一边更新每层 StS_t;窗口轮转后,旧 KV 页面可以释放,StS_t 继续保留;decode 阶段,新 token 继续读取和更新状态。请求被暂停、迁移或恢复时,除了 KV,还要保存循环状态及其位置。 公开实现当前强调的是单个请求生命周期内的状态连续性。请求结束后状态会释放,OpenAI 兼容接口也不会自动把一个请求的状态接到另一个独立请求。要把它用于跨会话长期记忆,产品还需定义用户—状态映射、持久化格式、版本升级、删除与隐私策略。

状态大小对历史长度是常数,对层数、head 数和 dkdvd_kd_v 则不小。若每层每个 head 都维护矩阵,批服务必须为每条活跃请求持有独立状态。它节省的是随历史长度增长的 KV,而不是把记忆成本变成零。比较吞吐时要报告活动窗口 KV、循环状态、状态迁移和记忆支路计算,而不能只看上下文上限。

与外部记忆的职责边界. 外部检索记忆通常经历抽取、存储、索引、查询和回填。它的优势是条目可见、可修改、可删除,能返回来源文本;缺点是检索 query 可能漏掉隐含相关历史,写入策略也会把错误摘要长期保存。LiveMem 每个 token 都自然更新状态,不需要显式决定“这一句是否入库”,适合维持连续语境;代价是内容分布在张量中,难以审计和定点纠正。 两条路线可以组合:外部存储保存用户事实、承诺和高风险约束,提供可核验原文;内生状态承接风格、近期事件形成的潜在语境和难以枚举的统计信息;当前窗口保存眼前需要精确推理的材料。对 Long-Horizon Agent,重要事实不应只存在于不可解释的循环状态里。

删除要求尤其能暴露差异。数据库条目可以按用户请求删除并记录审计;内生状态已经把信息与其他历史混合,当前方法很难证明某个事实被完全擦除。涉及隐私、授权撤销或事实纠正时,外部事实层仍应是权威源,内生状态必须能够重置或从经过清理的历史重放。

状态连续不能由模块名称证明,必须让证据退出活动窗口,再检查循环状态是否仍会影响行为。距离、干扰、修订与恢复需要分别控制。这些实验也限定了 LiveMem 在 Long-Horizon 系统中的角色:它维持计算连续性,但不能替代精确事实、审计和外部恢复。

怎样评测「状态连续」

一个可执行协议至少包含四条曲线。

第一条是证据距离:将关键事实放在位置 pp,查询放在 qq,保证 q−pq-p 超过活动窗口,观察准确率怎样随距离变化。第二条是干扰量:在事实与查询之间插入无关信息、相似实体和冲突更新,检查固定状态是否被覆盖。第三条是修订:先写“项目代号 Aurora”,后来明确改为 Borealis,查询应返回新值并避免旧值残留。第四条是恢复:处理中途保存状态,迁移进程后继续,输出应与不中断运行一致。

每组都要比较完整注意力上界、纯截断、外部检索、只有循环结构但未做记忆训练,以及完整 LiveMem。若缺少“未做记忆后训练”的结构对照,不能判断收益来自支路本身还是额外训练数据。 指标应拆开精确事实、对话偏好、长文摘要、程序状态和多步任务约束。论文在某些 QA 任务上表现领先,只说明对应训练与评测分布中的连续性;开放对话、精确 TTL、隐私删除和跨请求恢复需要各自实验。

还要记录活动窗口、总历史长度、循环状态字节、吞吐、首 token 延迟和 decode 延迟。固定容量状态在极长历史上有渐近优势,短历史却可能多付一条支路的计算。技术选择取决于会话生命周期和召回精度要求。

对 Long-Horizon 系统意味着什么. LiveMem 的核心启发是把推理状态的生命周期从当前上下文窗口中分离出来。一个矩阵无法替代所有记忆,但历史 token 被释放以后,请求仍然可以携带连续计算;这比每轮都把模型当作全新函数调用更接近长时间运行的 Agent。 它同时把新的系统责任带进来:状态属于谁、何时持久化、怎样迁移、版本不兼容怎么办、用户要求删除时如何处理、状态被污染后从哪里恢复。内生记忆提高了连续性,也让错误和过期信息可能在不可见状态中延续。

LiveMem 属于「状态、记忆与恢复」问题:它处理有界工作上下文轮转时怎样带着计算继续前进。它没有提供无限上下文,精确事实、审计、纠错和长期持久化仍需外部状态系统共同完成。

1.2. 推导、容量与训练边界

理解固定矩阵状态, 需要把遗忘、擦除、写入与读取逐项算开. 小维度手算能说明状态表示的性质, 却不能替代论文实验.

实验配置、分任务数字和训练消融需要一并核对. 单问题任务、NIAH 与位置上限中的负面结果同样构成方法边界.

逐项展开 GDN2 状态更新,论文把单个循环头的状态写成 St∈Rdk×dvS_t\in\mathbb R^{d_k\times d_v}。先计算遗忘后的状态

Sˉt=Diag⁡(exp⁡(gt))St−1,gt≤0.(10)\bar S_t=\operatorname{Diag}(\exp(g_t))S_{t-1}, \qquad g_t\le0. \tag{10}

因为 gt≤0g_t\le0,所以 0<exp⁡(gt)≤10<\exp(g_t)\le1。若 gt=(0,log⁡0.5)g_t=(0,\log0.5),原状态两行分别乘以 1 和 0.5,第二行的信息衰减一半。接着形成写入残差

ρt=wt⊙vt−Sˉt⊤(bt⊙kt),(11)\rho_t=w_t\odot v_t- \bar S_t^\top(b_t\odot k_t), \tag{11}

bt∈[0,1]dkb_t\in[0,1]^{d_k} 控制沿 key 方向擦除多少,wt∈[0,1]dvw_t\in[0,1]^{d_v} 控制 value 的写入幅度。收尾阶段执行秩一更新并读取:

St=Sˉt+ktρt⊤,rt=St⊤qt.(12)S_t=\bar S_t+k_t\rho_t^\top, \qquad r_t=S_t^\top q_t. \tag{12}

取 dk=dv=2d_k=d_v=2,为便于手算令

Sˉt=[1001],kt=[10],bt=[10],wt⊙vt=[23].\bar S_t=\begin{bmatrix}1&0\\0&1\end{bmatrix},\quad k_t=\begin{bmatrix}1\\0\end{bmatrix},\quad b_t=\begin{bmatrix}1\\0\end{bmatrix},\quad w_t\odot v_t=\begin{bmatrix}2\\3\end{bmatrix}.

于是 Sˉt⊤(bt⊙kt)=(1,0)⊤\bar S_t^\top(b_t\odot k_t)=(1,0)^\top,ρt=(1,3)⊤\rho_t=(1,3)^\top,从而

St=[1001]+[10][13]=[2301].(13)S_t= \begin{bmatrix}1&0\\0&1\end{bmatrix}+ \begin{bmatrix}1\\0\end{bmatrix} \begin{bmatrix}1&3\end{bmatrix} =\begin{bmatrix}2&3\\0&1\end{bmatrix}. \tag{13}

若查询 qt=(1,0)⊤q_t=(1,0)^\top,读取结果为 rt=(2,3)⊤r_t=(2,3)^\top。这个例子只展示矩阵运算,不代表真实训练出的门值;它说明更新没有保存原 token,而是把当前 key 与 value 方向写进固定大小矩阵。新信息不断进入时,遗忘、擦除与秩一写入共同决定旧信息是否还能影响输出。 主注意力输出与记忆支路输出相加:

otℓ=atℓ+rtℓ.(14)o_t^\ell=a_t^\ell+r_t^\ell. \tag{14}

论文将记忆支路的输出投影零初始化,因此训练开始时 rtℓ≈0r_t^\ell\approx0,模型行为接近原始注意力骨干;训练再逐渐打开支路。这降低了突然插入新模块对已有能力的扰动,但不保证支路会自动学会承担记忆。论文因此还需要 context turnover 与专门后训练,迫使答案证据离开主 KV 后,损失仍能通过记忆路径训练读写。

实验数字与适用边界,LiveMem v2于 2026 年 8 月 7 日修订。实验统一采用 Qwen3-4B-Instruct-2507 骨干;多数数据集把活动上下文限制为 32K,Wiki QA 与 LoCoMo 进一步限制为 8K。生成参数为 temperature 0.7、top-p 0.8、top-k 20。对照包括原始 Qwen3-4B、RAG、Recurrent、Context2LoRA、δ\delta-Mem,以及 LiveMem 的 SFT 和 RL 阶段。只有在这些共同条件下,表格中的横向比较才成立。 表 1 显示,LiveMem 并非每个单问题任务都最好。2Wiki 上 Qwen3-4B 为 0.817,δ\delta-Mem 为 0.824,LiveMem-SFT/RL 为 0.768/0.784;Hotpot 上原模型为 0.846,δ\delta-Mem 为 0.853,LiveMem-RL 为 0.772。优势更明显地出现在多问题共享历史的 MQ 设置:2Wiki-MQ 中 LiveMem-SFT/RL 为 0.551/0.587,原模型为 0.336,δ\delta-Mem 为 0.232;Hotpot-MQ 中对应数字为 0.477/0.487、0.329 与 0.226。

这个差异给出比「总体领先」更准确的解释。主注意力仍能直接看见证据时,固定矩阵压缩可能损失精度;历史被多次复用、证据离开活动窗口时,连续状态才显示价值。LongMemEval-S 的证据分组实验进一步报告:证据完全移出活动窗口时,LiveMem 比无历史访问的基线高出超过 10 个百分点;随证据距离增加,准确率略降但没有在一次 eviction 后立刻归零。论文没有据此声称逐 token 无损记忆。

附录的 needle-in-a-haystack 结果尤其重要。256K materialized context 下,needle 仍可由注意力直接访问,多数变体接近上限,LiveMem 没有系统性收益;32K 有界上下文下,几个系统都得到相同的低分。也就是说,当前固定容量状态不能可靠重建任意、事先不知道会不会重要的稀疏字符串。它更像有损的行为状态,不是档案库。 论文还明确限制输入最多处理到 256K token。虽然循环状态和活动 KV 的内存大小不随更早历史增长,Qwen3 骨干的 RoPE 配置最大位置为 262,144;超过训练与配置范围需要位置外推,质量没有保证。因此「固定容量」描述的是状态空间复杂度,不应改写成已经验证的无限上下文。

2. 训练消融告诉了什么

表 3 把可训练容量和课程分开。以 2Wiki-MQ 为例,side-path LoRA 得 0.479,完整训练支路得 0.551,完整支路再给主路径加 LoRA 得 0.520;但 LoCoMo 上三者分别为 0.256、0.234、0.220。不存在一个配置在所有任务都占优,论文对「完整支路更稳定」的解释是跨任务综合判断,不是逐列胜出。 训练混合也不是数据越多越好。Direct mixture 在 2Wiki-MQ 为 0.439,rebalanced mixture 为 0.452,先用长文本 warmup 再平衡为 0.479;LongMemEval-S 对应 0.298、0.326、0.362。作者解释,长文本 QA 占比过高时,模型可能不必依赖高精度记忆;直接删减又不足以先打开支路,所以采用先 warmup、再强化记忆要求的课程。

这组消融支撑一个工程判断:记忆模块能否存在、能否被训练使用、能否在证据退出窗口后继续承担信息,是三个不同问题。只添加循环层证明了结构存在;只有 turnover 后的因果对照,才能证明输出实际依赖该状态。

工程容量与因果验证,模型机制落地后,checkpoint 兼容、状态字节、批处理隔离和删除请求都会成为服务端责任。固定容量不表示多会话存储免费。 对循环状态的干预可以区分相关性与因果贡献。服务协议、容量估算和因果验证共同构成完整的工程闭环。

服务端需要守住的状态协议. 长运行服务至少要把模型权重版本、会话 ID、当前位置、活动 KV、各层循环状态和系统指令版本绑定在同一个 checkpoint 中。恢复时若只载入 StS_t,却换了支路参数 ϕ\phi,状态坐标系可能已经不兼容;若位置索引重置,RoPE 与原轨迹也不一致。可定义检查点

Kt=(id⁡,t,Ct,{Stℓ}ℓ=1L,hash⁡(θ,ϕ),vprompt).(15)K_t=(\operatorname{id},t,C_t,\{S_t^\ell\}_{\ell=1}^{L}, \operatorname{hash}(\theta,\phi),v_{\mathrm{prompt}}). \tag{15}

恢复前逐项匹配,任何不兼容都应显式迁移或从较早可重建状态开始,不能静默加载。 删除请求同样不能只删外部聊天文本。用户要求遗忘某段历史时,该信息可能仍影响循环矩阵;当前方法没有提供从 StS_t 中精确减去某段语义的一般操作。严格删除需要从删除点之前的 checkpoint 重放剩余合法历史,或终止旧状态并开启新生命周期。前者成本高,后者会丢失其他记忆,这正是内生有损状态的治理代价。

因此实际 Agent 更适合采用双层方案:外部状态保存精确目标、权限、事实、来源和审计;LiveMem 一类内生状态维持连续的背景影响。外部层负责可编辑、可删除与可追责,内生层负责低固定容量的在线连续性。两者发生冲突时,以当前环境和外部验证事实为准,不能让不可解释的 latent state 覆盖显式约束。

容量与计算量怎样估算. 单个循环头的状态含 dkdvd_kd_v 个标量。若有 HmH_m 个记忆头、LmL_m 个带记忆支路的层,每个标量占 bb 字节,则仅矩阵状态约占

Bstate=LmHmdkdvb.(16)B_{\mathrm{state}}=L_mH_md_kd_vb. \tag{16}

例如 Lm=32,Hm=8,dk=dv=128L_m=32,H_m=8,d_k=d_v=128,使用 2 字节精度时,状态为

32×8×128×128×2=8,388,608 bytes≈8 MiB.(17)32\times8\times128\times128\times2 =8{,}388{,}608\text{ bytes}\approx8\text{ MiB}. \tag{17}

这个数不含活动 KV、门控中间量、批处理 padding 和框架开销。它只说明循环状态对历史长度是常数;会话数增加时,服务端仍需为每个活跃会话保存一份。十万个并发会话即使每份只有 8 MiB,也无法全部常驻 GPU,必须设计 CPU、磁盘分层与淘汰策略。 每个 token 的秩一更新 ktρt⊤k_t\rho_t^\top 需要约 dkdvd_kd_v 次乘加,读取 St⊤qtS_t^\top q_t 也需要同阶运算,所以单头时间复杂度约为 O(dkdv)O(d_kd_v)。标准注意力在固定窗口 WW 下每 token 读取历史的相关部分约为 O(Wd)O(Wd)。LiveMem 没有消除主注意力成本,而是在有界 WW 之外增加固定状态支路;窗口越短,精确近邻信息越少,窗口越长,KV 成本越高。系统应把准确率、状态字节与吞吐放在同一张曲线上选点。

批处理还要求每条序列携带自己的 StS_t。序列完成、暂停或迁移时,状态必须与正确的会话槽位绑定;一次 batch 重排若把两条会话的状态交换,输出可能语法正常却被另一用户历史污染。这类错误很难靠模型自检发现,因此服务层需要会话 ID、状态校验和隔离测试。

如何做因果验证. 仅观察加入 LiveMem 后分数提高,仍不能证明答案来自循环状态。更强的验证是在证据退出窗口后,对 StS_t 做干预。第一种是清零状态,若准确率降到截断基线,说明状态是必要路径;第二种是在相同当前上下文下交换两条样本的状态,若答案随状态中的事实改变,说明模型确实读取它;第三种只遮蔽与目标证据相关的写入区间,检查下降是否具有内容选择性。 设完整系统准确率为 AfullA_{\mathrm{full}},清零状态为 A0A_{0},保留状态但不让历史退出窗口为 AvisibleA_{\mathrm{visible}}。可以报告状态贡献差

ΔM=Afull−A0.(18)\Delta_M=A_{\mathrm{full}}-A_0. \tag{18}

ΔM>0\Delta_M>0 说明在该数据与干预下状态有帮助,不表示其中存有可读的原文,也不表示所有历史都被保留。交换实验还要防止分布外状态导致模型普遍退化,应设置同标签与异标签交换对照。 对修订事实,先输入旧值 uu,后输入新值 vv,证据均移出窗口,再分别询问当前值与历史值。理想系统对当前查询回答 vv,对审计查询能在外部日志中找到 uu;内生状态不必独自承担二者。若回答仍是 uu,说明擦除或新写入不足;若随机漂移,则可能是压缩容量或读取选择失败。把错误按这三类分开,比一个总准确率更能指导训练。

一次请求中的状态时间线,官方仓库对生命周期给出了很清楚的边界:LiveMem 状态在同一请求内持续,当前 OpenAI-compatible API 不会自动把它复用到下一次独立请求。单次输入还受 262,144 token 的位置范围约束。它解决的是请求内部发生 context turnover 时的连续计算,不等同于跨天账户记忆。

请求开始
  S_0=0
    │ prefill: 历史 token 逐步写入 S_t
    ▼
活动 KV 达到 8K/32K
    │ 旧 KV page 释放,S_t 继续保留
    ▼
逐 token decode: attention window + recurrent state
    │
    ▼
请求结束 → S_t 释放

state 模式让完整历史持续更新循环状态,注意力只保留 system sink 与最近窗口;truncate 模式由客户端先删除旧历史,服务器从零状态处理留下的后缀。两种模式若使用相同的 window_size,模型可见的精确 KV 数量相似,历史是否进入循环状态却完全不同,因此它们构成直接对照。 服务端必须把 memory cache 与 KV cache 绑定在同一个请求身份上。Prefill 完成后若 decoding worker 迁移,迁移内容至少包含层级 memory state、位置计数、system sink 与活动 KV 页映射。只迁 KV 会丢掉早期历史影响;只迁循环状态会丢掉最近 token 的精确上下文。

状态更新的数值直觉. 将单头状态简化为 St∈Rdk×dvS_t\in\mathbb R^{d_k\times d_v},当前 key 为 ktk_t,value 为 vtv_t。模型先读取旧状态对当前 key 的预测:

v^t=St−1⊤kt.(19)\hat v_t=S_{t-1}^{\top}k_t. \tag{19}

残差为 rt=vt−v^tr_t=v_t-\hat v_t,再按写门 βt\beta_t 更新:

St=St−1+βtktrt⊤.(20)S_t=S_{t-1}+\beta_t k_tr_t^{\top}. \tag{20}

假设 dk=dv=2d_k=d_v=2,初始状态为零,k1=(1,0)⊤,v1=(2,1)⊤,β1=0.5k_1=(1,0)^\top,v_1=(2,1)^\top,\beta_1=0.5,则:

S1=[10.500].(21)S_1= \begin{bmatrix}1&0.5\\0&0\end{bmatrix}. \tag{21}

下一次用同方向 k2=(1,0)⊤k_2=(1,0)^\top 读取,得到 v^2=(1,0.5)⊤\hat v_2=(1,0.5)^\top。若目标 value 仍为 (2,1)⊤(2,1)^\top,残差只剩 (1,0.5)⊤(1,0.5)^\top,再次写入会逐渐逼近目标。若新事实要求不同 value,残差方向改变,状态会沿相同 key 方向修订。真实 GDN2 还含衰减、擦除和多头门控,式 (20) 只是帮助跟算 delta rule 的核心。 固定矩阵会产生干扰。两个语义不同的 key 若方向接近,它们的秩一更新落在相似子空间,读取时可能混合。提高维度、学习更好的 key 与门控能缓解,却无法让固定容量无损保存无限历史。状态连续意味着旧信息仍能影响计算,不保证逐字回放。

Serving 资源构成,官方仓库当前 vLLM 插件锁定 vllm==0.19.1,支持 8K 与 32K 活动窗口。Hugging Face quick check 可以显式创建 GDN2 cache,适合功能验证,却没有 vLLM 路径的 paged-KV eviction;评测上下文轮转必须使用真正释放旧 KV 的 serving 路径,否则早期证据仍可能留在注意力里。 延续式 (16) 的示例,每请求 memory state 约 8 MiB。若 1000 个活跃请求全驻 GPU,仅循环状态约需 7.8 GiB;再加 32K KV、模型权重、激活与调度缓存,内存压力远高于这一个数字。暂停会话若迁往 CPU,恢复时又会产生 PCIe 或网络传输延迟。 设每份状态大小为 BsB_s,活跃请求数为 NaN_a,暂停请求数为 NpN_p,GPU 与 CPU 驻留比例分别为 qg,qcq_g,q_c,则两层存储约为:

BGPU=qgNaBs,BCPU=(qcNa+Np)Bs.(22)B_{GPU}=q_gN_aB_s, \qquad B_{CPU}=(q_cN_a+N_p)B_s. \tag{22}

若服务允许断点恢复,还要给磁盘 checkpoint 计算写放大。每生成一个 token 都保存状态会产生巨大 I/O;只在轮次边界、上下文轮转或显式暂停时保存,恢复点更稀疏。选择取决于单次请求价值与重算成本。 吞吐还受双路径计算影响。每层输出为:

ot=otattn+otmem.(23)o_t=o_t^{attn}+o_t^{mem}. \tag{23}

注意力路径随活动窗口增长,memory 路径对历史长度保持常数,但增加固定矩阵读写。应报告 prefill token/s、decode token/s、首 token 延迟、峰值显存和并发请求数。只报告 KV 节省无法判断新增分支是否把算力瓶颈推到矩阵更新。

训练资源与可复现边界. 官方 README 已公开两阶段 SFT、checkpoint 导出、GRPO 和评测入口。论文 SFT 使用两台节点,每台 8 张 A800-80GB,固定 64K token pack:第一阶段训练 100 step,第二阶段从前一 checkpoint 恢复后训练 500 step。Paper-scale RL 使用两台 8-GPU trainer 节点、一台 8-GPU rollout 节点,另有 2-GPU judge 服务。 这组资源说明开源代码不等于低成本复现。单机可以运行 run_grpo_dev.sh 做两 GPU、五步的开发检查,却不能把它的吞吐和论文规模等同。缩小节点数时,pack size、梯度累积、并行策略和 rollout 并发都会改变;报告应列出总训练 token、有效 batch 与墙钟时间,而不只写训练 step。

默认训练冻结 attention 与 FFN 主路径,完整训练循环记忆支路;LoRA 只是框架提供的可选参数组,并非默认 recipe。复现时若启用 LoRA,已经改变可训练参数与比较条件。导出工具会把训练后的 memory branch 合到冻结 backbone 上,并生成 Hugging Face/vLLM 可加载 checkpoint。

2.1. 状态治理和失败边界

循环状态缺少可读 schema,工程系统无法直接列出其中保存了哪些用户事实。状态串线、错误修订和隐私删除因此比外部数据库更难处理。会话 ID 与状态 checksum 能发现传输错配,却无法证明语义内容正确。 多租户服务必须禁止状态复用。一个请求结束后,GPU/CPU 缓冲区在交给下一请求前要清零;批处理重排要通过 request ID 绑定每层 cache;故障恢复只能加载同一模型版本与状态 schema。用另一 checkpoint 读取旧状态,即使 shape 相同,key/value 表示也可能已经变化。

长期运行还会遇到状态饱和。新信息持续写入固定矩阵,旧方向被衰减或覆盖。可以按证据离开窗口后的距离分桶测准确率,观察性能何时下降;也可以在输入中周期性修订同一事实,测旧值残留。总体平均分会把远距离和高冲突样本混在一起,无法判断容量边界。 LiveMem 与外部检索组合时,权威事实仍由外部层提供。循环状态可以让模型记得「此前讨论过 Aurora 项目」,需要删除、审计或精确引用时则回到版本化记录。内生状态承担连续影响,外部状态承担可编辑事实,这个分工也为隐私删除留出可执行路径。

训练与部署必须看到同一种轮转,训练时若让完整历史始终留在注意力窗口,模型会走最省力的精确注意力路径,循环状态即使存在也可能闲置。LiveMem 使用动态 attention mask 模拟 context turnover,使旧证据在训练中离开可见窗口,同时仍参与循环状态更新。部署端再真正释放对应 KV page,训练与 serving 才共享同一可见性边界。 设证据位于 token ii,查询位于 jj,活动窗口为 WW。当 j−i>Wj-i>W 时,主注意力无法直接访问证据,回答依赖 memory state 或外部检索:

p(yj∣x1:j)=p(yj∣xj−W:j,Sj−W).(24)p(y_j\mid x_{1:j}) =p(y_j\mid x_{j-W:j},S_{j-W}). \tag{24}

若训练 mask 仍允许注意力偷看 xix_i,损失下降也无法证明 SS 学会了承载证据。评测同理:仅在 prompt 文本上声明窗口为 8K,却没有从 KV cache 中移除旧页,模型仍可能通过实现细节访问早期 token。 动态 mask 的采样分布会决定记忆偏好。训练总把证据放在窗口外很近的位置,模型可能只学会短距离延续;部署运行数十万 token 后,状态干扰更强。应按 evidence distance 分桶,并报告超过 1、2、4、8 个窗口长度后的表现。官方论文的 evidence-distance analysis 正是在检查信息离开活动窗口后还能影响多远。

SFT 与 RL 分别补什么. SFT 用带答案的数据教 memory branch 写入和读取有用信息。官方 recipe 分两阶段:第一阶段在长文本混合数据上建立基础连续性,第二阶段加入 QA、分类、多问题和长文本数据,让状态更贴近下游决策。主 attention/FFN 路径冻结,减少新增支路破坏基座能力的风险。 RL 在 SFT checkpoint 上继续优化最终回答。组内八条 response、无 KL penalty、0.20/0.28 clipping 和 token-mean loss 是官方开发脚本当前公开的配置,论文规模的资源布局更大。无 KL 意味着稳定性更多依赖初始化、clip 与数据;换数据或扩大训练步数时,不能假定同一配置天然稳定。

终局 reward 仍很稀疏。回答正确会共同强化写入、保留和读取行为,却难指出哪个 token 的记忆操作起作用。可以用状态干预做训练后诊断:清零某段状态、交换状态或屏蔽某个写入区间,再观察 reward 变化。诊断结果不必直接进入训练,也能判断增益是否真的经过 memory branch。

并发、轮转与状态几何,普通 vLLM 调度主要管理 KV block,LiveMem 还要管理每层循环状态。请求从 running 转为 waiting 时,状态可留在 GPU、换到 CPU 或写入磁盘;选择取决于预计等待时间。短暂停留在 GPU 避免传输,长暂停继续占显存则会阻塞新请求。 设 GPU↔CPU 带宽为 qq bytes/s,状态大小为 BsB_s,一次换出再换入的理论传输下界为:

Tswap≥2Bsq.(25)T_{swap}\ge \frac{2B_s}{q}. \tag{25}

8 MiB 状态在 16 GB/s 有效带宽下,纯传输约 1 ms;实际还有同步、序列化、批量碎片和每层 cache 管理。状态很小并不保证切换免费,P99 延迟仍需实测。 调度器还要防止 ABA 问题:会话槽位被释放后又分给新请求,迟到的异步回调若只携带 slot ID,可能把旧状态写进新会话。请求 ID、generation counter 与状态版本三者共同校验,才能拒绝迟到写入。

2.2. 仓库状态与复现入口

截至 2026 年 10 月,官方仓库已公开模型实现、训练脚本、数据处理、评测和 vLLM 插件,并提供 chen-l/LiveMem-SFT 与 chen-l/LiveMem-RL checkpoint 链接。仓库历史仍很短,依赖版本较窄;vLLM 插件面向 0.19.1,Flash Linear Attention 使用仓库 vendored 版本。复现时应锁定 commit 与依赖,不使用浮动最新版替换后仍声称同配置。 最小功能检查用 Hugging Face 路径显式创建 FLACache,确认 prefill 与 decode 之间状态保留;窗口轮转与吞吐实验改用 vLLM state-8k/state-32k 服务;truncate 服务作为无状态后缀对照。三条服务必须使用同一 checkpoint、采样参数和评测集合。

官方评测支持断点续跑,结果默认写入 results/eval/。断点恢复时还要保存已运行样本、server 模式、窗口大小和 checkpoint ID;只按样本序号续跑,若中途换了服务配置,会把两套结果拼进一个目录。

连续状态和历史访问的差别,RAG、长窗口和摘要主要解决「还能不能看到旧内容」,LiveMem 关注的是「旧内容离开工作窗口后,计算是否仍沿着同一状态继续」。两者容易混在一起,因为问答任务最终都表现为能否回答过去的信息。但它们的系统语义不同。 历史访问要求在需要时找回一段原始或近似原始证据。检索器可以在查询到来后搜索,长窗口则始终保留 token。状态连续性把历史经过递推写进固定容量状态,后续每个 token 都在这个状态上继续计算,即使系统尚不知道未来会问什么。它更像在线滤波,而不是事后查档。

设历史为 x1:tx_{1:t},检索式系统在查询 qq 到来后计算

Rt=Retrieve⁡(q,x1:t),(18)R_t=\operatorname{Retrieve}(q,x_{1:t}), \tag{18}

LiveMem 则持续更新

St=F(St−1,xt),yt=G(St,Wt),(19)S_t=F(S_{t-1},x_t),\qquad y_t=G(S_t,W_t), \tag{19}

其中 WtW_t 是当前注意力窗口。StS_t 在查询出现之前已经形成,因此不能为每个未来问题重新选择最相关片段。固定状态的优势是持续、低延迟和不随历史长度增长;代价是有损压缩和难以回到精确证据。 一个反例能说明边界。用户在十万轮前给出一串随机 128 位密钥,之后从未重复。RAG 若有精确索引可以取回,固定状态必须在有限维连续向量中与所有其他历史竞争,无法保证任意随机串无损保存。相反,长流程中某个变量经过数百次更新,检索单个旧片段还需重放更新,递推状态可以直接保留当前聚合结果。

因此两条路线适合组合。循环状态保存持续演化的任务态、偏好统计和隐变量,外部存储保存精确证据、文件版本和可审计事件。需要回答时,状态提供检索查询和当前语境,外部存储返回原文。只用其中一条,都难同时获得固定成本、精确回溯与可审计性。 评测时应把两类能力拆开。把证据移出窗口但允许外部检索,测的是历史访问;关闭检索,只保留递推状态,才隔离状态连续性。若数据集问题本身提供明显关键词,RAG 占优很正常;若答案依赖多轮累积而没有单一支持片段,递推状态才更可能显出价值。

GDN2 更新的矩阵几何,官方实现给出的 GDN2 更新可以写成

St=(I−kt(bt⊙kt)⊤)Diag⁡(egt)St−1+kt(wt⊙vt)⊤.(20)S_t=\left(I-k_t(b_t\odot k_t)^\top\right) \operatorname{Diag}(e^{g_t})S_{t-1} +k_t(w_t\odot v_t)^\top. \tag{20}

不同实现对矩阵左右方向的约定可能转置,但三个动作不变:gtg_t 对旧状态各方向做衰减,btb_t 沿当前 key 方向擦除旧关联,wtw_t 控制新 value 的写入。查询 qtq_t 再从状态读出 qt⊤Stq_t^\top S_t。 先看一维简化。令状态为标量 sts_t,所有 key 为 1,则

st=(1−bt)egtst−1+wtvt.(21)s_t=(1-b_t)e^{g_t}s_{t-1}+w_tv_t. \tag{21}

gt<0g_t<0 产生遗忘,btb_t 再决定当前地址覆盖多少,wtw_t 决定写入强度。若三者长期固定,旧值经过 τ\tau 步的系数为 [(1−b)eg]τ[(1-b)e^g]^\tau。这给出有效半衰期

τ1/2=log⁡(1/2)log⁡∣(1−b)eg∣.(22)\tau_{1/2}=\frac{\log(1/2)} {\log |(1-b)e^g|}. \tag{22}

高维情形不是每个记忆槽独立。key 方向相近的写入会共享矩阵子空间,擦除一个地址也会影响相似地址。若 ki⊤kjk_i^\top k_j 很大,两个实体的状态容易串扰;多头和逐层状态提供更多子空间,却没有消除固定容量上限。 状态更新还承担计算路径。某个早期 token 对远期输出的梯度要经过连续 Jacobian 乘积:

∂ST∂St=∏j=t+1T(I−kj(bj⊙kj)⊤)Diag⁡(egj).(23)\frac{\partial S_T}{\partial S_t} =\prod_{j=t+1}^{T} \left(I-k_j(b_j\odot k_j)^\top\right) \operatorname{Diag}(e^{g_j}). \tag{23}

谱范数长期小于 1 会让早期影响衰减,接近或大于 1 又可能造成数值不稳。注意力旁路让近期 token 不必完全经过这条长乘积,训练数据则需要迫使远期答案依赖已经退出窗口的信息,否则模型会一直走更容易的注意力路径。 写掩码提供了一个容易忽略的控制。官方代码允许将 gt,bt,wtg_t,b_t,w_t 同时置零,使 St=St−1S_t=S_{t-1},当前 token 仍能读取状态。连续扫描模式让所有 token 更新记忆;选择性写入模式只在将被驱逐的区域开放写门。前者获得完整在线轨迹,后者减少近期内容重复进入注意力与状态两条路径。二者对应不同的训练分布,不能只在部署时随意切换。