Cache Engineering for Agents(AKV serving engine)
报告的主要结果(均为原文自报,非本站复现)
(原文自报,3 个模型 × 4 个基准的平均。)
| 模型 | 方法 | 平均得分 % | 平均成本(美分/任务) |
|---|---|---|---|
| MiniMax-M2.7 | Standard / Text Eng. / AKV | 52.4 / 52.8 / 53.7 | 5.0 / 5.7 / 4.4 |
| GPT-OSS-120B | Standard / Text Eng. / AKV | 51.0 / 48.3 / 53.1 | 11.2 / 10.2 / 7.3 |
| MiroThinker-1.7-Mini | Standard / Text Eng. / AKV | 44.1 / 37.1 / 45.8 | 20.4 / 18.1 / 14.8 |
- 摘要:相对 Standard 平均成本降 27.7%,相对 Text Engineering 降 21.9%。
- 服务(GPT-OSS-120B,Top-80 SWE-Verified):各自峰值吞吐设置下,AKV(并发 14)较 Standard(并发 12)平均 / P95 请求延迟加速 1.36× / 1.51×,输入 / 输出吞吐为 1.53× / 1.18×。
- KV cache 读取占 API 总成本 82.4%(论文 Figure 14)。
通俗解释
智能体干活要反复调用工具,每次都把全部历史再喂给模型。历史越长越贵:论文测到,KV cache 的读取占了 API 总成本的 82.4%。
常规做法有两种:把旧历史裁掉,或者让模型写一段摘要。可是一旦改了历史的前面部分,后面所有已经算好的缓存都作废,要重新算(re-prefill)。于是大家只能「攒到很长再一次性大砍」,砍得狠就容易丢信息。
这篇论文的想法是:文字历史不改,只告诉服务器「这几段缓存以后别再看了」(drop),再把剩下的位置编号捋顺(repos)。剩下的缓存全部原样复用,不用重算。再配一套新的服务引擎 AKV,把「同样的文字、不同的丢弃顺序会产生不同缓存」这件事记清楚,保证复用是正确的。
专业解释
Cache engineering 是区别于 context engineering 的新范式:不修改 logical token sequence,而是直接对 active KV cache $\mathcal C$ 施加操作。定义三种原子操作 $\operatorname{append}$、$\operatorname{drop}(P)$、$\operatorname{repos}$。关键观察:KV 状态是 history-dependent 的——相同 token 序列与相同保留位置,在不同的 drop/append 顺序下会得到不同的 KV 状态(因为后续 token 的 KV 在计算时是否 attend 到被 drop 的内容不同),因此传统以 token 前缀为键的 prefix caching(RadixAttention 等)不再正确。
AKV 服务系统 遵循「stateless interface, stateful serving」:请求在 messages 之外携带 cache(drop 与 reposition 的操作序列,用 operate-after 语法),服务端内部:(1) extended radix tree:在 token 前缀树上插入 *drop node*(及 *reposition node*),按 token + 操作历史联合匹配以保证「当且仅当等价才复用」;(2) drop-aware eviction:被所有相关请求 drop 的缓存可提前回收,优先于已完成请求的缓存被逐出;(3) segment-batch attention:当缓存被逐出需要恢复时,在一次 prefill 内按 drop / repos 触发点把 query 切段,各段 attend 各自的活跃缓存,仅 attention 分段、FFN 仍整批计算,以避免重复读 FFN 权重。
主策略 tool-response rolling drop:保留所有推理(assistant)缓存与最近 12 条工具响应的缓存,逐步丢弃更老的工具响应缓存;$\operatorname{repos}$ 的触发阈值与 Standard 的摘要阈值相同。论文也展示了让智能体自我改进缓存策略(RSI)与 Cache-As-Tool(CAT)。
详细算法
1. 问题设定
自回归 LLM:$p_\theta(x_{t+1}\mid x_{1:t})$;有 KV cache 时 $p_\theta(x_{t+1}\mid x_t,\mathcal C_{1:t-1})$。智能体轨迹 $x_{1:t}$ 包含 prompt、assistant 消息与工具响应,称为 logical token sequence。Active cache $\mathcal C$ 是后续 attention 实际可见的 KV 集合,其长度不必等于逻辑长度,且缓存项的位置编码索引也可独立于其逻辑索引。
目标:在不改变轨迹文本、不 re-prefill 保留部分的情况下,让 $\mathcal C$ 受智能体 / harness 控制,同时服务端能正确复用、驱逐与恢复这些「历史相关」的缓存。
2. 关键公式
三种缓存操作:
$$\operatorname{append}(x_{t+1}):\ \mathcal C\leftarrow[\mathcal C;\,C_{t+1}]$$
$$\operatorname{drop}(P):\ \mathcal C\leftarrow\mathcal C\setminus\{C_i:i\in P\}$$
(drop 只让这些 KV 不再参与后续 attention,保留项及其位置编码不变。)
Repos(RoPE 重定位):保留 $r$ 个缓存项,其位置索引重置为 $0,\ldots,r-1$,下一个 token 使用索引 $r$。对 RoPE 键从位置 $p$ 移到 $q$:
$$K\leftarrow R(q)\,R(p)^{-1}K,\qquad V\ \text{不变}$$
缓存操作序列(确定性地描述缓存状态,从空缓存起):
$$o_{1:m}=(o_1,\ldots,o_m),\qquad o_j\in\{\operatorname{append}(x),\ \operatorname{drop}(P),\ \operatorname{repos}\}$$
对固定 LLM,该序列决定当前缓存状态;仅有 token 与保留位置不足以决定下一 token 的概率。
3. 逐步伪代码
# 智能体侧 (tool-response rolling drop, 主策略)
每轮 agent 迭代:
messages = 完整逻辑历史 # 文本不改
cache.drop = 把 "早于最近 12 条的工具响应" 的消息下标加入 drop 表
if 活跃上下文长度 > repos 阈值: cache.reposition 追加当前消息边界
请求 = {model, messages, cache} # 无状态: 每次请求完整描述自己用到的缓存
response = AKV.chat(请求)
# 服务端 AKV (对每个请求)
1. 前缀匹配: 在 extended radix tree 上沿 (token, 操作) 匹配
- 遇到 drop 节点 Δ(记录被丢弃的逻辑下标): 仅当操作历史一致才复用
- 遇到 reposition 节点: 位置编号一致则直接复用; 不一致则 "拷贝 + 旋转 K" (V 直接拷贝)
2. 缺失部分 (被逐出或首次出现) 用 segment-batch attention 单次 prefill 恢复:
for 每一层:
按 drop / repos 触发点把 query 切成段
每段: 因果地 attend 自己的 token + 之前各段的 *活跃* 缓存
(被 drop 的缓存对之后的段不可见, 对原先使用它的更早的段仍可见)
需要不同位置编码的段 -> 临时旋转 K / 拷贝 V 生成临时版本
FFN 对整个序列只做一次批处理
3. 解码: 在 active cache 上生成, 把新 KV 写入树
4. 逐出: 先回收 "已被所有相关请求 drop" 的缓存, 再回收已完成请求的缓存; 节点保留为空占位, 以便后代缓存仍可前缀匹配
4. 训练 / 推理流程
评测模型:MiniMax-M2.7(230B 总参 / 10B 激活)、GPT-OSS-120B(高推理强度)、MiroThinker-1.7-Mini(30B / 3B 激活)。基准:BrowseComp-Plus(BCP)、xbench-DeepSearch-2510、GAIA 文本验证子集(103 题)、SWE-bench Verified。
对照:Standard(模型相关的摘要阈值:96K / 96K / 192K tokens)与 Text Engineering(统一 48K 阈值摘要);AKV 取最近 12 条工具响应滚动 drop,repos 阈值同 Standard。
成本核算:用各厂商公开单价,对 AKV 每个被 repos 的 token 按缓存命中价额外计费(有意高估键旋转成本)。服务实验:基于 SGLang,8×A800-80GB(4 卡 prefill + 4 卡 decode,TP=4),因 A800 无原生 MXFP4,权重用 BF16。
与既有方法对比
- Context engineering(裁剪 / 摘要):改文本前缀 → 后缀 KV 全部失效 → re-prefill;为控制成本只能延迟到阈值再大幅压缩,导致信息丢失。Cache engineering 增量地丢弃、保留的缓存不重算,缓存里仍可能携带被丢历史的信息(因为它们当初是在看过那些历史的情况下算出来的——论文引 Fu 等 2026 等的观察)。
- 传统 prefix caching(vLLM / SGLang RadixAttention):只按 token 前缀匹配;在 drop / repos 之后会误复用不等价的缓存。AKV 的 extended radix tree 同时匹配 token 与操作历史。
- KV 压缩 / 逐出(H2O 类):按 token 重要性在服务内部决定;AKV 把「丢什么」的决策权交给 agent / harness,并给出能正确复用与恢复的系统。
优势
- 不改文本、只做缓存操作,兼顾「少付 KV 读取费」与「保留剩余缓存、避免 re-prefill」,打破 re-prefill 成本与准确率的两难。
- 正确性有明确定义:用「操作序列」刻画历史相关的缓存状态,并让 radix tree、驱逐与恢复都围绕它设计。
- 接口兼容现有 API(messages + 可选 cache 字段),客户端无状态,服务端被逐出后可单次 prefill 完整恢复。
- 给 agent 自我改进缓存策略(RSI)留出了可编程接口;代码在 GitHub 开源(本站已核对仓库链接可访问)。
劣势 / 局限
- 论文只提到:缓存策略的更多探索、在该方案下训练 agent、以及扩展到线性注意力模型都属未来工作(Limitations)。
- 需要服务端支持(基于 SGLang 的定制引擎);闭源 API 厂商不暴露此类 cache 接口时无法使用。
- SWE-bench Verified 上 MiroThinker 的绝对分数很低(7.4 ~ 7.8),且个别单项(如 GPT-OSS 的 xbench-DS 37.5 vs 38.5)低于基线,增益不是处处一致。
- 主要评测在 A800 + BF16(因缺 MXFP4 支持),与厂商生产部署环境不完全相同;成本按公开单价折算,并非真实账单。
- 不同缓存策略的最优性依赖任务;论文展示了两三种策略,但没给出通用选择规则(编者归纳)。
与工业 AI 的关系(作者判断,非论文结论)
工业智能体(巡检、故障诊断、产线问答)往往会连续多轮读取日志、点位、工单,上下文很快膨胀。AKV 的思路对「长时间运行的运维 agent」的成本控制很有参考价值:旧的工具输出缓存可增量丢弃而不是整段摘要。若我们自建推理服务(SGLang 系),可评估是否引入;若只用外部 API,则需要厂商支持,目前无法直接用。
待确认事项
- 待确认:各厂商(OpenAI / Anthropic 等)是否会对外提供类似的 cache drop 接口 依据:论文未讨论;本站未检索各厂商 API 文档(2026-10-31)
- 待确认:论文中 Figure 14 的「KV cache 读取占总成本 82.4%」的统计口径 依据:正文只引用该数字,图中口径未在本站复核(2026-10-31)