SepLLM让KV再次被砍价

本文摘要

SepLLM(Separator LLM)基于一个简单但强有力的观察:自然语言中的分隔符(如逗号、句号、换行等)在注意力中常充当信息汇聚点。本文方法在训练/预填充阶段通过 INS 稀疏可见性 强化这一现象:每个 token 仅关注 I(起始 attention sinks)、S(全部历史分隔符)与 N(最近邻若干个)三类关键位置,迫使段落信息被“压缩”到分隔符 token 的 KV 上;推理阶段据此仅保留 I/S/N 的 KV,以此达到原生稀疏注意力与 KV 压缩的统一。
在 Llama‑3‑8B 等模型与多项任务上,SepLLM 在几乎不损失精度的情况下将 KV 缓存减少 >50%;流式长上下文可在有限缓存下稳定处理 ≥4M tokens。训练端在达到相同损失时,计算量降低 28%、训练时间降低 26%、吞吐提升至 1.53×。方法既可作为 training‑free 的 SepCache 直接接入推理侧,也可用于从零训练或后训练,显著提升训练—推理一致性。与 H2O、StreamingLLM、SnapKV 等推理期 KV 选择方法相比,SepLLM 的语义分段与分隔符承载机制在效率、稳定性与可扩展性上展现出优势。

1. 这项工作想解决什么问题?

当 LLM 需要处理很长的上下文时,两件事最吃紧:

  • 显存 / 内存占用:KV 缓存在长度 (L) 上是线性累积的;
  • 计算开销:注意力要不断与“全部历史”交互,推理时延随上下文拉长。

很多工作(H2O、StreamingLLM、SnapKV 等)都在“推理期选择/舍弃部分 KV”。SepLLM 的关键不同在于:

  • 从语言规律出发,提前把信息“压”到少量关键 token(分隔符)上
  • 训练—推理一致:不是到推理时才决定丢谁,而是让模型在训练阶段就学会“把段落语义放到分隔符里”。

这让 SepLLM 既能做成 训练期的原生稀疏注意力,也能做成 推理期的即插即用缓存(SepCache),两条路都能走。


2. 方法核心:INS 稀疏注意力

2.1 观察

在多种模型/层的注意力可视化中,逗号、句号、分号、问号等分隔符 token 的注意力权重普遍偏高。这意味着“片段信息可以被这些分隔符很好地代表”。

2.2 稀疏可见性(训练/预填充)

为让信息真的被“挤”进分隔符,SepLLM 在训练或预填充阶段使用特定的注意力掩码:当前 token 只允许看三类 token:

  1. I:序列最前面的若干 attention sinks(如 BOS + 若干虚拟槽位);
  2. S:到当前为止,历史上所有出现过的分隔符 token
  3. N最近邻的 (n) 个 token(保证局部细节不丢)。

其它远处 token 被遮蔽,模型被迫把每段的关键信息“存放”到相应的分隔符 token 上。

2.3 推理与缓存

推理阶段据此 只在 KV 中保留 I/S/N 三类 token

  • 分隔符的 KV 会长期保留(代表每段摘要);
  • 最近邻窗口滚动保留;
  • 其余普通 token 的 KV 可以安全丢弃,从而显著降低显存与计算。

2.4 流式(Streaming‑SepLLM)

为适配无限长输入,采用四块缓存与周期性压缩,并配合位置编码平移。

2.4.1 四块缓存与变量
  • Initial Cache:attention sink,容量 a;
  • Local Window Cache:近邻滑窗,容量 w;
  • Past Window Cache:近邻溢出后的过渡区,压缩前暂存普通 KV;
  • Separator Cache:分隔符专用区,容量 s。

维护量:Size_init、Size_local_w、Size_past_w、Size_sep;运行期总占用 Size_run = 这四者之和,需满足 Size_run ≤ c(c 表示运行期 KV 缓存的总容量上限(token 级配额))。当前最近邻大小 n = Size_past_w + Size_local_w。约束关系:a + s + w < c;触顶时有 Size_past_w + Size_sep ≤ c − a − w。Past 与 Separator 共用同一物理区域,压缩时把 Past 中的分隔符 KV 迁入 Separator,其他丢弃。

2.4.2 迭代流程
  1. 先填 Initial 到 a,再填 Local 到 w;
  2. Local 满后新 token 进 Past;
  3. 未触顶时持续追加,n 线性增长;
  4. 触顶时压缩:迁入分隔符 KV、丢弃非分隔符、Past 清空;若 Separator 超过 s,淘汰最早分隔符,保留最近 s 个;
  5. 循环上述过程。Separator 第一次装满后,n 在区间 [w, c − a − s] 内呈现“增长 → 压缩回落 → 再增长”的周期性震荡。
2.4.3 平均占用
  • 平均 n(序列无限长):(w + (c − a − s)) / 2。
  • 平均 Size_run:平均 n + a + s = (w + c + a + s) / 2,小于 c,保证系统在固定容量下稳定运行。
2.4.4 位置编码

采用基于缓存位置的相对或旋转位置编码平移策略,随缓存滑动重映射相对位置,保证注意力对准缓存中的相对距离。

2.4.5 分隔符集合

默认集合可写作:[点号、逗号、问号、感叹号、分号、冒号、空格、TAB、换行]。中文可加入“,。;?!、”及换行,或设置自定义段落/代码块分隔符。

2.4.6 参数映射(以 SepCache 为例)

cache_size→c,init_cache_size→a,local_size→w,sep_cache_size→s,neighbor_window→n。可开启 USE_MAX_SEP_CACHE,仅保留最新 s 个分隔符;SEP_ACCUMULATION、SEP_PADDING_IN_BATCH 控制历史累计与 batch 对齐。

3. 关键效果(论文报告)

  • KV 缓存:在 Llama‑3‑8B 上跑 GSM8K‑CoT,KV 大小减少 > 50%,准确率几乎不变。
  • 流式长序列:能稳定处理 ≥ 4,000,000 tokens 的输入,语言建模性能保持稳定。
  • 训练端:达到相同 loss 时,计算量 −28%训练时间 −26%,吞吐 ×1.53;同规模算力下更快收敛。
  • 跨模型泛化:在 Pythia、Llama‑3、Falcon‑40B 等多架构上验证,困惑度、吞吐与 r.KV 指标均优。

注:论文观点,本人并未尝试!


4. 与相关工作的对比

方法思路训练参与推理侧改动长序列能力典型优点可能限制
SepLLM把片段信息压到分隔符;只保留 I/S/Nfrom-scratch / post‑training;也支持 training‑freeSepCache需要使用 SepCache 或配套稀疏注意力实现流式可达 4M+KV 减半+、一致性强、推理/训练皆加速对分隔符稀少/结构不规则文本,需调 邻近窗口 n 等超参
H2O高熵优先保留训练后仅推理期 KV 选择简单通用与模型训练分离,一致性较弱
StreamingLLM利用 Attention Sink,丢弃远处普通 token训练后仅推理期实现成熟,思路清晰依赖 sink 与距离启发式
SnapKV生成前快照 query,选“相关” KV训练后仅推理期相关性选择更精细需要额外一次匹配计算

上表为作者理解下的简化对照,供入门者快速定位差异。


H2O 并不是笔误,不是水,而是 “Heavy‑Hitter Oracle” 的缩写,是一套在推理阶段压缩/淘汰 KV 缓存的策略:用注意力得分找出贡献最大的少数 “重击手(heavy hitters)” token,并长期保留它们的 KV,同时也保留一部分最近 token;其余就可以丢弃,从而省显存、提吞吐。

5. 快速上手:两种路径

5.1 直接用 SepCache(training‑free)

适合先尝试就绪的推理加速。以 Llama‑3.1‑8B‑Instruct 为例:

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM

model_id = "meta-llama/Meta-Llama-3.1-8B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    torch_dtype=torch.bfloat16,
    device_map="auto",
)

prompt = "请用三句话介绍SepLLM的核心思想。"
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)

# 方式 A:Transformers 内置(当版本已集成时)
# from transformers import SepCache
# cache = SepCache(model.config, tokenizer=tokenizer)
# outputs = model.generate(**inputs, max_new_tokens=256, cache_implementation=cache)

# 方式 B:Hugging Face 自定义 generate(社区实现)
outputs = model.generate(
    **inputs,
    max_new_tokens=256,
    custom_generate="Gausson/sep_cache",  # 或 "transformers-community/sep_cache"
    # 关键超参(可按场景调整)
    sep_cache_config={
        "neighbor_window": 64,   # 最近邻窗口 N
        "max_separators": 4096,  # 分隔符容量上限
        "padding_id": tokenizer.eos_token_id,
    },
)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

依赖:transformers >= 4.53.0。首次尝试建议从 neighbor_window=64 起步,再按延迟/效果折中微调。

5.2 作为原生稀疏注意力训练/后训练

  • 若你要 从零训练,可在各层应用 INS 稀疏掩码;
  • 若你要 对现有模型后训练(继续预训练 / SFT / DPO),确保训练期也使用相同的 INS 掩码,以减小与推理的不一致;
  • 训练内核可配合 PyTorch FlexAttention 等高效实现,易于自定义注意力模式。

6. 实践建议

  1. 分隔符定义:中英文标点、换行、特殊分隔 token 都可以纳入;对代码/日志类文本,可自定义“分号、花括号、换行”等为分隔符。
  2. 邻近窗口(N):任务越依赖近场细节,N 越要大;一旦 N 过小,可能导致细粒度信息丢失、困惑度上升。
  3. 分隔符容量:流式场景中要给分隔符缓存足够空间;若容量打满,要设计迁移/淘汰策略(论文已有实现)。
  4. 评测维度:除准确率/困惑度外,务必记录 r.KV(KV 保留率)GPU 端到端时延吞吐峰值显存,对比基线更直观。
  5. 与现有优化叠加:PagedAttention、GQA、Flash/FlexAttention、量化、FP8、张量并行等都可以协同;不过要逐项 A/B,避免优化“相互抵消”。

7. 局限与开放问题

  • 语体依赖:SepLLM 对“分隔符清晰”的文本受益最大;对于分隔符稀缺或结构极不规则的输入(如部分代码、表格、拼接数据),需要调大 N 或引入自定义分隔符策略。
  • 跨语言与多模态:不同语言的标点、语法差异较大;多模态场景(如图文)如何定义“分隔符”与层级摘要,仍有探索空间。
  • 与检索/记忆模块的协同:分隔符承载了段落级摘要,或许能与 RAG/外部记忆更自然地结合,作为轻量“局部摘要器”。
  • 安全与对齐:当重要细节被过度压缩到少量 token,上下文攻击/绕过是否更容易?需要专门评测。

8. 参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值