[MInimax H3] Fix VAE decode - #14754
Conversation
|
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
|
/diffusers-bot pytest tests/models/autoencoders/test_models_autoencoder_kl_minimax_h3.py |
|
❌ |
|
/diffusers-bot pytest tests/models/autoencoders/test_models_autoencoder_kl_minimax_h3.py |
|
✅ |
| @classmethod | ||
| def from_pretrained(cls, pretrained_model_name_or_path: str | os.PathLike | None, **kwargs): | ||
| r""" | ||
| Load a pretrained MiniMax-H3 video autoencoder. | ||
|
|
||
| Takes the same arguments as [`ModelMixin.from_pretrained`], except that a requested `bfloat16` is loaded as | ||
| `float16`. Pipelines apply one dtype to every component, and this decoder degrades in `bfloat16` without using | ||
| any less memory than `float16`. | ||
| """ | ||
| for key in ("dtype", "torch_dtype"): | ||
| if kwargs.get(key) == torch.bfloat16: | ||
| kwargs[key] = torch.float16 | ||
| return super().from_pretrained(pretrained_model_name_or_path, **kwargs) |
There was a problem hiding this comment.
| @classmethod | |
| def from_pretrained(cls, pretrained_model_name_or_path: str | os.PathLike | None, **kwargs): | |
| r""" | |
| Load a pretrained MiniMax-H3 video autoencoder. | |
| Takes the same arguments as [`ModelMixin.from_pretrained`], except that a requested `bfloat16` is loaded as | |
| `float16`. Pipelines apply one dtype to every component, and this decoder degrades in `bfloat16` without using | |
| any less memory than `float16`. | |
| """ | |
| for key in ("dtype", "torch_dtype"): | |
| if kwargs.get(key) == torch.bfloat16: | |
| kwargs[key] = torch.float16 | |
| return super().from_pretrained(pretrained_model_name_or_path, **kwargs) |
|
/diffusers-bot pytest tests/models/autoencoders/test_models_autoencoder_kl_minimax_h3.py |
|
✅ |
How can we set up testing for this in a better manner? Also, we're not trimming |
it drops entire |
|
yeah, it narrows what's pinned inside the decoder, specific layers instead of the whole module, but I see how it can be misinterpreted so I changed the wording. about the tests, what do you think about this (proposed by claude): @pytest.mark.parametrize("dtype", [torch.float16, torch.bfloat16], ids=["fp16", "bf16"])
def test_decode_in_low_precision(self, tmp_path, dtype):
# Decode is mixed precision with no autocast, so every dtype seam has to hold on its own.
self.model_class(**self.get_init_dict()).save_pretrained(tmp_path)
model = self.model_class.from_pretrained(tmp_path, dtype=dtype).eval()
with torch.no_grad():
decoded = model.decode(torch.randn(1, 4, 7, 2, 2), return_dict=False)[0]
assert decoded.dtype == dtype |
|
@asomoza the test looks neat to me! Let's add it. |
What does this PR do?
Drops the fp16 autocast in the video decode block and replaces
decoderin_keep_in_fp32_moduleswith just the sensitive layers, so it runs at the dtype you pass instead of always fp32 weights with fp16 compute.Error vs a true fp32 decode with no autocast:
Reference links here and here.
bf16 is the worst of them but I don't see it visually when generating the video, still the reference doesn't use it and other libraries don't either,
so this PR forces it to fp16 anywayit's respected now.There's a user facing change with this, I now respect the dtype they set on the pipeline, so the generation changes for everyone except fp32 on CPU/MPS, including the bf16 recipe in the docs. Probably imperceptible to most eyes but still a difference..
videos:
Fp32
decoded_fp32.mp4
fp16
decoded_fp16.mp4
bf16
decoded_bf16.mp4
Fixes #14746
Who can review?
@yiyixuxu @sayakpaul