An image to serve the nvfp4 qwen3.8 flash next model on a single DGX spark
111
Serves primitive-ai/Qwen3.8-Flash-Next-NVFP4
on a DGX Spark (GB10). Point it at an empty cache volume and it downloads the model, builds what
it needs, and starts serving. No manual checkpoint surgery.
--gpus all needs to work).docker run -d --name qwen38-flash-next \
--gpus all --ipc=host -p 8000:8000 \
-v qwen-cache:/root/.cache \
<your-registry>/qwen3.8-flash-next-nvfp4-dgx-spark:latest
Mount the whole /root/.cache, not just the Hugging Face cache directory. GPU kernel autotuning
(FlashInfer, torch.compile) also lands under /root/.cache, and if you only persist the HF side
you'll re-pay the autotuning cost — several minutes — on every restart, not just the first one.
First boot is slow and that's normal: download the model if it's not cached, load 78 GiB of
weights off disk, then (first boot on a fresh cache volume only) autotune the GPU kernels. Could
be twenty minutes, could be longer depending on your connection. There's a HEALTHCHECK on
/health with a 40-minute start period, or just poll it yourself:
docker inspect --format '{{.State.Health.Status}}' qwen38-flash-next
This is upstream vllm/vllm-openai:qwen38-flash-next with a handful of file overlays on top —
nothing hidden. docker history shows every layer, each one a plain-text file a few KB to ~1 MB.
The GPU this targets (GB10 / SM121) has a real cuBLAS problem: its BF16 tensor-core GEMM path is broken under CUDA 13.0. The fix that actually matters here is enabling vLLM's CUTLASS "skinny GEMM" kernel for this chip — it was gated to a different Blackwell variant (SM103) and just needed the gate widened, plus some shape tuning for this model's dimensions at TP=1. That's the patch doing the real work: it's what the decode-step throughput depends on.
On top of that, the MTP draft head can score a curated 16,000-token subset of the 248,320-token
vocabulary instead of the whole thing (shortlists/lowcore_16k.json). Worth having, but don't
oversell it to yourself: it's a modest single-stream win (roughly 4-10%, and only once it's
routed through the skinny kernel too — otherwise it can lose to the full head). It does close to
nothing for saturated/concurrent throughput. The full target model verifies every token it
proposes either way, so none of this can change what comes out, only how fast.
Also in here: a PLE (position-learning embedding) table streaming setup that reads the model's
~102 GiB ngram table straight off disk via a byte-offset index instead of loading it into memory,
and a one-line chat-template fix so an out-of-range reasoning_effort degrades instead of
hard-erroring.
Everything below is an env var, or pass it as an extra flag to docker run (it wins over this
image's own default since it comes after):
| Variable | Default | What it does |
|---|---|---|
QWEN_FLASH_NEXT_REPO | primitive-ai/Qwen3.8-Flash-Next-NVFP4 | which HF repo |
QWEN_FLASH_NEXT_REVISION | pinned commit | snapshot revision — the shortlist and patches were validated against this one specifically, moving it is on you |
SERVED_MODEL_NAME | qwen38-flash-next | name in /v1/models |
GPU_MEMORY_UTILIZATION | 0.80 | fraction of the unified pool vLLM can claim |
MAX_NUM_SEQS | 32 | concurrent sequences (trades against MTP depth / KV cache size) |
MAX_MODEL_LEN | 131072 | context length |
VLLM_QWEN_MTP_SHORTLIST_PATH | baked-in lowcore_16k.json | unset/empty it to run the full-vocab draft head instead |
QWEN_FLASH_NEXT_SKIP_PREFLIGHT | unset | 1 skips the GPU/driver check — useful for poking at the download logic on a non-GPU box |
docker logs -f. Shard-loading percentages or kernel
autotune progress mean it's working, just slow. See the timing note above./root/.cache/huggingface
instead of all of /root/.cache. The autotuning caches live outside the HF path.Content type
Image
Digest
sha256:6fb29174c…
Size
9 GB
Last updated
1 day ago
docker pull krisbailey/qwen3.8-flash-next-nvfp4-dgx-spark