推理:上下文压缩与 KV 内存管理

推理:上下文压缩与 KV 内存管理

Charles Lv7

长上下文系统的真正瓶颈,常常不是模型参数,而是历史上下文如何存、如何压、何时丢。一旦请求从 4k 扩到 32k128k 甚至更长,KV cache 显存、prefill 开销和检索拼接策略都会迅速成为主问题。

长上下文系统的本质,不是把窗口一味做大,而是把记忆管理做成系统工程。

初学者先抓住

长上下文不等于“模型记性无限好”。窗口越长,prefill 越贵,KV cache 越大,历史噪声越多。真正可靠的系统会区分当前必需信息、可摘要信息、可检索信息和可丢弃信息。

有趣例子:整理会议纪要

一场三小时会议不应该把逐字稿全部塞进下一次讨论。更好的做法是保留决策、待办、约束和争议点,把闲聊和已废弃方案降级或归档。上下文压缩和 KV 淘汰也是在做类似的记忆整理。

vLLM logical and physical block table 原论文图

图源:Efficient Memory Management for Large Language Model Serving with PagedAttention,Figure 5。原论文图意:vLLM 用 block table 把 logical KV blocks 翻译到 physical KV blocks,使请求的 KV cache 不必连续存放。

图解:长上下文的第一问题是 KV 放在哪

这张图把“上下文很长”落到内存管理问题上:每段历史 token 生成的 KV 都要有物理存放位置。logical block 保持序列语义顺序,physical block 负责实际显存布局。理解了这个映射,后面看 KV eviction、prefix cache、swap、CPU/GPU 分层和多租户隔离会更自然。

长上下文为什么贵

KV cache 大小近似随序列长度线性增长:

MKV2BLTHdhbM_{\text{KV}} \sim 2\cdot B\cdot L\cdot T\cdot H\cdot d_h\cdot b

其中 BB 是并发数,LL 是层数,TT 是上下文长度,HH 是头数,dhd_h 是每头维度,bb 是每元素字节数。

长度翻倍,缓存几乎翻倍;模型越深、头越多、精度越高,缓存越贵。权重量化只能解决参数显存,不会自动解决 KV 增长。

Prefill 和 decode 的问题也不同:prefill 是一次性处理大量 token,计算和带宽压力高;decode 每步新增 token 少,但历史 KV 持续存在并影响每一步注意力。

上下文不是越长越有用

很多真实请求里,大量历史 token 对当前回答边际价值很低。企业助手长对话中可能保留了寒暄、重复确认、旧工具日志和已修正的错误中间结论;真正有价值的是最新目标、关键约束、已确认事实和当前工具状态。

因此上下文管理本质是一种记忆选择问题:

  1. 哪些内容必须高保真保留;
  2. 哪些内容可以摘要;
  3. 哪些内容可以转入外部记忆;
  4. 哪些内容可以丢弃;
  5. 哪些内容需要结构化而不是自然语言化。

好的长上下文系统不是“什么都记”,而是“记得有层次”。

压缩方式

方法 优点 风险
摘要压缩 简单、可读、适合纯文本对话 丢细节、摘要幻觉、约束模糊
结构压缩 保留目标、事实、工具状态、待办 需要 schema 和状态更新逻辑
向量检索 历史不必常驻上下文,可扩展 召回漏检或错召回会造成失忆
Token 级压缩 直接减少序列长度 压缩标准不稳,工程复杂
Learned memory 模型学习保留关键状态 可解释性和回归更难

Agent 系统通常更适合结构压缩,因为很多记忆不是故事,而是程序状态:哪个工具调用过、API 返回什么、网页表单填到哪里、哪些约束仍未满足。纯自然语言摘要很容易把动作状态压没。

KV 淘汰

如果显存有限,就必须淘汰或降级。可以把每段记忆看成有价值 uiu_i 和成本 cic_i,在预算 BB 内保留最大价值集合:

maxSiSuis.t.iSciB\max_{S}\sum_{i\in S}u_i \quad \text{s.t.} \quad \sum_{i\in S}c_i\le B

常见策略包括:

  1. FIFO:实现简单,但可能丢掉早期关键约束;
  2. 最近窗口:适合局部对话,但不适合长任务记忆;
  3. Attention-aware:按历史注意力或重要度保留,但计算和稳定性更复杂;
  4. Role-aware:系统 prompt、用户目标、工具结果优先;
  5. Segment-aware:按文档、回合、工具调用块淘汰;
  6. Risk-aware:高风险约束和安全相关状态强保留。

KV 淘汰不是纯缓存问题,它会影响回答质量和任务一致性。任何 eviction 策略都需要任务级回归。

内存分层

长上下文系统应有多层记忆:

层级 保存什么 访问特点
Prompt 内上下文 当前任务最关键 token 最贵但最可靠
KV cache 已 prefill 的历史 token 表示 decode 依赖,显存敏感
结构化状态 目标、约束、工具状态、事实表 低成本、可控、适合 agent
向量库/检索 长期历史和外部知识 召回质量决定效果
冷存储日志 全量历史、审计、复盘 不参与实时推理

设计目标是让高价值信息留在高成本层,低频或低置信信息退到低成本层。把所有东西都塞进 prompt,是最简单但通常最贵的方案。

质量风险

上下文压缩和 KV 淘汰常见失败包括:

  1. 关键约束被摘要丢失;
  2. 旧错误被压缩后变成“已确认事实”;
  3. 检索漏召回导致模型忘记重要背景;
  4. KV eviction 丢掉跨轮引用;
  5. 工具状态和自然语言上下文不一致;
  6. 压缩策略在短任务上没问题,长任务中累计漂移。

因此需要专门构造长任务回归:多轮约束保持、工具状态一致性、旧事实更正、跨文档引用、长会话恢复和安全约束保留。

评测与指标

建议同时看系统指标和任务指标:

  1. prefill token 节省量;
  2. KV 显存占用、碎片率、eviction 次数;
  3. 压缩后 token 数和压缩耗时;
  4. 检索召回率、错召回率、漏召回率;
  5. 多轮任务成功率;
  6. 约束保持率和事实一致性;
  7. p50/p95/p99 延迟;
  8. 出错时是否能追溯到哪一层记忆丢失。

长上下文优化不能只看“能塞多长”。真正的验收是:在固定显存和延迟预算下,系统是否更可靠地保留了对当前决策有用的记忆。

工程上建议把压缩策略、检索策略和 KV 淘汰策略都做成可回放配置。出现质量问题时,能够复现当时哪些内容被保留、哪些内容被摘要、哪些内容被淘汰,比单纯查看最终 prompt 更有排障价值。

如果系统面向多租户或企业场景,还要把记忆层级与权限系统绑定。被压缩或转入外部记忆的内容仍然可能包含敏感信息,不能因为它不在当前 prompt 里,就忽略审计、过期和删除策略。

真实排查案例:KV 淘汰省了显存,答案开始忘约束

输入症状:长会话 agent 接入激进 KV eviction 后,单机并发提升 35%,但多轮任务中“必须使用指定工具”“不能覆盖原文件”等约束遵守率下降。

关键指标:KV 显存水位下降,eviction 次数上升;平均延迟改善,但第 8 轮以后的任务成功率下降;错误集中在跨轮约束和工具状态一致性。

Nsight / trace 观察:系统 trace 显示 eviction 在 decode 前频繁触发,GPU kernel 没有异常;回放 prompt 发现自然语言摘要保留了目标,却丢掉了约束来源和工具状态版本。

判断:这是记忆层级策略问题,不是模型能力突然下降。KV 淘汰把对当前决策仍然关键的信息移出了高保真状态,摘要层又没有承接足够结构化约束。

修复:把约束、权限、工具状态从普通文本摘要中拆成结构化 memory;KV eviction 按“决策相关性”而非单纯时间淘汰;长会话回归集加入约束保持率、工具状态一致性和旧事实更正。

反例:如果任务是单轮长文档摘要,且关键证据已经被检索片段覆盖,激进上下文压缩可能很划算。多轮 agent 和机器人闭环则不能只按 token 节省量判断。

  • Title: 推理:上下文压缩与 KV 内存管理
  • Author: Charles
  • Created at : 2025-07-25 09:00:00
  • Updated at : 2025-07-25 09:00:00
  • Link: https://charles2530.github.io/2025/07/25/ai-files-inference-context-compression-kv-eviction-and-memory-hierarchies/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments