From f69ece85d529488072379e0b4cf8a181af617c50 Mon Sep 17 00:00:00 2001 From: seonjinn Date: Thu, 10 Sep 2026 03:48:06 -0700 Subject: [PATCH 1/5] test(qwen3.5): require vision freeze in text recipe Signed-off-by: seonjinn --- .../generation/test_vllm_qwen35_bf16_trtllm_recipe.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/unit/models/generation/test_vllm_qwen35_bf16_trtllm_recipe.py b/tests/unit/models/generation/test_vllm_qwen35_bf16_trtllm_recipe.py index b1f542efc23..2bb08229ae7 100644 --- a/tests/unit/models/generation/test_vllm_qwen35_bf16_trtllm_recipe.py +++ b/tests/unit/models/generation/test_vllm_qwen35_bf16_trtllm_recipe.py @@ -69,3 +69,13 @@ def test_qwen35_bf16_trtllm_recipe_uses_supported_expert_layout() -> None: "moe_backend": "flashinfer_trtllm", "expert_placement_strategy": "linear", } + + +def test_qwen35_bf16_trtllm_recipe_freezes_unused_vision_modules() -> None: + recipe = _load_recipe() + + assert recipe["policy"]["megatron_cfg"]["freeze_config"] == { + "freeze_vision_model": True, + "freeze_vision_projection": True, + "freeze_language_model": False, + } From 721cc5d4ade1a1163de32f9c61baf87744c7389c Mon Sep 17 00:00:00 2001 From: seonjinn Date: Thu, 10 Sep 2026 03:55:51 -0700 Subject: [PATCH 2/5] fix(qwen3.5): freeze vision modules in text recipes Signed-off-by: seonjinn --- .../llm/grpo-qwen3.5-35ba3b-2n8g-megatron-ep16tp2-fp8.yaml | 4 ---- .../llm/grpo-qwen3.5-35ba3b-2n8g-megatron-ep16tp2cp2.yaml | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/configs/recipes/llm/grpo-qwen3.5-35ba3b-2n8g-megatron-ep16tp2-fp8.yaml b/examples/configs/recipes/llm/grpo-qwen3.5-35ba3b-2n8g-megatron-ep16tp2-fp8.yaml index 66b85b2dfc6..98ebb44b452 100644 --- a/examples/configs/recipes/llm/grpo-qwen3.5-35ba3b-2n8g-megatron-ep16tp2-fp8.yaml +++ b/examples/configs/recipes/llm/grpo-qwen3.5-35ba3b-2n8g-megatron-ep16tp2-fp8.yaml @@ -14,10 +14,6 @@ policy: megatron_cfg: context_parallel_size: 1 moe_router_dtype: fp32 - freeze_config: - freeze_vision_model: true - freeze_vision_projection: true - freeze_language_model: false fp8_cfg: enabled: true optimizer: diff --git a/examples/configs/recipes/llm/grpo-qwen3.5-35ba3b-2n8g-megatron-ep16tp2cp2.yaml b/examples/configs/recipes/llm/grpo-qwen3.5-35ba3b-2n8g-megatron-ep16tp2cp2.yaml index 8687d981404..6ed27cef8e0 100644 --- a/examples/configs/recipes/llm/grpo-qwen3.5-35ba3b-2n8g-megatron-ep16tp2cp2.yaml +++ b/examples/configs/recipes/llm/grpo-qwen3.5-35ba3b-2n8g-megatron-ep16tp2cp2.yaml @@ -15,6 +15,10 @@ policy: context_parallel_size: 2 sequence_parallel: true expert_model_parallel_size: 16 + freeze_config: + freeze_vision_model: true + freeze_vision_projection: true + freeze_language_model: false apply_rope_fusion: false activation_checkpointing: true defer_fp32_logits: true From 83cac8ed173d5b552f26d71c6da1eec7ac48d705 Mon Sep 17 00:00:00 2001 From: seonjinn Date: Thu, 10 Sep 2026 04:20:30 -0700 Subject: [PATCH 3/5] test(qwen3.5): cover vision freeze across precisions Signed-off-by: seonjinn --- .../test_vllm_qwen35_bf16_trtllm_recipe.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/unit/models/generation/test_vllm_qwen35_bf16_trtllm_recipe.py b/tests/unit/models/generation/test_vllm_qwen35_bf16_trtllm_recipe.py index 2bb08229ae7..e9eae8e6922 100644 --- a/tests/unit/models/generation/test_vllm_qwen35_bf16_trtllm_recipe.py +++ b/tests/unit/models/generation/test_vllm_qwen35_bf16_trtllm_recipe.py @@ -15,6 +15,7 @@ from pathlib import Path from typing import Any +import pytest from omegaconf import OmegaConf from nemo_rl.utils.config import ( @@ -24,11 +25,15 @@ PROJECT_ROOT = Path(__file__).resolve().parents[4] RECIPE_NAME = "grpo-qwen3.5-35ba3b-6n4g-async-1off-bf16-trtllm.yaml" +TEXT_RECIPE_NAMES = ( + RECIPE_NAME, + "grpo-qwen3.5-35ba3b-2n8g-megatron-ep16tp2-fp8.yaml", +) -def _load_recipe() -> dict[str, Any]: +def _load_recipe(recipe_name: str = RECIPE_NAME) -> dict[str, Any]: register_omegaconf_resolvers() - recipe_path = PROJECT_ROOT / "examples/configs/recipes/llm" / RECIPE_NAME + recipe_path = PROJECT_ROOT / "examples/configs/recipes/llm" / recipe_name recipe = OmegaConf.to_container( load_config_with_inheritance(recipe_path), resolve=True ) @@ -71,8 +76,11 @@ def test_qwen35_bf16_trtllm_recipe_uses_supported_expert_layout() -> None: } -def test_qwen35_bf16_trtllm_recipe_freezes_unused_vision_modules() -> None: - recipe = _load_recipe() +@pytest.mark.parametrize("recipe_name", TEXT_RECIPE_NAMES) +def test_qwen35_text_recipe_freezes_unused_vision_modules( + recipe_name: str, +) -> None: + recipe = _load_recipe(recipe_name) assert recipe["policy"]["megatron_cfg"]["freeze_config"] == { "freeze_vision_model": True, From 78af1676f757d546eecb16a84fe76875d05f1ce1 Mon Sep 17 00:00:00 2001 From: seonjinn Date: Thu, 1 Oct 2026 03:18:32 +0200 Subject: [PATCH 4/5] test(qwen3.5): cover all text-only recipes Signed-off-by: seonjinn --- .../models/generation/test_vllm_qwen35_bf16_trtllm_recipe.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/unit/models/generation/test_vllm_qwen35_bf16_trtllm_recipe.py b/tests/unit/models/generation/test_vllm_qwen35_bf16_trtllm_recipe.py index e9eae8e6922..52c400930a9 100644 --- a/tests/unit/models/generation/test_vllm_qwen35_bf16_trtllm_recipe.py +++ b/tests/unit/models/generation/test_vllm_qwen35_bf16_trtllm_recipe.py @@ -27,7 +27,10 @@ RECIPE_NAME = "grpo-qwen3.5-35ba3b-6n4g-async-1off-bf16-trtllm.yaml" TEXT_RECIPE_NAMES = ( RECIPE_NAME, + "grpo-qwen3.5-9b-1n8g-megatron.yaml", + "grpo-qwen3.5-9b-1n8g-megatron-fp8.yaml", "grpo-qwen3.5-35ba3b-2n8g-megatron-ep16tp2-fp8.yaml", + "grpo-qwen3.5-397ba17b-32n8g-megatron.v2.yaml", ) From 3705bbc02525bbab0ecd5dabb8655a3a6e557a98 Mon Sep 17 00:00:00 2001 From: seonjinn Date: Thu, 1 Oct 2026 03:30:53 +0200 Subject: [PATCH 5/5] fix(qwen3.5): freeze vision in every text recipe Signed-off-by: seonjinn --- .../recipes/llm/grpo-qwen3.5-397ba17b-32n8g-megatron.v2.yaml | 4 ++++ .../recipes/llm/grpo-qwen3.5-9b-1n8g-megatron-fp8.yaml | 4 ---- .../configs/recipes/llm/grpo-qwen3.5-9b-1n8g-megatron.yaml | 4 ++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/examples/configs/recipes/llm/grpo-qwen3.5-397ba17b-32n8g-megatron.v2.yaml b/examples/configs/recipes/llm/grpo-qwen3.5-397ba17b-32n8g-megatron.v2.yaml index fd9af4c283d..45f2630e2e7 100644 --- a/examples/configs/recipes/llm/grpo-qwen3.5-397ba17b-32n8g-megatron.v2.yaml +++ b/examples/configs/recipes/llm/grpo-qwen3.5-397ba17b-32n8g-megatron.v2.yaml @@ -44,6 +44,10 @@ policy: moe_token_dispatcher_type: allgather apply_rope_fusion: false defer_fp32_logits: true + freeze_config: + freeze_vision_model: true + freeze_vision_projection: true + freeze_language_model: false optimizer: lr: 1.0e-06 min_lr: 1.0e-06 diff --git a/examples/configs/recipes/llm/grpo-qwen3.5-9b-1n8g-megatron-fp8.yaml b/examples/configs/recipes/llm/grpo-qwen3.5-9b-1n8g-megatron-fp8.yaml index 30e69bdabf5..5fdca15cef8 100644 --- a/examples/configs/recipes/llm/grpo-qwen3.5-9b-1n8g-megatron-fp8.yaml +++ b/examples/configs/recipes/llm/grpo-qwen3.5-9b-1n8g-megatron-fp8.yaml @@ -18,10 +18,6 @@ policy: make_sequence_length_divisible_by: 32 megatron_cfg: moe_router_dtype: fp32 - freeze_config: - freeze_vision_model: true - freeze_vision_projection: true - freeze_language_model: false fp8_cfg: enabled: true optimizer: diff --git a/examples/configs/recipes/llm/grpo-qwen3.5-9b-1n8g-megatron.yaml b/examples/configs/recipes/llm/grpo-qwen3.5-9b-1n8g-megatron.yaml index 2031e92f2a3..6203dd7e5d7 100644 --- a/examples/configs/recipes/llm/grpo-qwen3.5-9b-1n8g-megatron.yaml +++ b/examples/configs/recipes/llm/grpo-qwen3.5-9b-1n8g-megatron.yaml @@ -17,6 +17,10 @@ policy: apply_rope_fusion: false activation_checkpointing: true defer_fp32_logits: true + freeze_config: + freeze_vision_model: true + freeze_vision_projection: true + freeze_language_model: false generation: vllm_cfg: tensor_parallel_size: 4