Spaces:
Sleeping
Sleeping
File size: 8,969 Bytes
5c1626c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | """Composable conditioner and generator halves of MiniMax-H3, for both checkpoint partitions.
The blocks cut `MiniMaxH3Blocks` at its `text_encoder` step. They can run in separate Spaces with `prompt_embeds` and
`text_token_tags` as a wire format, or sequentially in one GPU worker when a compact local conditioner fits beside
the generator.
`resize` / `setup` run on **both** sides: they own no pretrained component, and each half needs the canvas and the
prepared keyframes or normalized references. Both conditioner halves also return the resolved `height` / `width` /
`num_frames`, which the generating half pins rather than re-deriving.
Two things the blocks leave to the caller: a keyframe reaches them EXIF-transposed and in RGB, and the `t2va` / `fl2va`
frame count is aligned to `17 * n + 5` before the call, since that arithmetic lives on the denoising side of the cut.
"""
from diffusers.modular_pipelines.minimax_h3.before_encoder import MiniMaxH3Ref2VASetupStep
from diffusers.modular_pipelines.minimax_h3.before_denoise import (
MiniMaxH3PrepareLatentsStep,
MiniMaxH3PrepareLayoutStep,
MiniMaxH3Ref2VAPrepareLayoutStep,
MiniMaxH3SetTimestepsStep,
)
from diffusers.modular_pipelines.minimax_h3.decoders import MiniMaxH3AfterDenoiseStep
from diffusers.modular_pipelines.minimax_h3.denoise import MiniMaxH3DenoiseStep, MiniMaxH3Ref2VADenoiseStep
from diffusers.modular_pipelines.minimax_h3.encoders import (
MiniMaxH3Ref2VAReferenceEncoderStep,
MiniMaxH3Ref2VATextEncoderStep,
MiniMaxH3TextEncoderStep,
)
from diffusers.modular_pipelines.minimax_h3.modular_blocks_minimax_h3 import (
MiniMaxH3AutoKeyframeVaeEncoderStep,
MiniMaxH3AutoResizeStep,
MiniMaxH3DecodeStep,
_generation_outputs,
)
from diffusers.modular_pipelines.modular_pipeline import SequentialPipelineBlocks
from diffusers.modular_pipelines.modular_pipeline_utils import InputParam, OutputParam
class _PreviewLoopMixin:
"""The pinned Diffusers loop plus four non-authoritative TAE preview emissions."""
@property
def loop_inputs(self):
# The stock loop has no reason to carry geometry into its inner BlockState. TAE has to invert the packed rows,
# so explicitly retain the three dimensions produced by `prepare_layout` alongside the ordinary timesteps.
return [
*super().loop_inputs,
InputParam("num_latent_frames", type_hint=int, required=True),
InputParam("latent_height", type_hint=int, required=True),
InputParam("latent_width", type_hint=int, required=True),
]
def __call__(self, components, state):
from h3_tae import maybe_emit_preview
block_state = self.get_block_state(state)
total = len(block_state.timesteps)
with self.progress_bar(total=total) as progress_bar:
for index, timestep in enumerate(block_state.timesteps):
components, block_state = self.loop_step(components, block_state, i=index, t=timestep)
maybe_emit_preview(components, block_state, index, total)
progress_bar.update()
self.set_block_state(state, block_state)
return components, state
class MiniMaxH3PreviewDenoiseStep(_PreviewLoopMixin, MiniMaxH3DenoiseStep):
pass
class MiniMaxH3Ref2VAPreviewDenoiseStep(_PreviewLoopMixin, MiniMaxH3Ref2VADenoiseStep):
pass
class MiniMaxH3PreviewCoreDenoiseStep(SequentialPipelineBlocks):
model_name = "minimax-h3"
block_classes = [
MiniMaxH3PrepareLayoutStep,
MiniMaxH3PrepareLatentsStep,
MiniMaxH3SetTimestepsStep,
MiniMaxH3PreviewDenoiseStep,
]
block_names = ["prepare_layout", "prepare_latents", "set_timesteps", "denoise"]
class MiniMaxH3Ref2VAPreviewCoreDenoiseStep(SequentialPipelineBlocks):
model_name = "minimax-h3"
block_classes = [
MiniMaxH3Ref2VAPrepareLayoutStep,
MiniMaxH3PrepareLatentsStep,
MiniMaxH3SetTimestepsStep,
MiniMaxH3Ref2VAPreviewDenoiseStep,
]
block_names = ["prepare_layout", "prepare_latents", "set_timesteps", "denoise"]
def _wire_outputs(num_frames: bool = True) -> list[OutputParam]:
"""The wire format of the split. `num_frames` is declared by the `ref2va` half alone, whose setup resolves one."""
return [
OutputParam.template("prompt_embeds"),
OutputParam("text_token_tags", description="The per-row modality tag of every row of `prompt_embeds`."),
OutputParam("height", type_hint=int, description="Resolved height of the generated video in pixels."),
OutputParam("width", type_hint=int, description="Resolved width of the generated video in pixels."),
*(
[OutputParam("num_frames", type_hint=int, description="Resolved number of frames, of the form 17 * n + 5.")]
if num_frames
else []
),
]
class MiniMaxH3ConditionerBlocks(SequentialPipelineBlocks):
"""The conditioner half of a split MiniMax-H3: the keyframes on the canvas plus the Qwen3-VL read at layer 50."""
model_name = "minimax-h3"
block_classes = [MiniMaxH3AutoResizeStep, MiniMaxH3TextEncoderStep]
block_names = ["resize", "text_encoder"]
@property
def description(self):
return (
"The conditioner half of a split MiniMax-H3 deployment: puts the keyframes onto the target canvas and "
"encodes MiniMax-H3's presentation of the request into the `prompt_embeds` / `text_token_tags` pair the "
"denoising half consumes. The frame count is the caller's to align."
)
@property
def outputs(self):
return _wire_outputs(num_frames=False)
class MiniMaxH3GeneratorBlocks(SequentialPipelineBlocks):
"""The denoising half of a split MiniMax-H3: `MiniMaxH3Blocks` with its `text_encoder` step removed."""
model_name = "minimax-h3"
block_classes = [
MiniMaxH3AutoResizeStep,
MiniMaxH3AutoKeyframeVaeEncoderStep,
MiniMaxH3PreviewCoreDenoiseStep,
MiniMaxH3AfterDenoiseStep,
MiniMaxH3DecodeStep,
]
block_names = ["resize", "vae_encoder", "denoise", "after_denoise", "decode"]
@property
def description(self):
return (
"The denoising half of a split MiniMax-H3 deployment: the `t2va` / `fl2va` branch of `MiniMaxH3Blocks` "
"without its text-encoder step, so `prompt_embeds` and `text_token_tags` come in as inputs and the "
"conditioner is supplied by the caller or by the preceding local conditioner half."
)
@property
def outputs(self):
return _generation_outputs()
class MiniMaxH3Ref2VAConditionerBlocks(SequentialPipelineBlocks):
"""The conditioner half of a split `ref2va`: the resolved plan plus the Qwen3-VL read at its 50th layer.
Component for component this is `MiniMaxH3ConditionerBlocks`, so one conditioner Space serves both partitions.
What differs is the presentation: `ref2va` prepends a label per reference and a vision block per image and per
merged video frame pair, so the references themselves have to reach this half.
"""
model_name = "minimax-h3"
block_classes = [MiniMaxH3Ref2VASetupStep, MiniMaxH3Ref2VATextEncoderStep]
block_names = ["setup", "text_encoder"]
@property
def description(self):
return (
"The conditioner half of a split MiniMax-H3 `ref2va` deployment: resolves the request plan (canvas, frame "
"count, references normalized onto MiniMax-H3's own rates and resolutions) and encodes MiniMax-H3's "
"presentation of it into the `prompt_embeds` / `text_token_tags` pair the denoising half consumes."
)
@property
def outputs(self):
return _wire_outputs()
class MiniMaxH3Ref2VAGeneratorBlocks(SequentialPipelineBlocks):
"""The denoising half of a split `ref2va`: the `ref2va` branch with its `text_encoder` step removed.
`reference_encoder` stays here, next to the two autoencoders it runs: its output shapes are where every reference
block's geometry in the packed layout comes from.
"""
model_name = "minimax-h3"
block_classes = [
MiniMaxH3Ref2VASetupStep,
MiniMaxH3Ref2VAReferenceEncoderStep,
MiniMaxH3Ref2VAPreviewCoreDenoiseStep,
MiniMaxH3AfterDenoiseStep,
MiniMaxH3DecodeStep,
]
block_names = ["setup", "reference_encoder", "denoise", "after_denoise", "decode"]
@property
def description(self):
return (
"The denoising half of a split MiniMax-H3 `ref2va` deployment: the `ref2va` branch of `MiniMaxH3Blocks` "
"without its text-encoder step, so `prompt_embeds` and `text_token_tags` come in as inputs and the "
"conditioner is supplied by the caller or preceding local half. The transformer is the `transformer_ref` partition."
)
@property
def outputs(self):
return _generation_outputs() |