Repository: huggingface/diffusers

Issue:
AttributeError: 'ConsistencyDecoderVAE' object has no attribute 'tile_sample_min_size'
### Describe the bug

The new decoder has enable_tiling and disable_tiling methods but has not correctly implemented the support attributes.

### Reproduction

```python
import torch
from diffusers import ConsistencyDecoderVAE
vae = ConsistencyDecoderVAE.from_pretrained("openai/consistency-decoder")
vae.enable_tiling()
vae.encode(torch.randn(1, 4, 256, 256))
```

### Logs

```shell
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ in <cell line: 1>                                                                                │
│                                                                                                  │
│ D:\CondaM\lib\site-packages\diffusers\utils\accelerate_utils.py:46 in wrapper                    │
│                                                                                                  │
│   43 │   def wrapper(self, *args, **kwargs):                                                     │
│   44 │   │   if hasattr(self, "_hf_hook") and hasattr(self._hf_hook, "pre_forward"):             │
│   45 │   │   │   self._hf_hook.pre_forward(self)                                                 │
│ ❱ 46 │   │   return method(self, *args, **kwargs)                                                │
│   47 │                                                                                           │
│   48 │   return wrapper                                                                          │
│   49                                                                                             │
│                                                                                                  │
│ D:\CondaM\lib\site-packages\diffusers\models\consistency_decoder_vae.py:285 in encode            │
│                                                                                                  │
│   282 │   │   │   │   [`~models.consistency_decoder_vae.ConsistencyDecoderVAEOutput`] is retur   │
│   283 │   │   │   │   is returned.                                                               │
│   284 │   │   """                                                                                │
│ ❱ 285 │   │   if self.use_tiling and (x.shape[-1] > self.tile_sample_min_size or x.shape[-2] >   │
│   286 │   │   │   return self.tiled_encode(x, return_dict=return_dict)                           │
│   287 │   │                                                                                      │
│   288 │   │   if self.use_slicing and x.shape[0] > 1:                                            │
│                                                                                                  │
│ D:\CondaM\lib\site-packages\diffusers\models\modeling_utils.py:222 in __getattr__                │
│                                                                                                  │
│    219 │   │   │   return self._internal_dict[name]                                              │
│    220 │   │                                                                                     │
│    221 │   │   # call PyTorch's https://pytorch.org/docs/stable/_modules/torch/nn/modules/modul  │
│ ❱  222 │   │   return super().__getattr__(name)                                                  │
│    223 │                                                                                         │
│    224 │   @property                                                                             │
│    225 │   def is_gradient_checkpointing(self) -> bool:                                          │
│                                                                                                  │
│ D:\CondaM\lib\site-packages\torch\nn\modules\module.py:1614 in __getattr__                       │
│                                                                                                  │
│   1611 │   │   │   modules = self.__dict__['_modules']                                           │
│   1612 │   │   │   if name in modules:                                                           │
│   1613 │   │   │   │   return modules[name]                                                      │
│ ❱ 1614 │   │   raise AttributeError("'{}' object has no attribute '{}'".format(                  │
│   1615 │   │   │   type(self).__name__, name))                                                   │
│   1616 │                                                                                         │
│   1617 │   def __setattr__(self, name: str, value: Union[Tensor, 'Module']) -> None:             │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
AttributeError: 'ConsistencyDecoderVAE' object has no attribute 'tile_sample_min_size'
```
```


### System Info

- `diffusers` version: 0.24.0
- Platform: Windows-10-10.0.22621-SP0
- Python version: 3.8.13
- PyTorch version (GPU?): 2.0.1+cu118 (True)
- Huggingface_hub version: 0.19.4
- Transformers version: 4.29.0
- Accelerate version: 0.18.0
- xFormers version: not installed
- Using GPU in script?: Y/N both the same issue
- Using distributed or parallel set-up in script?: N

### Who can help?

@patrickvonplaten @saya


Discussion:
`enable_tiling()` needs to be implemented for the class. We're happy to accept contributions for that. 

Cc: @williamberman 
This issue has been automatically marked as stale because it has not had recent activity. If you think this still needs to be addressed please comment on this thread.

Please note that issues that do not follow the [contributing guidelines](https://github.com/huggingface/diffusers/blob/main/CONTRIBUTING.md) are likely to be ignored.
The request is still open.
https://github.com/huggingface/diffusers/issues/6126#issuecomment-1849609444 as mentioned. 
This issue has been automatically marked as stale because it has not had recent activity. If you think this still needs to be addressed please comment on this thread.

Please note that issues that do not follow the [contributing guidelines](https://github.com/huggingface/diffusers/blob/main/CONTRIBUTING.md) are likely to be ignored.
@sayakpaul 
it seems to be implemented here https://github.com/huggingface/diffusers/blob/a5fc62f81957c739b1d4a8fd99bf551a2949dc3c/src/diffusers/models/autoencoders/consistency_decoder_vae.py#L348

So probably just not correctly implemented - I don't have time for this right now. let's see if anyone in the community can help
This issue has been automatically marked as stale because it has not had recent activity. If you think this still needs to be addressed please comment on this thread.

Please note that issues that do not follow the [contributing guidelines](https://github.com/huggingface/diffusers/blob/main/CONTRIBUTING.md) are likely to be ignored.

Resolving patch:
diff --git a/src/diffusers/models/autoencoders/consistency_decoder_vae.py b/src/diffusers/models/autoencoders/consistency_decoder_vae.py
--- a/src/diffusers/models/autoencoders/consistency_decoder_vae.py
+++ b/src/diffusers/models/autoencoders/consistency_decoder_vae.py
@@ -63,7 +63,8 @@ class ConsistencyDecoderVAE(ModelMixin, ConfigMixin):
         ...     "runwayml/stable-diffusion-v1-5", vae=vae, torch_dtype=torch.float16
         ... ).to("cuda")
 
-        >>> pipe("horse", generator=torch.manual_seed(0)).images
+        >>> image = pipe("horse", generator=torch.manual_seed(0)).images[0]
+        >>> image
         ```
     """
 
@@ -72,6 +73,7 @@ def __init__(
         self,
         scaling_factor: float = 0.18215,
         latent_channels: int = 4,
+        sample_size: int = 32,
         encoder_act_fn: str = "silu",
         encoder_block_out_channels: Tuple[int, ...] = (128, 256, 512, 512),
         encoder_double_z: bool = True,
@@ -153,6 +155,16 @@ def __init__(
         self.use_slicing = False
         self.use_tiling = False
 
+        # only relevant if vae tiling is enabled
+        self.tile_sample_min_size = self.config.sample_size
+        sample_size = (
+            self.config.sample_size[0]
+            if isinstance(self.config.sample_size, (list, tuple))
+            else self.config.sample_size
+        )
+        self.tile_latent_min_size = int(sample_size / (2 ** (len(self.config.block_out_channels) - 1)))
+        self.tile_overlap_factor = 0.25
+
     # Copied from diffusers.models.autoencoders.autoencoder_kl.AutoencoderKL.enable_tiling
     def enable_tiling(self, use_tiling: bool = True):
         r"""
@@ -272,7 +284,7 @@ def encode(
         Args:
             x (`torch.FloatTensor`): Input batch of images.
             return_dict (`bool`, *optional*, defaults to `True`):
-                Whether to return a [`~models.consistecy_decoder_vae.ConsistencyDecoderOoutput`] instead of a plain
+                Whether to return a [`~models.consistency_decoder_vae.ConsistencyDecoderVAEOutput`] instead of a plain
                 tuple.
 
         Returns:
@@ -305,6 +317,19 @@ def decode(
         return_dict: bool = True,
         num_inference_steps: int = 2,
     ) -> Union[DecoderOutput, Tuple[torch.FloatTensor]]:
+        """
+        Decodes the input latent vector `z` using the consistency decoder VAE model.
+
+        Args:
+            z (torch.FloatTensor): The input latent vector.
+            generator (Optional[torch.Generator]): The random number generator. Default is None.
+            return_dict (bool): Whether to return the output as a dictionary. Default is True.
+            num_inference_steps (int): The number of inference steps. Default is 2.
+
+        Returns:
+            Union[DecoderOutput, Tuple[torch.FloatTensor]]: The decoded output.
+
+        """
         z = (z * self.config.scaling_factor - self.means) / self.stds
 
         scale_factor = 2 ** (len(self.config.block_out_channels) - 1)
@@ -345,7 +370,9 @@ def blend_h(self, a: torch.Tensor, b: torch.Tensor, blend_extent: int) -> torch.
             b[:, :, :, x] = a[:, :, :, -blend_extent + x] * (1 - x / blend_extent) + b[:, :, :, x] * (x / blend_extent)
         return b
 
-    def tiled_encode(self, x: torch.FloatTensor, return_dict: bool = True) -> ConsistencyDecoderVAEOutput:
+    def tiled_encode(
+        self, x: torch.FloatTensor, return_dict: bool = True
+    ) -> Union[ConsistencyDecoderVAEOutput, Tuple]:
         r"""Encode a batch of images using a tiled encoder.
 
         When this option is enabled, the VAE will split the input tensor into tiles to compute encoding in several


Test patch:
diff --git a/tests/models/autoencoders/test_models_vae.py b/tests/models/autoencoders/test_models_vae.py
--- a/tests/models/autoencoders/test_models_vae.py
+++ b/tests/models/autoencoders/test_models_vae.py
@@ -1116,3 +1116,33 @@ def test_sd_f16(self):
         )
 
         assert torch_all_close(actual_output, expected_output, atol=5e-3)
+
+    def test_vae_tiling(self):
+        vae = ConsistencyDecoderVAE.from_pretrained("openai/consistency-decoder")
+        pipe = StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5", vae=vae, safety_checker=None)
+        pipe.to(torch_device)
+        pipe.set_progress_bar_config(disable=None)
+
+        out_1 = pipe(
+            "horse",
+            num_inference_steps=2,
+            output_type="pt",
+            generator=torch.Generator("cpu").manual_seed(0),
+        ).images[0]
+
+        # make sure tiled vae decode yields the same result
+        pipe.enable_vae_tiling()
+        out_2 = pipe(
+            "horse",
+            num_inference_steps=2,
+            output_type="pt",
+            generator=torch.Generator("cpu").manual_seed(0),
+        ).images[0]
+
+        assert torch_all_close(out_1, out_2, atol=5e-3)
+
+        # test that tiled decode works with various shapes
+        shapes = [(1, 4, 73, 97), (1, 4, 97, 73), (1, 4, 49, 65), (1, 4, 65, 49)]
+        for shape in shapes:
+            image = torch.zeros(shape, device=torch_device)
+            pipe.vae.decode(image)