Repository navigation
move unpack out of the flux, krea2 and ltx decoders into the core denoise groups - #14737
Conversation
…eaves in the state
…rately Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
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. |
yiyixuxu
left a comment
There was a problem hiding this comment.
thanks a lot! really nice work
I left some feedbacks
| @@ -28,6 +28,64 @@ | |||
|
|
|||
|
|
|||
| # auto_docstring | |||
There was a problem hiding this comment.
ohh I think this #auto_docstring maker is in wrong place
There was a problem hiding this comment.
can you update the description here?
| "the VAE takes (still normalized). Closes the core denoise group, so the blocks that follow take the same " | ||
| "form the VAE produces and need no geometry inputs." |
There was a problem hiding this comment.
| "the VAE takes (still normalized). Closes the core denoise group, so the blocks that follow take the same " | |
| "form the VAE produces and need no geometry inputs." | |
| "the VAE takes (still normalized)." |
| "VAE takes (still normalized). Closes the core denoise group, so the blocks that follow take the same " | ||
| "form the VAE encoder produces and need no geometry inputs." |
There was a problem hiding this comment.
| "VAE takes (still normalized). Closes the core denoise group, so the blocks that follow take the same " | |
| "form the VAE encoder produces and need no geometry inputs." | |
| "VAE takes (still normalized)." |
| type_hint=torch.Tensor, | ||
| description="The denoised latents from the denoising step, packed, of shape `[B, S, C]`.", | ||
| ), | ||
| InputParam("height", default=1024), |
There was a problem hiding this comment.
height/width should be required with no default
| "the VAE takes (still normalized). Closes the core denoise group, so the blocks that follow take the same " | ||
| "form the VAE encoder produces and need no geometry inputs." |
There was a problem hiding this comment.
| "the VAE takes (still normalized). Closes the core denoise group, so the blocks that follow take the same " | |
| "form the VAE encoder produces and need no geometry inputs." | |
| "the VAE takes (still normalized)." |
| # Still the packed `[B, S, C]` form: #14612 moves ltx2 to the VAE form and updates this. | ||
| expected_latents_shape = (1, 768, 4) |
There was a problem hiding this comment.
| # Still the packed `[B, S, C]` form: #14612 moves ltx2 to the VAE form and updates this. | |
| expected_latents_shape = (1, 768, 4) |
let's not give the wrong "expected_latents_shape" just so that the test pass - it's misleading
we can skip the test explicitly with something like this
@pytest.mark.skip(reason="ltx2 still leaves packed `[B, S, C]` latents in the state; #14612 moves it to the VAE form.")
def test_latents_output_in_canonical_form(self):
pass| if self.latents_output_name is None: | ||
| pytest.skip("This family decodes inside its denoise loop and leaves no latents in the state.") |
There was a problem hiding this comment.
| if self.latents_output_name is None: | |
| pytest.skip("This family decodes inside its denoise loop and leaves no latents in the state.") |
the subclass can skip it with `@pytest.mark.skip(...)
sayakpaul
left a comment
There was a problem hiding this comment.
I like the PR. I think it aims at a standardization that we have been discussing in other threads. Thank you!
|
|
||
| Each should be applied and undone in mirrored pairs, and the core denoise group hands latents back in the same form it received them. The `latents` output of the denoise group should always be in one form: unpacked and still normalized, the same form its VAE encoder blocks produce. Whatever runs next (a decoder, a latent upsampler, a second denoise group) consumes that form, and no block outside the group needs `height`/`width`/`num_frames` just to interpret tokens. | ||
|
|
||
| The pattern: `encode -> norm -> pack -> denoise -> unpack -> denorm -> decode` |
There was a problem hiding this comment.
Should provide a reference from the codebase here.
| "packed latents", | ||
| "1.0.0", |
There was a problem hiding this comment.
I think we can deprecate before. Like give it ~5 releases? I would also add a test to ensure the deprecation is actually raised (if not already added).
| InputParam.template("height", default=1024), | ||
| InputParam.template("width", default=1024), |
There was a problem hiding this comment.
No defaults here following https://github.com/huggingface/diffusers/pull/14737/changes#r4304769059?
| pipeline_blocks_class = LTX25AutoBlocks | ||
| pretrained_model_name_or_path = LTX25_REPO_ID | ||
| # Still the packed `[B, S, C]` form: #14612 moves ltx2 to the VAE form and updates this. | ||
| expected_latents_shape = (1, 768, 4) |
There was a problem hiding this comment.
can we explicitly skip this one too?
|
/diffusers-bot pytest tests/modular_pipelines/flux tests/modular_pipelines/krea2 tests/modular_pipelines/ltx -k test_decode_accepts_packed_latents_with_deprecation |
|
❌ |
| output_name = "images" | ||
| # State name of the latents the denoise group hands to the decoder. Chunked families that hand over a list of | ||
| # per-chunk latents (e.g. `latent_chunks`) are checked chunk by chunk. Families that decode inside their | ||
| # denoise loop and leave no latents in the state set this to `None`. |
There was a problem hiding this comment.
can you update the comment here? better to skip explicitly with a reason
There was a problem hiding this comment.
Added this
State name of the latents the denoise group hands to the decoder. Chunked families that hand over a list of per-chunk latents (e.g. latent_chunks) are checked chunk by chunk. A family that leaves no latents in the state, or not yet in its canonical form, skips test_latents_output_in_canonical_form with a reason.
| decoder.to(torch_device) | ||
|
|
||
| # The 9-frame 32x32 dummy video is a `[1, 8, 5, 16, 16]` latent, packed to 1280 tokens of 8 channels. | ||
| packed_latents = torch.randn(1, 1280, 8, generator=self.get_generator()) |
There was a problem hiding this comment.
| packed_latents = torch.randn(1, 1280, 8, generator=self.get_generator()) | |
| packed_latents = torch.randn(1, 1280, 8, generator=self.get_generator()).to(torch_device) |
can you update the other 2 tests too? see https://github.com/huggingface/diffusers/actions/runs/39362689598/job/118432333376#step:8:58
yiyixuxu
left a comment
There was a problem hiding this comment.
thanks a lot for working on this!
What does this PR do?
Fixes #14730.
Adds a test to the modular tester mixin that checks the shape of the latents each pipeline leaves in the state after denoising, and every tester now declares
expected_latents_shape. Running it across all families catches the three from the issue, plus ltx2 (being moved in #14612, so it's declared at its current packed shape until then) and wan_animate_2, which decodes inside its segment loop and never leaves latents behind, so it opts out withlatents_output_name = None.For flux, krea2 and ltx the unpack now happens at the end of the core denoise group, same shape as
Flux2UnpackLatentsStep. The decoders just denormalize and decode. They still accept packed latents with a deprecation warning, which is why height/width (and num_frames for ltx) are still on them, and there's a test per family for that path.Outputs are identical to main on the test repos and on the real checkpoints (images in akshan-main/latents-form-verification). Loading LTX-Video with
ModularPipeline.from_pretrainedneeds #14736. Also wrote the principle down in.ai/references/modular.mdin a separate commit; feel free to drop it or change it.Before submitting
Who can review?
@yiyixuxu