feat: Multi-Teacher On-Policy Distillation (MOPD) - #2780
Conversation
Ports MOPD from ultra-v3 to main. Uses main's overlapped gym-init / deferred-vLLM: vLLM weight-load, policy load, and NeMo-Gym spin-up run in parallel in setup(). Teacher init runs serially after policy + vLLM are ready; parallelizing races on Megatron-Bridge's HF->mcore cache when student == teacher (shared iter_0000000/ path). Algorithm: - OPDAdvantageEstimator: token-level distillation advantage (Eq. 8) - teacher_worker_group.py: non-colocated teacher inference workers - opd.py: teacher worker group orchestration + reference resolution Integration in setup()/async_grpo_train(): - Reserve nodes for non-colocated OPD teachers (subtract from policy_nodes) - Init teacher worker groups after policy + generation are ready - Return teacher_worker_groups + alias_to_group_alias from setup() - Pass them to AsyncTrajectoryCollector (collection-time teacher logprobs) - Extract teacher_reference_logprobs from per-prompt batches in async path - Pad teacher logprobs to make_sequence_length_divisible_by-aligned train_S - Plumb teacher_logprobs through adv_estimator.compute_advantage - Warn when loss_fn isn't configured per MOPD paper (disable_ppo_ratio, use_importance_sampling_correction, icepop) Smoke recipe: - examples/nemo_gym/mopd_nanov3_4n8g_smoke.yaml - launch_mopd_nanov3_4n8g_smoke.sh - 4 H100 nodes (2 policy + 1 vLLM + 1 teacher), Nemotron-3-Nano-30B-A3B - student==teacher -> OPD loss expected ~= 0 Signed-off-by: Yi-Fu Wu <yifu.wu@gmail.com>
Signed-off-by: Yi-Fu Wu <yifu.wu@gmail.com>
|
/ok to test 99b0186 |
Signed-off-by: Yi-Fu Wu <yifu.wu@gmail.com>
Signed-off-by: Yi-Fu Wu <yifu.wu@gmail.com>
Signed-off-by: Yi-Fu Wu <yifu.wu@gmail.com>
|
/ok to test 7203c79 |
Signed-off-by: Yi-Fu Wu <yifu.wu@gmail.com>
Signed-off-by: Yi-Fu Wu <yifu.wu@gmail.com>
Signed-off-by: Yi-Fu Wu <yifu.wu@gmail.com>
Signed-off-by: Yi-Fu Wu <yifu.wu@gmail.com>
Signed-off-by: Yi-Fu Wu <yifu.wu@gmail.com>
Signed-off-by: Yi-Fu Wu <yifu.wu@gmail.com>
Signed-off-by: Yi-Fu Wu <yifu.wu@gmail.com>
Signed-off-by: Yi-Fu Wu <yifu.wu@gmail.com>
|
/ok to test 8d0844c |
|
/ok to test ff604ae |
RL POR Test Summary — MOPD (Multi-Teacher On-Policy Distillation)Feature under test: NVIDIA-NeMo/RL PR #2780 — Multi-Teacher On-Policy Distillation Result: PASS ✅
Source: What the test exercisesDrives the shipped recipe directly — no fork of product config:
Self-distillation (student == teacher == Qwen3-1.7B), so the OPD advantage loss MOPD code paths covered
Real per-step evidence (stdout.log)
CI shrink (product behavior untouched)Only step count and sequence length reduced to fit CI:
MOPD knobs left at recipe defaults: adv_estimator, async_grpo, teacher Notes / observations
Registration"test_grpo_mopd_qwen3_1p7b_megatron_multinode": {
"tier": "e2e", "submit_mode": "sbatch", "num_gpus": 24, "timeout_sec": 9000,
"slurm": { "nodes": 3, "exclusive": true, "ray_bringup": true },
"tags": ["codecoverage", "rc_p0"],
"status": "new", "version": "nightly",
"pr": "https://github.com/NVIDIA-NeMo/RL/pull/2780"
} |
What does this PR do ?
Adds Multi-Teacher On-Policy Distillation (MOPD) on top of async GRPO. MOPD distills one or more teacher models into the policy using token-level teacher-vs-student logprob advantages, with teachers served by non-colocated inference worker groups. Teacher routing is per-agent (via NeMo-Gym), so different environments/agents can be distilled from different teachers.
Algorithm
OPDAdvantageEstimator(nemo_rl/algorithms/advantage_estimator.py): token-level distillation advantageÂ_t = sg[log π_teacher − log π_student]. Importance-sampling truncation is handled separately by the ICE-POP gate in the loss function.loss_fn:disable_ppo_ratio(REINFORCE form) +use_importance_sampling_correctionwithtruncated_importance_sampling_type: icepop. Whenadv_estimator.name: opdis set without these,_create_advantage_estimatoremits warnings.Teacher infrastructure
nemo_rl/algorithms/opd.py(new):on_policy_distillationconfig schemas (pydanticBaseModel), teacher routing (agent → teacher-alias resolution and deduplication of shared checkpoints), teacher worker-group creation, and the TP-aligned sequence-pad helper for non-packed teachers.nemo_rl/models/policy/teacher_worker_group.py(new):TeacherWorkerGroup, an inference-only Megatron worker group (no optimizer, no reference model) that loads a teacher checkpoint and exposesget_logprobs, plus config builders with per-teacher overrides and dedup.nemo_rl/models/megatron/setup.py: freezes all parameters for inference-only workers so DDP skips gradient-buffer allocation (significant memory savings for large models).Integration
on_policy_distillationis now a typed field on the GRPOMasterConfig.setup()reserves nodes for non-colocated teachers and returns the teacher worker groups plus the alias→group mapping.Config, examples, and tests
on_policy_distillationfield in thegrpo_math_1Bexemplar (and reference config).examples/configs/recipes/llm/mopd-qwen3-1.7b-3n8g-megatron-pack.yaml: dense Qwen3-1.7B self-distill (student == teacher → OPD loss ≈ 0) on 3 nodes (1 policy + 1 vLLM + 1 teacher), added to the nightly suite. The driver asserts the loss stays near zero.mopdis registered as a recipe algo prefix.Issues
List issues that this PR closes (syntax):
Usage
MOPD requires async GRPO with non-colocated teachers (NeMo-Gym). Enable it via:
See examples/configs/recipes/llm/mopd-qwen3-1.7b-3n8g-megatron-pack.yaml for a complete example.
Additional Information