qwen3.8-Flash-DGX README

The project's README from github.com/blazux/qwen3.8-Flash-DGX. As one markdown file: README.md.

Qwen3.8-Flash-Next on a single DGX Spark (GB10)

Run Qwen3.8-Flash-Next — a ~176B-parameter model (125B main + 51B n-gram, 6B active) — on one NVIDIA DGX Spark / ASUS GX10 with vLLM, at full prefill speed, with MTP speculative decoding, working prefix caching, deterministic greedy decoding, and up to 500k tokens of context.

The catch this repo solves: the NVFP4 checkpoint is 126 GiB, which does not fit next to a usable KV cache in the Spark's 128 GB unified pool. 48 GiB of that is the n-gram embedding ("PLE") table — a pure lookup that a token only touches 16 rows of. This repo patches the official vLLM image to serve that table from NVMe via mmap instead of keeping it resident. Weights drop to ~76 GiB, the rest of the pool goes to KV, and everything runs on stock GB10 kernels.

Along the way it also fixes two things that were broken for this model on GB10 — prefix caching (a vLLM block-size bug silently restored an all-zero Mamba state on every cache hit) and non-deterministic top-k in the sparse attention (a GB10 kernel that drops candidates) — and offers an optional hybrid checkpoint layout (NVFP4 experts + fp8 side layers) that decodes ~20% faster at the same quality.

TL;DR — run it on a DGX Spark

git clone https://github.com/blazux/qwen3.8-Flash-DGX.git && cd qwen3.8-Flash-DGX
docker build -t qwen38-flash-dgx .            # ~1 min: official vLLM image + the 10 patches below
scripts/download-weights.sh                   # RadixArk NVFP4 checkpoint, ~126 GiB, resumable (one-time)
scripts/prepare-hybrid.sh                     # recommended: fp8 side layers, +20% decode, same quality (~10 min, one-time)
MODE=hybrid YARN=1 CTX=500000 scripts/serve.sh   # the recipe our own box runs; 500k context, ~13 min to load
docker logs -f qwen38-flash                   # ready at "Application startup complete"
scripts/smoke-test.sh                         # health, coherence, prefix-cache hit, determinism, tok/s

OpenAI-compatible API on http://localhost:18300/v1, model name qwen3.8-flash-next, tool calling and reasoning parsers on. Every default is the setting that scored best on our agentic tournament (see How the defaults are chosen); what you get on a GX10: ~37 tok/s single-stream decode, ~2,500–3,000 tok/s prefill, prefix caching, deterministic greedy output, 500k tokens of context. Want the checkpoint exactly as published? Drop prepare-hybrid.sh and MODE=hybrid. Want speed over the last percent of quality? MTP=3, and MODE=hybrid-mtp for more KV — both explained in the options table. Everything below is the long version: what was broken on GB10, what was fixed, and the numbers.

Independently reproduced on a DGX Spark by @jschmied — see issue #1 and their write-up.

Update 2026-09-08 — what changed

Newest first. If you cloned this before, this is the short version; details in the linked sections.

2026-09-08 — the defaults are now decided by an agentic/coding benchmark (called tournament), and two new ones came out of it:

2026-09-07 — kernel pin bump and multi-client guidance:

2026-08-29 → 2026-09-07:

Everything was measured on one ASUS GX10 with a 17-scenario agentic tournament (3 repeats each), single-request speed benches on real prompts, and state checksums for the prefix-caching work; nothing here is extrapolated.

llama.cpp IQ4_XS NVFP4 (this repo) hybrid (this repo)
Prefill ~540 tok/s ~2,400–2,900 tok/s (deterministic kernel; warm page cache — a first pass over a cold region of the table reads from NVMe and can be 2–3× slower, see PREWARM) same
Decode, single stream ~22 tok/s (no MTP) ~26 tok/s with MTP=2 ~37 tok/s (reduced draft vocabulary; ~31 without)
Prefix-cache hit, TTFT on a 20k-token prefix n/a ~1.4 s (vs ~14 s cold) same
Context 262k 262k native, 500k with YaRN same
KV cache @0.80 (500k YaRN, MTP) — ~580k tokens ~630k tokens
Deterministic at temperature 0 yes yes (DET_TOPK=1) yes

Measured on an ASUS GX10 (GB10, 128 GB), single request, real prompts, greedy. Quality (a 17-scenario agentic tournament, 3 repeats) is identical across NVFP4 and hybrid: 45/51 both, same two scenarios failed by every quantization we tried. Details and the full comparison tables are in docs/HOW-IT-WORKS.md.


How the defaults are chosen: quality first, speed as an option

Every default in scripts/serve.sh is the setting that scored best on our 17-scenario agentic tournament (tool loops, long-context extraction, multi-step reasoning; 3 repeats, temperature 0.2), run on the GX10 with one variable changed at a time, on the same day. A change that only buys tok/s or TTFT and costs even a point there ships as an option, off by default, with its measured cost next to it. Two runs of the same configuration differ by up to 2 points day to day, so anything inside that band is treated as equal and the faster one wins; anything below it stays an option.

what default measured effect (GX10, hybrid, MTP=2, prefix caching, YaRN 500k)
Hybrid checkpoint (MODE=hybrid) recommended, nvfp4 as published is the default +20% decode, +8% KV, same tournament score
Deterministic top-k kernel (DET_TOPK=1) on identical greedy outputs, full prefill speed, tournament neutral (44/51)
Reduced draft vocabulary (DRAFT_VOCAB=1) on +20% decode, tournament 45/51 (the best run), outputs unchanged by construction
MADV_RANDOM on the table (MADVISE=random) on cold prefill −4–8%, cleaner page cache, tournament neutral
Prefix caching (PREFIX_CACHE=1) on ~14 s → ~1.4 s TTFT on a repeated 20k prefix
MTP=3 option (MTP=2 default) +7% decode, −1 point at the tournament (44 vs 45/51)
NVFP4 MTP draft experts (MODE=hybrid-mtp) option +22% KV pool, −3.9 GiB weights, decode unchanged here, tournament neutral (44/51)
fp8 KV cache (KV_DTYPE=fp8_e4m3) option ×1.9 KV pool, 1M context; −10% decode, −30% prefill, one scenario lost
M%4 GEMM padding (PAD_M4=1) option no-op with prefix caching on; −40% TTFT at 8k with it off
Exact torch.topk (EXACT_TOPK=1) fallback deterministic like the kernel, −20–40% long prefill
--long-prefill-token-threshold (via EXTRA) option keeps decoding clients responsive under concurrent prefills, at a TTFT cost

If your priority is raw throughput rather than the agent's reliability, the fast profile is MODE=hybrid MTP=3 (41 tok/s in the tournament against 38.5 for the default), and MODE=hybrid-mtp on top if you need the KV pool more than the last few percent of quality.

Requirements

Quickstart

The commands are in the TL;DR at the top. Once the log says Application startup complete, hit the OpenAI-compatible API:

curl http://localhost:18300/v1/chat/completions -H 'Content-Type: application/json' -d '{
  "model": "qwen3.8-flash-next",
  "messages": [{"role":"user","content":"Write a haiku about a desktop supercomputer."}],
  "max_tokens": 512
}'

MODE=nvfp4 scripts/serve.sh (the default) serves the checkpoint as published at the native 262k context; YARN=1 CTX=500000 goes to 500k (validated with a needle-in-a-haystack at 414k tokens); GPU_MEM=0.80 is the long-running-service setting, see Tuning.

Two checkpoint modes: NVFP4 or hybrid

scripts/serve.sh serves one of two layouts of the same RadixArk NVFP4 checkpoint; pick with MODE=.

MODE=nvfp4 (default) MODE=hybrid
Routed experts (the bulk, ~63 GiB) NVFP4 NVFP4 (unchanged)
GDN in/out projections, QSA q/k/v/o, shared experts (~15 GiB) bf16, as published blockwise fp8-e4m3 (128×128 blocks, DeepSeek layout)
Extra preparation none scripts/prepare-hybrid.sh once (~10 min, +13 GB disk)
Decode (MTP=2, greedy, real answers) ~26 tok/s ~31 tok/s (+20%)
Prefill same same (±5%)
KV cache ~580k tokens ~630k tokens (+8%), weights ~7 GiB smaller
Tournament quality (17 agentic scenarios × 3) 45/51 45/51
Deterministic at T=0 yes yes
Behavioural difference we noticed — slightly "more careful" in tool loops: it sometimes checks state first (one extra tool call), which is the only place it scored differently before we raised the turn budget

Why it works: those side layers are dense and read in full on every decoded token, so they dominate decode bandwidth; the experts are sparse (10 of 512 active) and already 4-bit. Halving the dense part is where the tokens/s come from. The MoE path — where the quality lives — is untouched. Conversion uses @Saren-Arterius's fp8_convert.py (worst per-tensor max relative error 3.5%), and a small dispatch shim (src/vllm_fp8_hybrid_modelopt.py) that routes those layers to vLLM's blockwise-fp8 GEMM while the ModelOpt NVFP4 config keeps handling the experts.

scripts/prepare-hybrid.sh                 # builds <snapshot>-fp8hybrid/ next to the HF snapshot
MODE=hybrid YARN=1 CTX=500000 GPU_MEM=0.80 scripts/serve.sh

Our own box runs the hybrid. If you want the checkpoint exactly as published, stay on MODE=nvfp4 — you lose ~5 tok/s and nothing else.

NVFP4 MTP draft experts (MODE=hybrid-mtp)

A graft on top of the hybrid: the MTP draft head's routed experts (BF16 fused, 4.7 GiB) are replaced by the NVFP4 draft experts from Inferact/Qwen3.8-Flash-Next-NVFP4 (1.4 GiB) — the combination neither parent ships: fp8 PLE table and a cheap draft. scripts/prepare-mtp-graft.sh builds it in ~5 min (3.3 GB of real bytes: one shard rewritten without the 2 fused BF16 MTP tensors, a symlink to the donor shard, and the index + both quantization exclusion lists fixed — the blanket mtp.* globs are replaced by the donor's 29 explicit non-expert MTP module names in both config.json and hf_quant_config.json, or the draft loads unquantized and dies). Both parents are modelopt quantizations of the same base — verified by hashing embed_tokens.weight and all 29 shared draft tensors byte-for-byte before grafting. The graft reads through both parents (it is a directory of symlinks); don't delete either one.

Measured on the GX10 (hybrid, MTP=2, greedy, real answers):

MODE=hybrid MODE=hybrid-mtp
Weights on card 77.83 GiB 74.75 GiB (−3.1)
KV cache @0.80 625,669 tok 734,292 tok (+17%)
Max concurrency @262k 2.39x 2.80x
Decode, 5-prompt greedy probe 26.6–33.8 tok/s 34.7–42.5 tok/s (+20–27%)
Mean acceptance length ~2.73 ~2.58 (same band)
Tournament quality 45/51 same target model, byte-identical greedy outputs (see below)

Those are the author's numbers. Ours, measured the way defaults are decided here (same box, same day as the table in Reduced draft vocabulary, full-vocabulary draft on both arms):

MODE=hybrid MODE=hybrid-mtp
Tournament (17 scenarios × 3) 44.5/51 44/51 (same failures, within the day's noise)
tok/s in the tournament 33.5 33.0
Decode, single stream (bench) 33.1 tok/s 32.6 tok/s
MTP acceptance 75% (mean length 2.50) 63.5% (2.27)
KV pool @0.80, YaRN 500k 626k tok 764k tok (+22%)
Weights on card 77.8 GiB 73.9 GiB
Deterministic 4/4, smoke-test (cache hit + logprobs) yes yes

So on this box the graft is a memory win, not a speed win: the NVFP4 drafter reads ~4× fewer bytes per draft step but its proposals are accepted less often, and the two cancel. It is quality-neutral, which is why it ships as an option rather than the default; take it when the KV pool or concurrency matters more than the last percent. Not yet measured in combination

qwen3.8-Flash-DGX (blazux/qwen3.8-Flash-DGX)

Searching Database…

这是什么?这是一份在单台 NVIDIA DGX Spark(GB10)上用 vLLM 服务约 1760 亿参数 Qwen3.8-Flash-Next 模型的方案(脚本加打过补丁的 Docker 镜像)。它要解决的问题是:126 GiB 的 NVFP4 检查点在 Spark 的 128 GB 统一内存里放不下,还要给可用的 KV 缓存留地方;做法是通过 mmap 从 NVMe 流式读取一张 48 GiB 的查找表,而不是让它常驻内存。
这是独立应用,还是叠在 vLLM 上的补丁?它不是新应用——而是一组 shell 脚本(download-weights.sh、serve.sh、prepare-hybrid.sh)和补丁,用来修改官方 vLLM Docker 镜像并以正确的标志启动;模型仍然通过 vLLM 自己的 OpenAI 兼容 API 提供服务。
怎么让它跑起来?克隆仓库,运行 scripts/download-weights.sh 拉取检查点(可选地运行 scripts/prepare-hybrid.sh 得到更快的混合布局),然后运行 scripts/serve.sh 构建并启动打过补丁的 vLLM Docker 镜像;它会以模型名 qwen3.8-flash-next 暴露一个 OpenAI 兼容 API。
尝试之前需要什么硬件和软件?一台 NVIDIA DGX Spark 或兼容的 GB10(sm121)机器,带 128 GB 统一内存、aarch64、较新的 NVIDIA 驱动、带 NVIDIA container runtime 的 Docker,以及约 140 GB 的高速磁盘(推荐 NVMe,因为查找表会在运行时从它读取)。
有什么不完善的地方需要知道?有几个 GB10 特有的 bug 必须打补丁修复(一个会悄悄破坏前缀缓存命中的 vLLM block-size bug,以及稀疏注意力里一个非确定性的 top-k kernel);另外,只要另一个客户端的提示正在预填充,某个客户端的解码就会明显停顿——那是 vLLM 的 chunked-prefill 行为,不是本仓库的 bug。
这必须要 DGX Spark 那种硬件,还是任意 NVIDIA GPU 都行?它专门针对 DGX Spark / ASUS GX10 里那颗带 128 GB 统一内存的 GB10(sm121)芯片调优;构建是多架构的,所以也能在 x86 Blackwell(sm120,如 RTX PRO 6000)上编译用于测试,但优化目标是 Spark。
什么是 MTP 投机解码,它为什么在这里重要?MTP 用一个小型起草模型提前起草额外的 token,让模型每一步能验证多个 token;在默认 MTP=2 和精简起草词表的设置下,它把单流解码从约 26 tok/s 提到约 37 tok/s,同时不改变经过验证的输出。
它实际能吃下多大的上下文?在模型原生 262k 上下文之上,通过 YaRN 缩放最高到 500k token;在推荐的 0.80 GPU 内存占比下,大约有 580k-630k token 的 KV 缓存可用。
nvfp4 和 hybrid 两种检查点模式有什么区别?MODE=nvfp4 完全按发布原样提供检查点;MODE=hybrid 通过一次性的 prepare-hybrid.sh 脚本,在 NVFP4 专家旁边换入 fp8 侧层,在实测质量相同的前提下,解码快约 20%,KV 缓存多 8%。
默认设置是怎么定下来的?scripts/serve.sh 里的每个默认值,都是在一项内部 17 场景代理锦标赛(工具循环、长上下文提取、多步推理,重复 3 次)中得分最高的设置;那些只提升速度却会丢锦标赛分数的选项,默认保持关闭。
Creator
blazux
Size
0.6 MB
Stars
456
Updated
CommitOct 16
Age
1mo
Commits · 90 Days