diff --git a/tests/config/test_omni_config.py b/tests/config/test_omni_config.py index 97f9a5370..c0ac38924 100644 --- a/tests/config/test_omni_config.py +++ b/tests/config/test_omni_config.py @@ -255,6 +255,30 @@ def test_from_pipeline_config_applies_cli_overrides_without_stage_config_runtime assert stage1.runtime_config.num_gpus == stage1.parallel_config.world_size +def test_diffusion_cli_parallel_overrides_beat_nested_deploy_parallel_config(): + """Flat CLI parallel flags override the deploy YAML's nested parallel_config. + + Regression for the NPU nightly failure (#7778): hunyuan_image3_dit.yaml's + platform section sets nested parallel_config.tensor_parallel_size=4 while + the perf tests pass --tensor-parallel-size 2. The flat CLI value must win, + mirroring StageConfig.to_omegaconf, or the stage demands more devices than + the machine has (tp=4 x usp=2 = 8 on a 4-card box). + """ + omni_config = VllmOmniConfig.from_pipeline_config( + _resolve_pipeline_or_skip("hunyuan_image3_dit"), + user_deploy_config=DeployConfig( + stages=[StageDeployConfig(stage_id=0, engine_extras={"parallel_config": {"tensor_parallel_size": 4}})] + ), + cli_overrides={"tensor_parallel_size": 2, "ulysses_degree": 2}, + ) + + stage = omni_config.stage_by_id(0) + + assert stage.parallel_config.tensor_parallel_size == 2 + assert stage.parallel_config.ulysses_degree == 2 + assert stage.parallel_config.world_size == 4 + + @pytest.mark.parametrize( "cli_overrides", [ diff --git a/vllm_omni/config/omni_config.py b/vllm_omni/config/omni_config.py index 1407615ab..f1e5de26a 100644 --- a/vllm_omni/config/omni_config.py +++ b/vllm_omni/config/omni_config.py @@ -43,6 +43,7 @@ from vllm_omni.config.stage_config import ( StageExecutionType, StagePipelineConfig, StageType, + _apply_diffusion_parallel_runtime_overrides, _apply_platform_overrides, _get_recursively_merged_dict, _resolve_scheduler, @@ -1328,8 +1329,13 @@ def _stage_engine_values( if topology.omni_kv_config: engine["omni_kv_config"] = _copy_value(topology.omni_kv_config) if stage_cli_overrides: + stage_cli_overrides = dict(stage_cli_overrides) if topology.execution_type == StageExecutionType.DIFFUSION: # Mirror StageConfig.to_omegaconf so both projections resolve alike. + # CLI parallel fields move into the nested ``parallel_config`` dict, + # otherwise the deploy YAML's nested values would win over flat CLI + # flags when ``_build_parallel_config`` merges nested over flat. + _apply_diffusion_parallel_runtime_overrides(engine, stage_cli_overrides) reconcile_diffusion_attention_overrides(engine, stage_cli_overrides) for key, value in stage_cli_overrides.items(): existing = engine.get(key)