On-policy Distillation#

We provide an example on-policy distillation experiment using the DeepScaler dataset.

Note

Distillation currently supports the DTensor and vLLM generation backend. Megatron generation/training paths are not supported yet.

On-policy Distillation Single Node#

To run on-policy distillation on a single GPU using Qwen/Qwen3-1.7B-Base as the student and Qwen/Qwen3-4B as the teacher:

uv run python examples/run_distillation.py

Customize parameters with command-line overrides. For example:

uv run python examples/run_distillation.py \
  policy.model_name="Qwen/Qwen3-1.7B-Base" \
  teacher.model_name="Qwen/Qwen3-4B" \
  cluster.gpus_per_node=8

On-policy Distillation with NeMo Gym#

On-policy distillation can use NeMo Gym for multi-step or multi-turn rollout collection. In this mode, NeMo RL exposes the student vLLM generation worker as an OpenAI-compatible HTTP server, NeMo Gym runs the environment interaction, and the resulting student samples are used for teacher-logit distillation.

Use the NeMo Gym distillation entrypoint with the example config. The checked-in config uses placeholder dataset paths, so override them for your local data:

uv run python examples/nemo_gym/run_distillation_nemo_gym.py \
  --config examples/nemo_gym/distillation_qwen3_0_6b.yaml \
  data.train.data_path=/path/to/train.jsonl \
  data.validation.data_path=/path/to/validation.jsonl

The config must enable the vLLM async HTTP server and NeMo Gym:

policy:
  generation:
    backend: vllm
    vllm_cfg:
      async_engine: true
      expose_http_server: true

env:
  should_use_nemo_gym: true

NeMo Gym controls the rollout turn count from its environment and agent configuration. The standard distillation distillation.max_rollout_turns setting is not used by the NeMo Gym rollout path.

On-policy Distillation Multi-node#

# Run from the root of NeMo RL repo
NUM_ACTOR_NODES=2

COMMAND="uv run ./examples/run_distillation.py --config examples/configs/distillation_math.yaml cluster.num_nodes=2 cluster.gpus_per_node=8 checkpointing.checkpoint_dir='results/distill_2nodes' logger.wandb_enabled=True logger.wandb.name='distill-2nodes'" \
CONTAINER=YOUR_CONTAINER \
MOUNTS="$PWD:$PWD" \
sbatch \
    --nodes=${NUM_ACTOR_NODES} \
    --account=YOUR_ACCOUNT \
    --job-name=YOUR_JOBNAME \
    --partition=YOUR_PARTITION \
    --time=4:0:0 \
    --gres=gpu:8 \
    ray.sub

Note

For GB200 systems with 4 GPUs per node, use --gres=gpu:4 instead.