From b9e1b66d968fd51f9aaf3930c343e69a1e95a5bb Mon Sep 17 00:00:00 2001 From: stevhliu Date: Fri, 10 Jul 2026 09:31:36 -0700 Subject: [PATCH 1/4] alias --- src/diffusers/loaders/single_file.py | 4 +++- src/diffusers/loaders/single_file_model.py | 4 +++- src/diffusers/models/adapter.py | 2 +- src/diffusers/models/auto_model.py | 2 +- src/diffusers/models/controlnets/multicontrolnet.py | 2 +- src/diffusers/models/controlnets/multicontrolnet_union.py | 2 +- src/diffusers/models/modeling_utils.py | 4 +++- src/diffusers/modular_pipelines/modular_pipeline_utils.py | 3 ++- src/diffusers/pipelines/auto_pipeline.py | 8 ++++---- src/diffusers/pipelines/pipeline_utils.py | 8 ++++++-- 10 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/diffusers/loaders/single_file.py b/src/diffusers/loaders/single_file.py index e1cc7f5afe1e..881ff9b96a4c 100644 --- a/src/diffusers/loaders/single_file.py +++ b/src/diffusers/loaders/single_file.py @@ -281,7 +281,7 @@ def from_single_file(cls, pretrained_model_link_or_path, **kwargs) -> Self: - A link to the `.ckpt` file (for example `"https://huggingface.co//blob/main/.ckpt"`) on the Hub. - A path to a *file* containing all pipeline weights. - torch_dtype (`str` or `torch.dtype`, *optional*): + dtype (`str` or `torch.dtype`, *optional*): Override the default `torch.dtype` and load the model with another dtype. force_download (`bool`, *optional*, defaults to `False`): Whether or not to force the (re-)download of the model weights and configuration files, overriding the @@ -361,6 +361,8 @@ def from_single_file(cls, pretrained_model_link_or_path, **kwargs) -> Self: local_files_only = kwargs.pop("local_files_only", False) revision = kwargs.pop("revision", None) torch_dtype = kwargs.pop("torch_dtype", None) + dtype = kwargs.pop("dtype", None) + torch_dtype = dtype if dtype is not None else torch_dtype disable_mmap = kwargs.pop("disable_mmap", False) is_legacy_loading = False diff --git a/src/diffusers/loaders/single_file_model.py b/src/diffusers/loaders/single_file_model.py index 9c8508914f3d..56770fd9b6c3 100644 --- a/src/diffusers/loaders/single_file_model.py +++ b/src/diffusers/loaders/single_file_model.py @@ -277,7 +277,7 @@ def from_single_file(cls, pretrained_model_link_or_path_or_dict: str | None = No original_config (`str`, *optional*): Dict or path to a yaml file containing the configuration for the model in its original format. If a dict is provided, it will be used to initialize the model configuration. - torch_dtype (`torch.dtype`, *optional*): + dtype (`torch.dtype`, *optional*): Override the default `torch.dtype` and load the model with another dtype. force_download (`bool`, *optional*, defaults to `False`): Whether or not to force the (re-)download of the model weights and configuration files, overriding the @@ -351,6 +351,8 @@ def from_single_file(cls, pretrained_model_link_or_path_or_dict: str | None = No revision = kwargs.pop("revision", None) config_revision = kwargs.pop("config_revision", None) torch_dtype = kwargs.pop("torch_dtype", None) + dtype = kwargs.pop("dtype", None) + torch_dtype = dtype if dtype is not None else torch_dtype quantization_config = kwargs.pop("quantization_config", None) low_cpu_mem_usage = kwargs.pop("low_cpu_mem_usage", _LOW_CPU_MEM_USAGE_DEFAULT) device = kwargs.pop("device", None) diff --git a/src/diffusers/models/adapter.py b/src/diffusers/models/adapter.py index d387859ffbd1..1d146e5575c7 100644 --- a/src/diffusers/models/adapter.py +++ b/src/diffusers/models/adapter.py @@ -166,7 +166,7 @@ def from_pretrained(cls, pretrained_model_path: str | os.PathLike | None, **kwar pretrained_model_path (`os.PathLike`): A path to a *directory* containing model weights saved using [`~diffusers.models.adapter.MultiAdapter.save_pretrained`], e.g., `./my_model_directory/adapter`. - torch_dtype (`torch.dtype`, *optional*): + dtype (`torch.dtype`, *optional*): Override the default `torch.dtype` and load the model under this dtype. output_loading_info(`bool`, *optional*, defaults to `False`): Whether or not to also return a dictionary containing missing keys, unexpected keys and error messages. diff --git a/src/diffusers/models/auto_model.py b/src/diffusers/models/auto_model.py index d3010266ef70..83ba3bca3c1a 100644 --- a/src/diffusers/models/auto_model.py +++ b/src/diffusers/models/auto_model.py @@ -173,7 +173,7 @@ def from_pretrained(cls, pretrained_model_or_path: str | os.PathLike | None = No cache_dir (`str | os.PathLike`, *optional*): Path to a directory where a downloaded pretrained model configuration is cached if the standard cache is not used. - torch_dtype (`torch.dtype`, *optional*): + dtype (`torch.dtype`, *optional*): Override the default `torch.dtype` and load the model with another dtype. force_download (`bool`, *optional*, defaults to `False`): Whether or not to force the (re-)download of the model weights and configuration files, overriding the diff --git a/src/diffusers/models/controlnets/multicontrolnet.py b/src/diffusers/models/controlnets/multicontrolnet.py index 995637c965d3..0ba9f9264f7b 100644 --- a/src/diffusers/models/controlnets/multicontrolnet.py +++ b/src/diffusers/models/controlnets/multicontrolnet.py @@ -163,7 +163,7 @@ def from_pretrained(cls, pretrained_model_path: str | os.PathLike | None, **kwar A path to a *directory* containing model weights saved using [`~models.controlnets.multicontrolnet.MultiControlNetModel.save_pretrained`], e.g., `./my_model_directory/controlnet`. - torch_dtype (`torch.dtype`, *optional*): + dtype (`torch.dtype`, *optional*): Override the default `torch.dtype` and load the model under this dtype. output_loading_info(`bool`, *optional*, defaults to `False`): Whether or not to also return a dictionary containing missing keys, unexpected keys and error messages. diff --git a/src/diffusers/models/controlnets/multicontrolnet_union.py b/src/diffusers/models/controlnets/multicontrolnet_union.py index 577492074243..92fe1b0019f2 100644 --- a/src/diffusers/models/controlnets/multicontrolnet_union.py +++ b/src/diffusers/models/controlnets/multicontrolnet_union.py @@ -180,7 +180,7 @@ def from_pretrained(cls, pretrained_model_path: str | os.PathLike | None, **kwar A path to a *directory* containing model weights saved using [`~models.controlnets.multicontrolnet.MultiControlNetUnionModel.save_pretrained`], e.g., `./my_model_directory/controlnet`. - torch_dtype (`torch.dtype`, *optional*): + dtype (`torch.dtype`, *optional*): Override the default `torch.dtype` and load the model under this dtype. output_loading_info(`bool`, *optional*, defaults to `False`): Whether or not to also return a dictionary containing missing keys, unexpected keys and error messages. diff --git a/src/diffusers/models/modeling_utils.py b/src/diffusers/models/modeling_utils.py index 650ab4c7fcda..d79994de6efb 100644 --- a/src/diffusers/models/modeling_utils.py +++ b/src/diffusers/models/modeling_utils.py @@ -892,7 +892,7 @@ def from_pretrained(cls, pretrained_model_name_or_path: str | os.PathLike | None cache_dir (`str | os.PathLike`, *optional*): Path to a directory where a downloaded pretrained model configuration is cached if the standard cache is not used. - torch_dtype (`torch.dtype`, *optional*): + dtype (`torch.dtype`, *optional*): Override the default `torch.dtype` and load the model with another dtype. force_download (`bool`, *optional*, defaults to `False`): Whether or not to force the (re-)download of the model weights and configuration files, overriding the @@ -1018,6 +1018,8 @@ def from_pretrained(cls, pretrained_model_name_or_path: str | os.PathLike | None token = kwargs.pop("token", None) revision = kwargs.pop("revision", None) torch_dtype = kwargs.pop("torch_dtype", None) + dtype = kwargs.pop("dtype", None) + torch_dtype = dtype if dtype is not None else torch_dtype subfolder = kwargs.pop("subfolder", None) device_map = kwargs.pop("device_map", None) max_memory = kwargs.pop("max_memory", None) diff --git a/src/diffusers/modular_pipelines/modular_pipeline_utils.py b/src/diffusers/modular_pipelines/modular_pipeline_utils.py index 656ab253ccc2..7aa61c55ef1f 100644 --- a/src/diffusers/modular_pipelines/modular_pipeline_utils.py +++ b/src/diffusers/modular_pipelines/modular_pipeline_utils.py @@ -311,10 +311,11 @@ def load(self, **kwargs) -> Any: from diffusers import AutoModel - # `torch_dtype` is not an accepted parameter for tokenizers and processors. + # `dtype`/`torch_dtype` is not an accepted parameter for tokenizers and processors. # As a result, it gets stored in `init_kwargs`, which are written to the config # during save. This causes JSON serialization to fail when saving the component. if self.type_hint is not None and not issubclass(self.type_hint, (torch.nn.Module, AutoModel)): + kwargs.pop("dtype", None) kwargs.pop("torch_dtype", None) if self.type_hint is None: diff --git a/src/diffusers/pipelines/auto_pipeline.py b/src/diffusers/pipelines/auto_pipeline.py index 5fe97a969a3a..ebeff02e6fbd 100644 --- a/src/diffusers/pipelines/auto_pipeline.py +++ b/src/diffusers/pipelines/auto_pipeline.py @@ -426,7 +426,7 @@ def from_pretrained(cls, pretrained_model_or_path, **kwargs): - A path to a *directory* (for example `./my_pipeline_directory/`) containing pipeline weights saved using [`~DiffusionPipeline.save_pretrained`]. - torch_dtype (`torch.dtype`, *optional*): + dtype (`torch.dtype`, *optional*): Override the default `torch.dtype` and load the model with another dtype. force_download (`bool`, *optional*, defaults to `False`): Whether or not to force the (re-)download of the model weights and configuration files, overriding the @@ -717,7 +717,7 @@ def from_pretrained(cls, pretrained_model_or_path, **kwargs): - A path to a *directory* (for example `./my_pipeline_directory/`) containing pipeline weights saved using [`~DiffusionPipeline.save_pretrained`]. - torch_dtype (`str` or `torch.dtype`, *optional*): + dtype (`str` or `torch.dtype`, *optional*): Override the default `torch.dtype` and load the model with another dtype. force_download (`bool`, *optional*, defaults to `False`): Whether or not to force the (re-)download of the model weights and configuration files, overriding the @@ -1022,7 +1022,7 @@ def from_pretrained(cls, pretrained_model_or_path, **kwargs): - A path to a *directory* (for example `./my_pipeline_directory/`) containing pipeline weights saved using [`~DiffusionPipeline.save_pretrained`]. - torch_dtype (`str` or `torch.dtype`, *optional*): + dtype (`str` or `torch.dtype`, *optional*): Override the default `torch.dtype` and load the model with another dtype. force_download (`bool`, *optional*, defaults to `False`): Whether or not to force the (re-)download of the model weights and configuration files, overriding the @@ -1312,7 +1312,7 @@ def from_pretrained(cls, pretrained_model_or_path, **kwargs): - A path to a *directory* (for example `./my_pipeline_directory/`) containing pipeline weights saved using [`~DiffusionPipeline.save_pretrained`]. - torch_dtype (`torch.dtype`, *optional*): + dtype (`torch.dtype`, *optional*): Override the default `torch.dtype` and load the model with another dtype. force_download (`bool`, *optional*, defaults to `False`): Whether or not to force the (re-)download of the model weights and configuration files, overriding the diff --git a/src/diffusers/pipelines/pipeline_utils.py b/src/diffusers/pipelines/pipeline_utils.py index 7b653caa0657..f1bf0efe4881 100644 --- a/src/diffusers/pipelines/pipeline_utils.py +++ b/src/diffusers/pipelines/pipeline_utils.py @@ -639,7 +639,7 @@ def from_pretrained(cls, pretrained_model_name_or_path: str | os.PathLike, **kwa saved using [`~DiffusionPipeline.save_pretrained`]. - A path to a *directory* (for example `./my_pipeline_directory/`) containing a dduf file - torch_dtype (`torch.dtype` or `dict[str, Union[str, torch.dtype]]`, *optional*): + dtype (`torch.dtype` or `dict[str, Union[str, torch.dtype]]`, *optional*): Override the default `torch.dtype` and load the model with another dtype. To load submodels with different dtype pass a `dict` (for example `{'transformer': torch.bfloat16, 'vae': torch.float16}`). Set the default dtype for unspecified components with `default` (for example `{'transformer': @@ -769,6 +769,8 @@ def from_pretrained(cls, pretrained_model_name_or_path: str | os.PathLike, **kwa revision = kwargs.pop("revision", None) from_flax = kwargs.pop("from_flax", False) torch_dtype = kwargs.pop("torch_dtype", None) + dtype = kwargs.pop("dtype", None) + torch_dtype = dtype if dtype is not None else torch_dtype custom_pipeline = kwargs.pop("custom_pipeline", None) custom_revision = kwargs.pop("custom_revision", None) provider = kwargs.pop("provider", None) @@ -2121,7 +2123,9 @@ def from_pipe(cls, pipeline, **kwargs): """ original_config = dict(pipeline.config) - torch_dtype = kwargs.pop("torch_dtype", torch.float32) + torch_dtype = kwargs.pop("torch_dtype", None) + dtype = kwargs.pop("dtype", None) + torch_dtype = dtype if dtype is not None else (torch_dtype if torch_dtype is not None else torch.float32) trust_remote_code = kwargs.pop("trust_remote_code", False) # derive the pipeline class to instantiate From 8b6fd02ad328f91c4adb273c457e8fe3f019c9f2 Mon Sep 17 00:00:00 2001 From: stevhliu Date: Mon, 13 Jul 2026 10:36:52 -0700 Subject: [PATCH 2/4] add tests --- tests/models/testing_utils/common.py | 15 +++++++++++++++ tests/pipelines/test_pipelines_common.py | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/tests/models/testing_utils/common.py b/tests/models/testing_utils/common.py index 570957cdaf74..59c2e240c1a3 100644 --- a/tests/models/testing_utils/common.py +++ b/tests/models/testing_utils/common.py @@ -379,6 +379,21 @@ def test_from_save_pretrained_dtype(self, tmp_path, dtype): new_model = self.model_class.from_pretrained(tmp_path, low_cpu_mem_usage=False, torch_dtype=dtype) assert new_model.dtype == dtype + @pytest.mark.parametrize("dtype", [torch.float32, torch.float16, torch.bfloat16], ids=["fp32", "fp16", "bf16"]) + def test_from_pretrained_dtype_alias(self, tmp_path, dtype): + # `dtype` is an alias for `torch_dtype` in `from_pretrained`. + model = self.model_class(**self.get_init_dict()) + model.to(torch_device) + model.eval() + + if torch_device == "mps" and dtype == torch.bfloat16: + pytest.skip(reason=f"{dtype} is not supported on {torch_device}") + + model.to(dtype) + model.save_pretrained(tmp_path) + new_model = self.model_class.from_pretrained(tmp_path, low_cpu_mem_usage=True, dtype=dtype) + assert new_model.dtype == dtype + @torch.no_grad() def test_determinism(self, atol=1e-5, rtol=0): model = self.model_class(**self.get_init_dict()) diff --git a/tests/pipelines/test_pipelines_common.py b/tests/pipelines/test_pipelines_common.py index 139adac2b41e..e70e0fc5c3bd 100644 --- a/tests/pipelines/test_pipelines_common.py +++ b/tests/pipelines/test_pipelines_common.py @@ -2408,6 +2408,26 @@ def test_torch_dtype_dict(self): f"Component '{name}' has dtype {component.dtype} but expected {expected_dtype}", ) + def test_dtype_alias(self): + # `dtype` is an alias for `torch_dtype` in `from_pretrained`. + components = self.get_dummy_components() + if not components: + self.skipTest("No dummy components defined.") + + pipe = self.pipeline_class(**components) + + with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as tmpdirname: + pipe.save_pretrained(tmpdirname, safe_serialization=False) + loaded_pipe = self.pipeline_class.from_pretrained(tmpdirname, dtype=torch.float16) + + for name, component in loaded_pipe.components.items(): + if isinstance(component, torch.nn.Module) and hasattr(component, "dtype"): + self.assertEqual( + component.dtype, + torch.float16, + f"Component '{name}' has dtype {component.dtype} but expected {torch.float16}", + ) + def test_pipeline_with_accelerator_device_map(self, expected_max_difference=1e-4): components = self.get_dummy_components() # Set text encoders to eval mode to match from_pretrained behavior From a0aadf2c9ad9422e7361c1dc987105fde32857b0 Mon Sep 17 00:00:00 2001 From: stevhliu Date: Mon, 13 Jul 2026 10:56:22 -0700 Subject: [PATCH 3/4] feedback --- tests/models/testing_utils/common.py | 6 +++--- tests/pipelines/test_pipelines_common.py | 3 --- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/models/testing_utils/common.py b/tests/models/testing_utils/common.py index 59c2e240c1a3..674421669f3d 100644 --- a/tests/models/testing_utils/common.py +++ b/tests/models/testing_utils/common.py @@ -382,13 +382,13 @@ def test_from_save_pretrained_dtype(self, tmp_path, dtype): @pytest.mark.parametrize("dtype", [torch.float32, torch.float16, torch.bfloat16], ids=["fp32", "fp16", "bf16"]) def test_from_pretrained_dtype_alias(self, tmp_path, dtype): # `dtype` is an alias for `torch_dtype` in `from_pretrained`. + if torch_device == "mps" and dtype == torch.bfloat16: + pytest.skip(reason=f"{dtype} is not supported on {torch_device}") + model = self.model_class(**self.get_init_dict()) model.to(torch_device) model.eval() - if torch_device == "mps" and dtype == torch.bfloat16: - pytest.skip(reason=f"{dtype} is not supported on {torch_device}") - model.to(dtype) model.save_pretrained(tmp_path) new_model = self.model_class.from_pretrained(tmp_path, low_cpu_mem_usage=True, dtype=dtype) diff --git a/tests/pipelines/test_pipelines_common.py b/tests/pipelines/test_pipelines_common.py index e70e0fc5c3bd..07aca0156cee 100644 --- a/tests/pipelines/test_pipelines_common.py +++ b/tests/pipelines/test_pipelines_common.py @@ -2411,9 +2411,6 @@ def test_torch_dtype_dict(self): def test_dtype_alias(self): # `dtype` is an alias for `torch_dtype` in `from_pretrained`. components = self.get_dummy_components() - if not components: - self.skipTest("No dummy components defined.") - pipe = self.pipeline_class(**components) with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as tmpdirname: From 5913ca38bd7a10b25b73c1424d6ebf44bacf1017 Mon Sep 17 00:00:00 2001 From: stevhliu Date: Mon, 13 Jul 2026 19:49:09 -0700 Subject: [PATCH 4/4] Fix failing test_dtype_alias pipeline tests Cosmos pipelines keep the safety_checker in float32 and require it to be passed explicitly on reload, mirroring their test_torch_dtype_dict overrides. PRX skips dtype-dict/save-load tests because the custom T5GemmaEncoder is not compatible with transformers v5; do the same for test_dtype_alias. Co-Authored-By: Claude Opus 4.8 --- tests/pipelines/cosmos/test_cosmos.py | 21 ++++++++++++++++++ .../cosmos/test_cosmos2_5_predict.py | 21 ++++++++++++++++++ .../cosmos/test_cosmos2_5_transfer.py | 22 +++++++++++++++++++ .../cosmos/test_cosmos2_text2image.py | 21 ++++++++++++++++++ .../cosmos/test_cosmos2_video2world.py | 21 ++++++++++++++++++ .../cosmos/test_cosmos_video2world.py | 21 ++++++++++++++++++ tests/pipelines/prx/test_pipeline_prx.py | 4 ++++ 7 files changed, 131 insertions(+) diff --git a/tests/pipelines/cosmos/test_cosmos.py b/tests/pipelines/cosmos/test_cosmos.py index 3aa92dca1677..f0407b032f3d 100644 --- a/tests/pipelines/cosmos/test_cosmos.py +++ b/tests/pipelines/cosmos/test_cosmos.py @@ -349,6 +349,27 @@ def test_torch_dtype_dict(self): f"Component '{name}' has dtype {component.dtype} but expected {expected_dtype}", ) + def test_dtype_alias(self): + # `dtype` is an alias for `torch_dtype` in `from_pretrained`. + components = self.get_dummy_components() + pipe = self.pipeline_class(**components) + + with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as tmpdirname: + pipe.save_pretrained(tmpdirname, safe_serialization=False) + loaded_pipe = self.pipeline_class.from_pretrained( + tmpdirname, safety_checker=DummyCosmosSafetyChecker(), dtype=torch.float16 + ) + + for name, component in loaded_pipe.components.items(): + if name == "safety_checker": + continue + if isinstance(component, torch.nn.Module) and hasattr(component, "dtype"): + self.assertEqual( + component.dtype, + torch.float16, + f"Component '{name}' has dtype {component.dtype} but expected {torch.float16}", + ) + @unittest.skip( "The pipeline should not be runnable without a safety checker. The test creates a pipeline without passing in " "a safety checker, which makes the pipeline default to the actual Cosmos Guardrail. The Cosmos Guardrail is " diff --git a/tests/pipelines/cosmos/test_cosmos2_5_predict.py b/tests/pipelines/cosmos/test_cosmos2_5_predict.py index 54d4edb485fe..6124e7be4b7b 100644 --- a/tests/pipelines/cosmos/test_cosmos2_5_predict.py +++ b/tests/pipelines/cosmos/test_cosmos2_5_predict.py @@ -328,6 +328,27 @@ def test_torch_dtype_dict(self): f"Component '{name}' has dtype {component.dtype} but expected {expected_dtype}", ) + def test_dtype_alias(self): + # `dtype` is an alias for `torch_dtype` in `from_pretrained`. + components = self.get_dummy_components() + pipe = self.pipeline_class(**components) + + with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as tmpdirname: + pipe.save_pretrained(tmpdirname, safe_serialization=False) + loaded_pipe = self.pipeline_class.from_pretrained( + tmpdirname, safety_checker=DummyCosmosSafetyChecker(), dtype=torch.float16 + ) + + for name, component in loaded_pipe.components.items(): + if name == "safety_checker": + continue + if isinstance(component, torch.nn.Module) and hasattr(component, "dtype"): + self.assertEqual( + component.dtype, + torch.float16, + f"Component '{name}' has dtype {component.dtype} but expected {torch.float16}", + ) + @unittest.skip( "The pipeline should not be runnable without a safety checker. The test creates a pipeline without passing in " "a safety checker, which makes the pipeline default to the actual Cosmos Guardrail. The Cosmos Guardrail is " diff --git a/tests/pipelines/cosmos/test_cosmos2_5_transfer.py b/tests/pipelines/cosmos/test_cosmos2_5_transfer.py index c098a46a8f8a..c7f2f799216f 100644 --- a/tests/pipelines/cosmos/test_cosmos2_5_transfer.py +++ b/tests/pipelines/cosmos/test_cosmos2_5_transfer.py @@ -426,6 +426,28 @@ def test_torch_dtype_dict(self): f"Component '{name}' has dtype {component.dtype} but expected {expected_dtype}", ) + def test_dtype_alias(self): + # `dtype` is an alias for `torch_dtype` in `from_pretrained`. + components = self.get_dummy_components() + pipe = self.pipeline_class(**components) + + with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as tmpdirname: + pipe.save_pretrained(tmpdirname, safe_serialization=False) + loaded_pipe = self.pipeline_class.from_pretrained( + tmpdirname, safety_checker=DummyCosmosSafetyChecker(), dtype=torch.float16 + ) + + for name, component in loaded_pipe.components.items(): + # Skip components that are not loaded from disk or have special handling + if name == "safety_checker": + continue + if isinstance(component, torch.nn.Module) and hasattr(component, "dtype"): + self.assertEqual( + component.dtype, + torch.float16, + f"Component '{name}' has dtype {component.dtype} but expected {torch.float16}", + ) + def test_save_load_optional_components(self, expected_max_difference=1e-4): self.pipeline_class._optional_components.remove("safety_checker") super().test_save_load_optional_components(expected_max_difference=expected_max_difference) diff --git a/tests/pipelines/cosmos/test_cosmos2_text2image.py b/tests/pipelines/cosmos/test_cosmos2_text2image.py index 71c61eff0054..2a7b130c5340 100644 --- a/tests/pipelines/cosmos/test_cosmos2_text2image.py +++ b/tests/pipelines/cosmos/test_cosmos2_text2image.py @@ -333,6 +333,27 @@ def test_torch_dtype_dict(self): f"Component '{name}' has dtype {component.dtype} but expected {expected_dtype}", ) + def test_dtype_alias(self): + # `dtype` is an alias for `torch_dtype` in `from_pretrained`. + components = self.get_dummy_components() + pipe = self.pipeline_class(**components) + + with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as tmpdirname: + pipe.save_pretrained(tmpdirname, safe_serialization=False) + loaded_pipe = self.pipeline_class.from_pretrained( + tmpdirname, safety_checker=DummyCosmosSafetyChecker(), dtype=torch.float16 + ) + + for name, component in loaded_pipe.components.items(): + if name == "safety_checker": + continue + if isinstance(component, torch.nn.Module) and hasattr(component, "dtype"): + self.assertEqual( + component.dtype, + torch.float16, + f"Component '{name}' has dtype {component.dtype} but expected {torch.float16}", + ) + @unittest.skip( "The pipeline should not be runnable without a safety checker. The test creates a pipeline without passing in " "a safety checker, which makes the pipeline default to the actual Cosmos Guardrail. The Cosmos Guardrail is " diff --git a/tests/pipelines/cosmos/test_cosmos2_video2world.py b/tests/pipelines/cosmos/test_cosmos2_video2world.py index 1b814257a30a..ca62dcc9665c 100644 --- a/tests/pipelines/cosmos/test_cosmos2_video2world.py +++ b/tests/pipelines/cosmos/test_cosmos2_video2world.py @@ -347,6 +347,27 @@ def test_torch_dtype_dict(self): f"Component '{name}' has dtype {component.dtype} but expected {expected_dtype}", ) + def test_dtype_alias(self): + # `dtype` is an alias for `torch_dtype` in `from_pretrained`. + components = self.get_dummy_components() + pipe = self.pipeline_class(**components) + + with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as tmpdirname: + pipe.save_pretrained(tmpdirname, safe_serialization=False) + loaded_pipe = self.pipeline_class.from_pretrained( + tmpdirname, safety_checker=DummyCosmosSafetyChecker(), dtype=torch.float16 + ) + + for name, component in loaded_pipe.components.items(): + if name == "safety_checker": + continue + if isinstance(component, torch.nn.Module) and hasattr(component, "dtype"): + self.assertEqual( + component.dtype, + torch.float16, + f"Component '{name}' has dtype {component.dtype} but expected {torch.float16}", + ) + @unittest.skip( "The pipeline should not be runnable without a safety checker. The test creates a pipeline without passing in " "a safety checker, which makes the pipeline default to the actual Cosmos Guardrail. The Cosmos Guardrail is " diff --git a/tests/pipelines/cosmos/test_cosmos_video2world.py b/tests/pipelines/cosmos/test_cosmos_video2world.py index 925c3b448677..dbe072d334c4 100644 --- a/tests/pipelines/cosmos/test_cosmos_video2world.py +++ b/tests/pipelines/cosmos/test_cosmos_video2world.py @@ -362,6 +362,27 @@ def test_torch_dtype_dict(self): f"Component '{name}' has dtype {component.dtype} but expected {expected_dtype}", ) + def test_dtype_alias(self): + # `dtype` is an alias for `torch_dtype` in `from_pretrained`. + components = self.get_dummy_components() + pipe = self.pipeline_class(**components) + + with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as tmpdirname: + pipe.save_pretrained(tmpdirname, safe_serialization=False) + loaded_pipe = self.pipeline_class.from_pretrained( + tmpdirname, safety_checker=DummyCosmosSafetyChecker(), dtype=torch.float16 + ) + + for name, component in loaded_pipe.components.items(): + if name == "safety_checker": + continue + if isinstance(component, torch.nn.Module) and hasattr(component, "dtype"): + self.assertEqual( + component.dtype, + torch.float16, + f"Component '{name}' has dtype {component.dtype} but expected {torch.float16}", + ) + @unittest.skip( "The pipeline should not be runnable without a safety checker. The test creates a pipeline without passing in " "a safety checker, which makes the pipeline default to the actual Cosmos Guardrail. The Cosmos Guardrail is " diff --git a/tests/pipelines/prx/test_pipeline_prx.py b/tests/pipelines/prx/test_pipeline_prx.py index 20c2727b3156..5cd46deadbb5 100644 --- a/tests/pipelines/prx/test_pipeline_prx.py +++ b/tests/pipelines/prx/test_pipeline_prx.py @@ -280,3 +280,7 @@ def test_save_load_optional_components(self): @unittest.skip("Custom T5GemmaEncoder not compatible with transformers v5.") def test_torch_dtype_dict(self): pass + + @unittest.skip("Custom T5GemmaEncoder not compatible with transformers v5.") + def test_dtype_alias(self): + pass