V100 Builds · released 2026-08-14
Qwen3.8-27B V100 Quants
The whole 27B VLM packed to 19.5 GB, vision and MTP head intact, on a pair of 32 GB V100s.
- W4A16
- 19.5 GB W4A16vision tower and MTP head intact
- MTP acceptance
- 92.5% MTP acceptanceK=2 drafts on SM70
- gsm8k
- 0.99 gsm8k100 items, 5-shot; 15/15 factual
- NVFP4
- 25.2 GB NVFP4loads on Volta (compute capability 7.0)
Qwen3.8-27B is the compact dense model of the Qwen3.8 generation: a native vision-language model with a 3:1 GatedDeltaNet/attention hybrid, an in-checkpoint MTP head, and 262K native context. I quantized the whole thing for Volta without stripping anything. The vision tower stays BF16, the MTP speculative head is grafted back verbatim, and the calibration runs in thinking mode so the quant does not corrupt the think tags. 55 GB of BF16 becomes 19.5 GB of INT4, which is what puts it on two 32 GB V100s with context headroom.
There are two formats. W4A16 AWQ is the one most people want: it serves on stock vLLM on any Ampere-or-newer GPU with no ceremony, and on 2x V100 through the SM70 TurboMind dequant path in 1Cat-vLLM. NVFP4 is the second, built as compressed-tensors nvfp4-pack-quantized specifically so it loads at compute capability 7.0 where ModelOpt NVFP4 refuses Volta outright, and runs native on Blackwell FP4 tensor cores. The NVFP4 recipe was not guessed; it was the winner of a five-recipe bake-off against the other public Qwen3.8-27B NVFP4 quants, all on one rig under one battery.
This runs on stock upstream 1Cat-vLLM. No engine fork, no custom wheel. The one GitHub repo that goes with it, qwen-3.8-v100, holds the 2x V100 launch profile pinned to an upstream release and an HF revision, so you can reproduce the serving setup without reverse-engineering flags.
- runs on
- 2× V100Tesla V100 32GB
- base model
- Qwen/Qwen3.8-27B
- engine
- 1Cat-vLLM (SM70), stock upstream · 1Cat-vLLM 1.5.1 (upstream release)
- links
- philbert440/Qwen3.8-27B-W4A16-AWQ (Hugging Face)philbert440/Qwen3.8-27B-NVFP4 (Hugging Face)Qwen/Qwen3.8-27B (base model)philbert440/qwen-3.8-v100 (launch profile)1CatAI/1Cat-vLLM1Cat-vLLM releasesllm-compressorMagpie-Reasoning-V2-CoT (calibration set)
- stack
- llm-compressor (AWQ + GPTQ)
- compressed-tensors (W4A16 + NVFP4)
- 1Cat-vLLM (SM70 TurboMind)
- MTP speculative decoding
- FP8 E5M2 KV cache
01
Research log
W4A16 live, NVFP4 in progress
Published the W4A16 AWQ card: whole model INT4 at 19.5 GB, vision and MTP intact, think-mode calibrated. NVFP4 was still quantizing (layer 62 of 65 that day). Both got their own cards with V100 numbers once validated.
Full V100 validation
Ran the battery on 2x V100 through 1Cat-vLLM: coherence, think-tag discipline, image understanding, GSM8K, long-form generation, and MTP in both draft modes. All checks passed. The stock prod serve later measured GSM8K 0.99 over 100 items.
Tokenizer fix across 15 repos
A reporter hit an HTTP 400 on a 2500x1406 image: the calibration save had left an active truncation block in tokenizer.json. Restored both tokenizer files byte-for-byte from the base model and pushed the fix to all 15 affected repos.
NVFP4 bake-off
Ran five candidate NVFP4 recipes against the Inferact and unsloth public quants on one rig with one battery. Found the GatedDeltaNet in_proj projections are the sensitive spot and calibration is the real quality lever, not which layers you keep in 16-bit.
NVFP4 v2 shipped
Replaced the NVFP4 checkpoint with recipe C, the bake-off winner: GDN in_proj kept BF16, a 4x larger and more diverse thinking-mode calibration set, act-order and MSE observer. Confabulation dropped 39 to 27 of 75 and GSM8K rose 0.940 to 0.965, at 96% of v1's single-stream V100 speed.
Serving moved to 1Cat-vLLM 1.5.0
Cut the service that runs this checkpoint over from the 1.3.0 line to 1.5.0. Functional validation passed clean; a warm throughput rerun was still pending at cutover, so the card's 1.2.2 tables stand as the published numbers.
Upstream 1.5.1
1Cat-vLLM tagged 1.5.1. Per the always-newest-engine rule the recommended base moved to it; the 1.5.1 bundled profile prefers FP8 E4M3 KV.
built on the work of
- The Qwen team for Qwen3.8-27B and the official BF16 release (Apache-2.0).
- The llm-compressor project (vLLM) for AWQModifier and GPTQModifier, and for the GatedDeltaNet calibration issue threads.
- 1CatAI for 1Cat-vLLM and its SM70 TurboMind and NVFP4 paths, which serve these checkpoints on Volta.
- Magpie-Align for the Magpie-Reasoning CoT dataset used for thinking-mode calibration.
- @elBuffo for reporting the tokenizer truncation bug.
02
Get it running
you'll need
- 2x V100 32GB (TP2) for the SM70 path. The W4A16 body is 19.5 GB, NVFP4 is 25.2 GB, both fit two cards with room for 32K+ context at gpu-memory-utilization 0.78.
- Any Ampere-or-newer GPU runs W4A16 on stock vLLM; NVFP4 runs native on Blackwell (SM100+) FP4 tensor cores, and via dequant on Ampere/Hopper.
- ninja on PATH: the SM70 dequant kernels JIT-compile at startup. Boot takes 3-5 minutes (weight load + torch.compile + CUDA graph capture).
- On V100 pairs without NVLink, NCCL_P2P_DISABLE=1 is not optional; leaving peer-to-peer on costs about 4x throughput.
- 1
Pick a format
W4A16 AWQ if you have Ampere-or-newer GPUs or a pair of V100s and want the simplest path; it is the format with the downloads behind it (over 64,000). NVFP4 if you are on Blackwell and want native FP4, or if you specifically need the NVFP4 build that loads on Volta. Both carry the vision tower and the MTP head.
- 2
Download the weights
W4A16 is 19.5 GB (a packed body plus a 0.85 GB BF16 MTP head). If you cloned before 2026-08-15, re-fetch tokenizer.json and tokenizer_config.json; an early calibration run shipped a broken truncation block that failed large image inputs.
shellhf download philbert440/Qwen3.8-27B-W4A16-AWQ --local-dir ./Qwen3.8-27B-W4A16-AWQphilbert440/Qwen3.8-27B-W4A16-AWQphilbert440/Qwen3.8-27B-NVFP4
- 3
Stock vLLM on modern GPUs
compressed-tensors W4A16 is natively supported, so on Ampere or newer there is nothing special to do. Add the MTP speculative config to get the draft head working. NVFP4 runs the same way on Blackwell; on Ampere/Hopper it falls back to a dequant path.
shellvllm serve philbert440/Qwen3.8-27B-W4A16-AWQ --max-model-len 32768 \ --speculative-config '{"method": "mtp", "num_speculative_tokens": 2}' - 4
Install the engine for 2x V100
Volta has no INT4 tensor-core path in stock vLLM, so the SM70 route is 1Cat-vLLM's TurboMind dequant path, from the stock upstream wheel; there is no custom wheel to build. Clone qwen-3.8-v100 and run its install.sh: it downloads the 1.5.1 release wheel, checks it against the pinned sha256, and sets up a Python 3.12 venv with the wheel and ninja (ninja has to be on PATH for the JIT kernels). The pip line below is the same thing by hand.
shellgit clone https://github.com/philbert440/qwen-3.8-v100 && cd qwen-3.8-v100 ./install.sh # by hand: uv pip install https://github.com/1CatAI/1Cat-vLLM/releases/download/v1.5.1/1cat_vllm-1.5.1-cp312-cp312-linux_x86_64.whl ninja - 5
Launch on 2x V100 (TP2, MTP)
The default profile, tp2-card, is the model card's SM70 serve command verbatim: TP2, FP8 E5M2 KV, 32K context, MTP with 2 draft tokens, utilization 0.78, plus the env a V100 pair needs. download.sh fetches the checkpoint at its pinned HF revision. Extra arguments to serve.sh go to vllm serve after the profile, so they override it. The raw command it runs is below the first two lines.
shell./download.sh w4a16 ./Qwen3.8-27B-W4A16-AWQ QWEN38_MODEL=./Qwen3.8-27B-W4A16-AWQ ./serve.sh # what the tp2-card profile runs: VLLM_SM70_QUANT_BACKEND=turbomind VLLM_SM70_FLASH_ATTN_V100=1 \ VLLM_SM70_MTP_DYNAMIC_DRAFT_VOCAB_DEFAULT=0 NCCL_P2P_DISABLE=1 \ vllm serve ./Qwen3.8-27B-W4A16-AWQ --dtype half --attention-backend FLASH_ATTN_V100 \ --tensor-parallel-size 2 --gpu-memory-utilization 0.78 \ --max-model-len 32768 --kv-cache-dtype fp8_e5m2 \ --enable-prefix-caching --reasoning-parser qwen3 \ --speculative-config '{"method":"mtp","num_speculative_tokens":2,"attention_backend":"FLASH_ATTN_V100","draft_sample_method":"probabilistic"}'
03
Downloads
| Variant | Format | Runs on | Size | DL / 30d |
|---|---|---|---|---|
| W4A16 AWQ, the 2x V100 default philbert440/Qwen3.8-27B-W4A16-AWQ | W4A16 AWQ (compressed-tensors, g128 asym) | 2× V100 | 19.5 GB | 115k |
| NVFP4, Blackwell-native, loads on SM70 philbert440/Qwen3.8-27B-NVFP4 | NVFP4 (compressed-tensors nvfp4-pack-quantized) | Blackwell | 25.2 GB | 288 |
04
Inference stack
The recommendation is stock upstream 1Cat-vLLM. These checkpoints need no engine fork and no custom wheel; the SM70 TurboMind and NVFP4 paths they rely on are in the upstream release.
qwen-3.8-v100 is not an engine fork. It holds the 2x V100 launch profile, the serve script, its env and flags, and a smoke test, pinned to a specific upstream 1Cat-vLLM release and HF revision. Its releases tag that pairing; there is no wheel in it.
The published model-card serve command and the throughput table were measured on 1Cat-vLLM 1.2.2. The launch profile pins 1.5.1, the newest upstream release, by wheel sha256, and keeps the cards' command verbatim, FP8 E5M2 KV included; the 1.5.1 bundled profile would prefer E4M3. Its release tag 1cat-v1.5.1 names that pairing.
05
Recipe
5.1W4A16 AWQ, the whole hybrid
llm-compressor AWQModifier, W4A16, group 128, asymmetric, with an MSE observer rather than min-max. 400 linears are quantized: all attention and MLP projections including the 144 GatedDeltaNet projections. The vision tower, the linear-attention in_proj_a/b, embeddings, lm_head and the MTP head stay BF16.
AWQ smoothing has to run across the entire hybrid topology, all four projection groups on the 48 GatedDeltaNet layers, not just the vanilla-attention subset. Two things make that work on this architecture: llm-compressor pinned to 0.12.1.dev30, because later 0.12.x regresses and crashes replaying the linear-attention smoothing mapping, and apply_mask_to_padding_states neutralized during calibration, because fx tracing cannot handle its shape-dependent control flow and the batches are size 1 anyway.
Calibration is 256 Magpie-Reasoning CoT samples at 1024 tokens, applied with thinking on. A thinking model calibrated with thinking off sees an empty think block on every sample, and that calibration/deployment mismatch is documented to corrupt think-tag behavior after quantization. This build never has the mismatch, and the think-tag battery confirms it.
5.2MTP head grafted back
transformers drops mtp.* at load time, so the quantizer never sees the head. It is grafted back verbatim in BF16 as model-mtp.safetensors and listed in quantization_config.ignore. A high-precision MTP head is standard practice: it sits at the end of the network and drives speculative decoding, where draft quality sets the acceptance rate directly.
Speculative decoding over the packed body was validated on SM70 at 92.5% draft acceptance with K=2. There is one MTP layer; higher num_speculative_tokens reuses it with decaying acceptance, and K=2 is the sweet spot on V100.
5.3NVFP4, chosen by bake-off
NVFP4 is GPTQ, Hessian-based and sequential over the decoder layers, with act-order on weights and an MSE scale observer, calibrated on 768 thinking-mode CoT samples plus 256 Wikipedia passages at 2048 tokens. The format is compressed-tensors nvfp4-pack-quantized: E2M1 4-bit weights, FP8-E4M3 per-group scales at group 16, FP32 per-tensor global. That format loads at capability 7.0; ModelOpt-exported NVFP4 needs 7.5+ and rejects Volta.
The recipe is recipe C out of a five-candidate campaign. What the campaign taught: the GatedDeltaNet in_proj_qkv and in_proj_z projections are the quantization-sensitive spot, and keeping them in BF16 closes most of the quality gap for about 6% speed. Keeping the full-attention layers in 16-bit buys nothing measurable and costs about 10%. AWQ smoothing before GPTQ gives a perfect factual score but does not move confabulation or GSM8K. The real quality lever is calibration: more, and more diverse, thinking-mode data with act-order and an MSE observer.
5.4Tokenizer fidelity
A calibration run that calls save_pretrained writes an active truncation block into tokenizer.json with max_length set to the calibration sequence length, and transformers 5.x also rewrites the pre-tokenizer regex and reformats tokenizer_config.json. Vision inputs longer than that limit then fail with a token-count mismatch that surfaces as an HTTP 400 from vLLM. Every quant script here now copies tokenizer.json and tokenizer_config.json verbatim from the base model after the save.
This was fixed retroactively across 15 affected HF repos, and the fix is verified against the 2500x1406 image that originally exposed it. The vocab, merges and added tokens were always identical to the base model; this was a metadata-only restore.
06
Results
Warm serve, fixed-length generations via ignore_eos, official Qwen3.8 sampling per mode, varied prompts. Mean tokens/s with sd. Quality is identical in both draft modes; spec-decode verification rejection-samples against the target, so only acceptance differs.
| Regime | greedy draft | probabilistic draft |
|---|---|---|
| 512-tok, thinking (n=10) | 55.6 +/- 1.7 | 59.3 +/- 1.4 |
| 2048-tok, thinking (n=3) | 53.2 +/- 1.8 | 56.3 +/- 1.1 |
| 512-tok, instruct (n=6) | 54.7 +/- 1.9 | 55.5 +/- 1.5 |
| 4-way concurrent 512-tok, aggregate (n=3) | 161.9 +/- 20.6 | 164.8 +/- 23.4 |
| Mean acceptance length, whole workload | 2.34 | 2.52 |
measured on: 2x V100-32GB, TP2, fp8_e5m2 KV, max_num_seqs 4, MTP K=2; 1Cat-vLLM 1.2.2
One rig, one battery: our recipes against the other public Qwen3.8-27B NVFP4 quants. Quality is a 150-item hallucination probe (75 factual, 75 unanswerable, grok-4.3 judge) and GSM8K strict-match on 200. tok/s columns are 512-tok thinking / 2048-tok thinking / 512-tok instruct / 4-way aggregate. Noise floor is +/-4 confab probes, +/-1.5 GSM8K points, +/-5% tok/s.
| Checkpoint | factual | confab (of 75) | GSM8K | tok/s |
|---|---|---|---|---|
| this repo (v2 = recipe C) | 0.973 | 27 | 0.965 | 47.1 / 42.3 / 44.7 / 126.6 |
| this repo v1 (first build) | 0.987 | 39 | 0.940 | 48.9 / 48.0 / 46.2 / 137.9 |
| Inferact NVFP4 (ModelOpt) | 0.973 | 34 | 0.950 | 46.7 / 43.8 / 43.7 / 137.5 |
| unsloth NVFP4 (compressed-tensors, mixed) | 0.973 | 29 | 0.955 | 34.4 / 35.1 / 33.8 / 107.1 |
| RadixArk NVFP4 (ModelOpt, FP8 attn) | - | - | - | does not load on SM70 |
| recipe A (GDN in_proj kept fp16) | 0.987 | 30 | 0.950 | 46.1 / 44.6 / 45.3 / 136.5 |
| recipe B (A + full-attn fp16) | 0.973 | 31 | 0.955 | 41.9 / 38.9 / 40.8 / 124.9 |
| recipe D (AWQ smoothing then GPTQ) | 1.000 | 30 | 0.950 | 45.1 / 42.1 / 42.5 / 130.4 |
| recipe E (B ignore-set + C calibration) | 0.973 | 24 | 0.950 | 42.0 / 39.1 / 39.4 / 127.4 |
measured on: 2x V100-32GB, TP2, fp8_e5m2 KV, MTP K=2 greedy, piecewise graphs; 1Cat-vLLM main (383bbdd)
GSM8K via lm-eval, 100 items, 5-shot, 3072-token budget. Factual and confabulation are LLM-judged: 15 answerable questions scored for accuracy, 15 unanswerable scored for whether the model made something up (refusing is the right answer).
| Metric | Value |
|---|---|
| GSM8K, flexible-extract | 0.99 |
| GSM8K, strict-match | 0.99 |
| Factual accuracy (15) | 1.00 (0 wrong) |
| Confabulation (15 unanswerable) | 0.067 (14/15 refused) |
| Think-tag leakage with thinking off | zero |
| Vision through the VLM path | pass |
| Degeneration / repetition | none |
measured on: 2x V100-32GB, TP2, fp8_e5m2 KV; 1Cat-vLLM 1.2.2
From the Qwen team's Qwen3.8-27B card. Quantization applies on top of these; they are not re-measured on these checkpoints. Shown against Qwen3.6-27B for context.
| Benchmark | Qwen3.8-27B | Qwen3.6-27B |
|---|---|---|
| Terminal Bench 2.1 (Terminus) | 73.0 | 63.4 |
| SWE-bench Pro | 53.5 | 57.6 |
| NL2Repo-Bench | 42.3 | 36.2 |
| GPQA Diamond | 89.2 | 87.8 |
| HLE | 30.8 | 24.0 |
| LiveCodeBench v6 | 83.9 | 89.6 |
| OmniDocBench 1.5 (VL) | 91.1 | 89.4 |
| RealWorldQA (VL) | 85.9 | 84.1 |
measured on: Qwen official BF16 (not re-measured on this quant)
07
Findings
- The calibration run's save_pretrained wrote an active truncation block into tokenizer.json, and transformers 5 also drifted the pre-tokenizer regex. Image inputs larger than the truncation limit then failed with a token-count mismatch, an HTTP 400 out of vLLM. It hit 15 repos before it was caught and fixed by restoring the two tokenizer files verbatim from the base model.
- NVFP4 has a CUDA-graph sizing trap, not a format flaw. With MTP each sequence schedules K+1 tokens per step, so an explicit cudagraph_capture_sizes below max_num_seqs times (K+1) pushes concurrent decode off CUDA graphs and collapses aggregate throughput about 3x. It reproduces identically on the W4A16 sibling. Engine-default auto sizing is correct; do not hand-set the capture sizes small.
- ModelOpt-exported NVFP4 does not run on Volta: it requires compute capability 7.5+ and its FP8 attention path has no SM70 kernel. The RadixArk checkpoint would not load at all. Building NVFP4 as compressed-tensors nvfp4-pack-quantized instead is what lets capability 7.0 serve it.
- The MTP head crashed generation when it ran in bf16 under an earlier engine build; it was fixed in a later point release, and the bf16-head regression check is the first step of the MTP test sequence now.
- On a V100 pair without NVLink, leaving NCCL peer-to-peer enabled cost roughly 4x throughput. NCCL_P2P_DISABLE=1 is mandatory there.
- VLLM_SM70_MTP_DYNAMIC_DRAFT_VOCAB_DEFAULT=0 is required whenever max_num_seqs is greater than 1 with MTP; the dynamic draft vocab guard otherwise forces max_num_seqs to 1 at boot.
- The model card still names 1Cat-vLLM 1.2.2 as the validated engine. The service that runs this checkpoint has since moved up through 1.5.0 and onto the 1.5.1 line; the throughput tables here are the 1.2.2 numbers and have not been re-measured on 1.5.1 single-stream.