Buckets:

|
download
raw
21 kB

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. -->

FLUX 3 Image Klein

FLUX 3 Image Klein is a 5.6B image generation model from Black Forest Labs: a single transformer (Flux3Transformer2DModel) generates images from a text prompt, alone or together with one or more reference images. Text conditioning comes from Qwen3-VL, and images use the FLUX.2 packed autoencoder (AutoencoderKLFlux2).

FLUX 3 Image Klein ships as a modular pipeline. It takes full scene captions, not short prompts: a request sent as typed gives generic output. We strongly advise running the prompt upsampler on every request, text-to-image and editing alike, or any LLM with the same system prompts; every example on this page does. The upsampler is a separate 9B model (black-forest-labs/flux-3-image-klein-pup) that the pipeline does not run on its own. Load it beside the pipeline, then generate:

import json

import torch
from diffusers import ModularPipeline
from huggingface_hub import hf_hub_download
from transformers import AutoProcessor, Qwen3_5ForConditionalGeneration

pipe = ModularPipeline.from_pretrained("black-forest-labs/flux-3-image-klein-base")
pipe.load_components(dtype={"vae": torch.float32, "default": torch.bfloat16})
pipe.to("cuda")

pup_id = "black-forest-labs/flux-3-image-klein-pup"
processor = AutoProcessor.from_pretrained(pup_id)
upsampler = Qwen3_5ForConditionalGeneration.from_pretrained(pup_id, dtype=torch.bfloat16, device_map="auto").eval()
system_prompts = json.load(open(hf_hub_download(pup_id, "system_prompts.json")))

def upsample(prompt, images=()):
    if images:
        text = (
            "Reference images follow in order (the first image, the second image, ...).\n"
            f"User request: {prompt}\nOutput the caption."
        )
        content = [{"type": "image", "image": image} for image in images] + [{"type": "text", "text": text}]
        messages = [{"role": "system", "content": system_prompts["i2i"]}, {"role": "user", "content": content}]
    else:
        messages = [{"role": "system", "content": system_prompts["t2i"]}, {"role": "user", "content": prompt}]
    inputs = processor.apply_chat_template(
        messages,
        add_generation_prompt=True,
        tokenize=True,
        return_dict=True,
        return_tensors="pt",
        enable_thinking=False,
    ).to(upsampler.device)
    with torch.no_grad():
        output = upsampler.generate(**inputs, max_new_tokens=3584, do_sample=False)
    return processor.decode(output[0, inputs["input_ids"].shape[1] :], skip_special_tokens=True).strip()

caption = upsample("A red fox in a snow-covered forest clearing at golden hour")
image = pipe(prompt=caption, generator=torch.Generator().manual_seed(0), output="images")[0]
image.save("fox.png")

prompt is the only required input of the pipeline: it carries the recommended sampling settings (50 steps, guidance scale 3.5, scheduler shift 6.93) and generates 1024 x 1024 images by default. It takes one prompt per call; use num_images_per_prompt for several images of the same prompt.

Prompt upsampling

The prompt upsampler turns a short request, together with the reference images when editing, into the full scene caption the model takes: medium and style, scene, lighting and camera, each subject with its colors, materials and position in the frame. upsample above runs it with Transformers: system_prompts["t2i"] for text-to-image, system_prompts["i2i"] with the references first in the user message for an edit, greedy decoding, thinking off. The model card has the decoding settings and the layout form (t2i_bbox, i2i_bbox), which keeps a list of boxes you pass as a box table after the caption.

Any other LLM can take its place: give it system_prompts["t2i"] (or "i2i" with the references) as the system prompt and the request as the user message, and pass the caption it returns as prompt.

Image-to-image

Pass one or more reference images with image. Every reference keeps its own resolution (center-cropped to the 16-pixel grid; references above 16 megapixels are downscaled first), and the generation size defaults to one megapixel at the first reference's aspect ratio. The prompt is the target image as a complete caption of the reference with the edit folded in, not a one-line instruction; the prompt upsampler writes it from the instruction and the references:

night = pipe(
    prompt=upsample("the same scene at night under a full moon", [image]),
    image=image,
    generator=torch.Generator().manual_seed(0),
    output="images",
)[0]

With several references, name them by position in the request, the first image, the second image, ... in the order they are passed to both upsample and image:

combined = pipe(
    prompt=upsample("put the fox from the first image on the wooden bench from the second image", [image, bench]),
    image=[image, bench],
    height=768,
    width=1360,
    output="images",
)[0]

Pass height and/or width to override the derived size.

Layout control

To place content explicitly, the caption tags regions with <id> and ends with a JSON list of regions. Each region has an id, a bbox of [y0, x0, y1, x1] (top-left and bottom-right corners, origin top-left) normalized to 0-1000 on both axes so it is independent of the output size, and a desc. This is the form the upsampler writes with its t2i_bbox and i2i_bbox system prompts from a request and a list of boxes (scaffold on its model card); the prompts below are that output, passed as prompt:

prompt = (
    "Minimalist graphic illustration featuring a black silhouette of a person <silhouette_1> centered against a "
    "solid, vibrant chartreuse background <background_1>. "
    '[{"id": "background_1", "bbox": [0, 0, 1000, 1000], "desc": "A flat field of neon yellow-green."}, '
    '{"id": "silhouette_1", "bbox": [150, 150, 850, 850], "desc": "A black silhouette of a person in motion."}]'
)

When editing, each region names its source reference with from (for example "ref_image_0"), where it is in that image with src_bbox, and where it should end up with tgt_bbox. Equal boxes keep a region in place:

prompt = (
    "In <ref_image_0>, move the knight figure <knight_1> upwards and to the left. Keep the rest of the image "
    "unchanged, preserving the backdrop <backdrop_1>. "
    '[{"id": "knight_1", "from": "ref_image_0", "src_bbox": [500, 150, 850, 350], "tgt_bbox": [194, 55, 544, 255], '
    '"desc": "A miniature amigurumi knight crocheted from grey yarn."}, '
    '{"id": "backdrop_1", "from": "ref_image_0", "src_bbox": [0, 0, 1000, 1000], "tgt_bbox": [0, 0, 1000, 1000], '
    '"desc": "A soft, out-of-focus backdrop of knitted yarn."}]'
)
image = pipe(prompt=prompt, image=knight, output="images")[0]

Guidance scale

The pipeline applies classifier-free guidance through its guider component and does not take a guidance_scale argument at call time. The default guider is ClassifierFreeGuidance with guidance_scale=3.5, the recommended setting for both workflows. To change it, create an updated copy of the guider:

pipe.guider = pipe.guider.new(guidance_scale=5.0)

See the guiders guide to switch to a different guidance method.

Step-distilled model

The step-distilled checkpoint generates in 16 steps without classifier-free guidance. Its transformer is a flow map: at every step it is told the current timestep and the one the step jumps to. It loads like the base model (the repo's modular_model_index.json resolves to Flux3DistilledModularPipeline and Flux3DistilledAutoBlocks); the pipeline has no guider and does not take negative_prompt:

pipe = ModularPipeline.from_pretrained("black-forest-labs/flux-3-image-klein")
pipe.load_components(dtype=torch.bfloat16)
pipe.to("cuda")

image = pipe(prompt=upsample("An astronaut riding a horse"), generator=torch.Generator().manual_seed(0), output="images")[0]

It serves the same two workflows as the base model. num_inference_steps defaults to 16; the model is trained for 4 to 16 steps.

Reproducible generation

A generator fixes the noise the pipeline draws (see Reproducibility). To reuse noise drawn elsewhere, pass it as latents with shape (batch_size, 128, height // 16, width // 16). For example, the BFL implementation draws its noise as image tokens on the CPU and casts it to bf16; this reproduces its sample for a given seed:

height, width = 1024, 1024
h, w = height // 16, width // 16

noise = torch.randn((h * w, 128), generator=torch.Generator().manual_seed(0)).to(torch.bfloat16)
latents = noise.T.reshape(1, 128, h, w)

image = pipe(prompt=caption, latents=latents, height=height, width=width, output="images")[0]

Workflows

The pipeline serves two workflows, text2image and image_conditioned; the one that runs is picked by the inputs (image selects image-to-image). from_pretrained() can also build a pipeline for one workflow with the workflow argument, which then only expects and loads the components that workflow needs:

from diffusers.modular_pipelines import Flux3AutoBlocks

print(Flux3AutoBlocks().available_workflows)
# ["text2image", "image_conditioned"]

t2i = ModularPipeline.from_pretrained("black-forest-labs/flux-3-image-klein-base", workflow="text2image")
print(t2i.blocks.doc)

Memory

Loading everything in bf16 takes about 20 GB of weights (the transformer is 5.5B parameters, the Qwen3-VL-4B text encoder 4B), with the image VAE in fp32; the prompt upsampler is another 18.8 GB, placed by device_map="auto". For GPUs with less memory, enable component offloading:

pipe = ModularPipeline.from_pretrained("black-forest-labs/flux-3-image-klein-base")
pipe.load_components(dtype={"vae": torch.float32, "default": torch.bfloat16})
pipe.enable_auto_cpu_offload(device="cuda")

Single-file loading

Flux3Transformer2DModel loads the transformer straight from a Black Forest Labs model package with from_single_file(). The package config.json is not read; pass the diffusers config with config and subfolder.

import torch
from diffusers import Flux3Transformer2DModel, ModularPipeline

transformer = Flux3Transformer2DModel.from_single_file(
    "https://huggingface.co/black-forest-labs/flux-3-image-klein-base/blob/main/model.safetensors",
    config="black-forest-labs/flux-3-image-klein-base",
    subfolder="transformer",
    dtype=torch.bfloat16,
)

pipe = ModularPipeline.from_pretrained("black-forest-labs/flux-3-image-klein-base")
pipe.load_components(dtype={"vae": torch.float32, "default": torch.bfloat16})
pipe.update_components(transformer=transformer)
pipe.to("cuda")

Load the other components by name first: load_components() without names would also load the transformer from the pipeline repo.

Loading the FP8r and NVFP4 single-file checkpoints are also supported. Both load through the same call with a BFLQuantizationConfig. See the BFL quantization guide for the kernel requirements of each scheme.

from diffusers import BFLQuantizationConfig

transformer = Flux3Transformer2DModel.from_single_file(
    "https://huggingface.co/black-forest-labs/flux-3-image-klein-base/blob/main/variants/nvfp4/model.safetensors",
    config="black-forest-labs/flux-3-image-klein-base",
    subfolder="transformer",
    quantization_config=BFLQuantizationConfig(compute_dtype=torch.bfloat16),
    dtype=torch.bfloat16,
)

When loading the step-distilled checkpoints, we need their configs (flow_map=True):

transformer = Flux3Transformer2DModel.from_single_file(
    "https://huggingface.co/black-forest-labs/flux-3-image-klein/blob/main/variants/nvfp4/model.safetensors",
    config="black-forest-labs/flux-3-image-klein",
    subfolder="transformer",
    quantization_config=BFLQuantizationConfig(compute_dtype=torch.bfloat16),
    dtype=torch.bfloat16,
)

Flux3ModularPipeline[[diffusers.Flux3ModularPipeline]]

diffusers.Flux3ModularPipeline[[diffusers.Flux3ModularPipeline]]

diffusers.Flux3ModularPipeline(blocks: diffusers.modular_pipelines.modular_pipeline.ModularPipelineBlocks | None = None, pretrained_model_name_or_path: str | os.PathLike | None = None, components_manager: diffusers.modular_pipelines.components_manager.ComponentsManager | None = None, collection: str | None = None, workflow: str | None = None, modular_config_dict: dict[str, typing.Any] | None = None, config_dict: dict[str, typing.Any] | None = None, **kwargs)

Source

A ModularPipeline for FLUX.3.

Flux3AutoBlocks[[diffusers.Flux3AutoBlocks]]

diffusers.Flux3AutoBlocks[[diffusers.Flux3AutoBlocks]]

diffusers.Flux3AutoBlocks()

Source

Auto blocks that perform text-to-image and image-to-image generation using FLUX.3.

Supported workflows:

  • text2image: requires prompt
  • image_conditioned: requires prompt, image

Components: text_encoder (Qwen3VLForConditionalGeneration) tokenizer (AutoProcessor) image_processor (Flux3ImageProcessor) vae (AutoencoderKLFlux2) transformer (Flux3Transformer2DModel) scheduler (FlowMatchEulerDiscreteScheduler) guider (ClassifierFreeGuidance)

Inputs: prompt (str): The prompt to guide the generation (one prompt per call) negative_prompt (str, optional): The prompt not to guide the generation max_sequence_length (int, optional, defaults to 8192): Maximum number of prompt tokens; longer prompts are truncated. text_encoder_out_layers (tuple, optional, defaults to (4, 8, 12, 16, 20, 24, 28, 32)): Indices of the text-encoder hidden layers whose states are stacked to form the text embeddings image (Image | list, optional): The reference image or images to condition the generation on; each keeps its own resolution (center-cropped to the 16-pixel grid) num_images_per_prompt (int, optional, defaults to 1): The number of images to generate per prompt. image_cond_latents (list, optional): Normalized packed latents of the reference images, one tensor of shape (B, C, height_i//16, width_i//16) per image height (int, optional, defaults to None or 1024, depending on the workflow): The height in pixels of the generated image; defaults to the first reference image's aspect ratio at the default area width (int, optional, defaults to None or 1024, depending on the workflow): The width in pixels of the generated image; defaults to the first reference image's aspect ratio at the default area latents (Tensor): Pre-generated noisy latents for image generation. generator (Generator, optional): Torch generator for deterministic generation. num_inference_steps (int): The number of denoising steps. timesteps (Tensor): Timesteps for the denoising process. (overrides num_inference_steps when provided) sigmas (list, optional): Custom sigmas for the denoising process. (overrides num_inference_steps when provided) **denoiser_input_fields (None, optional): conditional model inputs for the denoiser: e.g. prompt_embeds, negative_prompt_embeds, etc. attention_kwargs (dict, optional): Additional kwargs for attention processors. output_type (str, optional, defaults to pil): Output format: 'pil', 'np', 'pt'.

Outputs: images (list): Generated images. latents (Tensor): Denoised latents.

Flux3DistilledAutoBlocks[[diffusers.Flux3DistilledAutoBlocks]]

diffusers.Flux3DistilledAutoBlocks[[diffusers.Flux3DistilledAutoBlocks]]

diffusers.Flux3DistilledAutoBlocks()

Source

Auto blocks that perform text-to-image and image-to-image generation using the step-distilled FLUX.3 model (16 steps, no classifier-free guidance).

Supported workflows:

  • text2image: requires prompt
  • image_conditioned: requires prompt, image

Components: text_encoder (Qwen3VLForConditionalGeneration) tokenizer (AutoProcessor) image_processor (Flux3ImageProcessor) vae (AutoencoderKLFlux2) transformer (Flux3Transformer2DModel) scheduler (FlowMatchEulerDiscreteScheduler)

Inputs: prompt (str): The prompt to guide the generation (one prompt per call) max_sequence_length (int, optional, defaults to 8192): Maximum number of prompt tokens; longer prompts are truncated. text_encoder_out_layers (tuple, optional, defaults to (4, 8, 12, 16, 20, 24, 28, 32)): Indices of the text-encoder hidden layers whose states are stacked to form the text embeddings image (Image | list, optional): The reference image or images to condition the generation on; each keeps its own resolution (center-cropped to the 16-pixel grid) num_images_per_prompt (int, optional, defaults to 1): The number of images to generate per prompt. image_cond_latents (list, optional): Normalized packed latents of the reference images, one tensor of shape (B, C, height_i//16, width_i//16) per image height (int, optional, defaults to None or 1024, depending on the workflow): The height in pixels of the generated image; defaults to the first reference image's aspect ratio at the default area width (int, optional, defaults to None or 1024, depending on the workflow): The width in pixels of the generated image; defaults to the first reference image's aspect ratio at the default area latents (Tensor): Pre-generated noisy latents for image generation. generator (Generator, optional): Torch generator for deterministic generation. num_inference_steps (int): The number of denoising steps. timesteps (Tensor): Timesteps for the denoising process. (overrides num_inference_steps when provided) sigmas (list, optional): Custom sigmas for the denoising process. (overrides num_inference_steps when provided) **denoiser_input_fields (None, optional): conditional model inputs for the denoiser: e.g. prompt_embeds, negative_prompt_embeds, etc. output_type (str, optional, defaults to pil): Output format: 'pil', 'np', 'pt'.

Outputs: images (list): Generated images. latents (Tensor): Denoised latents.

Flux3DistilledModularPipeline[[diffusers.Flux3DistilledModularPipeline]]

diffusers.Flux3DistilledModularPipeline[[diffusers.Flux3DistilledModularPipeline]]

diffusers.Flux3DistilledModularPipeline(blocks: diffusers.modular_pipelines.modular_pipeline.ModularPipelineBlocks | None = None, pretrained_model_name_or_path: str | os.PathLike | None = None, components_manager: diffusers.modular_pipelines.components_manager.ComponentsManager | None = None, collection: str | None = None, workflow: str | None = None, modular_config_dict: dict[str, typing.Any] | None = None, config_dict: dict[str, typing.Any] | None = None, **kwargs)

Source

A ModularPipeline for the step-distilled FLUX.3 model (16 steps, no classifier-free guidance).

Xet Storage Details

Size:
21 kB
·
Xet hash:
0af878b6690009bdb9f28a8f904468cbedf047c8cf4d72cc25674d6f06fe99a1

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.