Skip to content

Adding KV-Cache Support to Flux2.Klein Image Editing - #465

Draft
amepas wants to merge 2 commits into
mainfrom
onboarding-imageedit-kv-flux2klein
Draft

Adding KV-Cache Support to Flux2.Klein Image Editing#465
amepas wants to merge 2 commits into
mainfrom
onboarding-imageedit-kv-flux2klein

Conversation

@amepas

@amepas amepas commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

Speeding up Image Editing on Flux2.Klein models by onboarding Flux2.Klein-9B-KV model variant. This is a separate model (same architecture, different weights) that was trained to support caching KV for reference images during image editing.

Usage

Just adding the use_kv=True flag to the 9B model call will switch to the KV-cache model support.

python generate_flux2klein.py
  prompt="add a bunch of animals swimming in the water in front of the castle and get rid of all birds" \
  image_paths="['/path/to/img1.png', '/path/to/img2.png']" \
  use_kv=True

Speed-Ups

Block-sizes can be tuned for each setting. Using default settings still gives substantial improvements

Reference Images ($1024 \times 1024$) Latency Speedup
1 Image 1.28x
2 Images 1.32x
4 Images 1.74x

Visual Verification

Prompt: change the painting so she is facing forward instead of looking over her shoulder

Original:
image

Edited:
image

Correctness

E2E parity test against reference diffusers implementation shows high visual similarity (SSIM>0.9). Smoke test also included to prevent any implementation regressions in future PRs.

@github-actions

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for the Flux2Klein model, including new configuration files, NNX-based model implementations for the Transformer and VAE, and a dedicated pipeline. It also adds end-to-end parity and smoke tests. The review identified several critical issues: missing imports in flux2klein_pipeline.py and generate_flux2klein.py that will cause runtime errors, and the incorrect use of nnx.silu instead of jax.nn.silu across multiple model files.

Comment thread src/maxdiffusion/pipelines/flux/flux2klein_pipeline.py
Comment on lines +88 to +89
try:
fb_dir = snapshot_download(repo_id=repo_id, local_files_only=True)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

snapshot_download is called here but is not imported in this scope (it is only imported inside main). This will cause a NameError when encode_prompt is executed. Please import snapshot_download.

    try:
      from huggingface_hub import snapshot_download
      fb_dir = snapshot_download(repo_id=repo_id, local_files_only=True)

def __call__(self, x: jax.Array) -> jax.Array:
x = self.linear_in(x)
x1, x2 = jnp.split(x, 2, axis=-1)
hidden = nnx.silu(x1) * x2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

nnx.silu is not a valid attribute of flax.nnx. Please use jax.nn.silu instead.

Suggested change
hidden = nnx.silu(x1) * x2
hidden = jax.nn.silu(x1) * x2

temb = temb.astype(hidden_states.dtype)

temb_silu = jax.nn.silu(temb)
temb_silu = nnx.silu(temb)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

nnx.silu is not a valid attribute of flax.nnx. Please use jax.nn.silu instead.

Suggested change
temb_silu = nnx.silu(temb)
temb_silu = jax.nn.silu(temb)

num_img_tokens = hidden_states.shape[1] - num_ref_tokens
ref_timestep = jnp.full_like(timestep_scaled, ref_fixed_timestep * 1000.0)
ref_temb = self.time_text_embed(ref_timestep, guidance_scaled, pooled_projections).astype(hidden_states.dtype)
ref_temb_silu = nnx.silu(ref_temb)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

nnx.silu is not a valid attribute of flax.nnx. Please use jax.nn.silu instead.

Suggested change
ref_temb_silu = nnx.silu(ref_temb)
ref_temb_silu = jax.nn.silu(ref_temb)

Comment on lines +155 to +159
h = self.norm1(x)
h = nnx.silu(h)
h = self.conv1(h)
h = self.norm2(h)
h = nnx.silu(h)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

nnx.silu is not a valid attribute of flax.nnx. Please use jax.nn.silu instead.

Suggested change
h = self.norm1(x)
h = nnx.silu(h)
h = self.conv1(h)
h = self.norm2(h)
h = nnx.silu(h)
h = self.norm1(x)
h = jax.nn.silu(h)
h = self.conv1(h)
h = self.norm2(h)
h = jax.nn.silu(h)

Comment on lines +452 to +454
x = self.conv_norm_out(x)
x = nnx.silu(x)
x = self.conv_out(x)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

nnx.silu is not a valid attribute of flax.nnx. Please use jax.nn.silu instead.

Suggested change
x = self.conv_norm_out(x)
x = nnx.silu(x)
x = self.conv_out(x)
x = self.conv_norm_out(x)
x = jax.nn.silu(x)
x = self.conv_out(x)

Comment on lines +536 to +538
x = self.conv_norm_out(x)
x = nnx.silu(x)
x = self.conv_out(x)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

nnx.silu is not a valid attribute of flax.nnx. Please use jax.nn.silu instead.

Suggested change
x = self.conv_norm_out(x)
x = nnx.silu(x)
x = self.conv_out(x)
x = self.conv_norm_out(x)
x = jax.nn.silu(x)
x = self.conv_out(x)

amepas and others added 2 commits August 26, 2026 07:04
…X (4B & 9B) with E2E parity and smoke tests

- Add multi-image editing pipeline (FlaxFlux2KleinPipeline) supporting arbitrary reference image conditioning
- Port VAE encoder and decoder to Flax NNX (AutoencoderKLFlux2NNX)
- Implement efficient image preprocessing, tiling, aspect-ratio-aware padding, and packing utilities
- Support fast sharded safetensors loading and TP sharding for Klein 4B & 9B
- Use standard HF_HOME resolution without machine-specific hardcoded paths
- Ensure clean compatibility across Transformers 4.x and 5.x via lazy module loading and dynamic FlaxPreTrainedModel lookup
- Add end-to-end multi-image editing parity test and preprocessing unit test suite
…age editing with E2E parity and smoke tests

- Implement prefix extraction phase (step 0) and cached denoising scan loop in FlaxFlux2KleinPipeline
- Support KV cache slicing and concatenation across Flax NNX Double and Single transformer blocks
- Safely bound Splash/Flash attention block sizes for asymmetric cross-attention sequences
- Add CLI and config support for use_kv with dynamic FLUX.2-klein-9b-kv repository resolution
- Add cross-framework E2E parity test achieving 0.9037 SSIM / 23.30 dB PSNR
- Add 9B KV-cache image editing smoke test with verified golden reference image
@amepas
amepas force-pushed the onboarding-imageedit-kv-flux2klein branch from 709b764 to 6238524 Compare August 26, 2026 08:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant