Qwen3.8-27B-DSpark-NVFP4

NVFP4-quantized DSpark drafter for gittensor-model-hub/Qwen3.8-27B-NVFP4-RTX5090.

Mixed-precision NVFP4 via NVIDIA ModelOpt: MLP and attention output projections at 4 bits, everything precision-sensitive left in BF16.

Retrained so the drafter sees what the model actually serves. The previous release was trained on a corpus with two mismatches against inference: tool examples used Hermes-style JSON (<tool_call>{"name":...}) while serving emits XML (<function=…><parameter=…>), and prompts were rendered with a generic template carrying no think blocks, no reasoning-effort preamble and no tools preamble. Both are now closed β€” every response is regenerated on-policy through the published chat template.

Previous release This model Ξ”
Agentic tool calling 3.299 3.766 +14.2%
Held-out accept length 2.761 2.886 +4.5%
Throughput 150.74 tok/s 155.75 tok/s +3.3%
Checkpoint size 1.30 GB 1.30 GB β€”

Same size, same recipe, same behaviour β€” the gain is purely in how often the target accepts a drafted block.


Results

RTX 5090 32 GB Β· concurrency 1 Β· 64K context Β· FP8 KV Β· 240 held-out prompts, identical across all profiles.

Profile tok/s Drafter
This model 155.75 1.41 GB
Previous release 150.74 1.41 GB
BF16 drafter 141.99 2.72 GB
Stock RadixArk DSpark 139.35 2.72 GB
Built-in MTP head 136.90 5.53 GB
No speculation 81.58 β€”

1.91Γ— the decode throughput of the same checkpoint without speculation.

Throughput for the top two rows was measured cold in one session; the older rows come from earlier sessions, where run-to-run variance on this harness is roughly 2%.

Per domain

Acceptance is measured per request with the prefix cache flushed between requests, derived from cumulative verify counters rather than a sampled gauge.

Domain Previous This model Ξ”
Math 3.810 4.388 +15.2%
Coding 3.729 3.804 +2.0%
JSON / structured output 3.328 3.571 +7.3%
Chat 2.305 2.450 +6.3%
Long-context 2.484 2.334 βˆ’6.1%
Instruction 2.195 2.323 +5.9%
Overall 2.761 2.886 +4.5%

Long-context is the one regression. The training corpus caps sequences at 2,048 tokens, so it was never well represented, and the shift toward agentic and think-block data appears to have cost it.

Agentic tool calling

Real tool use β€” tools declared, <tool_call> XML emitted, tool responses replayed β€” measured on 60 scenarios across 10 tool schemas. This is the workload the retraining targeted, and it improved in every phase:

Phase Previous This model Ξ”
Parallel calls 4.169 5.075 +21.7%
Initial call 3.683 4.302 +16.8%
Error recovery 3.028 3.493 +15.4%
After a tool result 3.524 3.895 +10.5%
Second call in a loop 3.155 3.445 +9.2%
Two-step chain 2.605 2.816 +8.1%
Overall 3.299 3.766 +14.2%

Tool-call emission rate is unchanged (38/60 on both), so this is an acceptance gain rather than a change in what the model decides to do.

Note that the "JSON / structured output" row above is schema-constrained generation, not tool calling β€” those held-out prompts declare no tools. It was previously labelled "Tool calling", which understated the drafter on the workload it is named after.


Quantization recipe

Mixed precision, chosen by measuring every stage rather than quantizing everything:

Precision Modules
NVFP4 (W4, group 16) mlp.gate_proj, mlp.up_proj, mlp.down_proj, self_attn.o_proj
BF16 q_proj, k_proj, v_proj, fc, RMSNorm, Q/K norm, Markov head, confidence head

Q/K/V are deliberately not quantized. A full-NVFP4 variant including them was built and measured: it reaches 150.73 tok/s but acceptance falls to 2.546. Keeping QKV in BF16 costs ~3 tok/s and buys back the acceptance, which is the better production trade.

Measured ladder:

Variant tok/s Accept VRAM
MLP only 147.61 2.521 1.58 GB
MLP + O (this model) 147.87 2.792 1.41 GB
MLP + O + QKV 150.73 2.546 1.17 GB

Adding the O projection to MLP recovers acceptance fully; adding QKV loses it again.

fc (the 25600β†’5120 aux projection) stays BF16 because SGLang constructs it as a plain nn.Linear with no quantized loader.

Calibration

Post-training quantization with NVIDIA ModelOpt, calibrated to resemble real serving rather than synthetic input:

  • 512 conversations, regenerated on-policy by the NVFP4 target at temperature 0
  • Tool-weighted mixture (37.5% tool calling) to protect the most structurally rigid output
  • Real captured target auxiliary features and real token embeddings for the draft input path
  • Calibration data is disjoint from the evaluation set β€” no benchmark prompt was ever calibrated on

The tool weighting is measurable: it lifts tool acceptance from 3.15 to 3.85 versus a balanced calibration, at a cost of 0.8 tok/s overall.


Usage

Requires the Qwen3.8 SGLang build. Pin the image β€” DSpark runtime support moves quickly.

docker run --gpus all --ipc=host --shm-size 32g -p 30000:30000 \
  -v ~/.cache/huggingface:/root/.cache/huggingface \
  lmsysorg/sglang:qwen38-27b \
  sglang serve \
    --model-path gittensor-model-hub/Qwen3.8-27B-NVFP4-RTX5090 \
    --speculative-algorithm DSPARK \
    --speculative-draft-model-path gittensor-model-hub/Qwen3.8-27B-DSpark-NVFP4 \
    --speculative-draft-model-quantization modelopt_fp4 \
    --speculative-dspark-block-size 7 \
    --trust-remote-code --tp-size 1 \
    --context-length 122880 --kv-cache-dtype fp8_e4m3 \
    --attention-backend flashinfer --chunked-prefill-size 1024 \
    --mamba-radix-cache-strategy extra_buffer_lazy \
    --mamba-ssm-dtype bfloat16 \
    --max-mamba-cache-size 8 \
    --mm-feature-transport cpu \
    --cuda-graph-max-bs-decode 1 \
    --mem-fraction-static 0.86 --max-running-requests 1 \
    --reasoning-parser qwen3 --tool-call-parser qwen3_coder \
    --host 0.0.0.0 --port 30000

Flags that are not optional on 32 GB:

  • --mamba-ssm-dtype bfloat16 β€” without it the hybrid GDN state cache cannot allocate a single request slot and the server exits at startup.
  • --max-mamba-cache-size 8 β€” this must leave headroom. Under DSpark, Qwen3.8 consumes 4 GDN state slots per request, so --max-mamba-cache-size 4 provisions exactly one request and nothing spare. Radix-cached prefixes hold slots from the same pool under extra_buffer_lazy, so if a cached state is locked when the next request needs a slot, eviction fails and the server aborts with AssertionError: Can not alloc mamba cache. Size 8 halves peak utilisation (0.75 β†’ 0.38 under abort-heavy multi-turn traffic) at a cost of some KV pool. Rule of thumb: --max-mamba-cache-size β‰₯ 4 Γ— --max-running-requests + 4.
  • --speculative-draft-model-quantization modelopt_fp4 β€” this checkpoint is pre-quantized; loading it any other way will fail.
  • --mem-fraction-static 0.86 β€” leave ~3.5 GB free. See below.

Context limits

The freed 1.31 GB converts directly into KV pool: 122,995 tokens at 64K settings, versus 72,485 for the BF16 drafter.

max_total_num_tokens is not the serving limit

At --mem-fraction-static 0.94 the server starts, reports a large pool, and then dies on the first long request:

causal_conv1d_triton.py:443   out = torch.empty_like(x)
torch.OutOfMemoryError: Tried to allocate 40.00 MiB. 9.81 MiB is free.

The pool is allocated optimistically and does not reserve for GDN prefill activations. Leave ~3.5 GB free and it is stable.

Concurrency and the 262K question

SGLang caps this configuration at max_running_requests = 1. Qwen3.8's GDN state cache costs ~147 MB per request across 4 slots; there is no room for a second on 32 GB. This ceiling is inherent to the target's hybrid architecture β€” the built-in MTP head hits it identically.

With this drafter Target alone, no speculation
Max context ~116K+ 262K (verified: 252,849-token prompt served)
Short-prompt decode 147.87 tok/s 81.58 tok/s
Cold TTFT at 250K n/a ~121 s

Full 262K with speculation does not fit on one 32 GB card even at 4 bits: the target's own FP8 KV needs ~8 GiB at 262K, and the draft KV pool is sized to the full target context. Use the no-speculation profile for maximum context.

Note also that speculative decoding accelerates decode only, never prefill.

Output quality is unchanged. The target verifies every drafted token under strict acceptance (speculative_accept_threshold_single=1.0, rejection sampling off). Speculation changes speed, not outputs β€” and that guarantee is what makes 4-bit drafting safe.


Model

Item Value
Architecture Qwen3DSparkModel β€” 5 full-attention layers
Hidden size 5120 Β· 40 heads Β· 8 KV heads Β· intermediate 10240
Block size (gamma) 7
Target aux layers [4, 16, 28, 40, 52]
Markov head vanilla, rank 256, confidence head enabled
Quantization NVFP4 W4 group-16 (ModelOpt 0.45.0), mixed with BF16
Checkpoint 1.30 GB

Certified stack

DSpark runtime support is evolving quickly; this checkpoint was measured against exactly:

target   gittensor-model-hub/Qwen3.8-27B-NVFP4-RTX5090
draft    gittensor-model-hub/Qwen3.8-27B-DSpark-NVFP4
runtime  lmsysorg/sglang:qwen38-27b (0.0.0.dev0+qwen38.27b.g561c8f3)
hardware RTX 5090 32 GB

Evaluated on 240 held-out prompts (40 per domain), unseen during training and calibration. Greedy decoding, thinking disabled, 256 max new tokens. All profiles ran on identical prompts minutes apart on the same machine.

Caveat on margins. The acceptance figures average over many verification steps and are the more reliable signal. Throughput differences of 1–2% are measured across 72 requests per profile and should be read as directional.

License

Apache 2.0, matching the base drafter and the Qwen3.8-27B target.

Downloads last month
3,407
Safetensors
Model size
0.9B params
Tensor type
BF16
Β·
U8
Β·
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Model tree for gittensor-model-hub/Qwen3.8-27B-DSpark-NVFP4

Quantized
(1)
this model

Collection including gittensor-model-hub/Qwen3.8-27B-DSpark-NVFP4