Skip to content

Commit a52c5a7

Browse files
feat: TurboShimmy INT4 KV cache — v2.1.0 release
2 parents cb0c3da + f2503b5 commit a52c5a7

18 files changed

Lines changed: 361 additions & 148 deletions

CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [2.1.0] - 2026-06-02
11+
12+
### Added
13+
- **TurboShimmy INT4 KV cache** — per-head-vector INT4 compression for KV buffers,
14+
cutting KV VRAM usage ~7× with no measured retrieval loss. Enable via
15+
`SHIMMY_KV_QUANT=int4`. See airframe 0.2.0 release notes.
16+
17+
### Fixed
18+
- **wgpu 27 staging-buffer panic on GTX 1050 Ti and similar older GPUs** (issue #205,
19+
reported by @Kuntey). Upgraded to airframe 0.2.1, which fixes `max_buffer_size`
20+
being incorrectly capped to `max_storage_buffer_binding_size`. On some older GPU/driver
21+
stacks these limits differ, causing a deferred validation error that wgpu 27 surfaced as
22+
a cryptic "Staging Buffer is invalid" panic. A pre-flight size guard now returns a clear
23+
error message if the model exceeds the GPU's binding limit.
24+
- Removed spurious `WARNING: Missing Norm Tensor post_attention_norm/post_ffw_norm` log
25+
spam for Llama, Mistral, Phi and Qwen models. These tensors are Gemma-only.
26+
27+
### Changed
28+
- Airframe dependency updated to 0.2.1.
29+
30+
---
31+
1032
## [2.0.0] - 2026-05-26
1133

1234
### 🚀 **v2.0 PUBLIC RELEASE** — Airframe GPU Engine

Cargo.lock

Lines changed: 8 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
[package]
22
name = "shimmy"
3-
version = "2.0.1"
3+
version = "2.1.0"
4+
# publish = false while airframe 0.2.1 is local (path dep). Remove path dep and
5+
# this line once airframe 0.2.1 is published to crates.io, then `cargo publish`.
6+
publish = false
47
edition = "2021"
58
license = "MIT"
69
description = "Lightweight Ollama-compatible inference server with native SafeTensors support. No Python dependencies, cross-platform WebGPU acceleration via Airframe."
@@ -19,7 +22,6 @@ include = [
1922
"LICENSE",
2023
"build.rs"
2124
]
22-
publish = true
2325

2426
[features]
2527
default = ["airframe", "huggingface"] # Full GPU build; use --no-default-features --features huggingface for CPU-only
@@ -68,7 +70,7 @@ dirs = "5.0"
6870
reqwest = { version = "0.12", features = ["json", "rustls-tls", "stream"], default-features = false }
6971

7072
# Airframe native GPU inference — public crate on crates.io
71-
airframe = { version = "0.1", optional = true }
73+
airframe = { version = "0.2.1", path = "../airframe", optional = true }
7274

7375
[dev-dependencies]
7476
tokio-tungstenite = "0.20"

README.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
- [What Is Shimmy?](#drop-in-openai-api-replacement-for-local-llms)
3838
- [🔥 Airframe Engine (v2.0)](#-airframe-engine)
39+
- [⚡ TurboShimmy INT4 KV (v2.1)](#-turboshimmy-int4-kv)
3940
- [🎯 Supported Models](#-supported-models)
4041
- [📦 Migrating from v1.x](#-migrating-from-v1x)
4142
- [⚡ Quick Start (30 seconds)](#quick-start-30-seconds)
@@ -59,6 +60,8 @@ Shimmy is a **single-binary** that provides **100% OpenAI-compatible endpoints**
5960

6061
**🎉 NEW in v2.0.0**: Shimmy now runs on [Airframe](#-airframe-engine), a pure-Rust WGSL GPU engine. No C++ toolchain, no backend flags, no compilation required.
6162

63+
**⚡ NEW in v2.1.0**: [TurboShimmy INT4 KV](#-turboshimmy-int4-kv)~7× less KV cache VRAM with one flag. Run Llama-3.2-3B on 4 GB GPUs.
64+
6265
## 🔥 Airframe Engine
6366

6467
Starting in v2.0.0, Shimmy's default inference engine is **Airframe** — a pure-Rust WebGPU (WGSL) transformer runtime built from scratch.
@@ -79,6 +82,61 @@ SHIMMY_BASE_GGUF=/path/to/TinyLlama-1.1B-Chat-v1.0.Q4_0.gguf ./shimmy serve
7982
SHIMMY_BASE_GGUF=/path/to/model.gguf SHIMMY_MAX_CTX=4096 ./shimmy serve
8083
```
8184

85+
## ⚡ TurboShimmy INT4 KV
86+
87+
**TurboShimmy** is Shimmy's on-GPU INT4 KV-cache compression system, shipping in v2.1.0. It squeezes the KV cache from 32-bit floats down to per-head-vector 4-bit integers — entirely in WGSL compute shaders with no CPU roundtrips — delivering ~7× less KV VRAM with no measurable quality loss at normal context lengths.
88+
89+
**One flag. ~7× less KV VRAM. Same output quality.**
90+
91+
```bash
92+
# Enable TurboShimmy on any GGUF model
93+
./shimmy serve --kv-quant int4
94+
95+
# Or via environment variable (docker-compose, systemd, etc.)
96+
SHIMMY_KV_QUANT=int4 ./shimmy serve
97+
98+
# Windows GPU + long prompts: reduce per-dispatch work to prevent TDR resets
99+
./shimmy serve --kv-quant int4 --prefill-chunk 8
100+
```
101+
102+
**Why it matters** — TurboShimmy changes what fits on your GPU:
103+
104+
| GPU VRAM | Without TurboShimmy | With TurboShimmy (`--kv-quant int4`) |
105+
|---|---|---|
106+
| 3 GB | Llama-3.2-1B only | **Llama-3.2-3B fits ✅** |
107+
| 4 GB | Llama-3.2-3B, ctx=2048 (tight) | **Llama-3.2-3B at ctx=8192 ✅** |
108+
| 6 GB | 3B models, short context | **7B models with reasonable context ✅** |
109+
110+
**VRAM comparison (Llama-3.2-3B, ctx=2048):**
111+
112+
| Mode | KV cache | Total VRAM | Min GPU needed |
113+
|---|---|---|---|
114+
| Default (f32) | ~512 MB | ~2.4 GB | 3 GB (tight) |
115+
| TurboShimmy (int4) | **~72 MB** | **~2.0 GB** | **2.5 GB ✅** |
116+
117+
**VRAM comparison (TinyLlama 1.1B, ctx=2048):**
118+
119+
| Mode | KV cache | Total VRAM |
120+
|---|---|---|
121+
| Default (f32) | 88 MB | ~700 MB |
122+
| TurboShimmy (int4) | **~13 MB** | **~650 MB** |
123+
124+
**When to use TurboShimmy:**
125+
126+
| Situation | Recommendation |
127+
|---|---|
128+
| 3B model on a 4 GB GPU | `--kv-quant int4` — enables models that wouldn't fit otherwise |
129+
| 7B model at ctx=4096+ | `--kv-quant int4` — cuts KV from ~512 MB → ~72 MB |
130+
| Short chat sessions (ctx ≤ 2048) | `--kv-quant int4` — safe, no quality tradeoff |
131+
| Long-form generation (ctx > 8192) | Default `f32` — keep maximum quality |
132+
| Windows GPU + TDR crashes on long prompts | `--kv-quant int4 --prefill-chunk 8` |
133+
134+
**How it works:** Each K/V head vector is independently quantized to 4-bit integers with a per-vector F32 scale factor, encoded as packed nibbles by WGSL compute shaders. Dequantization happens on-the-fly when computing attention scores — also on GPU. The Airframe engine's helical context-shift operates directly on the packed INT4 representation. No CPU roundtrips at any step. Full architecture details in the [Airframe engine](https://github.com/Michael-A-Kuykendall/airframe).
135+
136+
> **Quality validation:** Needle-in-a-haystack benchmarks on Llama-3.2-3B show zero retrieval degradation vs F32 at ctx≤2048 across all tested depths (15%, 50%, 85%). Full benchmark data and setup guide: [TurboShimmy on the wiki](https://github.com/Michael-A-Kuykendall/shimmy/wiki/TurboShimmy).
137+
138+
> **Windows stability:** Airframe v0.2.1 ships a `device.on_uncaptured_error` handler so GPU validation errors surface as clean HTTP 500 responses instead of crashes. Use `--prefill-chunk 8` to prevent Windows TDR resets during long prefills on older GPUs (GTX 10xx/16xx series).
139+
82140
## 🎯 Supported Models
83141

84142
Airframe v2.0 ships with GPU-verified support across **7 model architectures** and **5 quantization types**, covering the models most commonly run on consumer hardware. Context window is read directly from each model's GGUF metadata — no hardcoded limits.
@@ -452,6 +510,8 @@ I built Shimmy to retain privacy-first control on my AI development and keep thi
452510
| `SHIMMY_MODEL_PATHS` | *(see Zero Config)* | Colon-separated extra model search paths |
453511
| `SHIMMY_ENGINE_BACKEND` | `airframe` | `airframe` (default) or `llama` (legacy path) |
454512
| `SHIMMY_ROPE_SCALE` | *(auto)* | Override computed YaRN scale factor |
513+
| `SHIMMY_KV_QUANT` | `f32` | KV cache quantization: `f32` (default) or `int4` ([TurboShimmy](#-turboshimmy-int4-kv)) |
514+
| `SHIMMY_PREFILL_CHUNK` | `64` | Tokens per prefill dispatch. Set to `8` on Windows if you see GPU TDR resets on long prompts |
455515
| `RUST_BACKTRACE` | *(off)* | Set to `1` to print crash backtraces |
456516

457517
### CLI Commands
@@ -460,6 +520,8 @@ shimmy serve # Start server (auto port allocation)
460520
shimmy serve --bind 127.0.0.1:8080 # Manual port binding
461521
shimmy serve --gpu-backend auto # WebGPU adapter auto-select (default)
462522
shimmy serve --gpu-backend cpu # Force CPU (disable GPU)
523+
shimmy serve --kv-quant int4 # Enable TurboShimmy INT4 KV cache compression
524+
shimmy serve --kv-quant int4 --prefill-chunk 8 # INT4 + Windows TDR prevention
463525
shimmy list # Show available models
464526
shimmy discover # Refresh model discovery
465527
shimmy generate --name X --prompt "Hi" # Test generation

docker-compose.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ services:
1313
- SHIMMY_BASE_GGUF=/app/models # Point to mounted models
1414
- SHIMMY_PORT=11434 # Server port
1515
- SHIMMY_HOST=0.0.0.0 # Listen on all interfaces
16+
# TurboShimmy v2.1 — cut KV cache VRAM ~60% (recommended for 4 GB GPUs)
17+
# Uncomment to enable INT4 KV quantization:
18+
# - SHIMMY_KV_QUANT=int4
19+
# Uncomment to reduce prefill chunk size (prevents Windows TDR crashes on long prompts):
20+
# - SHIMMY_PREFILL_CHUNK=8
21+
# Uncomment to override max context length (default: model's native ctx from GGUF):
22+
# - SHIMMY_MAX_CTX=4096
1623
restart: unless-stopped
1724
deploy:
1825
resources:
@@ -24,4 +31,4 @@ services:
2431

2532
volumes:
2633
shimmy-cache:
27-
driver: local
34+
driver: local

docs/zh-CN/README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,40 @@ curl http://127.0.0.1:11435/v1/chat/completions \
9797

9898
---
9999

100+
## ⚡ TurboShimmy INT4 KV —— v2.1.0 新功能
101+
102+
**TurboShimmy** 是 Shimmy v2.1.0 带来的纯 GPU INT4 KV 缓存压缩系统。通过 WGSL 计算着色器,将 KV 缓存从 32 位浮点数压缩为逐头向量 4 位整数,全程在 GPU 上完成。**一行指令,约 7 倍 KV 显存节省,输出品质不变。**
103+
104+
```bash
105+
# 启用 TurboShimmy
106+
SHIMMY_KV_QUANT=int4 ./shimmy serve
107+
108+
# 或通过命令行参数
109+
./shimmy serve --kv-quant int4
110+
111+
# Windows + 长提示:预防 GPU TDR 重置
112+
./shimmy serve --kv-quant int4 --prefill-chunk 8
113+
```
114+
115+
**TurboShimmy 改变了消费级 GPU 的可用范围:**
116+
117+
| GPU 显存 | 未启用 TurboShimmy | 启用后(`--kv-quant int4`|
118+
|---|---|---|
119+
| 3 GB | 仅能运行 Llama-3.2-1B | **Llama-3.2-3B 可运行 ✅** |
120+
| 4 GB | Llama-3.2-3B,ctx=2048(勉强) | **Llama-3.2-3B,ctx=8192 ✅** |
121+
| 6 GB | 3B 模型,短上下文 | **7B 模型,合理上下文 ✅** |
122+
123+
**显存对比(Llama-3.2-3B,ctx=2048):**
124+
125+
| 模式 | KV 缓存 | 总显存 | 最低显存 |
126+
|---|---|---|---|
127+
| 默认(f32) | ~512 MB | ~2.4 GB | 3 GB(勉强) |
128+
| TurboShimmy(int4) | **~72 MB** | **~2.0 GB** | **2.5 GB ✅** |
129+
130+
> **品质验证:** 在 Llama-3.2-3B 上进行的“大海捕针”基准测试表明,ctx≤2048 时 INT4 对比 F32 检索准确率零退化(各测试深度 15%〈50%〈85% 均为 100%)。详细文档:[TurboShimmy Wiki](https://github.com/Michael-A-Kuykendall/shimmy/wiki/TurboShimmy-zh-CN)
131+
132+
---
133+
100134
## 🖥️ 已验证的 GPU 支持
101135

102136
| 平台 | GPU 类型 | 后端 |
@@ -133,6 +167,9 @@ Shimmy 是纯 Rust 实现,无 Python 运行时,无 C++ 依赖,启动时间
133167
**如何选择模型量化格式?**
134168
日常使用首选 `Q4_K_M`——在文件大小和推理质量之间取得了最好的平衡。若追求最高质量且显存充足,选 `Q8_0`。详见[量化格式详解](QUANTIZATION.md)
135169

170+
**如何在 4 GB 显存的显卡上运行 3B 模型?**
171+
启用 TurboShimmy:`SHIMMY_KV_QUANT=int4 ./shimmy serve`。这将 KV 显存减少约 7 倍,使 Llama-3.2-3B 能在 2.5 GB 总显存下运行。详见[上方 TurboShimmy 节](#turboshimmy-int4-kv--v210-)
172+
136173
**上下文长度不够怎么办?**
137174
设置 `SHIMMY_MAX_CTX=8192`(或更高)即可,Airframe 会自动应用 YaRN RoPE 缩放。注意超出模型原生上下文 2 倍以上时质量会有所下降。详见[扩展上下文窗口](EXTENDED_CONTEXT.md)
138175

docs/zh-TW/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ Shimmy 是純 Rust 實作,無 Python 執行環境,無 C++ 相依,啟動時
133133
**如何選擇模型量化格式?**
134134
日常使用首選 `Q4_K_M`——在檔案大小和推論品質之間取得了最好的平衡。若追求最高品質且顯存充足,選 `Q8_0`。詳見[量化格式詳解](QUANTIZATION.md)
135135

136+
**如何在 4 GB 顯示記憶體的顯示卡上執行 3B 模型?**
137+
啟用 TurboShimmy:`SHIMMY_KV_QUANT=int4 ./shimmy serve`。這將 KV 顯示記憶體減少約 7 倍,使 Llama-3.2-3B 能在 2.5 GB 總顯示記憶體下執行。詳見[上方 TurboShimmy 節](#turboshimmy-int4-kv--v210-)
138+
136139
**上下文長度不夠怎麼辦?**
137140
設定 `SHIMMY_MAX_CTX=8192`(或更高)即可,Airframe 會自動套用 YaRN RoPE 縮放。注意超出模型原生上下文 2 倍以上時品質會有所下降。詳見[擴展上下文視窗](EXTENDED_CONTEXT.md)
138141

src/cli.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,27 @@ pub struct Cli {
3737
/// Use legacy CPU adapter instead of Airframe GPU
3838
#[arg(long, global = true)]
3939
pub legacy: bool,
40+
41+
/// Enable TurboShimmy INT4 KV cache to cut VRAM usage ~60% with minimal quality loss.
42+
/// Values: f32 (default, full precision) | int4 (TurboShimmy — recommended for 4GB+ GPUs)
43+
#[arg(
44+
long,
45+
global = true,
46+
value_name = "MODE",
47+
default_value = "f32",
48+
value_parser = ["f32", "int4"],
49+
help = "KV cache precision: f32 (default) or int4 (TurboShimmy — ~60% less VRAM)"
50+
)]
51+
pub kv_quant: String,
52+
53+
/// Prefill chunk size for long-context stability on Windows (default: 64).
54+
/// If you see GPU TDR crashes on long prompts, set this to 8 or 16.
55+
#[arg(long, global = true, value_name = "N")]
56+
pub prefill_chunk: Option<u32>,
57+
58+
/// Override maximum context length (tokens). Default: model's native context from GGUF.
59+
#[arg(long, global = true, value_name = "N")]
60+
pub ctx: Option<u32>,
4061
}
4162

4263
#[derive(Subcommand, Debug)]

src/discovery.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -428,15 +428,24 @@ mod tests {
428428

429429
let discovery = ModelDiscovery::from_env();
430430

431-
// Should include home-based paths
432-
assert!(discovery
433-
.search_paths
434-
.iter()
435-
.any(|p| p.to_string_lossy().contains(".cache/huggingface")));
436-
assert!(discovery
437-
.search_paths
438-
.iter()
439-
.any(|p| p.to_string_lossy().contains("models")));
431+
// Should include home-based paths. Use slash-normalized comparison so
432+
// the test passes on Windows (PathBuf uses backslashes on Windows).
433+
assert!(
434+
discovery
435+
.search_paths
436+
.iter()
437+
.any(|p| p.to_string_lossy().replace('\\', "/").contains(".cache/huggingface")),
438+
"Expected .cache/huggingface in search paths, got: {:?}",
439+
discovery.search_paths
440+
);
441+
assert!(
442+
discovery
443+
.search_paths
444+
.iter()
445+
.any(|p| p.to_string_lossy().contains("models")),
446+
"Expected models dir in search paths, got: {:?}",
447+
discovery.search_paths
448+
);
440449

441450
// Restore original environment
442451
env::remove_var("HOME");

0 commit comments

Comments
 (0)