Files
vllm-project--vllm-omni/tests/entrypoints/test_async_omni_diffusion_config.py
wehub-resource-sync eec33d25b2
pre-commit / pre-commit (push) Failing after 1s
Build Wheel / build (3.11) (push) Failing after 1s
Build Wheel / build (3.12) (push) Failing after 0s
chore: import upstream snapshot with attribution
2026-07-13 12:29:08 +08:00

374 lines
13 KiB
Python

# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
from types import SimpleNamespace
import pytest
from vllm_omni.diffusion.data import AttentionConfig
from vllm_omni.engine.async_omni_engine import AsyncOmniEngine
from vllm_omni.entrypoints.cli.serve import OmniServeCommand
from vllm_omni.utils.tracking_parser import TrackingArgumentParser
pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
def test_default_stage_config_includes_cache_backend():
"""Ensure cache knobs survive the default diffusion-stage builder."""
stage_cfg = AsyncOmniEngine._create_default_diffusion_stage_cfg(
{
"cache_backend": "cache_dit",
"cache_config": '{"Fn_compute_blocks": 2}',
"vae_use_slicing": True,
"ulysses_degree": 2,
}
)[0]
engine_args = stage_cfg["engine_args"]
assert stage_cfg["stage_type"] == "diffusion"
assert engine_args["cache_backend"] == "cache_dit"
assert engine_args["cache_config"]["Fn_compute_blocks"] == 2
assert engine_args["vae_use_slicing"] is True
assert engine_args["parallel_config"].ulysses_degree == 2
assert engine_args["model_stage"] == "diffusion"
def test_default_cache_config_used_when_missing():
"""Ensure default cache_config is synthesized when only backend is given."""
stage_cfg = AsyncOmniEngine._create_default_diffusion_stage_cfg(
{
"cache_backend": "cache_dit",
}
)[0]
cache_config = stage_cfg["engine_args"]["cache_config"]
assert cache_config is not None
assert cache_config["Fn_compute_blocks"] == 1
def test_default_stage_devices_from_sequence_parallel():
"""Ensure runtime devices reflect computed diffusion world size."""
stage_cfg = AsyncOmniEngine._create_default_diffusion_stage_cfg(
{
"ulysses_degree": 2,
"ring_degree": 2,
}
)[0]
assert stage_cfg["runtime"]["devices"] == "0,1,2,3"
def test_default_stage_config_uses_parallel_size_kwargs():
"""Ensure default diffusion parallel_config uses CLI/API parallel sizes."""
stage_cfg = AsyncOmniEngine._create_default_diffusion_stage_cfg(
{
"pipeline_parallel_size": 2,
"data_parallel_size": 3,
"tensor_parallel_size": 4,
"enable_expert_parallel": True,
}
)[0]
parallel_config = stage_cfg["engine_args"]["parallel_config"]
assert parallel_config.pipeline_parallel_size == 2
assert parallel_config.data_parallel_size == 3
assert parallel_config.tensor_parallel_size == 4
assert parallel_config.enable_expert_parallel is True
def test_default_stage_config_defaults_nullified_parallel_size_kwargs():
"""Ensure nullified diffusion parallel-size kwargs fall back to defaults."""
stage_cfg = AsyncOmniEngine._create_default_diffusion_stage_cfg(
{
"pipeline_parallel_size": None,
"data_parallel_size": None,
"tensor_parallel_size": None,
"enable_expert_parallel": None,
"enforce_eager": None,
}
)[0]
parallel_config = stage_cfg["engine_args"]["parallel_config"]
assert parallel_config.pipeline_parallel_size == 1
assert parallel_config.data_parallel_size == 1
assert parallel_config.tensor_parallel_size == 1
assert parallel_config.enable_expert_parallel is False
assert stage_cfg["engine_args"]["enforce_eager"] is False
def test_default_stage_config_propagates_ulysses_mode():
"""Ensure UAA mode survives default diffusion-stage creation."""
stage_cfg = AsyncOmniEngine._create_default_diffusion_stage_cfg(
{
"ulysses_degree": 4,
"ulysses_mode": "advanced_uaa",
}
)[0]
parallel_config = stage_cfg["engine_args"]["parallel_config"]
assert parallel_config.ulysses_degree == 4
assert parallel_config.ulysses_mode == "advanced_uaa"
def test_default_stage_config_includes_default_sampling_params():
"""Ensure default sampling params survive the default diffusion-stage builder."""
stage_cfg = AsyncOmniEngine._create_default_diffusion_stage_cfg(
{
"default_sampling_params": '{"0": {"generator_device":"cpu", "guidance_scale":7.5}}',
}
)[0]
assert stage_cfg["default_sampling_params"] == {
"generator_device": "cpu",
"guidance_scale": 7.5,
}
def test_default_stage_config_includes_diffusion_attention_backend():
"""Ensure diffusion attention shorthand lands in engine_args.diffusion_attention_config."""
stage_cfg = AsyncOmniEngine._create_default_diffusion_stage_cfg(
{
"diffusion_attention_backend": "FLASH_ATTN",
}
)[0]
diffusion_attention_config = stage_cfg["engine_args"]["diffusion_attention_config"]
assert isinstance(diffusion_attention_config, AttentionConfig)
assert diffusion_attention_config.default is not None
assert diffusion_attention_config.default.backend == "FLASH_ATTN"
def test_default_stage_config_includes_diffusion_attention_config():
"""Ensure structured diffusion attention config survives default stage creation."""
stage_cfg = AsyncOmniEngine._create_default_diffusion_stage_cfg(
{
"diffusion_attention_config": {
"default": {"backend": "FLASH_ATTN"},
"per_role": {"cross": {"backend": "TORCH_SDPA"}},
},
}
)[0]
diffusion_attention_config = stage_cfg["engine_args"]["diffusion_attention_config"]
assert isinstance(diffusion_attention_config, AttentionConfig)
assert diffusion_attention_config.default is not None
assert diffusion_attention_config.default.backend == "FLASH_ATTN"
assert diffusion_attention_config.per_role["cross"].backend == "TORCH_SDPA"
def test_default_stage_config_rejects_conflicting_diffusion_attention_inputs():
"""Ensure shorthand and default.backend stay mutually exclusive."""
with pytest.raises(ValueError, match="mutually exclusive"):
AsyncOmniEngine._create_default_diffusion_stage_cfg(
{
"diffusion_attention_backend": "FLASH_ATTN",
"diffusion_attention_config": {
"default": {"backend": "TORCH_SDPA"},
},
}
)
def test_default_stage_config_engine_args():
"""Ensure default diffusion-stage builder sets and propagates engine_args."""
stage_cfg = AsyncOmniEngine._create_default_diffusion_stage_cfg(
{
"distributed_executor_backend": "ray",
"boundary_ratio": 0.875,
"flow_shift": 5.0,
"trust_remote_code": True,
}
)[0]
engine_args = stage_cfg["engine_args"]
assert engine_args["distributed_executor_backend"] == "ray"
assert engine_args["boundary_ratio"] == 0.875
assert engine_args["flow_shift"] == 5.0
assert engine_args["trust_remote_code"] is True
def test_default_stage_config_whitelist_none_fallback():
"""DeployConfig / StageDeployConfig whitelist fields with value None
fall back to OmniDiffusionConfig dataclass defaults."""
stage_cfg = AsyncOmniEngine._create_default_diffusion_stage_cfg(
{
# DeployConfig pipeline-wide
"trust_remote_code": None,
"distributed_executor_backend": None,
"dtype": None,
# StageDeployConfig
"enforce_eager": None,
}
)[0]
engine_args = stage_cfg["engine_args"]
assert engine_args["trust_remote_code"] is False
assert engine_args["distributed_executor_backend"] == "mp"
assert engine_args["dtype"] == "auto"
assert engine_args["enforce_eager"] is False
def test_serve_cli_accepts_ulysses_mode():
"""Ensure diffusion serve CLI exposes ulysses_mode and wires it to parallel_config."""
parser = TrackingArgumentParser()
subparsers = parser.add_subparsers(dest="command")
OmniServeCommand().subparser_init(subparsers)
args = parser.parse_args(
[
"serve",
"Qwen/Qwen-Image",
"--omni",
"--usp",
"4",
"--ulysses-mode",
"advanced_uaa",
]
)
explicit_kwargs = args.get_explicit_kwargs_dict()
stage_cfg = AsyncOmniEngine._create_default_diffusion_stage_cfg(explicit_kwargs)[0]
parallel_config = stage_cfg["engine_args"]["parallel_config"]
assert args.ulysses_mode == "advanced_uaa"
assert parallel_config.ulysses_degree == 4
assert parallel_config.ulysses_mode == "advanced_uaa"
def test_serve_cli_accepts_diffusion_pipeline_profiler_flag():
"""Ensure diffusion serve CLI exposes the profiler switch."""
parser = TrackingArgumentParser()
subparsers = parser.add_subparsers(dest="command")
OmniServeCommand().subparser_init(subparsers)
args = parser.parse_args(
[
"serve",
"Wan-AI/Wan2.2-T2V-A14B-Diffusers",
"--omni",
"--enable-diffusion-pipeline-profiler",
]
)
explicit_kwargs = args.get_explicit_kwargs_dict()
stage_cfg = AsyncOmniEngine._create_default_diffusion_stage_cfg(explicit_kwargs)[0]
assert args.enable_diffusion_pipeline_profiler is True
assert stage_cfg["engine_args"]["enable_diffusion_pipeline_profiler"] is True
def test_serve_cli_accepts_diffusion_attention_backend():
"""Ensure diffusion serve CLI exposes the shorthand backend flag."""
parser = TrackingArgumentParser()
subparsers = parser.add_subparsers(dest="command")
OmniServeCommand().subparser_init(subparsers)
args = parser.parse_args(
[
"serve",
"Qwen/Qwen-Image",
"--omni",
"--diffusion-attention-backend",
"FLASH_ATTN",
]
)
explicit_kwargs = args.get_explicit_kwargs_dict()
stage_cfg = AsyncOmniEngine._create_default_diffusion_stage_cfg(explicit_kwargs)[0]
diffusion_attention_config = stage_cfg["engine_args"]["diffusion_attention_config"]
assert args.diffusion_attention_backend == "FLASH_ATTN"
assert isinstance(diffusion_attention_config, AttentionConfig)
assert diffusion_attention_config.default is not None
assert diffusion_attention_config.default.backend == "FLASH_ATTN"
def test_serve_cli_accepts_request_batch_max_wait_ms():
"""Ensure diffusion serve CLI forwards request-batch admission wait to stage config."""
parser = TrackingArgumentParser()
subparsers = parser.add_subparsers(dest="command")
OmniServeCommand().subparser_init(subparsers)
args = parser.parse_args(
[
"serve",
"Qwen/Qwen-Image",
"--omni",
"--request-batch-max-wait-ms",
"250",
]
)
explicit_kwargs = args.get_explicit_kwargs_dict()
stage_cfg = AsyncOmniEngine._create_default_diffusion_stage_cfg(explicit_kwargs)[0]
assert args.request_batch_max_wait_ms == 250.0
assert stage_cfg["engine_args"]["request_batch_max_wait_ms"] == 250.0
def test_serve_cli_accepts_additional_config():
"""Ensure diffusion serve CLI exposes additional_config and forwards it to stage config."""
parser = TrackingArgumentParser()
subparsers = parser.add_subparsers(dest="command")
OmniServeCommand().subparser_init(subparsers)
args = parser.parse_args(
[
"serve",
"Qwen/Qwen-Image",
"--omni",
"--additional-config",
'{"torchair_graph_config":{"enabled":true}}',
]
)
stage_cfg = AsyncOmniEngine._create_default_diffusion_stage_cfg(vars(args))[0]
engine_args = stage_cfg["engine_args"]
assert args.additional_config == {"torchair_graph_config": {"enabled": True}}
assert engine_args["additional_config"] == {"torchair_graph_config": {"enabled": True}}
def test_resolve_stage_configs_injects_additional_config_into_diffusion_stage(mocker):
"""Ensure YAML/deploy stage resolution forwards top-level additional_config."""
fake_diffusion_stage = SimpleNamespace(
stage_type="diffusion",
engine_args=SimpleNamespace(),
)
fake_llm_stage = SimpleNamespace(
stage_type="llm",
engine_args=SimpleNamespace(),
)
mocker.patch(
"vllm_omni.engine.async_omni_engine.load_and_resolve_stage_configs",
return_value=("dummy.yaml", [fake_llm_stage, fake_diffusion_stage], None),
)
engine = AsyncOmniEngine.__new__(AsyncOmniEngine)
engine._strip_single_engine_args = lambda kwargs: kwargs
_, stage_configs = engine._resolve_stage_configs(
"dummy-model",
{
"stage_configs_path": "dummy.yaml",
"additional_config": {"torchair_graph_config": {"enabled": True}},
},
)
assert not hasattr(stage_configs[0].engine_args, "additional_config")
assert stage_configs[1].engine_args.additional_config == {"torchair_graph_config": {"enabled": True}}
def test_default_stage_config_includes_quantization_config():
"""Ensure structured quantization_config survives default diffusion-stage creation."""
quantization_config = {
"method": "example_quant",
"weights": "weights.bin",
}
stage_cfg = AsyncOmniEngine._create_default_diffusion_stage_cfg({"quantization_config": quantization_config})[0]
assert stage_cfg["engine_args"]["quantization_config"] == quantization_config