jagat-primitive-org commited on
Commit
1f0c3f8
·
verified ·
1 Parent(s): 10713f4

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +105 -0
README.md ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ base_model: Qwen/Qwen3.8-Flash-Next
4
+ tags:
5
+ - qwen3.8-flash-next
6
+ - ple
7
+ - quantization
8
+ ---
9
+
10
+ # Qwen3.8-Flash-Next quantized PLE tables
11
+
12
+ The 51.2B-parameter n-gram (PLE) table is the reason this model wants ~100 GB of free host RAM:
13
+ the CPU-offload worker holds it in BF16 (95.4 GB). This repo ships the same table quantized —
14
+ **FP8 per-row (49 GB)** and **INT4 group-16 (32 GB)** — plus a two-file overlay for the
15
+ `vllm/vllm-openai:qwen38-flash-next` image that serves them memory-mapped straight from disk.
16
+ Host RAM cost becomes page cache only, reclaimable under pressure.
17
+
18
+ Built from the original BF16 tables, so it works with any checkpoint of this model that keeps
19
+ them: [our mixed NVFP4/FP8 build](https://huggingface.co/primitive-ai/Qwen3.8-Flash-Next-mixed-NVFP4-FP8),
20
+ [our plain NVFP4](https://huggingface.co/primitive-ai/Qwen3.8-Flash-Next-NVFP4), or the original
21
+ model. It does not apply to checkpoints that re-quantized the tables themselves.
22
+
23
+ ## Serve
24
+
25
+ ```bash
26
+ hf download primitive-ai/Qwen3.8-Flash-Next-PLE-quant \
27
+ worker_image_quant.py ple_layer_quant.py --local-dir .
28
+ hf download primitive-ai/Qwen3.8-Flash-Next-PLE-quant --include "ples_int4/*" --local-dir .
29
+ # (or ples_fp8/* for the FP8 table)
30
+
31
+ docker run --gpus all --ipc=host -p 8000:8000 \
32
+ -v $PWD/worker_image_quant.py:/usr/local/lib/python3.12/dist-packages/vllm/v1/ple_offload/worker.py:ro \
33
+ -v $PWD/ple_layer_quant.py:/usr/local/lib/python3.12/dist-packages/vllm/models/qwen3_8_flash_next/nvidia/ple_layer.py:ro \
34
+ -v $PWD/ples_int4:/ples_int4 -e VLLM_PLE_QUANT_DIR=/ples_int4 \
35
+ -e VLLM_PLE_CPU_OFFLOAD=1 -e VLLM_PLE_OFFLOAD_READY_TIMEOUT=3600 \
36
+ -e VLLM_GDN_DECODE_KERNEL=triton \
37
+ vllm/vllm-openai:qwen38-flash-next \
38
+ --model primitive-ai/Qwen3.8-Flash-Next-mixed-NVFP4-FP8 \
39
+ --distributed-executor-backend mp \
40
+ --gpu-memory-utilization 0.92 \
41
+ --enable-auto-tool-choice --tool-call-parser qwen3_coder \
42
+ --reasoning-parser qwen3
43
+ ```
44
+
45
+ Drop `-e VLLM_GDN_DECODE_KERNEL=triton` when serving the plain NVFP4 build. No container
46
+ memory cap needed: unlike the BF16 disk path, the quantized tables fit the page cache next to
47
+ checkpoint streaming.
48
+
49
+ ## Measured
50
+
51
+ One RTX PRO 6000 Blackwell (96 GB), 176 GB host, local NVMe, mixed NVFP4/FP8 checkpoint.
52
+ Throughput: 8K in / 512 out, prefix-cache-free, two seeds (shown a / b). Accuracy: the same
53
+ pinned 1,170-item knowledge + 200-item tool-calling protocol as the model cards, thinking on.
54
+
55
+ | table | size | host RSS | boot | tok/s @ 1 | tok/s @ 32 | TTFT @ 1 | knowledge | call acc |
56
+ |---|---|---|---|---|---|---|---|---|
57
+ | BF16, in RAM (baseline) | 95.4 GB | ~95 GB | 302 s | 84.5 / 84.4 | 516.8 / 523.6 | 569 / 573 ms | 92.2 | 84.8 (n=3) |
58
+ | FP8 per-row, mmapped | 49 GB | 52.6 GB° | 364 s | 80.3 / 80.1 | 489.7 / 500.7 | 759 / 768 ms | 92.2 | 77.5 (n=1) |
59
+ | INT4 group-16, mmapped | 32 GB | 32.9 GB° | 333 s | 80.2 / 80.1 | 483.6 / 487.9 | 663 / 671 ms | 92.9 | 79.5 (n=1) |
60
+
61
+ ° mapped file pages, reclaimable under memory pressure — not anonymous RAM. Tool-calling
62
+ single runs sit inside the suite's ±1.5 repeat spread (BF16 three-run pool: 78.0–80.5); the
63
+ BF16 column shows the published three-run mean. Generation-sanity gates passed on every
64
+ configuration.
65
+
66
+ ## Format
67
+
68
+ Sidecars are 128 shard files (`shard_N.safetensors`, 2,500,012 rows each, concatenated in
69
+ shard order) plus `META.json`. Row width 160.
70
+
71
+ | variant | tensors per shard | dequant |
72
+ |---|---|---|
73
+ | `ples_fp8` | `weight_fp8` [rows, 160] e4m3fn; `weight_scale` [rows] fp32 | `row = fp8 * scale[row]` |
74
+ | `ples_int4` | `weight_i4` [rows, 80] uint8, two nibbles, low first; `weight_scale` [rows, 10] fp16 | `row[c] = (nibble - 8) * scale[row, c // 16]` |
75
+
76
+ The overlay maps every shard with safetensors' native mmap and dequantizes only the gathered
77
+ rows (~100–200 KB per decoded token), so cold-start cost and steady-state RAM both scale with
78
+ the working set, not the table.
79
+
80
+ ## Notes
81
+
82
+ - The overlay targets this exact image; the gather hook lives in a vendored model file
83
+ (`vllm/models/qwen3_8_flash_next/nvidia/ple_layer.py`), which is why this ships as an overlay
84
+ rather than a vLLM PR. The BF16 disk path, which needs no model-file hook, is PR
85
+ [vllm-project/vllm#54070](https://github.com/vllm-project/vllm/pull/54070).
86
+ - MTP speculative decoding (`num_speculative_tokens: 3`) composes well with the quantized
87
+ tables: 129.6 tok/s single-stream on the real-prompt eval with the INT4 table, vs 142.6 with
88
+ the BF16 table in RAM and 77.5–82.3 with the BF16 table on NVMe. Speculation multiplies
89
+ gather traffic; the INT4 working set still fits the page cache where the BF16 one does not,
90
+ so quantization is what makes MTP + low-RAM hosts viable together.
91
+ - The image's stock worker cannot load quantized tables at all (it rejects
92
+ `ngram_embedding.weight_scale`), which also rules out CPU offload for checkpoints that ship
93
+ FP8 tables with a global scale.
94
+
95
+ ---
96
+
97
+ <p align="center">
98
+ <br>
99
+ <img src="https://huggingface.co/primitive-ai/Qwen3.8-Flash-Next-mixed-NVFP4-FP8/resolve/main/assets/primitive-logo.png" alt="Primitive" width="34"><br>
100
+ <sub>
101
+ <a href="https://primitive.com"><b>primitive</b></a> ·
102
+ <a href="https://huggingface.co/primitive-ai">more models</a> ·
103
+ inference economics for production LLM systems
104
+ </sub>
105
+ </p>