radixark/miles#2777. It lands as a set of
three: that branch, the SGLang
sglang-miles-qwen38next
branch, and radixark/Megatron-LM#89.
The image in section 3 pins all three.
1. Model Introduction
Qwen3.8-Flash-Next is Qwen’s 176 B-parameter (6 B active) GDN + QSA hybrid Mixture-of-Experts preview of the Qwen4 architecture. Despite the shared prefix it is not a variant of the dense Qwen3.8-27B — it is the next step of the Next line that Qwen3-Next started, and structurally it has far more in common with that model than with anything else carrying the Qwen3.8 name. The block spec is still a uniform GPT decoder, but three components sit outside what a stock Megatron layer provides, and each one is why a piece of this recipe exists: Hyper-connections replace the block layernorms. The checkpoint ships none: each hyper-connection’s ownhc_norm is the pre-block norm, so the spec drops every block
layernorm and a leftover TE fused norm corrupts the forward pass silently rather than
loudly. Miles fills Megatron’s HC ModuleSpec slots, but Qwen’s output contraction is not
DeepSeek-V4’s learned_output_contract — it is the same low-rank gated mean as the
per-layer hyper-connections, with the RMS taken per stream rather than over the whole
n*C vector. That needed a new Megatron spec slot, hc_head_contraction, which is what
Megatron#89 adds; the DeepSeek-V4 default path and its parameter names are untouched.
QSA (Qwen Sparse Attention) on the full-attention layers. Twelve of the 48 layers are
full attention. Each projects its own indexer queries and compressed keys, scores them, and
keeps indexer_budget key tokens per query; attention then reads only those. Miles
reimplements the indexer and a forward and backward Triton sparse-attention kernel rather
than importing SGLang’s inference path, with the selection rows built torch-side so the
kernel needs no causal or segment logic of its own.
A frozen, host-resident PLE table. The per-layer-embedding n-gram table is ~102 GB. It
lives in host memory, TP-row-sharded, and is deliberately not a checkpointed parameter;
token ids reach it over an explicit side channel that raises rather than defaulting when
nothing was published. It is also on the weight-update check’s skip list — see
section 5.5.
Key highlights:
- 48 layers, hybrid: 36 GDN linear-attention layers + 12 QSA full-attention layers, from
the released config’s
layer_types(equivalently, every 4th layer is full attention). - 512-expert MoE at top-10,
moe-ffn-hidden-size 640, plus a gated shared expert. - Hyper-connections at every block, with a model-supplied output contraction.
- PLE n-gram embeddings, frozen and host-resident.
- Attention output gate,
--qk-layernorm,--apply-layernorm-1p. - Shape: hidden 2560, 24 attention heads, 2 query groups,
kv-channels 256, vocab 248320,--rotary-base 10000000at--rotary-percent 0.25.
--mtp-num-layers is omitted, the
MTP tensors are not mapped yet) and the hyper-connection / PLE / QSA fields themselves,
which have no Megatron CLI flags and are derived from the checkpoint by the spec in
miles_plugins/models/qwen3_8_next/qwen3_8_next.py.
On the parameter count: Qwen’s published headline is 176 B total / 6 B active, while the
docstring in scripts/models/qwen3.8-flash-next.py counts 180 B / ~7.4 B from the released
config.json shapes. Nothing in the recipe depends on which figure you quote.
2. Supported Variants
--model-name selects between them and sets the matching megatron_model_type
(qwen3.8-flash-next / qwen3.8-flash-next-4layer), which in turn resolves the model args
and the torch_dist path. The launcher asserts the node shape, so a mismatched
--num-nodes / --num-gpus-per-node fails immediately rather than mid-run.
3. Environment Setup
Use thedocker.io/radixark/miles:qwen38next image. It is the rolling
radixark/miles:dev image with the three moving parts checked out at
the versions this recipe was built against, and nothing else changed — every prebuilt wheel,
TransformerEngine patch and version pin comes from dev. It is multi-arch, so the same tag
serves GB300 (aarch64) and x86 nodes.
3.1 Download model + dataset
CharyZeng/Qwen3.8-Flash-Next-4layer
into /root/models/Qwen3.8-Flash-Next-4layer instead — the launcher resolves
--hf-checkpoint as <--model-dir>/<--model-name>, which is the same path CI uses.
3.2 HF → Megatron torch_dist conversion
Unlike the launcher-prepared recipes, this one takes the converted reference checkpoint as
given: --ref-load resolves to <--ckpt-dir>/<megatron_model_type>_torch_dist, so the
conversion has to have run first. The output re-shards at load, so the conversion layout
does not have to match the training one:
qwen3.8-flash-next for qwen3.8-flash-next-4layer throughout to convert the smoke
slice.
4. Launch
The launcher assumes an already-running ray cluster: bring one up across the nodes,export MILES_SCRIPT_EXTERNAL_RAY=1, then run on the head node.
Full model, 8 nodes × 4 GPUs:
--model-dir (default /root/models), --data-dir (default
/root/datasets), --ckpt-dir (default /root/ckpt) and --megatron-path (default
/root/Megatron-LM). Saving is off by default (skip_saving); turning it on writes
checkpoints under <--save-dir>/<--run-id>/checkpoints every 10 rollouts, without optimizer
or RNG state.
5. Recipe Configuration
5.1 Parallelism
--sequence-parallel is on in every shape. Activation checkpointing is full and uniform at
one layer, with --micro-batch-size 1 and --max-tokens-per-gpu 8192.
5.2 Algorithm
GRPO, DAPO-Math-17k, thinking mode on:--lr 1e-6, constant schedule, --weight-decay 0.1,
--adam-beta1 0.9 --adam-beta2 0.98.
5.3 Rollout & SGLang
Rollout is colocated — trainer and engines share the GPUs — and the trainer offloads to disk rather than host RAM during rollout (--offload-train-target disk,
--offload-train-disk-dir /tmp/train_offload). Worth keeping in view when sizing hosts: the
PLE table is already holding ~102 GB of host memory for the full model. The 4-layer CI slice
overrides the target back to --offload-train-target cpu.
QSA_BACKEND=triton selects the sparse-attention kernel. The recipe also loosens router
health checking (--router-health-failure-threshold 40,
--router-health-check-interval-secs 15, --router-health-success-threshold 1) and raises
--rollout-health-check-interval / --rollout-health-check-timeout to 300 s.
5.4 What CI watches
tests/e2e/megatron/model_scripts/test_qwen3_8_next_4layer_ci.py runs the 4-layer slice on
8 × H200 in stage-c-8-gpu-h200 with rollout-routing replay on, and gates these metrics:
train/grad_normtrain/ppo_kltrain/train_rollout_logprob_abs_difftrain/train_rollout_klrollout/raw_reward
train/train_rollout_logprob_abs_diff is the one to read first on a fresh bring-up: it is
the direct measure of whether the SGLang and Megatron forward passes agree, and on this
architecture that covers the GDN, QSA and hyper-connection paths at once. See
True On-Policy for what the metric does and does
not tell you.
5.5 Notable quirks
- Weight-update checking skips two prefixes.
--check-weight-update-equalruns with--check-weight-update-skip-list visual. ple_embedding.— the PLE table is frozen and never shipped, so comparing it would fail on a parameter that is working as intended. - Every block layernorm is dropped. The checkpoint has none; each hyper-connection’s
hc_normis the pre-block norm. A leftover TE fused norm corrupts silently. --moe-aux-loss-coeff 0. Routing is not auxiliary-loss balanced here.- Triton and Inductor caches are pinned to
/tmp(TRITON_CACHE_DIR,TORCHINDUCTOR_CACHE_DIR) withTORCHINDUCTOR_COMPILE_THREADS=1. SGLANG_DISABLE_MULTIMEM_AG=1andSGLANG_SKIP_CHECKPOINT_LOAD_CHECK=1are set for the engines.- The model lives in
miles_plugins/models/qwen3_8_next/, and weight conversion inmiles/backends/megatron_utils/megatron_to_hf/qwen3_8_next.py.
6. Pairs Well With
- Qwen3-Next — the previous generation of the same line
- Qwen3.8 — the dense 27 B that shares the name and not the architecture
- Disk Offload
- True On-Policy

