本地运行编码智能体时,长会话失败往往会让人先检查:早先的接口定义、常量和业务规则,是不是被挤出了 KV 缓存?PACE v1 的 Qwen3-8B 实验把问题推进了一步:即使这些 token 几乎全部留住,模型后续使用它们的表现仍会下降。缓存里保存了什么,以及这些内容与当前查询相隔多远,是两个需要同时控制的变量。1[1]
论文构造了带随机规格的多轮编码会话:先写入定义,中间穿插代码材料,最后要求模型按照早先的规格完成任务。主要模型为 Qwen3-8B,实验使用单张 24 GB NVIDIA L4 GPU,主机内存为 128 GiB。比较组共享推理引擎、贪心解码和持久会话机制,KV 预算设为 2,048 token。1[1]
在总长 100K token 的会话中,规划引导的保留策略让后续步骤所需 token 的驻留率达到 99.6%。然而,当定义与使用之间的间隔从 2K 增至 90K token,隐藏测试检查的通过率从 93% 降至 64%。仅看驻留率,这个缓存管理器几乎完成了任务;看生成代码的执行结果,损失却已经很明显。1[1]
原因要从旋转位置编码 RoPE 看起。RoPE 按位置旋转查询向量 q 和键向量 k;两者计算注意力分数时,位置通过相对差值进入点积。设查询的位置为 m,旧键的位置为 n,这个关系可写成 ⟨Rₘq, Rₙk⟩ = ⟨q, Rₙ₋ₘk⟩。同样的内容向量,处在不同的位置差下,会以不同的旋转关系参与打分。2[2]
只看位置关系的示意:一个定义写在位置 1,000,后续查询来到位置 91,000。如果缓存淘汰了中间大部分内容,却继续沿用原位置,两者仍相隔 90,000 个位置。内存中剩下约两千条记录,并不会自动把这段距离缩短。数组里腾出了空间,注意力计算里的位置关系仍然保留着长会话的跨度。
这正是驻留率无法单独回答的问题:它能检查需要的 token 是否还在,却不能说明当前查询能否有效使用它们。PACE 的距离实验在高驻留率下观察到表现下降,再通过位置干预改善结果。因此,诊断长会话时还需要追踪模型实际看到的旋转位置距离,不能把累计会话长度、缓存条目数和位置距离当成同一个量。1[1]
PACE 的第一部分处理“保留什么”。规划器把后续步骤将读取的历史片段告诉缓存管理器,管理器据此提高这些片段的保留优先级。这样,一项暂时无人使用、稍后却会成为依赖的定义,也能得到保护。对于编码智能体,下一步需要哪个接口、哪个状态约定,正是执行计划可以提供的信息。1[1]
第二部分处理“保留下来的内容放在哪里”。当物理位置接近设定上限,PACE 按原有先后顺序,把仍驻留的 token 重新编成紧凑的位置序列,让新 token 接着这个序列继续编号。被淘汰内容留下的空隙随之消失。论文主要配置将上限 L 设为 8,192,使保留内容与当前查询之间的旋转位置距离持续受到约束。1[1]
重编号还必须同步处理缓存中的键向量。旧键已经携带原位置 p 的旋转;改到新位置 p′ 时,需要施加差值旋转 Rₚ′₋ₚ,使 Rₚ′₋ₚ(Rₚk) = Rₚ′k。只修改位置标签、继续使用旧旋转的键,会让标签与实际向量不一致。PACE 将位置重排和键的重新旋转一起完成,后续查询也使用更新后的物理位置。1[1]
两个部分是否都需要,论文用 100K-token 会话的配对实验作了比较。在相同的 2,048-token 缓存预算下,结果如下;通过率统计的是隐藏测试中的检查项。1[1]
| 配置 | 规划引导保留 | 位置上限 8K | 隐藏检查通过率 |
|---|---|---|---|
| H2O 基线 | 无 | 无 | 42% |
| 仅规划引导保留 | 有 | 无 | 63% |
| 仅有界位置 | 无 | 有 | 63% |
| PACE | 有 | 有 | 97% |
只保留关键内容,仍可能让它离查询过远;只把位置拉近,又可能在更早的步骤就淘汰了真正需要的内容。两者配合,才同时改善信息的存留与使用。PACE 在这组实验中通过 145/150 个检查项,30 次探针任务中有 28 次通过全部检查。这两个数字分别回答“通过了多少检查”和“完成了多少道任务”。1[1]
把会话继续拉长,保留策略的重要性更加明显。论文在同一张 24 GB GPU 上运行了 1M、2M-token 会话,让定义分别出现在使用前约 0.9M、1.8M token 的位置。PACE 的隐藏检查通过率仍为 99% 和 100%,两种长度下都召回了全部会话事实;只控制位置、缺少规划引导的配置则从 33% 降至 13%。1[1]
| 累计会话长度 | 定义至使用的间隔 | PACE 检查通过率 | 仅有界位置的检查通过率 |
|---|---|---|---|
| 1M token | 约 0.9M token | 99% | 33% |
| 2M token | 约 1.8M token | 100% | 13% |
这里的百万级数字描述累计会话历史。模型每一步使用的是预算约两千 token 的驻留工作集,规划决定哪些历史片段进入这个工作集,位置管理决定它们以怎样的距离参与计算。这也解释了为什么单卡可以承接很长的会话:服务过程持续更新有限的工作集,让早期依赖跨越很长的逻辑间隔继续发挥作用。1[1]
内存账可以按模型配置展开。Qwen3-8B 官方配置包含 36 层、8 个 KV 头,头维度为 128。按每个元素占 2 字节计算,一个 token 的 K、V 合计需要 2 × 36 × 8 × 128 × 2 = 147,456 字节,即 144 KiB。全量保留 1M、2M token 的 KV,分别约需 147 GB、295 GB,与论文给出的量级一致。3[3]
将预算固定在 2,048 token,驻留 KV 的对应量级约为 0.30 GB。PACE 还使用一份参考键存储支持反复重旋转,论文报告两部分 KV 状态合计低于 0.7 GB。本地部署规划显存时,需要在这项开销之外,继续计入模型权重、临时张量和推理后端的其他分配;主机内存也应单独记录。1[1]
因此,在自己的设备上评估长会话缓存压缩,可以从一组明确依赖的任务开始:前段写入接口、常量或规则,中段执行其他工作,后段要求代码准确使用前段信息,并用可执行测试判定结果。固定模型版本、权重与 KV 精度、后端版本、缓存预算和生成设置,让不同策略处理相同的会话。再逐步增加定义至使用的间隔,观察任务表现如何变化。
记录结果时,把过程连起来看:先检查依赖片段是否驻留,再检查它们与查询的物理位置距离,随后检查答案是否正确复用了事实,最后运行代码测试。依赖已经丢失,优先检查保留与恢复机制;依赖仍在而距离持续增长,优先检查位置管理;事实已正确复用、程序仍未通过,则继续定位实现错误。这样才能区分缓存问题和代码问题。
资源指标与任务指标应按同一批会话对齐记录。资源侧观察 KV 状态、总显存、主机内存和每轮耗时;任务侧同时记录检查项通过率、完整任务通过率及事实召回情况。尤其要保留随会话推进的变化曲线:一张最终显存截图,无法说明后半段任务还能否完成,也无法说明每轮等待时间是否增长。
时间同样属于这笔账。PACE 论文报告,相对 H2O,其 100K-token 实验的总墙钟时间增加约 9%。评估本地方案时,可以把缓存节省、任务通过率和耗时放在一起比较,再判断设备是否获得了可用的长会话能力。1[1]
对本地编码智能体而言,值得验收的是一条完整能力链:早先的信息能够留住,后续查询能够使用,生成的程序能够通过任务测试。PACE 的 Qwen3-8B 实验说明,规划引导保留与位置重编号分别修复了这条链上的不同环节。缓存占用告诉我们设备承受了多少状态,执行结果告诉我们这些状态最终完成了什么。