1. Model Introduction
DeepSeek-V3.2 is a 37 B-active / 671 B-total Mixture-of-Experts (MoE) model. It keeps the MoE and Multi-head Latent Attention (MLA) shapes of DeepSeek-V3 and adds DeepSeek Sparse Attention (DSA): a separate indexer scores the preceding tokens, and each query attends only to the highest-scoring ones. Key highlights:- Fine-grained MoE: 61 layers (3 dense, then 58 MoE), 256 routed experts with top-8 plus 1 shared expert, a sigmoid router with expert bias, group-limited routing over 8 groups with top-4 groups, and a routed scaling factor of 2.5.
- MLA with a sparse indexer: q-LoRA rank 1536, KV-LoRA rank 512, and 128 attention heads split into a 128-dim NoPE part and a 64-dim RoPE part. The indexer runs 64 heads at head dim 128 and keeps
index_topk=2048keys per query. - YaRN RoPE: rotary base 10000 with scaling factor 40, giving 163,840 max positions.
- Block-wise FP8 checkpoint: the published weights are 128×128 FP8 blocks with
ue8m0scales.
--spec miles_plugins.models.glm5.glm5 get_glm5_spec. Weight import and export run through DeepseekV32Bridge (miles_plugins/mbridge/deepseek_v32.py), which adds the indexer tensors on top of the V3 bridge. Training is BF16, so the FP8 checkpoint is cast up before conversion.
The raw path also supports Megatron’s native DSA through --dsa-impl megatron --dsa-kernel-backend cudnn; --dsa-impl miles remains the default. See the shared DSA training implementation selector for conversion flags and checkpoint compatibility.
2. Supported Variants
A 5-layer pruned Megatron config also ships as
deepseek-v32-5layer. You can select it with --megatron-model-type deepseek-v32-5layer when you have a matching pruned checkpoint and want a single-node smoke test.
3. Environment Setup
Run everything inside theradixark/miles:latest container at /root/miles. The whole recipe is driven by one Typer launcher, scripts/run_deepseek_v32.py.
3.1 Launcher defaults
Every option also binds to an env var named
MILES_SCRIPT_<FIELD_NAME_UPPER> (for example MILES_SCRIPT_MODEL_DIR), with precedence CLI flag > env var > built-in default. Run python scripts/run_deepseek_v32.py train --help to see each option’s env var name.
The launcher does not pass --colocate, so training and rollout occupy disjoint GPUs. The flags --actor-num-nodes and --rollout-num-gpus have no defaults, and every multi-node invocation has to supply them.
3.2 Download and convert
Theprepare subcommand downloads the model and the datasets, casts the FP8 checkpoint to BF16, and converts it to a Megatron torch_dist checkpoint:
torch_dist conversion then runs tools/convert_hf_to_torch_dist.py under torchrun across the Ray cluster. Both the cast and the conversion detect their own output and skip it, so re-running prepare after a failure is cheap. If your checkpoint is already BF16, --from-bf16-ckpt downloads it straight into the -bf16 directory and skips the cast.
Because the conversion fans out over Ray with ray.init(address="auto"), the cluster has to be up before you call prepare on more than one node.
3.3 Multi-node Ray
Start Ray yourself and point the launcher at it:MILES_SCRIPT_EXTERNAL_RAY=1, the training stage runs ray stop --force and starts a fresh local head, tearing down the cluster that the conversion just used. When RAY_ADDRESS is unset the launcher submits to http://127.0.0.1:8265.
4. Launch
4.1 Quick start
full-train subcommand chains download → FP8 → BF16 cast → optional rollout quantization → torch_dist conversion → training. Staging onto node-local disk is not a separate stage: train rsyncs the HF checkpoint and torch_dist into --model-local-dir on every trainer pod before the job starts.
4.2 Individual stages
4.3 Single-node smoke test
The--use-single-node flag pins the run to one node with 4 training GPUs and 4 rollout GPUs, switches the parallelism to TP4 / PP1 / EP4, converts the checkpoint on that single node, and runs SGLang with 2-GPU engines. Pair it with a pruned checkpoint — the full 671 B model does not fit on 4 GPUs.
5. Recipe Configuration
5.1 Parallelism
61 layers do not divide evenly into PP=4, so
--decoder-last-pipeline-num-layers 13 splits the training stages 16 / 16 / 16 / 13. Megatron also requires the world size to be divisible by expert-TP × EP × PP = 64, so --actor-num-nodes has to be a multiple of 8 at 8 GPUs per node.
The rest of the performance arguments are fixed by the launcher:
5.2 Algorithm
Using GRPO as an example, you can configure the algorithm with the following flags:--rm-type deepscaler: 32 prompts per rollout step, 8 samples per prompt, global batch size 256, and responses capped at 8192 tokens. Evaluation is off until you pass --enable-eval, which adds an aime-2024 pass every 20 rollouts at 16 samples per prompt.
The --enable-mis flag turns on truncated importance sampling to correct the train/inference mismatch. It writes a custom config with use_tis: true, tis_mode: truncate, and bounds [0.5, 2.0], then routes the policy loss through examples.infra_features.train_infer_mismatch_helper.mis.compute_mis_weights_with_cp. Rejection sampling rides along by default and is disabled with --no-tis-use-rs.
5.3 Rollout & SGLang
SGLANG_NSA_FORCE_MLA=1, SGLANG_NSA_PREFILL_DENSE_ATTN_KV_LEN_THRESHOLD=0, and NVSHMEM_DISABLE_NCCL=1.
5.4 Optimizer
5.5 Low-precision options
Both MXFP8 options require Blackwell and are rejected on H100 / H200, and the two rollout options are mutually exclusive. The
--rollout-mxfp8 path additionally keeps the MLA up-projections in BF16 — .kv_b_proj. on the HF side, linear_kv_up_proj / linear_k_up_proj / linear_v_up_proj on the Megatron side — via --extra-high-precision-layers-hf, --extra-high-precision-layers-megatron, and a generated Transformer Engine precision config.
5.6 Notable quirks
- The launcher always passes
--use-fault-tolerance, and checkpoints every 20 rollouts unless you pass--no-save. - Combining
--train-mxfp8with--fp8-param-gatherraisesNotImplementedError; MXFP8 parameter all-gather is not wired up yet. - Passing
--train-mxfp8without--rollout-mxfp8points--hf-checkpointat an-MXFP8directory that the prepare stage never builds, because only--rollout-mxfp8runs the MXFP8 conversion. Pass both flags together. - The multi-node conversion branch passes PP=6 with
--decoder-last-pipeline-num-layers 13, which leaves 48 layers for 5 middle stages and fails Megatron’s even-split check. Until that default is fixed, convert by callingtools/convert_hf_to_torch_dist.pydirectly with a layout that divides — PP=4 with the same last-stage size matches the training layout and works.
6. Pairs Well With
- Low Precision RL — background for the rollout and training quantization flags above.
- Fault Tolerance — enabled by default in this recipe.
- GLM-5.2 — the other recipe built on the same DSA attention implementation.
- Agentic Rollout — V3.2 renders through the
deepseekv32template.

