minimax-h3 / diffusers /modular_pipelines /flux /modular_blocks_flux_kontext.py
multimodalart's picture
multimodalart HF Staff
Sync the split MiniMax-H3 Spaces
186aa49 verified
Raw
History Blame Contribute Delete
23.1 kB
# Copyright 2026 The HuggingFace Team. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from ...utils import logging
from ..modular_pipeline import AutoPipelineBlocks, SequentialPipelineBlocks
from ..modular_pipeline_utils import InsertableDict, OutputParam
from .before_denoise import (
FluxKontextRoPEInputsStep,
FluxPrepareLatentsStep,
FluxRoPEInputsStep,
FluxSetTimestepsStep,
)
from .decoders import FluxDecodeStep
from .denoise import FluxKontextDenoiseStep
from .encoders import (
FluxKontextProcessImagesInputStep,
FluxTextEncoderStep,
FluxVaeEncoderStep,
)
from .inputs import (
FluxKontextAdditionalInputsStep,
FluxKontextSetResolutionStep,
FluxTextInputStep,
)
logger = logging.get_logger(__name__) # pylint: disable=invalid-name
# Flux Kontext vae encoder (run before before_denoise)
# auto_docstring
class FluxKontextVaeEncoderStep(SequentialPipelineBlocks):
"""
Vae encoder step that preprocess andencode the image inputs into their latent representations.
Components:
image_processor (`VaeImageProcessor`) vae (`AutoencoderKL`)
Inputs:
image (`None`, *optional*):
TODO: Add description.
_auto_resize (`bool`, *optional*, defaults to True):
TODO: Add description.
generator (`None`, *optional*):
TODO: Add description.
Outputs:
processed_image (`None`):
TODO: Add description.
image_latents (`Tensor`):
The latents representing the reference image
"""
model_name = "flux-kontext"
block_classes = [FluxKontextProcessImagesInputStep(), FluxVaeEncoderStep(sample_mode="argmax")]
block_names = ["preprocess", "encode"]
@property
def description(self) -> str:
return "Vae encoder step that preprocess andencode the image inputs into their latent representations."
# auto_docstring
class FluxKontextAutoVaeEncoderStep(AutoPipelineBlocks):
"""
Vae encoder step that encode the image inputs into their latent representations.
This is an auto pipeline block that works for image-conditioned tasks.
- `FluxKontextVaeEncoderStep` (image_conditioned) is used when only `image` is provided. - if `image` is not
provided, step will be skipped.
Components:
image_processor (`VaeImageProcessor`) vae (`AutoencoderKL`)
Inputs:
image (`None`, *optional*):
TODO: Add description.
_auto_resize (`bool`, *optional*, defaults to True):
TODO: Add description.
generator (`None`, *optional*):
TODO: Add description.
Outputs:
processed_image (`None`):
TODO: Add description.
image_latents (`Tensor`):
The latents representing the reference image
"""
model_name = "flux-kontext"
block_classes = [FluxKontextVaeEncoderStep]
block_names = ["image_conditioned"]
block_trigger_inputs = ["image"]
@property
def description(self):
return (
"Vae encoder step that encode the image inputs into their latent representations.\n"
+ "This is an auto pipeline block that works for image-conditioned tasks.\n"
+ " - `FluxKontextVaeEncoderStep` (image_conditioned) is used when only `image` is provided."
+ " - if `image` is not provided, step will be skipped."
)
# before_denoise: text2img
# auto_docstring
class FluxKontextBeforeDenoiseStep(SequentialPipelineBlocks):
"""
Before denoise step that prepares the inputs for the denoise step for Flux Kontext
Components:
scheduler (`FlowMatchEulerDiscreteScheduler`)
Inputs:
height (`int`, *optional*):
TODO: Add description.
width (`int`, *optional*):
TODO: Add description.
latents (`Tensor | NoneType`, *optional*):
TODO: Add description.
num_images_per_prompt (`int`, *optional*, defaults to 1):
TODO: Add description.
generator (`None`, *optional*):
TODO: Add description.
batch_size (`int`):
Number of prompts, the final batch size of model inputs should be `batch_size * num_images_per_prompt`.
Can be generated in input step.
dtype (`dtype`, *optional*):
The dtype of the model inputs
num_inference_steps (`None`, *optional*, defaults to 50):
TODO: Add description.
timesteps (`None`, *optional*):
TODO: Add description.
sigmas (`None`, *optional*):
TODO: Add description.
guidance_scale (`None`, *optional*, defaults to 3.5):
TODO: Add description.
prompt_embeds (`None`, *optional*):
TODO: Add description.
Outputs:
latents (`Tensor`):
The initial latents to use for the denoising process
timesteps (`Tensor`):
The timesteps to use for inference
num_inference_steps (`int`):
The number of denoising steps to perform at inference time
guidance (`Tensor`):
Optional guidance to be used.
txt_ids (`list`):
The sequence lengths of the prompt embeds, used for RoPE calculation.
img_ids (`list`):
The sequence lengths of the image latents, used for RoPE calculation.
"""
model_name = "flux-kontext"
block_classes = [FluxPrepareLatentsStep(), FluxSetTimestepsStep(), FluxRoPEInputsStep()]
block_names = ["prepare_latents", "set_timesteps", "prepare_rope_inputs"]
@property
def description(self):
return "Before denoise step that prepares the inputs for the denoise step for Flux Kontext\n"
"for text-to-image tasks."
# before_denoise: image-conditioned
# auto_docstring
class FluxKontextImageConditionedBeforeDenoiseStep(SequentialPipelineBlocks):
"""
Before denoise step that prepare the inputs for the denoise step for Flux Kontext
for image-conditioned tasks.
Components:
scheduler (`FlowMatchEulerDiscreteScheduler`)
Inputs:
height (`int`, *optional*):
TODO: Add description.
width (`int`, *optional*):
TODO: Add description.
latents (`Tensor | NoneType`, *optional*):
TODO: Add description.
num_images_per_prompt (`int`, *optional*, defaults to 1):
TODO: Add description.
generator (`None`, *optional*):
TODO: Add description.
batch_size (`int`):
Number of prompts, the final batch size of model inputs should be `batch_size * num_images_per_prompt`.
Can be generated in input step.
dtype (`dtype`, *optional*):
The dtype of the model inputs
num_inference_steps (`None`, *optional*, defaults to 50):
TODO: Add description.
timesteps (`None`, *optional*):
TODO: Add description.
sigmas (`None`, *optional*):
TODO: Add description.
guidance_scale (`None`, *optional*, defaults to 3.5):
TODO: Add description.
image_height (`None`, *optional*):
TODO: Add description.
image_width (`None`, *optional*):
TODO: Add description.
prompt_embeds (`None`, *optional*):
TODO: Add description.
Outputs:
latents (`Tensor`):
The initial latents to use for the denoising process
timesteps (`Tensor`):
The timesteps to use for inference
num_inference_steps (`int`):
The number of denoising steps to perform at inference time
guidance (`Tensor`):
Optional guidance to be used.
txt_ids (`list`):
The sequence lengths of the prompt embeds, used for RoPE calculation.
img_ids (`list`):
The sequence lengths of the image latents, used for RoPE calculation.
"""
model_name = "flux-kontext"
block_classes = [FluxPrepareLatentsStep(), FluxSetTimestepsStep(), FluxKontextRoPEInputsStep()]
block_names = ["prepare_latents", "set_timesteps", "prepare_rope_inputs"]
@property
def description(self):
return (
"Before denoise step that prepare the inputs for the denoise step for Flux Kontext\n"
"for image-conditioned tasks."
)
# auto_docstring
class FluxKontextAutoBeforeDenoiseStep(AutoPipelineBlocks):
"""
Before denoise step that prepare the inputs for the denoise step.
This is an auto pipeline block that works for text2image.
- `FluxKontextBeforeDenoiseStep` (text2image) is used.
- `FluxKontextImageConditionedBeforeDenoiseStep` (image_conditioned) is used when only `image_latents` is
provided.
Components:
scheduler (`FlowMatchEulerDiscreteScheduler`)
Inputs:
height (`int`, *optional*):
TODO: Add description.
width (`int`, *optional*):
TODO: Add description.
latents (`Tensor | NoneType`, *optional*):
TODO: Add description.
num_images_per_prompt (`int`, *optional*, defaults to 1):
TODO: Add description.
generator (`None`, *optional*):
TODO: Add description.
batch_size (`int`):
Number of prompts, the final batch size of model inputs should be `batch_size * num_images_per_prompt`.
Can be generated in input step.
dtype (`dtype`, *optional*):
The dtype of the model inputs
num_inference_steps (`None`, *optional*, defaults to 50):
TODO: Add description.
timesteps (`None`, *optional*):
TODO: Add description.
sigmas (`None`, *optional*):
TODO: Add description.
guidance_scale (`None`, *optional*, defaults to 3.5):
TODO: Add description.
image_height (`None`, *optional*):
TODO: Add description.
image_width (`None`, *optional*):
TODO: Add description.
prompt_embeds (`None`, *optional*):
TODO: Add description.
Outputs:
latents (`Tensor`):
The initial latents to use for the denoising process
timesteps (`Tensor`):
The timesteps to use for inference
num_inference_steps (`int`):
The number of denoising steps to perform at inference time
guidance (`Tensor`):
Optional guidance to be used.
txt_ids (`list`):
The sequence lengths of the prompt embeds, used for RoPE calculation.
img_ids (`list`):
The sequence lengths of the image latents, used for RoPE calculation.
"""
model_name = "flux-kontext"
block_classes = [FluxKontextImageConditionedBeforeDenoiseStep, FluxKontextBeforeDenoiseStep]
block_names = ["image_conditioned", "text2image"]
block_trigger_inputs = ["image_latents", None]
@property
def description(self):
return (
"Before denoise step that prepare the inputs for the denoise step.\n"
+ "This is an auto pipeline block that works for text2image.\n"
+ " - `FluxKontextBeforeDenoiseStep` (text2image) is used.\n"
+ " - `FluxKontextImageConditionedBeforeDenoiseStep` (image_conditioned) is used when only `image_latents` is provided.\n"
)
# inputs: Flux Kontext
# auto_docstring
class FluxKontextInputStep(SequentialPipelineBlocks):
"""
Input step that prepares the inputs for the both text2img and img2img denoising step. It:
- make sure the text embeddings have consistent batch size as well as the additional inputs (`image_latents`).
- update height/width based `image_latents`, patchify `image_latents`.
Inputs:
height (`None`, *optional*):
TODO: Add description.
width (`None`, *optional*):
TODO: Add description.
max_area (`int`, *optional*, defaults to 1048576):
TODO: Add description.
num_images_per_prompt (`None`, *optional*, defaults to 1):
TODO: Add description.
prompt_embeds (`Tensor`):
Pre-generated text embeddings. Can be generated from text_encoder step.
pooled_prompt_embeds (`Tensor`, *optional*):
Pre-generated pooled text embeddings. Can be generated from text_encoder step.
image_latents (`None`, *optional*):
TODO: Add description.
Outputs:
height (`int`):
The height of the initial noisy latents
width (`int`):
The width of the initial noisy latents
batch_size (`int`):
Number of prompts, the final batch size of model inputs should be batch_size * num_images_per_prompt
dtype (`dtype`):
Data type of model tensor inputs (determined by `prompt_embeds`)
prompt_embeds (`Tensor`):
text embeddings used to guide the image generation
pooled_prompt_embeds (`Tensor`):
pooled text embeddings used to guide the image generation
image_height (`int`):
The height of the image latents
image_width (`int`):
The width of the image latents
"""
model_name = "flux-kontext"
block_classes = [FluxKontextSetResolutionStep(), FluxTextInputStep(), FluxKontextAdditionalInputsStep()]
block_names = ["set_resolution", "text_inputs", "additional_inputs"]
@property
def description(self):
return (
"Input step that prepares the inputs for the both text2img and img2img denoising step. It:\n"
" - make sure the text embeddings have consistent batch size as well as the additional inputs (`image_latents`).\n"
" - update height/width based `image_latents`, patchify `image_latents`."
)
# auto_docstring
class FluxKontextAutoInputStep(AutoPipelineBlocks):
"""
Input step that standardize the inputs for the denoising step, e.g. make sure inputs have consistent batch size,
and patchified.
This is an auto pipeline block that works for text2image/img2img tasks.
- `FluxKontextInputStep` (image_conditioned) is used when `image_latents` is provided.
- `FluxKontextInputStep` is also capable of handling text2image task when `image_latent` isn't present.
Inputs:
height (`None`, *optional*):
TODO: Add description.
width (`None`, *optional*):
TODO: Add description.
max_area (`int`, *optional*, defaults to 1048576):
TODO: Add description.
num_images_per_prompt (`None`, *optional*, defaults to 1):
TODO: Add description.
prompt_embeds (`Tensor`):
Pre-generated text embeddings. Can be generated from text_encoder step.
pooled_prompt_embeds (`Tensor`, *optional*):
Pre-generated pooled text embeddings. Can be generated from text_encoder step.
image_latents (`None`, *optional*):
TODO: Add description.
Outputs:
height (`int`):
The height of the initial noisy latents
width (`int`):
The width of the initial noisy latents
batch_size (`int`):
Number of prompts, the final batch size of model inputs should be batch_size * num_images_per_prompt
dtype (`dtype`):
Data type of model tensor inputs (determined by `prompt_embeds`)
prompt_embeds (`Tensor`):
text embeddings used to guide the image generation
pooled_prompt_embeds (`Tensor`):
pooled text embeddings used to guide the image generation
image_height (`int`):
The height of the image latents
image_width (`int`):
The width of the image latents
"""
model_name = "flux-kontext"
block_classes = [FluxKontextInputStep, FluxTextInputStep]
block_names = ["image_conditioned", "text2image"]
block_trigger_inputs = ["image_latents", None]
@property
def description(self):
return (
"Input step that standardize the inputs for the denoising step, e.g. make sure inputs have consistent batch size, and patchified. \n"
" This is an auto pipeline block that works for text2image/img2img tasks.\n"
+ " - `FluxKontextInputStep` (image_conditioned) is used when `image_latents` is provided.\n"
+ " - `FluxKontextInputStep` is also capable of handling text2image task when `image_latent` isn't present."
)
# auto_docstring
class FluxKontextCoreDenoiseStep(SequentialPipelineBlocks):
"""
Core step that performs the denoising process for Flux Kontext.
This step supports text-to-image and image-conditioned tasks for Flux Kontext:
- for image-conditioned generation, you need to provide `image_latents`
- for text-to-image generation, all you need to provide is prompt embeddings.
Components:
scheduler (`FlowMatchEulerDiscreteScheduler`) transformer (`FluxTransformer2DModel`)
Inputs:
height (`None`, *optional*):
TODO: Add description.
width (`None`, *optional*):
TODO: Add description.
max_area (`int`, *optional*, defaults to 1048576):
TODO: Add description.
num_images_per_prompt (`None`, *optional*, defaults to 1):
TODO: Add description.
prompt_embeds (`Tensor`):
Pre-generated text embeddings. Can be generated from text_encoder step.
pooled_prompt_embeds (`Tensor`, *optional*):
Pre-generated pooled text embeddings. Can be generated from text_encoder step.
image_latents (`None`, *optional*):
TODO: Add description.
latents (`Tensor | NoneType`, *optional*):
TODO: Add description.
generator (`None`, *optional*):
TODO: Add description.
num_inference_steps (`None`, *optional*, defaults to 50):
TODO: Add description.
timesteps (`None`, *optional*):
TODO: Add description.
sigmas (`None`, *optional*):
TODO: Add description.
guidance_scale (`None`, *optional*, defaults to 3.5):
TODO: Add description.
joint_attention_kwargs (`None`, *optional*):
TODO: Add description.
Outputs:
latents (`Tensor`):
Denoised latents.
"""
model_name = "flux-kontext"
block_classes = [FluxKontextAutoInputStep, FluxKontextAutoBeforeDenoiseStep, FluxKontextDenoiseStep]
block_names = ["input", "before_denoise", "denoise"]
@property
def description(self):
return (
"Core step that performs the denoising process for Flux Kontext.\n"
+ "This step supports text-to-image and image-conditioned tasks for Flux Kontext:\n"
+ " - for image-conditioned generation, you need to provide `image_latents`\n"
+ " - for text-to-image generation, all you need to provide is prompt embeddings."
)
@property
def outputs(self):
return [
OutputParam.template("latents"),
]
AUTO_BLOCKS_KONTEXT = InsertableDict(
[
("text_encoder", FluxTextEncoderStep()),
("vae_encoder", FluxKontextAutoVaeEncoderStep()),
("denoise", FluxKontextCoreDenoiseStep()),
("decode", FluxDecodeStep()),
]
)
# auto_docstring
class FluxKontextAutoBlocks(SequentialPipelineBlocks):
"""
Modular pipeline for image-to-image using Flux Kontext.
Supported workflows:
- `image_conditioned`: requires `image`, `prompt`
- `text2image`: requires `prompt`
Components:
text_encoder (`CLIPTextModel`) tokenizer (`CLIPTokenizer`) text_encoder_2 (`T5EncoderModel`) tokenizer_2
(`T5Tokenizer`) image_processor (`VaeImageProcessor`) vae (`AutoencoderKL`) scheduler
(`FlowMatchEulerDiscreteScheduler`) transformer (`FluxTransformer2DModel`)
Inputs:
prompt (`None`, *optional*):
TODO: Add description.
prompt_2 (`None`, *optional*):
TODO: Add description.
max_sequence_length (`int`, *optional*, defaults to 512):
TODO: Add description.
joint_attention_kwargs (`None`, *optional*):
TODO: Add description.
image (`None`, *optional*):
TODO: Add description.
_auto_resize (`bool`, *optional*, defaults to True):
TODO: Add description.
generator (`None`, *optional*):
TODO: Add description.
height (`None`, *optional*):
TODO: Add description.
width (`None`, *optional*):
TODO: Add description.
max_area (`int`, *optional*, defaults to 1048576):
TODO: Add description.
num_images_per_prompt (`None`, *optional*, defaults to 1):
TODO: Add description.
image_latents (`None`, *optional*):
TODO: Add description.
latents (`Tensor | NoneType`, *optional*):
TODO: Add description.
num_inference_steps (`None`, *optional*, defaults to 50):
TODO: Add description.
timesteps (`None`, *optional*):
TODO: Add description.
sigmas (`None`, *optional*):
TODO: Add description.
guidance_scale (`None`, *optional*, defaults to 3.5):
TODO: Add description.
output_type (`None`, *optional*, defaults to pil):
TODO: Add description.
Outputs:
images (`list`):
Generated images.
"""
model_name = "flux-kontext"
block_classes = AUTO_BLOCKS_KONTEXT.values()
block_names = AUTO_BLOCKS_KONTEXT.keys()
_workflow_map = {
"image_conditioned": {"image": True, "prompt": True},
"text2image": {"prompt": True},
}
@property
def description(self):
return "Modular pipeline for image-to-image using Flux Kontext."
@property
def outputs(self):
return [OutputParam.template("images")]