@@ -1586,3 +1586,73 @@ def exec_runner(executable, argv, env):
15861586 assert calls [0 ] == ("environment" , effective_recipe )
15871587 assert calls [1 ][0 ] == "exec"
15881588 assert calls [1 ][2 ][1 ].endswith ("run_recipe.py" )
1589+
1590+
1591+ def test_complete_library_recipe_name_is_not_suffixed (monkeypatch ):
1592+ """CI can select a hardware-specific library recipe without renaming it."""
1593+ from megatron .bridge .recipes .common import _sft_common
1594+
1595+ recipe = _sft_common ()
1596+ name = "qwen35_text_35b_a3b_sft_long_context_16gpu_gb200_fp8mx_config"
1597+ module = SimpleNamespace (** {name : lambda : recipe })
1598+ monkeypatch .setattr (utils .importlib , "import_module" , lambda _ : module )
1599+ result = utils .build_recipe_config ("qwen" , name , "sft" , "ci-test" )
1600+ assert result is recipe
1601+ assert result .logger .wandb_exp_name == "ci-test"
1602+
1603+
1604+ @pytest .mark .parametrize ("dataset_kind" , ["text" , "energon" ])
1605+ def test_recipe_data_keeps_native_packing_tokenizer_and_schedule (dataset_kind ):
1606+ """A 100-step CI run must not replace SFT inputs or compress the LR schedule."""
1607+ from argument_parser import parse_cli_args
1608+
1609+ from megatron .bridge .data .builders import EnergonDatasetConfig , QwenVLEnergonTaskEncoderConfig
1610+ from megatron .bridge .recipes .common import _sft_common
1611+ from megatron .bridge .recipes .utils .dataset_utils import default_coderforge_config
1612+
1613+ args = parse_cli_args ().parse_args (
1614+ [
1615+ "--model_family_name" ,
1616+ "qwen" ,
1617+ "--model_recipe_name" ,
1618+ "test_config" ,
1619+ "--num_gpus" ,
1620+ "16" ,
1621+ "--gpu" ,
1622+ "gb200" ,
1623+ "--task" ,
1624+ "sft" ,
1625+ "--use_recipes" ,
1626+ "--data" ,
1627+ "recipe" ,
1628+ "--max_steps" ,
1629+ "100" ,
1630+ "--warmup_iters" ,
1631+ "200" ,
1632+ ]
1633+ )
1634+ cfg = _sft_common ()
1635+ cfg .dataset = (
1636+ EnergonDatasetConfig (
1637+ seq_length = 131072 ,
1638+ micro_batch_size = 1 ,
1639+ packing_buffer_size = 64 ,
1640+ task_encoder = QwenVLEnergonTaskEncoderConfig (hf_processor_path = "test-model" ),
1641+ )
1642+ if dataset_kind == "energon"
1643+ else default_coderforge_config (seq_length = 131072 , enable_offline_packing = True )
1644+ )
1645+ dataset , tokenizer = cfg .dataset , cfg .tokenizer
1646+ cfg .scheduler .lr_decay_iters = 300000
1647+ cfg .validation .eval_interval = 50
1648+ cfg .validation .eval_iters = 8
1649+ result = run_recipe ._apply_training_argparse_overrides (cfg , args )
1650+ assert result .dataset is dataset
1651+ assert result .tokenizer is tokenizer
1652+ assert result .train .train_iters == 100
1653+ assert result .scheduler .lr_warmup_iters == 200
1654+ assert result .scheduler .lr_decay_iters == 300000
1655+ assert result .validation .eval_interval == 50
1656+ assert result .validation .eval_iters == 8
1657+ assert result .train .eval_iters is None
1658+ assert result .train .eval_interval is None
0 commit comments