dLLM Fine-Tuning
dLLM Fine-Tuning
Introduction
Diffusion language models (dLLMs) generate text by iteratively denoising masked tokens, rather than generating one token at a time left-to-right like autoregressive (AR) models. Starting from a sequence of [MASK] tokens, the model progressively unmasks the most confident positions over multiple denoising steps until the full response is revealed.
This approach enables parallel token generation and bidirectional attention, which gives the model more context for each prediction compared to AR models.
NeMo AutoModel currently supports the following dLLM model families:
- LLaDA / LLaDA2 (MDLM) — Bidirectional masked diffusion. The model receives corrupted tokens and predicts the clean token at each masked position (see LLaDA2 paper).
- Nemotron-Labs-Diffusion (Hybrid) — Combines diffusion with an autoregressive loss. During training, the model processes clean tokens plus a
masked_indicessidecar and learns both a diffusion objective and an AR objective simultaneously. - DFlash — Speculative block diffusion. A small draft model proposes tokens for a block conditioned on frozen target LM hidden states; a decay-weighted loss trains it to predict the target’s distribution (see DFlash paper).
Workflow Overview
Supported Models
Install NeMo AutoModel
Alternatively, use the pre-built Docker container:
For the full set of installation methods, see the installation guide.
Configure Your Training Recipe
dLLM fine-tuning is driven by:
- A recipe script (
train_ft.py) — orchestrates the training loop with dLLM-specific corruption, loss, and batch handling. - A YAML configuration file — specifies the model, data, optimizer, dLLM-specific settings, and distributed training strategy.
The recipe uses a strategy pattern to handle differences between model families. The dllm.mode field in the YAML selects the strategy:
LLaDA Configuration
See llada_sft.yaml for the full working config. The key dLLM-specific sections are:
Nemotron-Labs-Diffusion Configuration
See nemotron_labs_diffusion_sft.yaml for the full working config. The key dLLM-specific sections are:
Key dLLM Config Fields
DFlash Configuration
DFlash trains a small draft model to predict tokens conditioned on a frozen causal target LM. Only the draft model’s weights are updated; the target LM is loaded once and kept frozen.
See dflash_sft.yaml for the full working config. The key DFlash-specific sections are:
DFlash Training Metrics
In addition to the shared metrics (loss, grad_norm, lr, mem, tps,
mfu), DFlash runs log a draft top-1 accuracy proxy for acceptance length:
Both are computed for free inside the chunked linear-CE path (same logits used
for the loss) and DP/CP-reduced via per-rank raw (correct, count) sums that
are SUM-allreduced and then divided post-reduction, so the values are correct
across arbitrary per-rank token distributions under any of AutoModel’s
distributed modes.
Prepare DFlash Training Data
The paper trains on responses regenerated by the target model (§5.1): “Instead of directly using the original dataset, we construct our training set with the responses generated by the target model for better target alignment.” Skipping this step trains the draft on a different output distribution than the target produces at inference, which directly reduces acceptance length.
The existing nemo_automodel.components.speculative.regenerate script handles
this. Stand up an SGLang server hosting the target, then re-roll the assistant
turns:
--temperature 0.8 (vs the script’s EAGLE-oriented 0.0 default) follows the
DFlash paper: sampling diversity in the supervised tokens teaches the draft to
handle a wider target distribution, improving acceptance length.
--concurrency 64 better saturates one vLLM/SGLang server.
Then point the recipe’s dataset.path_or_dataset_id at the regenerated
parquet shards (/data/dflash-train-regen) instead of the raw HF dataset.
Fine-Tune the Model
Fine-Tune LLaDA2
Fine-Tune with DFlash
Fine-Tune Nemotron-Labs-Diffusion
Run Inference
The generation script (generate.py) supports chat, raw, and infilling modes. Pick the sampler that matches the trained family with --sampler {llada,nemotron}.
--checkpoint accepts any of: a path to a consolidated/ directory, a step directory (.../epoch_0_step_499), or the top-level checkpoint dir (the script will follow LATEST/model/consolidated/).
Generate with LLaDA
Generate with Nemotron-Labs-Diffusion
Generation Parameters
The sampler selected with --sampler supplies these preset values. For LLaDA chat and raw generation, the standalone sampler consumes every field shown below and honors its command-line override. LLaDA infilling uses --steps, --block_size, --temperature, and --remasking while filling masks already present in the input, so it does not use --max_new_tokens. For Nemotron chat and raw generation, the script calls the model’s built-in generate(...), which consumes --max_new_tokens, --block_size, and --temperature from this table (as well as --threshold, which is not shown). Although --steps and --remasking are accepted and stored in the Nemotron preset config, the built-in generation path does not use them, so overriding those two flags does not affect that path.