diff --git a/tests/diffusion/models/hunyuan_video/__init__.py b/tests/diffusion/models/hunyuan_video/__init__.py new file mode 100644 index 000000000..208f01a7c --- /dev/null +++ b/tests/diffusion/models/hunyuan_video/__init__.py @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project diff --git a/tests/diffusion/models/hunyuan_video/test_hunyuan_video_quant_config_propagation.py b/tests/diffusion/models/hunyuan_video/test_hunyuan_video_quant_config_propagation.py new file mode 100644 index 000000000..524a9b93b --- /dev/null +++ b/tests/diffusion/models/hunyuan_video/test_hunyuan_video_quant_config_propagation.py @@ -0,0 +1,160 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +"""Unit tests for HunyuanVideo-1.5 quant_config propagation through transformer creation. + +Tests cover: +- HunyuanVideo15Pipeline passes quant_config to HunyuanVideo15Transformer3DModel +- HunyuanVideo15I2VPipeline passes quant_config to HunyuanVideo15Transformer3DModel +""" + +from types import SimpleNamespace +from unittest.mock import MagicMock, patch + +import pytest +import torch + +import vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5 as t2v_module +import vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5_i2v as i2v_module + +pytestmark = [pytest.mark.core_model, pytest.mark.cpu, pytest.mark.diffusion] + + +class TestHunyuanVideoQuantConfigPropagation: + """Verify quant_config is propagated to the transformer model in HunyuanVideo-1.5 pipelines.""" + + @patch( + "vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5.get_local_device", + return_value="cpu", + ) + @patch("vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5.prefetch_subfolders") + @patch( + "vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5.from_pretrained_with_prefetch", + return_value=MagicMock(), + ) + @patch( + "vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5.Qwen2Tokenizer.from_pretrained", + return_value=MagicMock(), + ) + @patch( + "vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5.ByT5Tokenizer.from_pretrained", + return_value=MagicMock(), + ) + @patch( + "vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5.AutoConfig.from_pretrained", + return_value=MagicMock(), + ) + @patch( + "vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5.T5EncoderModel", + return_value=MagicMock(), + ) + @patch( + "vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5.FlowMatchEulerDiscreteScheduler.from_pretrained", + return_value=MagicMock(), + ) + @patch( + "vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5.get_transformer_config_kwargs", + return_value={}, + ) + def test_t2v_quant_config_passed_through( + self, + mock_get_kwargs, + mock_scheduler, + mock_t5_encoder, + mock_auto_config, + mock_byt5_tok, + mock_qwen2_tok, + mock_from_pretrained, + mock_prefetch, + mock_get_device, + ): + captured_kwargs = {} + + class FakeTransformer: + def __init__(self, **kwargs): + captured_kwargs.update(kwargs) + + with patch.object(t2v_module, "HunyuanVideo15Transformer3DModel", FakeTransformer): + fake_qc = MagicMock() + od_config = SimpleNamespace( + model="fake-t2v-model", + dtype=torch.bfloat16, + flow_shift=None, + tf_model_config=SimpleNamespace(), + quantization_config=fake_qc, + enable_diffusion_pipeline_profiler=False, + ) + + t2v_module.HunyuanVideo15Pipeline(od_config=od_config) + + assert captured_kwargs.get("quant_config") is fake_qc + + @patch( + "vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5_i2v.get_local_device", + return_value="cpu", + ) + @patch("vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5_i2v.prefetch_subfolders") + @patch( + "vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5_i2v.from_pretrained_with_prefetch", + return_value=MagicMock(), + ) + @patch( + "vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5_i2v.Qwen2Tokenizer.from_pretrained", + return_value=MagicMock(), + ) + @patch( + "vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5_i2v.ByT5Tokenizer.from_pretrained", + return_value=MagicMock(), + ) + @patch( + "vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5_i2v.AutoConfig.from_pretrained", + return_value=MagicMock(), + ) + @patch( + "vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5_i2v.T5EncoderModel", + return_value=MagicMock(), + ) + @patch( + "vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5_i2v.SiglipImageProcessor.from_pretrained", + return_value=MagicMock(), + ) + @patch( + "vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5_i2v.FlowMatchEulerDiscreteScheduler.from_pretrained", + return_value=MagicMock(), + ) + @patch( + "vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5_i2v.get_transformer_config_kwargs", + return_value={}, + ) + def test_i2v_quant_config_passed_through( + self, + mock_get_kwargs, + mock_scheduler, + mock_siglip_processor, + mock_t5_encoder, + mock_auto_config, + mock_byt5_tok, + mock_qwen2_tok, + mock_from_pretrained, + mock_prefetch, + mock_get_device, + ): + captured_kwargs = {} + + class FakeTransformer: + def __init__(self, **kwargs): + captured_kwargs.update(kwargs) + + with patch.object(i2v_module, "HunyuanVideo15Transformer3DModel", FakeTransformer): + fake_qc = MagicMock() + od_config = SimpleNamespace( + model="fake-i2v-model", + dtype=torch.bfloat16, + flow_shift=None, + tf_model_config=SimpleNamespace(), + quantization_config=fake_qc, + enable_diffusion_pipeline_profiler=False, + ) + + i2v_module.HunyuanVideo15I2VPipeline(od_config=od_config) + + assert captured_kwargs.get("quant_config") is fake_qc diff --git a/vllm_omni/diffusion/models/hunyuan_video/pipeline_hunyuan_video_1_5_i2v.py b/vllm_omni/diffusion/models/hunyuan_video/pipeline_hunyuan_video_1_5_i2v.py index 9eb296150..583ef87ed 100644 --- a/vllm_omni/diffusion/models/hunyuan_video/pipeline_hunyuan_video_1_5_i2v.py +++ b/vllm_omni/diffusion/models/hunyuan_video/pipeline_hunyuan_video_1_5_i2v.py @@ -186,7 +186,9 @@ class HunyuanVideo15I2VPipeline( self.scheduler._shift = od_config.flow_shift transformer_kwargs = get_transformer_config_kwargs(od_config.tf_model_config, HunyuanVideo15Transformer3DModel) - self.transformer = HunyuanVideo15Transformer3DModel(od_config=od_config, **transformer_kwargs) + self.transformer = HunyuanVideo15Transformer3DModel( + od_config=od_config, quant_config=od_config.quantization_config, **transformer_kwargs + ) self.use_meanflow = getattr(od_config.tf_model_config, "use_meanflow", False)