Skip to content

feat(flux3): load quantized FLUX.3 single files - #10093

Open
Pfannkuchensack wants to merge 7 commits into
invoke-ai:mainfrom
Pfannkuchensack:feat/flux3-quantized
Open

Pfannkuchensack wants to merge 7 commits into
invoke-ai:mainfrom
Pfannkuchensack:feat/flux3-quantized

Conversation

@Pfannkuchensack

@Pfannkuchensack Pfannkuchensack commented Nov 1, 2026 •

Copy link
Copy Markdown
Member

Summary

The quantized FLUX.3 Image Klein / Klein Base single files were refused at install. They now load:

Build Source Layers kept quantized Resident
int8_convrot Comfy-Org (flux3-image-klein{,-base}-int8-convrot) 258 (fused qkv split into q, k, v) 5.43 GiB
nvfp4 Comfy-Org (flux3-image-klein{,-base}-nvfp4) 198 (33 of 43 blocks, as published) 4.92 GiB
nvfp4 BFL variants/nvfp4 (NVIDIA ModelOpt packing) 198, re-laid out to Comfy's packing 4.92 GiB
fp8r BFL variants/fp8r (per-row scaled fp8) 234, kept in fp8 with FP8 Storage or folded to bf16 5.84 / 10.34 GiB
  • Identification and the loader share one rule set (invokeai/backend/flux3/checkpoint_quantization.py). A file the loader cannot run is refused at install with a reason: torchao, bitsandbytes, fp8 scales in an unknown spelling, int8 without markers, unnamed or half-stored nvfp4, int8 mixed with another scheme, packed input embedders.
  • BFL's nvfp4 file holds exactly Comfy-Org's values in ModelOpt packing (low nibble first, row-major block scales). It is re-laid out after the cache reservation; afterwards all 198 layers are byte-identical to Comfy-Org's file.
  • Comfy-Org's int8 build fuses q, k and v per block; the converter splits the codes, per-row scales and markers into the model's three projections, and mirrors the output adaLN's [shift, scale] row swap onto per-row scales in every scheme.
  • New starters: Klein and Klein Base in int8 and NVFP4, pinned to Comfy-Org revision feef60b0…. BFL's variants install by URL (both are named model.safetensors); the docs give pinned fp8r URLs.
  • Docs: the FLUX.3 page gets a measured speed and quality table per build. Its outdated per-image times (15 s for Klein on a 4090) are replaced with measured ones (6.5 s; 13.5 s with one reference, 31.7 s with three; 36.7 s for Klein Base). The int8 Compute page gets a FLUX.3 row.

Related Issues / Discussions

Follow-up to #9883 and #10084.

QA Instructions

  • CPU, through the production loader on the real Klein files: every build identifies as one FLUX.3 Klein match; reserved bytes equal resident bytes; dequantized layers against the bf16 file: int8 worst cosine 0.99995 (rel. error 1 %), nvfp4 worst cosine 0.9966 (rel. error 8 %, inherent to fp4), fp8r worst cosine 0.99965 (rel. error 2.6 %).

  • pytest tests/backend/flux3 tests/backend/quantization tests/backend/model_manager/configs tests/backend/model_manager/load tests/model_identification and the starter tests — pass.

  • GPU, RTX 4090, FLUX.3 Klein at 1024², 16 steps, three prompts × three seeds. Each build starts from an empty model cache with one warm-up image. The builds ran once in each order, and the table averages both orders, because the card slows a little over a series:

    Build Denoise s/image With int8_compute / fp8_compute VRAM peak PSNR vs bf16, mean (lowest)
    bf16 6.22 6.20 19.5 GiB reference
    int8_convrot (Comfy-Org) 7.01 4.07, 1.52× bf16 14.4 GiB 33.2 dB (18.0); 34.5 dB (27.2) with int8_compute
    nvfp4 (Comfy-Org) 6.82 not affected 14.1 GiB 22.8 dB (14.9)
    nvfp4 (BFL) 6.84 not affected 14.3 GiB bit-identical images to Comfy-Org's nvfp4
    fp8r (BFL, FP8 Storage) 6.61 5.35, 1.16× bf16 15.0 GiB 26.8 dB (17.4); 25.4 dB (16.9) with fp8_compute
    Q8_0 GGUF, for comparison 6.78 not affected 14.5 GiB 34.4 dB (19.1)
    • VRAM peaks are nvidia-smi readings and include the text encoder and the desktop.
    • The lowest values come from one seed of the sign prompt, whose letter colours shift in every quantized build, Q8_0 GGUF included. For that prompt every build spells the sign's text correctly in all three seeds, with and without the switches.
    • With fp8_compute on, the scaled-fp8 text encoder runs on fp8 compute as well, so that run's images, bf16 included, differ from the default run. Its PSNR values compare against the bf16 images of the same run.
    • Without the compute switches, the quantized layers are dequantized on every forward: the builds run up to 13 % slower than bf16 and use about 5 GiB less VRAM.
    • The server log confirms what each build keeps: 258 int8 layers, 198 nvfp4 layers packed, 234 fp8r layers in fp8.
  • Docs: pnpm build in docs/ builds all 360 pages, and the link validator reports no broken link.

Review

  • Install first accepted any packed file the loader could not run (an NF4 file would have installed and failed at the first render); identification and loader now share one rule set.
  • torchao exports that also quantize the modulation layers were identified as unknown instead of refused; the FLUX.3 fingerprint now accepts torchao's spelling.
  • BFL's nvfp4 re-layout allocated about 2.1 GiB before the cache reservation; it now runs after it.
  • Known, not changed here: for nvfp4 builds the Model Manager can show FP8 Storage as on (the shared install default counts nvfp4's fp8 block scales). FP8 Storage does not apply to int8/nvfp4 FLUX.3 builds; the loader skips it and logs that. A fix in the shared default would change Krea-2, Z-Image and LTX-2 defaults and belongs in its own change.

Compatibility / Rollout

  • No migration: quantized FLUX.3 files use the existing checkpoint record. Records created before this PR are unaffected.

Checklist

  • The PR has a short but descriptive title, suitable for a changelog
  • Meaningful regression coverage added / updated where needed; obsolete tests/code removed
  • Persisted-state and API changes include required migrations / compatibility validation
  • Relevant performance/efficiency opportunities considered; material claims have evidence
  • Material review findings resolved and relevant checks rerun
  • Documentation added / updated (if applicable)
  • Updated What's New copy (if doing a release after this PR)

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

FLUX.3 Klein and Klein Base now load Comfy-Org's int8_convrot and nvfp4 files and BFL's fp8r and nvfp4 variants; one rule set refuses at install what the loader cannot run.
BFL's nvfp4 is re-laid out to Comfy's packing after the reservation, and the int8 build's fused qkv is split into the model's projections.
@github-actions github-actions Bot added python PRs that change python files backend PRs that change backend files python-tests PRs that change python tests docs PRs that change docs labels Nov 1, 2026
@lstein lstein self-assigned this Nov 2, 2026
@lstein lstein added the 7.0.0 label Nov 2, 2026
@lstein lstein moved this to 7.0.0: UX overhaul in Invoke - Community Roadmap Nov 2, 2026
Comment on lines +100 to +106
int8_markers = {path: marker for path, marker in markers.items() if marker.get("format") == INT8_TENSORWISE_FORMAT}
reject_unmarked_int8_weights(state_dict, int8_markers, "FLUX.3")
for path, marker in int8_markers.items():
group_size = marker.get("convrot_groupsize", CONVROT_GROUP_SIZE)
try:
if marker.get("convrot"):
check_hadamard_size(int(group_size))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] Unsupported int8 layouts pass installation validation, then fail on first generation.

Validation checks marker presence and power-of-four rotation groups, but omits required scales, supported scale shapes, and divisibility against the input width.

The fresh reviewer reproduced three cases on pinned HEAD: a missing weight_scale, an unsupported blockwise scale, and a rotation group larger than the input width. The identification validator accepted each; the production loader rejected each. Users consequently get an installed model that cannot generate.

Reuse existing int8 layout validation in the shared checker and add installation-refusal coverage. This is a bounded validation defect affecting malformed or unsupported repacks; it does not demonstrate a failure in the four published builds.

…hecks

Install-time validation now reuses check_int8_layer_layout, so a missing scale, blockwise scale or oversized rotation group is refused at install.
… check

Split the rotation-width rule out of check_int8_layer_layout so the swap runs it after the target-shape check; install runs both.
@Pfannkuchensack

Copy link
Copy Markdown
Member Author

Fixed: install validation now uses the loader's own checks. check_int8_layer_layout checks scale presence, scale layout and the marker. check_int8_rotation_width checks the group size against the input width. swap_in_int8_linears and the FLUX.3 checker share both functions, so each rule lives in one place. The loader keeps its architecture-mismatch message ahead of the rotation check. The three cases (missing weight_scale, blockwise scale, group wider than the input) are now refused at install, with tests.

# Conflicts:
#	docs/src/content/docs/Users Guide/03.Models/Local Models/flux-3.mdx
#	invokeai/backend/flux3/denoise_working_memory.py
# Conflicts:
#	docs/src/content/docs/Users Guide/03.Models/Local Models/flux-3.mdx

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

7.0.0 backend PRs that change backend files docs PRs that change docs python PRs that change python files python-tests PRs that change python tests

Projects

Status: 7.0.0: UX overhaul

Development

Successfully merging this pull request may close these issues.

3 participants