kvpress
kvpress 是一款专为优化大语言模型长文本处理而设计的开源工具,旨在让 KV 缓存压缩变得简单高效。在处理百万级 token 的超长上下文时,传统 Transformer 模型的键值(KV)缓存会线性增长,导致显存需求激增(例如 Llama 3.1-70B 处理 1M token 需高达 330GB 内存),这使得部署成本极高且难以落地。kvpress 通过集成多种先进的压缩算法,在模型预填充阶段甚至生成过程中动态压缩缓存,显著降低显存占用,同时尽量保持模型回答的准确性。
该工具特别适合 AI 研究人员和开发者使用。它基于 🤗 transformers 生态构建,提供了便捷的管道接口,用户只需几行代码即可调用如“期望注意力压缩”等策略,无需深入底层实现就能快速验证新算法或部署长上下文应用。此外,kvpress 还创新性地支持实验性的“解码期压缩”功能,允许在文本生成过程中周期性清理缓存,进一步突破长度限制。无论是希望降低推理成本的工程师,还是致力于探索更高效压缩机制的研究者,kvpress 都提供了一个灵活、易用的基准平台,助力长上下文大模型的普及与优化。
使用场景
某法律科技团队正在构建基于 Llama 3.1-70B 的智能合同审查系统,需要让模型一次性读取并分析长达数十万字的复杂并购协议。
没有 kvpress 时
- 显存成本极高:处理百万级 token 上下文时,仅 KV 缓存就需要占用高达 330GB 显存,迫使团队租用昂贵的多卡 A100/H100 集群。
- 推理延迟严重:随着文档长度增加,注意力机制的计算量线性增长,导致首字生成等待时间过长,无法满足实时交互需求。
- 部署门槛过高:巨大的内存需求使得在单卡消费级显卡或边缘设备上部署长文本模型成为不可能,限制了产品落地场景。
- 开发调试困难:研究人员尝试自定义压缩算法时,需深入修改底层 Transformer 代码,迭代周期长且容易引入错误。
使用 kvpress 后
- 显存占用骤降:通过 ExpectedAttentionPress 等策略在预填充阶段压缩缓存,将显存需求降低 50% 以上,单卡即可运行超长上下文任务。
- 推理速度提升:大幅减少了注意力计算的关键值对数量,显著缩短首字延迟,使长文档问答变得流畅自然。
- 部署灵活便捷:借助
kv-press-text-generation管道,无需改动模型架构即可轻松将长文本能力集成到现有服务中,甚至支持更轻量级的硬件。 - 算法验证高效:内置多种压缩基准和评分器,开发者可快速切换不同压缩策略(如 KNormPress)并对比效果,加速算法研发。
kvpress 通过高效的 KV 缓存压缩技术,打破了长上下文大模型的显存与速度瓶颈,让百亿参数模型在低成本硬件上处理百万字文档成为现实。
运行环境要求
- Linux
- macOS
- 需要 NVIDIA GPU(示例代码指定 device='cuda:0'),部分功能(如 FlashAttention)需特定硬件支持
- 显存需求取决于模型大小和上下文长度(原文示例:Llama 3.1-70B 处理 1M tokens 需 330GB,压缩可降低此需求)
未说明

快速开始

由于Transformer模型中的键值(KV)缓存呈线性增长,部署长上下文LLM的成本非常高。例如,使用Llama 3.1-70B以float16格式处理100万 tokens 需要高达330GB的内存。kvpress实现了多种KV缓存压缩方法,并基于🤗 Transformers进行了基准测试,旨在为该领域的研究人员和开发者简化新方法的开发流程。
安装
pip install kvpress
若需本地安装,请使用 uv:
git clone https://github.com/NVIDIA/kvpress.git
cd kvpress
uv sync
如需安装所有可选依赖项,请执行以下命令:
git clone https://github.com/NVIDIA/kvpress.git
cd kvpress
uv sync --extra eval --extra flash-attn
使用
KVPress提供了一系列在预填充阶段压缩KV缓存的“压缩器”。每个压缩器都关联有一个compression_ratio属性,用于衡量缓存的压缩程度。使用压缩器最简单的方式是通过我们自定义的KVPressTextGenerationPipeline。当导入kvpress时,它会自动注册为名为“kv-press-text-generation”的Transformers流水线,并为您处理聊天模板和分词:
from transformers import pipeline
from kvpress import ExpectedAttentionPress
model = "Qwen/Qwen3-8B"
pipe = pipeline("kv-press-text-generation", model=model, device_map="auto", dtype="auto")
context = "一段您希望一次性压缩的超长文本"
question = "\n关于压缩后上下文的一个问题" # 可选
press = ExpectedAttentionPress(compression_ratio=0.5)
answer = pipe(context, question=question, press=press)["answer"]
在上述代码片段中,压缩仅应用于上下文tokens,以便您可以针对不同问题评估压缩效果。更多详细示例请参阅Wikipedia笔记本演示,该演示也在Colab上提供此处。
解码阶段的压缩
默认情况下,KVPress会在预填充阶段应用压缩。作为一项新的(实验性)功能,我们现在支持通过`DecodingPress`包装器实现解码阶段的压缩。`DecodingPress`会在生成token的过程中定期压缩KV缓存,同时可以选择性地保留最近隐藏状态的缓冲区。`DecodingPress`支持以下参数:base_press: 任何ScorerPress(例如KNormPress、CriticalKVPress)compression_interval: 压缩之间的步数(默认:10)target_size: 压缩后缓存的目标大小(默认:1024)hidden_states_buffer_size: 压缩前需要缓冲的隐藏状态数量(默认:128)。某些压缩器不需要缓冲隐藏状态,可以将此值设为0。
与压缩比不同,解码压缩使用target_size来控制缓存的压缩程度。这意味着缓存会每隔compression_interval步进行一次压缩,而压缩比则会自动计算,以确保压缩后的缓存大小等于target_size。
解码压缩的示例:
from transformers import pipeline
from kvpress import KnormPress
from kvpress import DecodingPress
# 初始化流水线
device = "cuda:0"
model = "meta-llama/Llama-3.1-8B-Instruct"
model_kwargs = {"attn_implementation": "flash_attention_2"}
pipe = pipeline("kv-press-text-generation", model=model,device=device,model_kwargs=model_kwargs)
# 创建一个每10步压缩一次,目标缓存大小为512 tokens 的解码压缩器
decoding_press = DecodingPress(
base_press=KnormPress(),
compression_steps=10,
token_buffer_size=512
)
# 与流水线结合使用
context = "一段您希望在生成过程中压缩的超长文本"
question = "请根据这段上下文讲一个长故事"
response = pipe(context,question=question,press=decoding_press)["answer"]
并非所有现有压缩器都完全兼容
DecodingPress,因为解码阶段和预填充阶段的压缩机制存在根本差异。特别是,我们目前仅支持将ScorerPress用作基础压缩器。
可用的压缩器
当前所有的压缩器都不需要训练,并且都继承自 BasePress(源代码)。
其中,若干压缩器继承自 ScorerPress(源代码),它们依赖于一个分数来裁剪重要性最低的 KV 对:
RandomPress(源代码):随机分数KnormPress(源代码,论文):键的逆范数SnapKVPress(源代码,论文):最后查询的平均注意力权重ExpectedAttentionPress(源代码,笔记本):生成阶段的期望注意力权重StreamingLLMPress(源代码,论文):仅保留初始和最近的标记TOVAPress(源代码,论文):对所有头的最后查询注意力权重取平均ObservedAttentionPress(源代码,论文):在预填充阶段观察到的平均注意力权重QFilterPress(源代码,论文):将键表示投影到查询向量的主要奇异值分解成分上,以近似计算注意力分数。PyramidKVPress(源代码,论文):维持金字塔形的缓存大小,为较低层分配更多缓存预算,而为较高层分配较少。LagKVPress(源代码,论文):利用 KV 延迟相关信息进行压缩。它无需查询、无需注意力权重,且兼容 Flash Attention。KeyDiffPress(源代码,论文):仅根据键的相似性驱逐标记。NonCausalAttnPress(源代码,论文):基于非因果分块注意力分数驱逐标记。LeverageScorePress(源代码,论文):根据近似的统计杠杆度驱逐标记(即保留键空间中的异常值)。CompactorPress(源代码,论文):根据压缩比混合使用NonCausalAttnPress和LeverageScorePress。CURPress(源代码,论文):基于 CUR 分解和近似杠杆度分数修剪键和值。KVzapPress(源代码,论文,训练):通过快速代理模型近似 KVzip+。需与DMSPress配合使用。FastKVzipPress(源代码,论文):通过轻量级门控机制近似 KVzip。
还有一些压缩器采用不同的逻辑:
ThinKPress(源代码,论文):根据最后查询上的通道注意力分数压缩键的维度。SimLayerKVPress(源代码,论文):识别“懒惰”层,并对其应用 StreamingLLM 方法。DuoAttentionPress(源代码,论文):将注意力头分为检索头(不压缩)和流式头(采用 StreamingLLM 方法)。FinchPress(源代码,论文):类似于 SnapKV,但具有动态窗口大小和键值重旋转。KVzipPress(源代码,论文):通过上下文重建识别冗余的 KV 对。以多次前向传播为代价,实现近乎无损的压缩。
最后,我们提供了一些可以与其他压缩器组合使用的包装型压缩器:
AdaKVPress(源代码,论文):裁剪任何ScorerPress的底部分数,但跨所有头执行,从而实现按头的压缩。PerLayerCompressionPress(源代码):为每一层使用不同的压缩比进行压缩(实验性功能)。ComposedPress(源代码):通过串联多个压缩器的前向钩子将其组合在一起。KeyRerotationPress(源代码):对已压缩的键进行重新旋转,以保持连续的 RoPE 嵌入。ChunkKVPress(源代码,论文):通过选择重要区块进行压缩,同时保持语义连贯性。ChunkPress(源代码,论文):分别对每个序列区块的 KV 缓存进行压缩。这可以在长序列中实现更均匀的压缩效果。CriticalKVPress和CriticalAdaKVPress(源代码,论文):利用 Wo @ 值的 L1 范数细化分数,并结合两阶段选择机制。BlockPress(源代码,论文):将输入序列划分为不重叠的块,并迭代式地进行压缩(⚠️ 并非真正的分块预填充实现)。DecodingPress(源代码):允许在解码过程中进行压缩,请参阅本 README 中的解码部分。PrefillDecodingPress(源代码):允许在预填充和解码过程中同时进行压缩。DMSPress(源代码,论文):对于任何ScorerPress,驱逐分数低于给定阈值的键和值,而不是依赖于 top-k 分数。支持预填充和解码(若 decoding=True),但仅支持密集预填充,不支持稀疏预填充。
有关现有 KV 缓存压缩方法的详细列表,请参阅 Awesome-KV-Cache-Compression 或 Awesome-LLM-Compression。
评估
我们提供了一个简单的命令行界面,用于在多个长上下文数据集上评估不同压缩方法的性能。
- 准确性:使用我们的 CLI 直接在流行的基准测试上测试您的方法。
- 速度与内存:speed_and_memory 笔记本可以帮助您测量峰值内存使用量和总时间节省。
有关更多详细信息和结果,请参阅此仓库中的 evaluation 目录。
以下是我们从 报告的不同压缩方法在 RULER 数据集中、4k 上下文长度下的平均性能。
量化
我们通过 transformers 的 QuantizedCache 类支持 KV 缓存量化(参见 HF 博客文章)。要使用它,只需将缓存对象传递给您的管道:
from transformers import QuantizedCache
cache = QuantizedCache(backend="quanto", nbits=4)
pipe(..., cache=cache)
默认情况下,使用的是 DynamicCache(不进行量化)。
[!重要]
要使用QuantizedCache, 您需要安装额外的依赖项(例如pip install optimum-quanto)。
贡献
我们欢迎贡献!要添加新的压缩方法,只需打开一个问题或提交拉取请求。请查看 new_press.ipynb 笔记本,获取分步指南。
引用
如果您在研究中使用 KVPress,请引用我们的论文:
@article{devoto2025expectedattention,
title={Expected Attention: KV Cache Compression by Estimating Attention from Future Queries Distribution},
author={Devoto, Alessio and Jeblick, Maximilian and J{\'e}gou, Simon},
journal={arXiv preprint arXiv:2510.00636},
year={2025},
url={https://arxiv.org/abs/2510.00636}
}
常见问题解答
支持哪些模型?
某些压缩方法依赖于模型架构(例如 ExpectedAttentionPress 或 SnapKVPress),因此可能无法适用于所有模型。我们已测试了对 LlamaForCausalLM、MistralForCausalLM、Phi3ForCausalLM、Qwen2ForCausalLM、Qwen3ForCausalLM 和 Gemma3ForCausalLM 的支持,但由于这些模型在 transformers 中的实现通常相似,许多其他模型也可能开箱即用地得到支持。
如何在多 GPU 上运行推理?
kvpress 通过 accelerate 支持多 GPU 推理:
pipe = pipeline("kv-press-text-generation", model=model, device_map="auto")
内存和吞吐量的提升是多少?
内存使用量应减少大约 compression_ratio * kv_cache_size。由于 KV 缓存更小,解码速度也会更快。您可以使用 this notebook 测量峰值内存使用量的提升和总时间节省。
压缩方法是如何工作的?
压缩方法会在预填充阶段为每个注意力层注册一个前向钩子(press.forward_hook 方法)。注册可以通过将压缩方法作为上下文管理器(press.__call__ 方法)来应用:
import torch
from transformers import AutoModelForCausalLM
from kvpress import KnormPress
device = "cuda:0"
ckpt = "meta-llama/Meta-Llama-3.1-8B-Instruct"
model = AutoModelForCausalLM.from_pretrained(ckpt).to(device)
press = KnormPress(compression_ratio=0.4)
inputs = model.dummy_inputs["input_ids"].to(device)
with torch.no_grad():
print(model(inputs).past_key_values[0][0].shape)
# torch.Size([3, 8, 5, 128])
with torch.no_grad(), press(model):
print(model(inputs).past_key_values[0][0].shape)
# torch.Size([3, 8, 3, 128])
为什么不直接使用 model.generate?
实际上,您也可以通过将压缩方法作为上下文管理器来配合 model.generate 使用:
with press(model):
outputs = model.generate(inputs)
然而,generate 方法无法将问题部分排除在压缩之外,这会人为地偏向像 SnapKV 这样的方法。理想情况下,我们希望有一种无论后续内容如何都能有效工作的压缩方法(例如用于聊天或文档问答等场景)。此外,generate 方法也不支持同时生成多个问题的回答。
</details。
我可以结合预填充和解码阶段的压缩吗?
结合预填充和解码阶段的独立压缩方法。
参数:
prefilling_press: 预填充阶段使用的压缩方法decoding_press: 解码阶段使用的压缩方法
使用示例
基本解码压缩
from transformers import pipeline
from kvpress import KnormPress
from kvpress import DecodingPress
# 初始化管道
device = "cuda:0"
model = "meta-llama/Llama-3.1-8B-Instruct"
model_kwargs = {"attn_implementation": "flash_attention_2"}
pipe = pipeline("kv-press-text-generation", model=model, device=device, model_kwargs=model_kwargs)
# 创建一个每 10 步压缩到 512 个 token 的解码压缩方法
decoding_press = DecodingPress(
base_press=KnormPress(),
compression_steps=10,
token_buffer_size=512
)
# 与管道一起使用
context = "一段非常长的文本,您希望在生成过程中对其进行压缩"
question = "请根据这段上下文讲一个长故事"
response = pipe(context, question=question, press=decoding_press)["answer"]
预填充 + 解码联合压缩
from transformers import pipeline
from kvpress import CriticalKVPress、KnormPress
from kvpress import DecodingPress、PrefillDecodingPress
# 初始化管道
device = "cuda:0"
model = "meta-llama/Llama-3.1-8B-Instruct"
model_kwargs = {"attn_implementation": "flash_attention_2"}
pipe = pipeline("kv-press-text-generation", model=model, device=device, model_kwargs=model_kwargs)
# 预填充和解码采用不同的策略
prefill_press = CriticalKVPress(KnormPress())
decoding_press = DecodingPress(
base_press=KnormPress(compression_ratio=0.2),
compression_steps=5,
token_buffer_size=256
)
# 将两者结合
combined_press = PrefillDecodingPress(
prefilling_press=prefill_press,
decoding_press=decoding_press
)
context = "一段非常长的上下文,将在预填充阶段被压缩"
question = "生成一份详细的分析报告,该报告将在解码阶段被压缩"
response = pipe(context,question=question,press=combined_press)["answer"]
版本历史
v0.5.22026/04/01v0.5.12026/02/16v0.5.02026/01/28v0.4.32026/01/27v0.4.22026/01/21v0.4.12026/01/14v0.4.02025/12/05v0.3.02025/09/04v0.2.102025/08/06v0.2.92025/07/28v0.2.82025/07/08v0.2.72025/07/07v0.2.62025/06/16v0.2.52025/04/17v0.2.42025/03/17v0.2.32025/02/18v0.2.22025/02/12v0.2.12025/01/21v0.2.02025/01/13v0.1.12025/01/07常见问题
相似工具推荐
openclaw
OpenClaw 是一款专为个人打造的本地化 AI 助手,旨在让你在自己的设备上拥有完全可控的智能伙伴。它打破了传统 AI 助手局限于特定网页或应用的束缚,能够直接接入你日常使用的各类通讯渠道,包括微信、WhatsApp、Telegram、Discord、iMessage 等数十种平台。无论你在哪个聊天软件中发送消息,OpenClaw 都能即时响应,甚至支持在 macOS、iOS 和 Android 设备上进行语音交互,并提供实时的画布渲染功能供你操控。 这款工具主要解决了用户对数据隐私、响应速度以及“始终在线”体验的需求。通过将 AI 部署在本地,用户无需依赖云端服务即可享受快速、私密的智能辅助,真正实现了“你的数据,你做主”。其独特的技术亮点在于强大的网关架构,将控制平面与核心助手分离,确保跨平台通信的流畅性与扩展性。 OpenClaw 非常适合希望构建个性化工作流的技术爱好者、开发者,以及注重隐私保护且不愿被单一生态绑定的普通用户。只要具备基础的终端操作能力(支持 macOS、Linux 及 Windows WSL2),即可通过简单的命令行引导完成部署。如果你渴望拥有一个懂你
stable-diffusion-webui
stable-diffusion-webui 是一个基于 Gradio 构建的网页版操作界面,旨在让用户能够轻松地在本地运行和使用强大的 Stable Diffusion 图像生成模型。它解决了原始模型依赖命令行、操作门槛高且功能分散的痛点,将复杂的 AI 绘图流程整合进一个直观易用的图形化平台。 无论是希望快速上手的普通创作者、需要精细控制画面细节的设计师,还是想要深入探索模型潜力的开发者与研究人员,都能从中获益。其核心亮点在于极高的功能丰富度:不仅支持文生图、图生图、局部重绘(Inpainting)和外绘(Outpainting)等基础模式,还独创了注意力机制调整、提示词矩阵、负向提示词以及“高清修复”等高级功能。此外,它内置了 GFPGAN 和 CodeFormer 等人脸修复工具,支持多种神经网络放大算法,并允许用户通过插件系统无限扩展能力。即使是显存有限的设备,stable-diffusion-webui 也提供了相应的优化选项,让高质量的 AI 艺术创作变得触手可及。
everything-claude-code
everything-claude-code 是一套专为 AI 编程助手(如 Claude Code、Codex、Cursor 等)打造的高性能优化系统。它不仅仅是一组配置文件,而是一个经过长期实战打磨的完整框架,旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。 通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能,everything-claude-code 能显著提升 AI 在复杂任务中的表现,帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略,使得模型响应更快、成本更低,同时有效防御潜在的攻击向量。 这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库,还是需要 AI 协助进行安全审计与自动化测试,everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目,它融合了多语言支持与丰富的实战钩子(hooks),让 AI 真正成长为懂上
ComfyUI
ComfyUI 是一款功能强大且高度模块化的视觉 AI 引擎,专为设计和执行复杂的 Stable Diffusion 图像生成流程而打造。它摒弃了传统的代码编写模式,采用直观的节点式流程图界面,让用户通过连接不同的功能模块即可构建个性化的生成管线。 这一设计巧妙解决了高级 AI 绘图工作流配置复杂、灵活性不足的痛点。用户无需具备编程背景,也能自由组合模型、调整参数并实时预览效果,轻松实现从基础文生图到多步骤高清修复等各类复杂任务。ComfyUI 拥有极佳的兼容性,不仅支持 Windows、macOS 和 Linux 全平台,还广泛适配 NVIDIA、AMD、Intel 及苹果 Silicon 等多种硬件架构,并率先支持 SDXL、Flux、SD3 等前沿模型。 无论是希望深入探索算法潜力的研究人员和开发者,还是追求极致创作自由度的设计师与资深 AI 绘画爱好者,ComfyUI 都能提供强大的支持。其独特的模块化架构允许社区不断扩展新功能,使其成为当前最灵活、生态最丰富的开源扩散模型工具之一,帮助用户将创意高效转化为现实。
markitdown
MarkItDown 是一款由微软 AutoGen 团队打造的轻量级 Python 工具,专为将各类文件高效转换为 Markdown 格式而设计。它支持 PDF、Word、Excel、PPT、图片(含 OCR)、音频(含语音转录)、HTML 乃至 YouTube 链接等多种格式的解析,能够精准提取文档中的标题、列表、表格和链接等关键结构信息。 在人工智能应用日益普及的今天,大语言模型(LLM)虽擅长处理文本,却难以直接读取复杂的二进制办公文档。MarkItDown 恰好解决了这一痛点,它将非结构化或半结构化的文件转化为模型“原生理解”且 Token 效率极高的 Markdown 格式,成为连接本地文件与 AI 分析 pipeline 的理想桥梁。此外,它还提供了 MCP(模型上下文协议)服务器,可无缝集成到 Claude Desktop 等 LLM 应用中。 这款工具特别适合开发者、数据科学家及 AI 研究人员使用,尤其是那些需要构建文档检索增强生成(RAG)系统、进行批量文本分析或希望让 AI 助手直接“阅读”本地文件的用户。虽然生成的内容也具备一定可读性,但其核心优势在于为机器
LLMs-from-scratch
LLMs-from-scratch 是一个基于 PyTorch 的开源教育项目,旨在引导用户从零开始一步步构建一个类似 ChatGPT 的大型语言模型(LLM)。它不仅是同名技术著作的官方代码库,更提供了一套完整的实践方案,涵盖模型开发、预训练及微调的全过程。 该项目主要解决了大模型领域“黑盒化”的学习痛点。许多开发者虽能调用现成模型,却难以深入理解其内部架构与训练机制。通过亲手编写每一行核心代码,用户能够透彻掌握 Transformer 架构、注意力机制等关键原理,从而真正理解大模型是如何“思考”的。此外,项目还包含了加载大型预训练权重进行微调的代码,帮助用户将理论知识延伸至实际应用。 LLMs-from-scratch 特别适合希望深入底层原理的 AI 开发者、研究人员以及计算机专业的学生。对于不满足于仅使用 API,而是渴望探究模型构建细节的技术人员而言,这是极佳的学习资源。其独特的技术亮点在于“循序渐进”的教学设计:将复杂的系统工程拆解为清晰的步骤,配合详细的图表与示例,让构建一个虽小但功能完备的大模型变得触手可及。无论你是想夯实理论基础,还是为未来研发更大规模的模型做准备