jagat-primitive-org commited on
Commit
12ba94e
·
verified ·
1 Parent(s): 226f060

Card: report call/abstain in the headline, fix the MoVA restack figure (15.1 GB, not 7.55), one decimal throughout, pin the serve image

Browse files
Files changed (1) hide show
  1. README.md +99 -97
README.md CHANGED
@@ -29,12 +29,13 @@ thumbnail: https://huggingface.co/primitive-ai/K2-Horizon-MoVA-36B-A4B-mixed-NVF
29
  <img src="https://img.shields.io/badge/vs%20BF16-1.7×%20smaller-F98424?style=flat-square" alt="1.7x smaller than BF16">
30
  <img src="https://img.shields.io/badge/vs%20official%20FP8-8%25%20smaller-F98424?style=flat-square" alt="8 percent smaller than the official FP8">
31
  <img src="https://img.shields.io/badge/knowledge-level%20with%20BF16%20%26%20FP8-3DD13D?style=flat-square" alt="knowledge level with BF16 and FP8">
32
- <img src="https://img.shields.io/badge/tool%20calling-1.4%20below%20FP8-lightgrey?style=flat-square" alt="tool calling 1.4 below the official FP8">
 
33
  <img src="https://img.shields.io/badge/requires-Blackwell-lightgrey?style=flat-square" alt="requires Blackwell">
34
  <a href="https://primitive.com"><img src="https://img.shields.io/badge/web-primitive.com-lightgrey?style=flat-square" alt="primitive.com"></a>
35
  </p>
36
 
37
- <h3 align="center">8% smaller than the official FP8, level on knowledge, 1.4 behind on tool calling.</h3>
38
 
39
  <p align="center">
40
  Mixed-precision quantization of <a href="https://huggingface.co/IFM/K2-Horizon-MoVA-36B-A4B">IFM/K2-Horizon-MoVA-36B-A4B</a> to
@@ -42,11 +43,11 @@ Mixed-precision quantization of <a href="https://huggingface.co/IFM/K2-Horizon-M
42
  15 of the 45 sparse layers carry NVFP4 experts; the other 30 carry FP8 with block scales.
43
  </p>
44
 
45
- > **This is the more accurate of our two builds, and it needs Blackwell.** There is also a
46
  > [pure NVFP4 build](https://huggingface.co/primitive-ai/K2-Horizon-MoVA-36B-A4B-NVFP4) at
47
  > 36.74 GB that is 7.74 GB smaller, 1.21× faster at concurrency 32, and **the only one of the two
48
- > that runs on Ampere**. Take this one if tool calling matters most; take that one for
49
- > pre-Blackwell hardware, the smallest footprint, or throughput under load.
50
 
51
  ---
52
 
@@ -54,21 +55,19 @@ Mixed-precision quantization of <a href="https://huggingface.co/IFM/K2-Horizon-M
54
 
55
  * 🗜️ **8% smaller than IFM's own FP8, 1.7× smaller than BF16.** 44.48 GB against 48.36 GB and
56
  74.89 GB.
57
- * 🎯 **Knowledge is level with both references.** 87.31 against the official FP8's 86.84 and BF16's
58
- 85.94 over 1,170 items. It is the highest number in the table and it is still a tie — read the
59
- four builds as one group on this axis.
60
- * 🎯 **The better of our two builds on tool calls.** 73.47 on call accuracy against the pure NVFP4
61
- build's 71.77, for 7.74 GB more the one axis that separates the two (t = +2.42). Against the
62
- official FP8 the pooled gap is 1.44 and neither half of the suite separates on its own.
63
- * 🧠 **The lever was the weight-scale scheme, not the bit width.** Moving two thirds of the expert
64
- layers from group-wise 4-bit to FP8 with `[128,128]` block scales is worth about a point of tool
65
- calling; every build we measured between 36.74 GB and 48.39 GB otherwise lands in the same band.
66
  * 🖥️ **One card, no tensor parallelism.** Both official recipes use TP=2; this fits TP=1 with
67
  231,488 tokens of KV at 32K context.
68
  * ⚠️ **Blackwell.** Two thirds of the expert layers carry FP8 block scales and sm_80 has no FP8
69
- tensor cores, so we neither built nor tested this one for Ampere. The pure NVFP4 build is
70
- verified there.
71
- * 🔧 **`compressed-tensors`, no custom kernels.** Stock vLLM off the nightly image, no patches.
72
 
73
  ---
74
 
@@ -79,17 +78,22 @@ K2-Horizon support merged into vLLM `main` on 3 September 2026
79
  0.28.0 predates it. Use a `main`/nightly build:
80
 
81
  ```bash
 
 
 
82
  docker run --gpus all --ipc=host -p 8000:8000 -v $PWD:/models \
83
- vllm/vllm-openai:nightly \
84
  --model /models/K2-Horizon-MoVA-36B-A4B-mixed-NVFP4-FP8 \
85
  --trust-remote-code --max-model-len 32768 \
86
  --gpu-memory-utilization 0.92 \
87
  --reasoning-parser k2_horizon
88
  ```
89
 
90
- Verified on the pinned nightly `8a728663c1c3` (vllm `0.28.1rc1.dev388`), one RTX PRO 6000
91
- Blackwell: 43.02 GiB resident for weights, 42.39 GiB left for KV **231,488 tokens at 32K context,
92
- 7.06× concurrency** and engine init in 198 s.
 
 
93
 
94
  **Reasoning effort is a server-level choice on this architecture, not a per-request one.** The
95
  template emits a different tag pair per effort and `K2HorizonReasoningParser` picks one pair once
@@ -121,10 +125,10 @@ the runs counted in the `runs k/a` column.
121
 
122
  | build | size | knowledge | call | abstain | tool calling | runs k/a | finished | out/answer |
123
  |---|---|---|---|---|---|---|---|---|
124
- | [IFM BF16](https://huggingface.co/IFM/K2-Horizon-MoVA-36B-A4B) | 74.89 GB | 85.94 ±0.66 | 74.58 ±1.30 | 60.83 ±2.89 | 71.83 ±1.04 | 2/3 | 95.8% | 1206 |
125
- | [IFM FP8](https://huggingface.co/IFM/K2-Horizon-MoVA-36B-A4B-FP8) | 48.36 GB | 86.84 ±0.48 | 74.90 ±1.50 | 60.42 ±2.92 | 72.00 ±0.77 | 2/6 | 96.1% | 1176 |
126
- | **this repo** | **44.48 GB** | 87.31 ±1.03 | 73.47 ±1.71 | 58.89 ±3.09 | 70.56 ±1.40 | 2/9 | 96.3% | 1118 |
127
- | [our pure NVFP4](https://huggingface.co/primitive-ai/K2-Horizon-MoVA-36B-A4B-NVFP4) | 36.74 GB | 86.54 ±0.54 | 71.77 ±1.00 | 60.42 ±3.68 | 69.50 ±1.38 | 2/6 | 95.6% | 1234 |
128
 
129
  `call` is accuracy on the 160 tool-calling items that require a call; `abstain` is the 40 whose
130
  correct action is to call **nothing**; `tool calling` is the two pooled as 200. We report the halves
@@ -132,22 +136,19 @@ separately because pooling hides which one moved. `runs k/a` is the number of kn
132
  runs behind each row. `finished` is the share of the 1,170 knowledge items that answered inside the
133
  token budget; `out/answer` is mean output tokens.
134
 
135
- **Knowledge is one group.** This build's 87.31 is the highest number in the column and it does not
136
- separate from anything: against the official FP8 it is t = +0.59, at n=2 on both sides. The four
137
- means span 1.4 points, which is inside a single checkpoint's own repeat spread. Don't rank on this
138
  column.
139
 
140
- **Tool calling: 1.44 below the official FP8, and here is the honest version of that.** The pooled
141
- 200-item number separates (t = −2.56 over nine runs here and six there). Neither half separates on
142
- its own: `call` is 1.42 low at t = −1.70, `abstain` is 1.53 low at t = −0.97. So the loss is small,
143
- real in aggregate, and spread across both halves of the suite rather than concentrated in one. That
144
- is a different result from our pure NVFP4 build, where the loss is 3.12 on `call` alone (t = −4.24)
145
- and abstention is untouched.
146
 
147
- **It is not a formatting failure.** Unparsed replies run at 14 per 1,800 here (0.78%) against 13
148
- per 1,200 for the official FP8 (1.08%) and 6 per 600 for BF16 (1.00%) — ours is the cleanest of the
149
- three. Thinking fired on 99–100% of items in every row. The model produces well-formed calls; the
150
- residual is argument accuracy.
151
 
152
  <details>
153
  <summary>Per-benchmark detail, both suites</summary>
@@ -175,7 +176,7 @@ Pooled over every run behind the row, so a cell rests on `runs × items`. `when2
175
  40 abstention items; the other four tool-calling benchmarks supply the 160 call items.
176
 
177
  **Where the tool-calling difference sits.** xlam/APIGen is 40.2 here against the official FP8's
178
- 44.8 4.6 points on 45 items, and the largest single-benchmark gap on the page. The pure NVFP4
179
  build gives up 7.0 points on the same benchmark, so this build recovers about a third of that loss.
180
  xlam items carry the longest argument lists in the suite.
181
 
@@ -183,20 +184,19 @@ xlam items carry the longest argument lists in the suite.
183
 
184
  > **The noise floor, and why the run counts are in the table.** Every build compared here has at
185
  > least six agentic runs, the one exception being the BF16 reference at three. It needs to be six.
186
- > The official FP8's tool-calling figure read 72.67 ±0.29 after three runs and 72.00 ±0.77 after
187
- > six; this build's read 70.33 ±1.61 after three and 70.56 ±1.40 after nine. On the 1,170-item
188
- > knowledge suite, repeat runs of a single checkpoint span up to 1.9 points, so **treat any
189
- > knowledge gap under about 1.2 points as unresolved** every gap in that column is smaller than
190
- > that. We publish ties as ties.
191
-
192
- **Two footnotes on the table.** The BF16 row was served at 20,480 context against the quants'
193
- 32,768, because 74.89 GB of weights leaves only 81,664 tokens of KV on a 96 GB card; the generation
194
- budget was the same 16,384 tokens for every row. And `out/answer` is a mean over a long tail
195
- median output is 204 tokens here against a mean of 1,118, a ratio near 5.5×. That ratio is usually
196
- the signature of a model that reaches its answer and cannot stop, so it is worth saying plainly
197
- that it is not: the official FP8 shows 1,176 against a median of 211 on the same items, the same
198
- ratio, and the same ~4% of items hitting the budget. It is how K2-Horizon reasons short answers
199
- most of the time, occasional long chains — and quantization did not cause it.
200
 
201
  ---
202
 
@@ -205,7 +205,8 @@ most of the time, occasional long chains — and quantization did not cause it.
205
  Cache-free, 8,192 tokens in and 512 out, one RTX PRO 6000 Blackwell, same nightly and same serve
206
  flags as the accuracy rows. Prefix caching is disabled and every measurement runs on its own seed,
207
  so no row is reading a cache the previous one filled. These come from one sitting and drift a few
208
- percent between sittings, so read them as a bracket rather than to the decimal.
 
209
 
210
  | build | tok/s @ conc 1 | TPOT @ conc 1 | tok/s @ conc 32 | TPOT @ conc 32 | median TTFT @ conc 32 |
211
  |---|---|---|---|---|---|
@@ -213,17 +214,17 @@ percent between sittings, so read them as a bracket rather than to the decimal.
213
  | **this repo** | 29.99 | 32.56 ms | 248.4 | 89.5 ms | 3.59 s |
214
  | [our pure NVFP4](https://huggingface.co/primitive-ai/K2-Horizon-MoVA-36B-A4B-NVFP4) | **30.45** | **32.10 ms** | **301.5** | 93.1 ms | **1.54 s** |
215
 
216
- **Quantizing this model buys prefill, not decode.** Those three builds span 12 GB and land within
217
- 0.7 tok/s of each other at concurrency 1, and their per-token decode cost at concurrency 32 is
218
- within 5% (89.293.1 ms). The aggregate difference is almost entirely time to first token. Prefill
219
- is compute-bound and lower-precision expert GEMMs are faster; decode is bandwidth-bound and cannot
220
- improve much, because vLLM restacks the 7.55 GB of BF16 MoVA value-experts on every forward pass
221
- whatever the routed experts are quantized to. That fixed cost dominates a single stream and is the
222
- reason single-stream latency is flat across the whole size range.
223
 
224
- This build sits between the two on every throughput column, which is what its size predicts. If
225
- throughput under load is the priority rather than call accuracy, the pure NVFP4 build is 1.21×
226
- this one at concurrency 32 and reaches first token in 1.54 s against 3.59 s.
227
 
228
  ---
229
 
@@ -232,21 +233,20 @@ this one at concurrency 32 and reaches first token in 1.54 s against 3.59 s.
232
  | | **this repo** | [pure NVFP4](https://huggingface.co/primitive-ai/K2-Horizon-MoVA-36B-A4B-NVFP4) |
233
  |---|---|---|
234
  | size | 44.48 GB | **36.74 GB** |
235
- | knowledge | 87.31 ±1.03 | 86.54 ±0.54 |
236
- | call | **73.47 ±1.71** | 71.77 ±1.00 |
237
- | abstain | 58.89 ±3.09 | 60.42 ±3.68 |
238
- | tool calling, pooled | 70.56 ±1.40 | 69.50 ±1.38 |
239
  | tok/s @ conc 32 | 248.4 | **301.5** |
240
  | median TTFT @ conc 32 | 3.59 s | **1.54 s** |
241
  | Blackwell | yes | yes |
242
  | **Ampere (A100)** | **no** | **yes** |
243
 
244
- This build spends 7.74 GB, +21%, and call accuracy is the one axis that pays it back: +1.70 at
245
- t = +2.42. The pooled tool-calling lead of 1.06 does not separate (t = +1.45), nor does knowledge
246
- (t = +0.94). **If tool calling dominates
247
- your workload and you have 48 GB, IFM's own FP8 is still the most accurate option** it leads this
248
- build by 1.44 pooled. What this build offers against it is 8% less memory at a gap that neither
249
- half of the suite resolves on its own.
250
 
251
  **On Ampere.** We have not tested this build on an A100 and do not expect FP8 block scales to load
252
  on sm_80, which has no FP8 tensor cores. The pure NVFP4 build does run there through Marlin
@@ -262,7 +262,7 @@ different `temperature`, or whether the model was allowed to reason at all. So e
262
  table, on this card and on our other cards, comes from the one fixed protocol described above — the
263
  same 1,370 items, auto-scored, no LLM judge.
264
 
265
- | model | shape | size | overall | knowledge | call | abstain | finished | out |
266
  |---|---|---|---|---|---|---|---|---|
267
  | [Laguna-XS-2.1](https://huggingface.co/primitive-ai/Laguna-XS-2.1-mixed-NVFP4-MXFP8) | 31 B MoE | 19.3 GiB | 81.7 | 83.8 | 68.4 | 73.5 | 98.9% | 1097 |
268
  | [Nemotron-3.5-Lightning-30B-A3B](https://huggingface.co/primitive-ai/Nemotron-3.5-Lightning-30B-A3B-mixed-INT4-INT8) | 30 B MoE+Mamba | 19.2 GiB | 87.1 | 87.9 | 85.4 | 70.5 | 97.9% | 1429 |
@@ -270,17 +270,17 @@ same 1,370 items, auto-scored, no LLM judge.
270
  | [Muse-Glimmer-30B](https://huggingface.co/primitive-ai/Muse-Glimmer-30B-mixed-NVFP4) | 30 B MoE | 20.4 GiB | 86.6 | 88.8 | 78.6 | 54.5 | 99.7% | 800 |
271
  | [Qwen3.8-27B](https://huggingface.co/primitive-ai/Qwen3.8-27B-mixed-NVFP4-FP8) | 27 B dense | 20.7 GiB | 88.8 | 90.4 | 85.5 | 54.5 | 99.7% | 651 |
272
  | [Granite-4.2-30B](https://huggingface.co/primitive-ai/granite-4.2-30b-mixed-NVFP4-FP8) | 30 B dense | 18.1 GB | 85.5 | 86.2 | 85.8 | 60.8 | 98.5% | 1502 |
273
- | [K2-Horizon-MoVA-36B-A4B NVFP4](https://huggingface.co/primitive-ai/K2-Horizon-MoVA-36B-A4B-NVFP4) | 37 B MoE+MoVA, 4 B active | 36.74 GB | 84.1 | 86.5 | 71.8 | 60.4 | 95.6% | 1234 |
274
- | **K2-Horizon-MoVA-36B-A4B mixed** (this repo) | 37 B MoE+MoVA, 4 B active | **44.48 GB** | **84.9** | 87.3 | 73.5 | 58.9 | 96.3% | 1118 |
275
  | [Laguna-S-2.1](https://huggingface.co/primitive-ai/Laguna-S-2.1-mixed-NVFP4-MXFP8) | 110 B MoE | 64.0 GiB | 84.3 | 87.1 | 64.6 | 81.0 | 97.3% | 995 |
276
  | [Qwen3.8-Flash-Next](https://huggingface.co/primitive-ai/Qwen3.8-Flash-Next-mixed-NVFP4-FP8) | 180 B MoE, 6 B active | 183.7 GB | 90.3 | 92.2 | 84.8 | 56.7 | 99.5% | 686 |
277
 
278
  `overall` pools the two suites as 1,370 items, weighted 85.4% knowledge and 14.6% tool calling by
279
  item count. **Read it with `finished`**: `overall` scores an answer that overran the token budget as
280
  wrong, but it cannot tell you whether the model needed the room or failed to stop — `finished` and
281
- `out` separate those, and this model's 96.3% is among the lowest `finished` in the table because it
282
- reasons in long chains. A gap under **1.0** in `overall` is a tie. Sizes are as each card reports
283
- them, which mixes GB and GiB; the rest of this page is GB.
284
 
285
  ---
286
 
@@ -290,24 +290,26 @@ The model is 37.4 B parameters in five very unequal pieces:
290
 
291
  | | params | share |
292
  |---|---|---|
293
- | routed MoE experts, 45 layers × 100 × 3 × 2560×768 | 26.54 B | 70.9% |
294
  | MoVA value-experts, 45 layers × 64 × 2560×1024 | 7.55 B | 20.2% |
295
  | attention `qk_proj` / `o_proj` / `gate_proj` | 1.61 B | 4.3% |
296
  | `embed_tokens` + `lm_head`, untied, vocab 250624 | 1.28 B | 3.4% |
297
  | shared experts + the three dense MLP layers | 0.41 B | 1.1% |
298
 
 
 
299
  | tensors | count | format |
300
  |---|---|---|
301
  | routed experts on 30 of the 45 sparse layers | 9,000 | FP8 E4M3, block scales `[128,128]` |
302
  | routed experts on the other 15 sparse layers | 4,500 | NVFP4, group 16 |
303
  | MoVA `v_experts` and `v_router`; `qk_proj`/`o_proj`/`gate_proj`; `mlp.gate`; shared experts; dense layers 0–2; `lm_head`; embeddings; norms | 3,408 | BF16 |
304
 
305
- `compressed-tensors`, top-level format `mixed-precision`, two config groups. The NVFP4 group is
306
- W4A4 and carries observed activation scales plus a tensor-level `weight_global_scale`; the FP8 group
307
- is weight-only with block scales.
308
 
309
- **The second-largest block is off limits for a concrete reason, not caution.** vLLM's MoVA attention
310
- does this on every forward pass:
311
 
312
  ```python
313
  w1 = torch.stack([expert.weight for expert in self.v_experts], dim=0).contiguous()
@@ -318,17 +320,16 @@ It stacks the raw `.weight` of all 64 value-experts and hands `fused_mova_impl`
318
  quantized `Linear` carries `weight_packed` plus scales and no `weight`, so a quantized v_expert
319
  either fails at load or feeds packed bytes to a kernel that reads them as bfloat16. IFM's own FP8
320
  ignores all 2,880 of them for the same reason. That is 20% of the model pinned to BF16 in any build,
321
- which is why lower precision buys less here than the parameter count suggests and, per the
322
- throughput section, why decode speed barely moves.
 
323
 
324
- Attention is left alone too: MoVA fuses `q` and `k` into a single `qk_proj`, so those two would have
325
- to share one scheme. And a layer's experts are quantized as a unit: vLLM's fused MoE requires one
326
- scheme across an expert's `gate`/`up`/`down`, so the mixture here is per layer, never per
327
- projection.
328
 
329
- We publish the formats and the measurements. How the allocation was chosen is ours; note that a
330
- servable `compressed-tensors` checkpoint must declare its targets in `config.json`, so which modules
331
- sit in which format is visible there by necessity.
332
 
333
  ## Attribution
334
 
@@ -337,8 +338,9 @@ sit in which format is visible there by necessity.
337
  - Calibration: 496 conversations at seqlen 2048, used to observe activation scales.
338
  - The checkpoint carries IFM's `modeling_k2_horizon.py` and `configuration_k2_horizon.py`
339
  unchanged, so `--trust-remote-code` works for tooling that wants the reference implementation.
340
- - Audited before publication: every fused NVFP4 group shares one `weight_global_scale`, no
341
- activation scale is zero or NaN, and `config.json` agrees with the tensors actually present.
 
342
 
343
  ---
344
 
 
29
  <img src="https://img.shields.io/badge/vs%20BF16-1.7×%20smaller-F98424?style=flat-square" alt="1.7x smaller than BF16">
30
  <img src="https://img.shields.io/badge/vs%20official%20FP8-8%25%20smaller-F98424?style=flat-square" alt="8 percent smaller than the official FP8">
31
  <img src="https://img.shields.io/badge/knowledge-level%20with%20BF16%20%26%20FP8-3DD13D?style=flat-square" alt="knowledge level with BF16 and FP8">
32
+ <img src="https://img.shields.io/badge/call%20accuracy-1.4%20below%20FP8-lightgrey?style=flat-square" alt="call accuracy 1.4 below the official FP8">
33
+ <img src="https://img.shields.io/badge/vs%20our%20NVFP4-%2B1.7%20call%20accuracy-F98424?style=flat-square" alt="plus 1.7 call accuracy versus our pure NVFP4 build">
34
  <img src="https://img.shields.io/badge/requires-Blackwell-lightgrey?style=flat-square" alt="requires Blackwell">
35
  <a href="https://primitive.com"><img src="https://img.shields.io/badge/web-primitive.com-lightgrey?style=flat-square" alt="primitive.com"></a>
36
  </p>
37
 
38
+ <h3 align="center">8% smaller than the official FP8, level on knowledge, 1.4 behind on call accuracy.</h3>
39
 
40
  <p align="center">
41
  Mixed-precision quantization of <a href="https://huggingface.co/IFM/K2-Horizon-MoVA-36B-A4B">IFM/K2-Horizon-MoVA-36B-A4B</a> to
 
43
  15 of the 45 sparse layers carry NVFP4 experts; the other 30 carry FP8 with block scales.
44
  </p>
45
 
46
+ > **This is the better of our two builds on call accuracy, and it needs Blackwell.** There is also a
47
  > [pure NVFP4 build](https://huggingface.co/primitive-ai/K2-Horizon-MoVA-36B-A4B-NVFP4) at
48
  > 36.74 GB that is 7.74 GB smaller, 1.21× faster at concurrency 32, and **the only one of the two
49
+ > that runs on Ampere**. Take this one if tool calling matters most; take that one for pre-Blackwell
50
+ > hardware, the smallest footprint, or throughput under load.
51
 
52
  ---
53
 
 
55
 
56
  * 🗜️ **8% smaller than IFM's own FP8, 1.7× smaller than BF16.** 44.48 GB against 48.36 GB and
57
  74.89 GB.
58
+ * 🎯 **Knowledge is level with both references.** 87.3 against the official FP8's 86.8 and BF16's
59
+ 85.9 over 1,170 items. It is the highest number in that column and it is still a tie.
60
+ * 🧭 **The better of our two builds on tool calls.** 73.5 on call accuracy against the pure NVFP4
61
+ build's 71.8, for 7.74 GB more the one axis that separates the two (t = +2.4). Against the
62
+ official FP8 the gap is 1.4 and neither half of the suite separates on its own.
63
+ * 🧠 **Block scales, not bit width, are what moved tool calling here.** Two thirds of the expert
64
+ layers carry FP8 with `[128,128]` block scales rather than group-wise 4-bit.
 
 
65
  * 🖥️ **One card, no tensor parallelism.** Both official recipes use TP=2; this fits TP=1 with
66
  231,488 tokens of KV at 32K context.
67
  * ⚠️ **Blackwell.** Two thirds of the expert layers carry FP8 block scales and sm_80 has no FP8
68
+ tensor cores, so we neither built nor tested this one for Ampere. The pure NVFP4 build is verified
69
+ there.
70
+ * 🔧 **Serves on stock vLLM `main`, no patches and no custom kernels.** Plain `compressed-tensors`.
71
 
72
  ---
73
 
 
78
  0.28.0 predates it. Use a `main`/nightly build:
79
 
80
  ```bash
81
+ hf download primitive-ai/K2-Horizon-MoVA-36B-A4B-mixed-NVFP4-FP8 \
82
+ --local-dir ./K2-Horizon-MoVA-36B-A4B-mixed-NVFP4-FP8
83
+
84
  docker run --gpus all --ipc=host -p 8000:8000 -v $PWD:/models \
85
+ vllm/vllm-openai:nightly-8a728663c1c3eeace834a95f5654fa653cc1998c \
86
  --model /models/K2-Horizon-MoVA-36B-A4B-mixed-NVFP4-FP8 \
87
  --trust-remote-code --max-model-len 32768 \
88
  --gpu-memory-utilization 0.92 \
89
  --reasoning-parser k2_horizon
90
  ```
91
 
92
+ That image tag is the nightly every number on this page was measured on (vllm
93
+ `0.28.1rc1.dev388`). On one RTX PRO 6000 Blackwell it leaves 43.02 GiB resident for weights and
94
+ 42.39 GiB for KV — **231,488 tokens at 32K context, 7.06× concurrency**. Expect a slow first boot:
95
+ engine init takes 198 s, of which 90 s is `torch.compile`, because the FP8 block-scale path compiles
96
+ more kernels than a pure NVFP4 one (97 s and 3 s respectively for our other build).
97
 
98
  **Reasoning effort is a server-level choice on this architecture, not a per-request one.** The
99
  template emits a different tag pair per effort and `K2HorizonReasoningParser` picks one pair once
 
125
 
126
  | build | size | knowledge | call | abstain | tool calling | runs k/a | finished | out/answer |
127
  |---|---|---|---|---|---|---|---|---|
128
+ | [IFM BF16](https://huggingface.co/IFM/K2-Horizon-MoVA-36B-A4B) | 74.89 GB | 85.9 ±0.7 | 74.6 ±1.3 | 60.8 ±2.9 | 71.8 ±1.0 | 2/3 | 95.8% | 1206 |
129
+ | [IFM FP8](https://huggingface.co/IFM/K2-Horizon-MoVA-36B-A4B-FP8) | 48.36 GB | 86.8 ±0.5 | 74.9 ±1.5 | 60.4 ±2.9 | 72.0 ±0.8 | 2/6 | 96.1% | 1176 |
130
+ | **this repo** | **44.48 GB** | 87.3 ±1.0 | 73.5 ±1.7 | 58.9 ±3.1 | 70.6 ±1.4 | 2/9 | 96.3% | 1118 |
131
+ | [our pure NVFP4](https://huggingface.co/primitive-ai/K2-Horizon-MoVA-36B-A4B-NVFP4) | 36.74 GB | 86.5 ±0.5 | 71.8 ±1.0 | 60.4 ±3.7 | 69.5 ±1.4 | 2/6 | 95.6% | 1234 |
132
 
133
  `call` is accuracy on the 160 tool-calling items that require a call; `abstain` is the 40 whose
134
  correct action is to call **nothing**; `tool calling` is the two pooled as 200. We report the halves
 
136
  runs behind each row. `finished` is the share of the 1,170 knowledge items that answered inside the
137
  token budget; `out/answer` is mean output tokens.
138
 
139
+ **Knowledge is one group.** This build's 87.3 is the highest number in the column and it does not
140
+ separate from anything: against the official FP8 it is t = +0.6, at n=2 per side. Don't rank on this
 
141
  column.
142
 
143
+ **Tool calling: where the 1.4 sits.** The pooled 200-item number separates from the official FP8
144
+ (t = −2.6 over nine runs here and six there), but neither half does on its own: `call` is 1.4 low at
145
+ t = −1.7 and `abstain` is 1.5 low at t = −1.0. So the loss is small, real in aggregate, and spread
146
+ across both halves of the suite rather than concentrated in one. Our pure NVFP4 build behaves
147
+ differently there the loss is 3.1 on `call` alone (t = −4.2) and abstention is untouched.
 
148
 
149
+ It is not a formatting failure. Unparsed replies run at 14 per 1,800 here (0.78%) against 13 per
150
+ 1,200 for the official FP8 (1.08%) and 6 per 600 for BF16 (1.00%) — cleaner than either IFM build,
151
+ and our pure NVFP4 build is cleaner still at 0.75%. Thinking fired on 99–100% of items in every row.
 
152
 
153
  <details>
154
  <summary>Per-benchmark detail, both suites</summary>
 
176
  40 abstention items; the other four tool-calling benchmarks supply the 160 call items.
177
 
178
  **Where the tool-calling difference sits.** xlam/APIGen is 40.2 here against the official FP8's
179
+ 44.8, 4.6 points on 45 items and this build's largest gap against that reference. The pure NVFP4
180
  build gives up 7.0 points on the same benchmark, so this build recovers about a third of that loss.
181
  xlam items carry the longest argument lists in the suite.
182
 
 
184
 
185
  > **The noise floor, and why the run counts are in the table.** Every build compared here has at
186
  > least six agentic runs, the one exception being the BF16 reference at three. It needs to be six.
187
+ > The official FP8's tool-calling figure read 72.7 ±0.3 after three runs and 72.0 ±0.8 after six;
188
+ > this build's read 70.3 ±1.6 after three and 70.6 ±1.4 after nine. On the 1,170-item knowledge
189
+ > suite, repeat runs of a single checkpoint span up to 1.9 points, so **treat a knowledge gap of a
190
+ > point or so as unresolved.** The widest gap in that column is 1.4, between this build and BF16,
191
+ > and even that is only t = +1.6. We publish ties as ties.
192
+
193
+ Two footnotes on the table. The BF16 row was served at 20,480 context against the quants' 32,768,
194
+ because 74.89 GB of weights leaves only 81,664 tokens of KV on a 96 GB card; the generation budget
195
+ was the same 16,384 tokens for every row. And `out/answer` is a mean over a long tail: median output
196
+ is 204 tokens against a mean of 1,118, a ratio of 5.5×. That shape usually means a model that
197
+ reaches its answer and cannot stop. Here it does not the official FP8 shows 1,176 against a
198
+ median of 211 on the same items, a ratio of 5.6×, with the same ~4% of items hitting the budget.
199
+ It is how K2-Horizon reasons, and quantization did not cause it.
 
200
 
201
  ---
202
 
 
205
  Cache-free, 8,192 tokens in and 512 out, one RTX PRO 6000 Blackwell, same nightly and same serve
206
  flags as the accuracy rows. Prefix caching is disabled and every measurement runs on its own seed,
207
  so no row is reading a cache the previous one filled. These come from one sitting and drift a few
208
+ percent between sittings, so read them as a bracket. BF16 is absent because at 74.89 GB it only
209
+ serves 20,480 context on this card, which would not be the same measurement.
210
 
211
  | build | tok/s @ conc 1 | TPOT @ conc 1 | tok/s @ conc 32 | TPOT @ conc 32 | median TTFT @ conc 32 |
212
  |---|---|---|---|---|---|
 
214
  | **this repo** | 29.99 | 32.56 ms | 248.4 | 89.5 ms | 3.59 s |
215
  | [our pure NVFP4](https://huggingface.co/primitive-ai/K2-Horizon-MoVA-36B-A4B-NVFP4) | **30.45** | **32.10 ms** | **301.5** | 93.1 ms | **1.54 s** |
216
 
217
+ **Quantizing this model buys throughput under load, not single-stream latency.** Those three builds
218
+ span 11.6 GB and land within 0.71 tok/s of each other at concurrency 1. At concurrency 32 their
219
+ per-token decode cost is nearly flat too — 89.2, 89.5 and 93.1 ms, a 4.4% spread so the aggregate
220
+ differences are not a decode-rate effect. They show up in prefill and in scheduling under load,
221
+ where median time to first token falls from 4.46 s to 1.54 s across the range. Decode stays pinned
222
+ because vLLM restacks the 15.1 GB of BF16 MoVA value-experts on every forward pass whatever the
223
+ routed experts are quantized to, and that fixed cost dominates a single stream.
224
 
225
+ This build sits between the two on all five columns, which is what its size predicts. If throughput
226
+ under load matters more than call accuracy, the pure NVFP4 build is 1.21× this one at concurrency 32
227
+ and reaches first token in 1.54 s against 3.59 s.
228
 
229
  ---
230
 
 
233
  | | **this repo** | [pure NVFP4](https://huggingface.co/primitive-ai/K2-Horizon-MoVA-36B-A4B-NVFP4) |
234
  |---|---|---|
235
  | size | 44.48 GB | **36.74 GB** |
236
+ | knowledge | 87.3 ±1.0 | 86.5 ±0.5 |
237
+ | call | **73.5 ±1.7** | 71.8 ±1.0 |
238
+ | abstain | 58.9 ±3.1 | 60.4 ±3.7 |
239
+ | tool calling, pooled | 70.6 ±1.4 | 69.5 ±1.4 |
240
  | tok/s @ conc 32 | 248.4 | **301.5** |
241
  | median TTFT @ conc 32 | 3.59 s | **1.54 s** |
242
  | Blackwell | yes | yes |
243
  | **Ampere (A100)** | **no** | **yes** |
244
 
245
+ This build spends 7.74 GB, +21%, and call accuracy is the one axis that pays it back: +1.7 at
246
+ t = +2.4. The pooled tool-calling lead of 1.1 does not separate (t = +1.5), nor does knowledge
247
+ (t = +0.9). **If tool calling dominates your workload and you have 48 GB, IFM's own FP8 is still the
248
+ most accurate option** it leads this build by 1.4 on call accuracy. What this build offers against
249
+ it is 8% less memory at a gap that neither half of the suite resolves on its own.
 
250
 
251
  **On Ampere.** We have not tested this build on an A100 and do not expect FP8 block scales to load
252
  on sm_80, which has no FP8 tensor cores. The pure NVFP4 build does run there through Marlin
 
262
  table, on this card and on our other cards, comes from the one fixed protocol described above — the
263
  same 1,370 items, auto-scored, no LLM judge.
264
 
265
+ | model | shape | size | overall | knowledge | call | abstain | finished | out/answer |
266
  |---|---|---|---|---|---|---|---|---|
267
  | [Laguna-XS-2.1](https://huggingface.co/primitive-ai/Laguna-XS-2.1-mixed-NVFP4-MXFP8) | 31 B MoE | 19.3 GiB | 81.7 | 83.8 | 68.4 | 73.5 | 98.9% | 1097 |
268
  | [Nemotron-3.5-Lightning-30B-A3B](https://huggingface.co/primitive-ai/Nemotron-3.5-Lightning-30B-A3B-mixed-INT4-INT8) | 30 B MoE+Mamba | 19.2 GiB | 87.1 | 87.9 | 85.4 | 70.5 | 97.9% | 1429 |
 
270
  | [Muse-Glimmer-30B](https://huggingface.co/primitive-ai/Muse-Glimmer-30B-mixed-NVFP4) | 30 B MoE | 20.4 GiB | 86.6 | 88.8 | 78.6 | 54.5 | 99.7% | 800 |
271
  | [Qwen3.8-27B](https://huggingface.co/primitive-ai/Qwen3.8-27B-mixed-NVFP4-FP8) | 27 B dense | 20.7 GiB | 88.8 | 90.4 | 85.5 | 54.5 | 99.7% | 651 |
272
  | [Granite-4.2-30B](https://huggingface.co/primitive-ai/granite-4.2-30b-mixed-NVFP4-FP8) | 30 B dense | 18.1 GB | 85.5 | 86.2 | 85.8 | 60.8 | 98.5% | 1502 |
273
+ | [K2-Horizon-MoVA-36B-A4B NVFP4](https://huggingface.co/primitive-ai/K2-Horizon-MoVA-36B-A4B-NVFP4) | 37 B MoE+MoVA, 4 B active | 36.7 GB | 84.1 | 86.5 | 71.8 | 60.4 | 95.6% | 1234 |
274
+ | **K2-Horizon-MoVA-36B-A4B mixed** (this repo) | 37 B MoE+MoVA, 4 B active | **44.5 GB** | **84.9** | 87.3 | 73.5 | 58.9 | 96.3% | 1118 |
275
  | [Laguna-S-2.1](https://huggingface.co/primitive-ai/Laguna-S-2.1-mixed-NVFP4-MXFP8) | 110 B MoE | 64.0 GiB | 84.3 | 87.1 | 64.6 | 81.0 | 97.3% | 995 |
276
  | [Qwen3.8-Flash-Next](https://huggingface.co/primitive-ai/Qwen3.8-Flash-Next-mixed-NVFP4-FP8) | 180 B MoE, 6 B active | 183.7 GB | 90.3 | 92.2 | 84.8 | 56.7 | 99.5% | 686 |
277
 
278
  `overall` pools the two suites as 1,370 items, weighted 85.4% knowledge and 14.6% tool calling by
279
  item count. **Read it with `finished`**: `overall` scores an answer that overran the token budget as
280
  wrong, but it cannot tell you whether the model needed the room or failed to stop — `finished` and
281
+ `out/answer` separate those, and this model's 96.3% is among the lowest `finished` in the table
282
+ because it reasons in long chains. A gap under **1.0** in `overall` is a tie. Sizes are as each card
283
+ reports them, which mixes GB and GiB.
284
 
285
  ---
286
 
 
290
 
291
  | | params | share |
292
  |---|---|---|
293
+ | routed MoE experts, 45 layers × 100 × 3 × 2560×768 | 26.54 B | 71.0% |
294
  | MoVA value-experts, 45 layers × 64 × 2560×1024 | 7.55 B | 20.2% |
295
  | attention `qk_proj` / `o_proj` / `gate_proj` | 1.61 B | 4.3% |
296
  | `embed_tokens` + `lm_head`, untied, vocab 250624 | 1.28 B | 3.4% |
297
  | shared experts + the three dense MLP layers | 0.41 B | 1.1% |
298
 
299
+ Which of those pieces got which format:
300
+
301
  | tensors | count | format |
302
  |---|---|---|
303
  | routed experts on 30 of the 45 sparse layers | 9,000 | FP8 E4M3, block scales `[128,128]` |
304
  | routed experts on the other 15 sparse layers | 4,500 | NVFP4, group 16 |
305
  | MoVA `v_experts` and `v_router`; `qk_proj`/`o_proj`/`gate_proj`; `mlp.gate`; shared experts; dense layers 0–2; `lm_head`; embeddings; norms | 3,408 | BF16 |
306
 
307
+ `compressed-tensors`, top-level format `mixed-precision`, two config groups. The NVFP4 group is W4A4
308
+ and carries observed activation scales plus a tensor-level `weight_global_scale`; the FP8 group is
309
+ weight-only with block scales.
310
 
311
+ **The second-largest block cannot be quantized at all.** vLLM's MoVA attention does this on every
312
+ forward pass:
313
 
314
  ```python
315
  w1 = torch.stack([expert.weight for expert in self.v_experts], dim=0).contiguous()
 
320
  quantized `Linear` carries `weight_packed` plus scales and no `weight`, so a quantized v_expert
321
  either fails at load or feeds packed bytes to a kernel that reads them as bfloat16. IFM's own FP8
322
  ignores all 2,880 of them for the same reason. That is 20% of the model pinned to BF16 in any build,
323
+ which is why lower precision buys less here than the parameter count suggests: those 7.55 B
324
+ parameters are 15.1 GB of BF16 that every forward pass moves regardless. Per the throughput section,
325
+ that is why decode speed barely moves.
326
 
327
+ Two engine constraints shape the rest. MoVA fuses `q` and `k` into a single `qk_proj`, so those two
328
+ would have to share one scheme. And a layer's experts are quantized as a unit: vLLM's fused MoE
329
+ requires one scheme across an expert's `gate`/`up`/`down`, so the mixture here is per layer, never
330
+ per projection.
331
 
332
+ ---
 
 
333
 
334
  ## Attribution
335
 
 
338
  - Calibration: 496 conversations at seqlen 2048, used to observe activation scales.
339
  - The checkpoint carries IFM's `modeling_k2_horizon.py` and `configuration_k2_horizon.py`
340
  unchanged, so `--trust-remote-code` works for tooling that wants the reference implementation.
341
+ - Audited before publication: every fused NVFP4 group shares one `weight_global_scale`, every FP8
342
+ block-scale tensor has the shape its group declares, no activation scale is zero or NaN, and
343
+ `config.json` agrees with the tensors actually present.
344
 
345
  ---
346