Gavin-chen commited on
Commit
2763b42
·
verified ·
1 Parent(s): 1b5c481

Upload README.zh.md

Browse files
Files changed (1) hide show
  1. README.zh.md +123 -0
README.zh.md ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ library_name: transformers
3
+ license: apache-2.0
4
+ tags:
5
+ - qwen-compress
6
+ - kv-cache
7
+ - compression
8
+ - qwen
9
+ - model-merging
10
+ - efficiency
11
+ datasets:
12
+ - gsm8k
13
+ - ifeval
14
+ ---
15
+
16
+ # Qwen-Compress:可學習加權平均實現 KV Cache 壓縮
17
+
18
+ **一種即插即用的 KV cache 壓縮方法,在每隔 4 層的 Transformer 層之間透過可學習的加權平均選擇性壓縮 hidden states,在不重新訓練基礎模型的情況下,將 prefill KV 大小減少最高約 4 倍。**
19
+
20
+ ## 概述
21
+
22
+ 標準的自迴歸 Transformer 需要**與 prefill 總長度成正比的 KV cache 成本**。Qwen-Compress 在特定層插入小型 **`HiddenStateCompressor`** 模組來緩解這個問題。每個 compressor 執行 **可學習的加權平均**:透過 learned linear projection 為每個 token 計算重要性分數,然後在連續 `ratio=4` 個 token 的滑動視窗上做 softmax,加權求和後將 4 個 token 壓縮成 1 個。同時保留最後 `window_size=128` 個 token 不做壓縮(tail retention)。
23
+
24
+ 關鍵洞察:在 hidden states **進入 compressor 層的 attention QKV projection 之前**進行壓縮。下游層透過正確的旋轉位置編碼(RoPE)索引來關注壓縮後的 KV 位置,避免位置錯配。
25
+
26
+ ### 靈感來源
27
+
28
+ 本專案受 **DeepSeek 的壓縮注意力機制**(DeepSeek-V4 使用)啟發。Qwen-Compress 將此概念適配到 Qwen 架構,並加入了逐序列壓縮排程與解碼階段 buffer 管理。
29
+
30
+ ## 架構
31
+
32
+ ### Compressor 模組
33
+
34
+ 一個 `HiddenStateCompressor` 是輕量級的可學習加權層:
35
+
36
+ ```
37
+ 輸入: (B, 4, D) — 4 個連續的 hidden states
38
+ │
39
+ ┌─────┴─────┐
40
+ │ wgate │ Linear(D, 1) → 每個 token 的重要性分數
41
+ │ + ape │ 學習到的位置偏置 (4, 1)
42
+ └─────┬─────┘
43
+ │ softmax over 4 tokens → 歸一化權重
44
+ │
45
+ 加權求和 → (B, 1, D) — 1 個壓縮後的 token
46
+ ```
47
+
48
+ **參數量**: ~D(一個 Linear 層 + 4 個學習到的標量)— 相較於基礎模型可忽略不計。
49
+
50
+ ### 放置位置
51
+
52
+ Compressor 被插入在 `layer_idx % 4 == 3` 的層(每 4 層)。非 compressor 層的 attention 保持不變。
53
+
54
+ ### 壓縮排程(Window + Ratio)
55
+
56
+ 對於 compressor 層的每個序列:
57
+
58
+ ```
59
+ true_len = 序列長度(左側填充後)
60
+ window = min(window_size=128, true_len) ← 完整保留
61
+ compressible = true_len - window
62
+ to_compress = compressible - (compressible % ratio=4)
63
+ compressed = to_compress / 4
64
+ residual = compressible % ratio ← 完整保留(0–3 個 token)
65
+ tail = window ← 最後 128 個 token 完整保留
66
+ ```
67
+
68
+ KV 位置會逐 token 追蹤,以確保正確的 RoPE 索引。批次中經零填充的條目透過 `kv_valid` 遮罩在生成過程中正確屏蔽。
69
+
70
+ ### 解碼階段的 Buffer 壓縮
71
+
72
+ 在自迴歸解碼過程中,新產生的 token 會累積在 **uncompressed buffer**(`buf_k`、`buf_v`、`buf_h`)中。當 buffer 達到 `window_size + ratio = 132` 個 token 時,最舊的 `ratio=4` 個 token 會被壓縮成 1 個並合併到持久 KV cache 中,使 buffer 維持在 `window_size` 個 token。這將解碼階段的 KV 開銷限制在每個 compressor 層最多 `window` 個 token。
73
+
74
+ ## 效能
75
+
76
+ 測試於 **Qwen3.6-27B (NF4,64 層)**。壓縮應用在每隔 4 層(i % 4 == 3),共 16 個 compressor。
77
+
78
+ ### GSM8K(5-shot)
79
+
80
+ | Filter | 基準 | 壓縮後 | 變化 |
81
+ |---------------------|----------|----------|--------|
82
+ | flexible-extract | 0.8749 | 0.7331 | −16.2% |
83
+ | strict-match | 0.8658 | 0.5785 | −33.2% |
84
+
85
+ ### IFEval(0-shot)
86
+
87
+ | Filter | 基準 | 壓縮後 | 變化 |
88
+ |----------------------------|----------|----------|--------|
89
+ | inst_level_loose_acc | 0.8849 | 0.8897 | +0.5% |
90
+ | inst_level_strict_acc | 0.8525 | 0.8513 | −0.1% |
91
+ | prompt_level_loose_acc | 0.8299 | 0.8355 | +0.7% |
92
+ | prompt_level_strict_acc | 0.7856 | 0.7856 | ±0.0% |
93
+
94
+ ### 關鍵結論
95
+
96
+ - **IFEval 幾乎不受影響** — 指令遵循、格式化和約束滿足能力被完整保留。
97
+ - **GSM8K 出現衰退** — 多步驟數學推理在壓縮下受到影響,尤其是嚴格的輸出格式匹配(`#### N`)。
98
+ - **壓縮比**:301 個 token 的 prefill 被壓縮至約 172 個 KV 條目(1.75 倍)。有效壓縮比隨提示長度變化(較短的提示收益較小,非常長的提示可接近 4 倍)。
99
+
100
+ ## 使用方式
101
+
102
+ 參考實作為一個 FastAPI 伺服器(`server.py`),啟動後會自動為 Qwen 模型打上 compressor patch 並提供 OpenAI 相容 API。
103
+
104
+ ```bash
105
+ # 安裝依賴
106
+ pip install torch transformers accelerate bitsandbytes
107
+
108
+ # 啟動伺服器(載入模型、patch compressors、listen on :8001)
109
+ python server.py
110
+
111
+ # 透過 curl 或任何 OpenAI client 發送請求
112
+ curl http://localhost:8001/v1/chat/completions \
113
+ -H "Content-Type: application/json" \
114
+ -d '{"model": "qwen-compress", "messages": [{"role": "user", "content": "1+1="}]}'
115
+ ```
116
+
117
+ Patching 邏輯在 `build_franken_qwen()`(`server.py:344`):每第 4 層的 attention forward 被替換為 `get_custom_qwen_forward(compressor, window_size=128, ratio=4)`,compressor 權重從檢查點載入。
118
+
119
+ ## 限制
120
+
121
+ - **推理能力衰退**:複雜的多步驟推理(GSM8K)準確率下降 16–33%。即便在關閉思考模式的情況下,compressor 仍可能破壞算術推理所需的 intermediate representations。
122
+ - **無聯合訓練恢復**:compressor 檢查點是獨立訓練的,未與基礎模型聯合微調。透過 post-training 或 LoRA 恢復可能縮小差距。
123
+ - **上下文無關的壓縮**:加權平均 compressor 獨立處理每個 4-token 窗口。跨窗口或雙向設計可能更好地保留整體推理結構。