Memento / KV Cache 深度解读

X Thread Reading · MEMENTO · KV Cache · Claude Code

为什么“清掉 KV cache”不只是丢一点加速?

DimitrisPapail 的这条 X 帖把 Claude Code idle 后的体验问题,连接到 MEMENTO 论文里一个更深的机制发现: 模型的可用上下文不只存在于可见文本,还部分存在于连续生成留下的 KV 表征里。

原帖:2026-04-08 补充讨论:2026-05-17 论文:MEMENTO arXiv 2604.09852 输出日期:2026-05-18
01

读了什么,怎么验证

原帖 2041974013950373901 的 OpenCLI 抓取结果显示正文只有一个 t.co 链接;短链解析到 X Article。 由于 opencli twitter article 对该 Article 返回 Article not found,本报告用 OpenCLI 线程、Microsoft Research 页面、项目 GitHub Pages 博客、GitHub README/vLLM README 和本地 PDF 文本交叉验证。

X thread

抓到原帖、作者回复、术语争议和关于 RoPE/restart/CLI agent 的讨论;主帖短链指向 X Article。

论文与博客

MEMENTO: Teaching LLMs to Manage Their Own Context;Microsoft Research 文章和 GitHub Pages 博客提供方法、结果和实现说明。

代码材料

GitHub README、data pipeline README 和 vLLM overlay README 用来核对特殊 token、物理 KV compaction 和运行参数。

02

问题不是“上下文太长”,而是模型不会自己管理中间状态

长 CoT 推理的基本矛盾很直接:模型通过生成大量 token 来做 test-time compute,但每个过去 token 的 key/value 向量都会留在 KV cache 里。 上下文越长、并发越高,KV cache 越容易成为显存和吞吐瓶颈。传统做法一般在模型外部加 summarizer、RAG memory 或 orchestration,把历史消息替换成压缩文本。

MEMENTO 的问题设定更激进:context management 不应该只是外部系统帮模型做的 housekeeping,而应该变成模型自己学会的 metacognitive skill:什么时候分段、压缩什么、忘掉什么、从什么状态继续。

所以这条 X 帖的技术含义不是“KV cache 很贵”这个常识,而是:“重启 + 文本摘要恢复”可能破坏模型内部状态连续性。 MEMENTO 的实验恰好给了一个机制级解释:summary token 的 KV state 本身也在存信息。

03

Memento 怎么工作:block、summary 与 KV 驱逐

一个 Memento-trained 模型把自己的 reasoning 分成多个语义 block。每个 block 结束后,模型生成一个 memento: 这不是普通自然语言摘要,而是尽量短但足以继续推理的 state compression,保留公式、中间值、结论、被拒绝路线和下一步策略。

<think>
<|block_start|> reasoning block T1 <|block_end|>
<|summary_start|> memento M1 <|summary_end|>

<|block_start|> reasoning block T2 <|block_end|>
<|summary_start|> memento M2 <|summary_end|>
...
</think>
final answer

<|summary_end|> 生成后,前一个 reasoning block 对未来 token 不再可见。重要的是,MEMENTO 的 vLLM overlay 不是只做逻辑 attention mask, 而是把对应 block 的 KV entries 物理 compact/evict,释放 KV pool 空间。

生成 T_i

模型展开当前 reasoning block,此时 KV cache 正常增长。

生成 M_i

模型在看见 T_i 的条件下生成 memento。M_i 的文本是摘要;M_i 的 KV state 是“看过 T_i 后”算出来的隐藏表征。

驱逐 T_i

summary 完成后,vLLM 把 T_i 的 KV entries 物理移除,只保留 prompt、mementos 和当前 block。

继续推理

未来 token attend 到 M_i;它看到的不只是 memento 文本,还包括 M_i KV state 里残留的原 block 信息。

线程里 masking / evict / flush 的争议:作者在回复中承认不同 backend 下 masking 不一定总是物理 evict;但为了获得 MEMENTO 的 memory saving,他们的 vLLM 实现确实做了 KV eviction/compaction。因此可以把论文里的 “mask” 理解成语义上的不可见,把工程实现理解成物理 KV 驱逐。

04

数据与训练:复杂的是数据 pipeline,不是 loss

MEMENTO 构造了 OpenMementos:约 228K 条从 OpenThoughts-v3 派生的 reasoning traces,带 block segmentation 和 memento summaries。数据来源主要是 QwQ-32B 生成的高质量推理轨迹。

阶段做什么为什么这样做
Seed selection从 OpenThoughts-v3 选择 reasoning traces。复用已有高质量 CoT,避免从零生成。
Sentence splitting把 trace 切成句子、代码块、数学表达式等 atomic units。避免在公式、代码或连续推导中间切断。
Boundary scoringLLM judge 给相邻单元边界打 0-3 分。把全局分段难题拆成局部判断。
DP segmentation动态规划选择边界,奖励高分切点并惩罚 block size 不均。LLM 不擅长一次性做全局组合优化,算法更稳。
Iterative summaryCompressor 生成 memento,Judge 六维评分,低于阈值则反馈重写。单轮 summary 容易漏公式/数值;两轮反馈通过率从约 28% 到约 92%。

两阶段 SFT

Stage 1: Full Attention

标准 causal attention,loss 作用在所有 token 上。模型先学习 block/memento 格式和特殊 token 的使用。

Stage 2: Memento Attention

每个 memento 完成后,前一个 thinking block 对后续 token 被 mask。模型被迫让 memento 足够自洽。

这里没有引入复杂的新监督目标;训练目标仍是 next-token SFT。关键变化是第二阶段的 attention pattern,让训练条件和部署时 block masking 对齐。 作者在 X 回复中说“训练动态很像正常 SFT”就是这个意思:训练目标简单,但数据构造和推理引擎不简单。

05

最强证据:同样 summary 文本,重算 KV 后性能大跌

如果 Memento 只是文本摘要,那么一种更简单的实现应该可行:每生成一个 summary,就重启一次 API call,用 prompt + summaries 重新 prefill。 论文专门做了 restart ablation 来测试这个想法。

推理模式保持不变的部分改变的部分AIME24 Pass@1
正常 Memento attentionM_i 文本、block/memento 结构M_i KV 在看过 T_i 后保留66.1%
Memento attention + restartM_i 文本相同丢弃 KV,重新 prefill prompt + M_1...M_i,M_i KV 不再包含 T_i 信息50.8%
差距文本相同只隔离 KV 表征通道-15.3 pp
\[ \text{KV}_{M_i}^{\text{normal}} = f(M_i \mid T_i, M_{

这个对照很干净:summary text 一样,差异来自 KV vectors 的计算条件。性能大跌说明 M_i 的 KV state 不是无关缓存,而是携带了下游推理会使用的信息。

Passcode probe:隐式通道里能恢复信息

论文进一步把随机 5 位 passcode 注入到真实 AIME25 trace 的某个 block 中,然后从后续 memento 的 KV state 训练 probe 预测这些数字。 在 masked 条件下,M3 不能直接看见被注入的 T2;如果仍能预测,说明信息通过 memento KV chain 传播了。

条件含义结果解释
DirectProbe M2 的 KV,M2 生成时能看见 T2。能恢复约 60-70%,说明 KV state 包含比文本更多的信息。
MaskedProbe M3 的 KV,M3 不能直接看见 T2。Qwen3-8B 约 26.7%、Qwen3-32B 约 23.0%,显著高于 10% chance。
Causal controlProbe T2 之前的 M1。接近 10% chance,说明信号方向正确,不是 probe 作弊。

主评估结果怎么读

MEMENTO 的主要评估不是通用聊天记忆,而是压缩自身 reasoning trace 后,在数学、科学、代码 benchmark 上能否保留解题能力并降低 KV 成本。

指标定义报告中的作用
Pass@1 accuracy每题多次采样后按单次正确率平均。衡量压缩后单次解题稳定性。
Peak KV请求期间 KV cache 峰值显存。决定能否服务长上下文/高并发。
AUC KVKV 占用随生成步数的曲线下面积。衡量 memory-time cost;能揭示“峰值降了但生成变长”的失败模式。
Pass@64 / overlap大量采样下能解出的题集重合度。判断损失是 capability 下降还是 consistency 下降。

论文里 Qwen3-32B 在 AIME26 上从 Base 75.2% 到 Memento 72.6%,只降 2.6 pp,同时显著降低 Peak KV。 Qwen3-8B 的 SFT gap 更大,但 RL 后 AIME26 从 57.3% 回到 64.9%,说明压缩造成的主要是单次采样一致性问题,而不是能力完全消失。

06

这对 Claude Code / CLI agent 意味着什么

Claude Code 这类 coding agent 的长会话不是单题数学推理,而是跨文件、跨命令、跨测试日志的状态累积。 它的“记忆”不仅包括 transcript 里的显式文本,还包括模型在连续推理中形成的中间表征。

关键区别:保存 transcript 并不等于保存 session state。文本重放能恢复一部分显式信息,但不能恢复原来 token 生成时形成的 KV 表征,尤其不能恢复“summary token 看过完整上下文后”的隐藏状态。

长 agent session 里的状态普通文本 memory 能否保存KV 连续性可能保存什么
已读文件、错误日志、用户约束可以,但取决于是否完整记录/检索。可能形成对当前任务状态的连续隐式压缩。
“我刚刚为什么放弃那条路线”如果模型写出来就能保存;没写出来则丢失。可能残留在当前 reasoning 状态中。
代码库局部结构的注意力焦点摘要可能很粗糙。KV state 可能携带更高带宽但不可解释的焦点信息。
长时间 idle 后恢复通常依赖 transcript/prompt compaction。如果 KV 被 flush,则这层状态消失。

所以 Dimitris 的抱怨应该理解为:对长任务 agent 来说,idle 后清 cache 可能不只是性能优化策略,而是改变了模型继续工作的计算条件。 Memento 没有直接证明 Claude Code 的内部实现,但它证明了“flush KV 会丢隐式信息”在一个受控 reasoning setting 中是真实可测的。

07

不要过度解读的地方

08

我的判断:LLM 的上下文不是纯文本对象

MEMENTO 最重要的贡献不是省了多少 KV cache,而是把一个常被系统工程处理的问题变成了模型能力问题: 模型可以学会主动压缩自己的推理状态,而不是被外部 summarizer 被动改写历史。

更深的 insight 是:今天很多 agent framework 默认把“上下文”抽象成文本列表,所以可以随时裁剪、总结、重启、重放。 MEMENTO 说明这个抽象是有损的。连续生成中的 KV state 是一条高带宽、不可解释、但会影响结果的状态通道。

对工程实践来说,未来强长期 agent 很可能不会只靠一种 memory。更合理的结构是三层并存: 显式 transcript 负责可审计记录,外部 memory/RAG 负责跨会话长期知识,服务端 KV/state management 负责连续推理中的短期隐式状态。 “不要 flush KV”只是表层口号,真正的方向是:让模型和 serving system 共同学习如何压缩、迁移和保留有用状态。

09

复现命令记录

opencli list -f yaml | rg -i "twitter|x.com|web"
opencli twitter --help
opencli twitter thread --help
opencli twitter article --help
opencli twitter thread "2041974013950373901" --limit 80 -f json --trace retain-on-failure
curl -Ls -o /dev/null -w '%{url_effective}\n%{http_code}\n' "https://t.co/lbjcGDxpJn"
curl -L "https://raw.githubusercontent.com/microsoft/memento/main/docs/memento.pdf" -o "memento-kv-cache-x/refs/memento.pdf"
pdfinfo "memento-kv-cache-x/refs/memento.pdf"
pdftotext -layout "memento-kv-cache-x/refs/memento.pdf" "memento-kv-cache-x/refs/memento.txt"