Downloads · 30 days
166
20% of all-time downloads
gratex/Qwen3.8-27B-DFlash2-W4A16-g128-sym-GPTQ
Qwen3.8-27B-DFlash2-W4A16-g128-sym-GPTQ is a machine learning model from gratex. Use it for the machine learning task on the model card, and read the license before you ship it in a product. The card lists the license as apache-2.0.
This repository contains a 4-bit weight-only quantized draft model for speculative decoding with Qwen3.8-27B. The drafter implements the DFlash2 (block diffusion) architecture, which predicts a block of tokens in a si…
Downloads · 30 days
166
20% of all-time downloads
All-time downloads
822
Public
Parameters
1.9B
1.3 GB on disk
Likes
2
Public
Click a slice to open those files.
.safetensors1.3 GB · 100%
How the weights are stored.
I321.7B · 90%
From the Hugging Face model README
This repository contains a 4-bit weight-only quantized draft model for speculative decoding with Qwen3.8-27B. The drafter implements the DFlash2 (block diffusion) architecture, which predicts a block of tokens in a single forward pass and uses a lightweight path selector to trace a coherent sequence through the candidate tokens.
The drafter shares the target model's embed_tokens and lm_head; neither is shipped here, which keeps the footprint minimal.
| Property | Value |
|---|---|
| Base draft model | incoai/Qwen3.8-27B-DFlash2 |
| Target model | Qwen/Qwen3.8-27B, or any Qwen3.8-27B quantization |
| Quantization | W4A16 (4-bit weights, BF16 activations), group_size=128, symmetric |
| Format | compressed-tensors pack-quantized (Marlin-compatible) |
| Quantized size | 1.19 GB (vs 3.85 GB BF16, a 3.2× reduction) |
| Architecture | DFlash2DraftModel (5 Qwen3-style layers) |
| Draft layers | 5 |
| Hidden size | 5,120 |
| Intermediate size | 17,408 |
| Attention heads | 32 (query), 8 (key/value, GQA) |
| Head dimension | 128 |
| Vocabulary size | 248,320 |
| Block size | 8 (1 verified + 7 speculative tokens) |
| Target layers | [5, 19, 33, 47, 61] of the 64-layer target model |
| Path selector | Bilinear attention, rank=256, top-16 candidates |
| Convolution | Two-tap dynamic convolution (group_size=16) |
| Attention | Sliding window (2048), bidirectional (is_causal=false) |
| License | Apache 2.0 |
All 35 linear layers across the five draft layers are quantized to INT4:
| Component | Precision | Count |
|---|---|---|
layers.N.self_attn.{q,k,v,o}_proj | INT4 g128 sym | 5 × 4 = 20 |
layers.N.mlp.{gate,up,down}_proj | INT4 g128 sym | 5 × 3 = 15 |
fc (target hidden state projection, 5120 × 25600) | INT4 g128 sym | 1 |
The following components are preserved in BF16:
| Component | Reason |
|---|---|
candidate_selector.* (codebooks, hidden_projection) | Gather-based lookup, not a linear layer |
*.kernel_projection (attention_conv, mlp_conv) | Grouped convolution, not a linear layer |
| All norms (input_layernorm, post_attention_layernorm, etc.) | Non-linear |
*.base_kernel (conv kernels) | Convolution kernels |
rotary_emb.inv_freq | RoPE frequencies |
Benchmarks were run on a single RTX 5090 (32 GB) with gratex/Qwen3.8-27B-W4A16-g128-sym-GPTQ as the target model. Prompts use unique random seeds to prevent prefix-cache hits from skewing the results. Each configuration was measured three times.
| Config | C=1 tok/s | C=1 acceptance | C=8 tok/s | C=8 acceptance | KV cache tokens |
|---|---|---|---|---|---|
| No speculative decoding | 88.8 | — | 577 | — | 79,510 |
| spec=3, fp8 KV, gpu_mem=0.98 | 185 | 70.0% (2.10/3) | 995 | 69.5% (2.09/3) | 58,173 |
| spec=7, fp8 KV, gpu_mem=0.98 | 260 | 46.8% (3.28/7) | 868 | 46.3% (3.24/7) | 38,751 |
| spec=3, bf16 KV, gpu_mem=0.90 | 189 | 69.9% (2.10/3) | 1,013 | 70.5% (2.11/3) | 31,495 |
| spec=7, bf16 KV, gpu_mem=0.90 | 270 | 47.3% (3.31/7) | 776 | 47.0% (3.29/7) | 22,454 |
| Config | C=1 speedup | C=8 speedup |
|---|---|---|
| spec=3, fp8 KV | 2.08× | 1.72× |
| spec=7, fp8 KV | 2.93× | 1.50× |
| spec=3, bf16 KV | 2.13× | 1.75× |
| spec=7, bf16 KV | 3.04× | 1.34× |
num_speculative_tokensThe optimal number of speculative tokens depends on concurrency:
num_speculative_tokens=7 gives the maximum speedup (2.9–3.0×).num_speculative_tokens=3 gives the maximum speedup (1.72–1.75×), because smaller draft blocks leave more KV cache for concurrent requests.num_speculative_tokens_per_batch_size to switch automatically based on batch size (see the vLLM speculative decoding docs).Using --kv-cache-dtype fp8_e4m3 increases KV cache capacity by roughly 85% with no measurable impact on acceptance or throughput. This is recommended for multi-user scenarios.
vllm/vllm-openai:cu129-nightly Docker image (built after 2026-08-21) includes this support.docker run -d --name vllm-dflash2 \
--runtime=nvidia --gpus '"device=0"' \
-p 8000:8000 \
-v /path/to/target-model:/workspace/base \
-v /path/to/this-model:/workspace/draft \
-v ./scripts/check_drafter.py:/tmp/check_drafter.py \
-v ./scripts/apply_dense_kv_fix.py:/tmp/apply_dense_kv_fix.py \
--ipc=host --shm-size=16g \
--entrypoint bash \
vllm/vllm-openai:cu129-nightly \
-c 'python3 /tmp/check_drafter.py /workspace/draft && \
python3 /tmp/apply_dense_kv_fix.py && \
exec vllm serve /workspace/base \
--speculative-config "{\"method\":\"dflash\",\"model\":\"/workspace/draft\",\"num_speculative_tokens\":3}" \
--trust-remote-code --dtype bfloat16 --max-model-len 8192 \
--kv-cache-dtype fp8_e4m3 --gpu-memory-utilization 0.98 \
--max-num-seqs 8 --max-num-batched-tokens 2048 \
--enable-auto-tool-choice --tool-call-parser qwen3_xml --reasoning-parser qwen3'
Allow roughly 240 seconds for model loading and CUDA graph compilation, then verify with:
curl http://localhost:8000/health
Due to vLLM issue #51581, the DFlash2 loader in qwen3_dflash.py slices qkv_proj.weight directly, which fails when the drafter is quantized (packed weights have no .weight attribute, or .weight is packed as uint8/float8). A patch is therefore required.
The patch adds a _dense_kv_rows() helper that dequantizes the packed qkv_proj before slicing. It is included in this repository at scripts/apply_dense_kv_fix.py.
Run check_drafter.py and apply_dense_kv_fix.py before starting vLLM, as shown in the Quick Start above.
All scripts live in scripts/.
apply_dense_kv_fix.py — vLLM Patch (v4)Patches qwen3_dflash.py to fix bug #51581 for quantized DFlash2 drafter formats. It injects a _dense_kv_rows() helper that dequantizes the fused QKV projection before slicing, dispatching on the quantization format:
| Format | Tier | Dequant path |
|---|---|---|
| Unquantized (bf16/fp16/fp32) | 1 | Direct slice (fast path) |
| FP8 (e4m3/e5m2) | 2 | weight * weight_scale (per-tensor / per-channel / per-shard[3] / block) |
| W4A16 GPTQ/AWQ (INT32 packed) | 3 | unpack_from_int32 + group scales |
| NVFP4 (compressed-tensors, W4A16) | 4 | E2M1 LUT + FP8 group scale × 1/global |
| MXFP4 (compressed-tensors, W4A16) | 5 | E2M1 LUT + E8M0 scale |
Every path either returns a valid tensor or raises ValueError with diagnostics. Formats not yet validated (for example ModelOpt NVFP4 via the weight_scale_2 marker, bitsandbytes, GGUF) fail loudly with a message that names the supported alternatives.
The patch was validated on hardware (RTX 5090, vLLM nightly) against three target quantizations:
| Target model | BF16 (52 GB, CPU offload) | W4A16 g128 (19 GB) | NVFP4 (22 GB) |
|---|---|---|---|
| DFlash2 drafter (BF16) | 63.3% | 57.5% | 54.0% |
| W4A16 GPTQ drafter | 58.0% | 61.1% | 60.7% |
| NVFP4 drafter | 64.7% | 53.2% | 62.1% |
| FP8 drafter | 61.8% | 56.0% | 60.2% |
Values are draft-token acceptance rates. All 12 combinations boot and draft correctly.
check_drafter.py — Pre-flight Completeness CheckA DFlash2 drafter that has lost candidate_selector, fc, or hidden_norm (for example through a naive transformers/llmcompressor re-quantization) loads in vLLM without error but yields 0% speculative acceptance. This script verifies that the checkpoint contains the required modules before vLLM starts:
python3 scripts/check_drafter.py /path/to/drafter
# Exit 0 = complete, 1 = incomplete (message printed), 2 = invalid path
quant_dflash2.py — RTN/GPTQ QuantizationThe recommended way to quantize a drafter while preserving all DFlash2 modules. See "Reproducing the Quantization" below.
bench_dflash2_conc.py — Benchmark HarnessMeasures throughput and acceptance at a given concurrency. See "Running Benchmarks".
| Script | Purpose |
|---|---|
gptq_utils.py | GPTQ and RTN quantization primitives (used by quant_dflash2.py) |
launch_vllm_dflash2.sh | Example Docker launch script |
quant_nvfp4.py | Manual NVFP4 (W4A16) quantization preserving all DFlash2 modules |
quant_fp8.py | Manual FP8 (E4M3) quantization preserving all DFlash2 modules |
Note on transformers/llmcompressor: their quantizers load the drafter through transformers, which does not recognize the DFlash2 architecture and silently omits candidate_selector.*, fc, and hidden_norm from the output checkpoint, producing a drafter with 0% acceptance and no error. The manual scripts in this repository quantize the linear weights directly from the safetensors while preserving every other module.
├── model.safetensors # Quantized drafter weights (1.19 GB)
├── config.json # Model config with quantization_config
├── README.md # This file
└── scripts/
├── apply_dense_kv_fix.py # vLLM patch (v4, universal quantization support)
├── check_drafter.py # Pre-flight completeness check
├── quant_dflash2.py # RTN/GPTQ quantization script
├── gptq_utils.py # GPTQ + RTN quantization primitives
├── quant_nvfp4.py # NVFP4 quantization (preserves all modules)
├── quant_fp8.py # FP8 quantization (preserves all modules)
├── bench_dflash2_conc.py # Benchmark script (concurrency + acceptance)
└── launch_vllm_dflash2.sh # Example Docker launch script
# Install dependencies
pip install compressed-tensors safetensors torch
# Quantize (RTN — no calibration data required)
python scripts/quant_dflash2.py \
incoai/Qwen3.8-27B-DFlash2 \
./output \
--rtn --bits 4 --fc-bits 4 --group 128
The alternative-format scripts take an input drafter directory and an output directory:
# FP8 (E4M3, per-tensor)
python scripts/quant_fp8.py /path/to/bf16-drafter ./fp8-output
# NVFP4 (E2M1 + FP8 group scales, W4A16)
python scripts/quant_nvfp4.py /path/to/bf16-drafter ./nvfp4-output
# MXFP4 (E2M1 + E8M0 scales, W4A16)
python scripts/quant_mxfp4.py /path/to/bf16-drafter ./mxfp4-output
All three preserve candidate_selector, fc, hidden_norm, and the convolution kernels; only the linear projection weights are quantized. The output is a compressed-tensors checkpoint readable by the patched vLLM loader.
# Start vLLM (see above), then:
python scripts/bench_dflash2_conc.py # example: python scripts/bench_dflash2_conc.py 3 8
| Symptom | Cause | Fix |
|---|---|---|
| 0% acceptance, no error | Drafter lost candidate_selector/fc/hidden_norm (bad re-quantization) | Run scripts/check_drafter.py; re-quantize with quant_dflash2.py or use this checkpoint |
Tried to load weights of size [5120,2560] to a parameter of size [5120,2400] | 3-bit (or non-power-of-2) pack-quantized INT not supported by vLLM | Use a 4-bit (or FP8/NVFP4) drafter |
ModelOpt NVFP4 (weight_scale_2) error | ModelOpt NVFP4 format not yet validated by the patch | Use compressed-tensors NVFP4 (quant_nvfp4.py) |
KV cache too small for max_model_len | BF16 drafter on a small card | Reduce --max-model-len or add --cpu-offload-gb |
| 52 GB BF16 target does not fit on a 32 GB card | Model weights exceed VRAM | Use the W4A16 (19 GB) or NVFP4 (22 GB) target, or --cpu-offload-gb |
Apache 2.0, following the original DFlash2 drafter license.