Image21 Turbo OrbitQuant W4A4

OrbitQuant build of WaveCut/Image21-Turbo: Qwen-Image-2.1 with the Viggle turbo v0.2.1 LoRA merged and the Texture-Fix VAE. The diffusion transformer is W4A4, the Qwen3-VL-8B text encoder is W6A6; the few projections that create or cancel massive activations stay in fp16 in both. Text-to-image and editing in 6 steps without guidance, with every component resident in 13.6 GB. Built with Qwen.

Image21 Turbo fp16 versus OrbitQuant on twelve paired prompts

The preview links to the lossless 4096Γ—6576 matrix: twelve pairs at the native 1024Γ—1024, same prompt, seed and settings in each pair, tiles concatenated without resizing. The 24 PNGs are in artifacts/generations/.

At a glance

Item Value
Source WaveCut/Image21-Turbo (Qwen-Image-2.1 790c9263 + Viggle turbo v0.2.1 + Texture-Fix VAE)
Transformer 214 linears OrbitQuant W4A4; fp16: img_in, txt_in, modulation.1, img_mlp.out of blocks 0, 4–11, 13, timestep embedder, norm_out, proj_out
Text encoder 341 linears OrbitQuant W6A6 (language model, vision tower, lm_head); fp16: decoder layers 6, 16, 34, 35
Quantization RP-BH rotation, Lloyd-Max codebooks, no calibration data, OrbitQuant 0.9.8
Sampling 6 steps on the turbo sigmas, no CFG
Storage transformer 4.52 GB (fp16 14.23 GB), text encoder 8.33 GB (bf16 17.5 GB), VAE 1.35 GB
Benchmark RTX 5090 32 GB, torch 2.8.0+cu128, diffusers 0.41.0.dev0 80c7ed26, transformers 5.17.0

Install and run

pip install -r https://huggingface.co/WaveCut/Image21-Turbo-OrbitQuant-W4A4/resolve/main/runtime-requirements.txt
orbitquant kernels-install
import torch
import orbitquant
from diffusers import QwenImage21Pipeline

pipe = QwenImage21Pipeline.from_pretrained("WaveCut/Image21-Turbo-OrbitQuant-W4A4", dtype=torch.float16).to("cuda")

SIGMAS = [1.0, 0.9375, 0.875, 0.75, 0.5, 0.25]
image = pipe(
    prompt="A rain-soaked Warsaw street seen through a tram window",
    width=1024, height=1024,
    num_inference_steps=6, sigmas=SIGMAS,
    generator=torch.Generator("cuda").manual_seed(0),
).images[0]

edited = pipe(
    prompt="Turn <image1> into a snowy winter night; keep the composition unchanged.",
    image=[image], output_resolution=1024,
    num_inference_steps=6, sigmas=SIGMAS,
    generator=torch.Generator("cuda").manual_seed(0),
).images[0]

import orbitquant registers the loaders; kernels-install fetches the native kernel wheel for the running torch/CUDA ABI (--build compiles it when no prebuilt variant matches). Keep the VAE untiled in fp16: tiled fp16 decoding produces non-finite pixels; for 2048Β² text-to-image use pipe.vae.to(torch.bfloat16); pipe.vae.enable_tiling(). scripts/run_inference.py wraps the same calls with the turbo schedules.

Latency and VRAM

RTX 5090, fp16 compute, 6 steps, 10 prompts, median of two hot sweeps after a cold one. The fp16 source does not fit 32 GB with all components resident, so both builds are also measured staged: text encoder on the GPU for encoding, then transformer and VAE.

Metric Image21 Turbo fp16 OrbitQuant Change
1024Β², staged, hot end-to-end 2.685 s 2.122 s βˆ’21 %
1024Β², transformer 6 steps 2.426 s 1.816 s βˆ’25 %
1024Β², prompt encode 0.035 s 0.077 s +0.04 s
1024Β², VAE decode 0.224 s 0.229 s
1024Β², all resident, hot end-to-end does not fit 2.248 s
2048Β², hot end-to-end (tiled VAE) 17.88 s staged 13.95 s resident βˆ’22 %
Peak VRAM, encode stage 17.53 GB 8.96 GB βˆ’49 %
Peak VRAM, transformer + VAE stage, 1024Β² 22.45 GB 13.40 GB βˆ’40 %
Peak VRAM, all resident, 1024Β² / 2048Β² β€” 21.15 / 16.44 GB
Load from page cache to GPU 8.4 s 3.3 s βˆ’61 %
Learned-weight storage 33.1 GB 14.2 GB βˆ’57 %

VRAM is nvidia-smi (NVML) and includes the CUDA context. Raw records are in benchmark/.

What 4-bit breaks here and what stays in fp16

Both Qwen stacks carry massive activations β€” single channels of a few special tokens that grow to thousands. A module that writes or cancels such a value turns a routine 2–5 % quantization error into an error of the same order as the signal that survives:

  • Text encoder. Layer 16's MLP writes β‰ˆ9000 into channel 2276 of the user-turn <|im_start|> token, layers 34–35 cancel it to a few hundred, and the pipeline reads exactly that pre-norm last hidden state. Layer 6 writes β‰ˆ13000 into the same channel of the system-turn <|im_start|> token. With W4A4 everywhere the embeddings drop to cosine 0.86 (token 0: 0.36) and the images change composition.
  • Transformer. Text tokens carry values up to β‰ˆ9000 written by img_mlp.out of blocks 0, 4–11 and 13; the text stream feeds every image token through attention and the prefix KV cache.

The fix keeps those projections in fp16 and runs the rest of the text encoder at W6A6. Isolation on seven prompts (PSNR / SSIM against the fp16 pipeline; the fp16 pipeline with a bf16 text encoder scores 30.8 / 0.968):

Text encoder Transformer PSNR SSIM Encoder + transformer
W4A4 W4A4 14.49 dB 0.610 10.0 GB
fp16 W4A4 17.31 dB 0.707
fp16 W4A4 + fp16 massive-activation writers 19.11 dB 0.763
W4A4 fp16 15.27 dB 0.640
W6A6 + fp16 layers 6, 16, 34, 35 fp16 24.42 dB 0.909
W6A6 + fp16 layers 6, 16, 34, 35 W4A4 + fp16 massive-activation writers 18.66 dB 0.757 12.85 GB

Every transformer row keeps img_in, txt_in and modulation.1 in fp16.

Keeping all 32 img_mlp.out projections in fp16 instead of the ten writers costs 1.7 GB more and scores lower (18.84 dB). Across the twelve pairs of the matrix the final build scores 19.73 dB PSNR / 0.777 SSIM.

Sampling recipes

Measured on the fp16 Image21 Turbo pipeline, which this build follows step for step.

Recipe Settings Result
Default 6 steps, sigmas=[1, 0.9375, 0.875, 0.75, 0.5, 0.25], shipped scheduler, no CFG Sharpest detail; Latin and Cyrillic text mostly right
Text, posters, natural skin same sigmas, pipe.scheduler = FlowMatchEulerDiscreteScheduler.from_config(pipe.scheduler.config, use_dynamic_shifting=False, shift=3.0) Cleanest lettering, smoother skin, same speed
Dense text 8 steps, sigmas=[1, 0.9375, 0.875, 0.75, 0.625, 0.5, 0.25, 0.125] Same composition, small print slightly cleaner, +30 % time
Guidance 6 steps, true_cfg_scale=2 with a negative prompt More contrast and saturation, 2Γ— time
Avoid 4 steps [1, 0.75, 0.5, 0.25]; static shift 5 Ghosted double contours; soft, smeared detail

Editing: reference images are <image1>, <image2>, … in the prompt, in the order passed; references are encoded at output_resolutionΒ² area and the canvas follows the last reference unless width/height are given.

Comparison protocol

# Prompt Stress category Seed
01 studio-product product detail 61000
02 human-portrait portrait 61001
03 mucha-poster public-domain artist style 61002
04 hokusai-wave public-domain artist style 61003
05 bauhaus-risograph popular image style 61004
06 technical-cutaway technical diagram 61005
07 long-latin-text long Latin text 61006
08 long-cyrillic-text long Cyrillic text 61007
09 mixed-diagram mixed Latin/Cyrillic diagram 61008
10 wide-city-scene dense scene composition 61009
11 edit-background edit of pair 02's fp16 output 61010
12 edit-winter edit of pair 10's fp16 output 61011

1024Γ—1024, 6 steps, turbo sigmas, no CFG. Both columns of an edit pair start from the same fp16 input. Prompts are in benchmark/prompts.json. It is a deployment check, not an FID, CLIP or preference benchmark.

Repository contents

  • transformer/, text_encoder/ β€” OrbitQuant components; processor/, vae/, scheduler/, model_index.json β€” the rest of the diffusers pipeline.
  • assets/ β€” lossless comparison matrix, preview and its manifest with SHA-256 of every tile.
  • artifacts/generations/ β€” 12 fp16 and 12 OrbitQuant PNGs.
  • benchmark/ β€” timings, memory, prompts, environment, pairwise PSNR/SSIM.
  • scripts/run_inference.py β€” command-line runner; scripts/quantize.py β€” rebuilds both components from WaveCut/Image21-Turbo.
  • quantization_manifest.json β€” every quantized and fp16 module with parameter counts.
  • LICENSE, NOTICE β€” license, modified files, upstream notices.

Limitations

  • W4A4 moves the 6-step trajectory: object placement, faces and small print can differ from the fp16 build at the same seed; long Cyrillic text and dense mixed-script diagrams degrade more than Latin text.
  • The first call compiles Triton kernels for new shapes; measure hot latency after a warm-up.
  • Numbers are for one RTX 5090; other GPUs, drivers and torch builds differ.
  • Non-commercial: the Qwen RESEARCH LICENSE AGREEMENT applies to all weights.

License

Derivative of Qwen-Image-2.1 under the Qwen RESEARCH LICENSE AGREEMENT (LICENSE), research and evaluation only. NOTICE lists the modified files and the Viggle and madebyollin notices.

Qwen is licensed under the Qwen RESEARCH LICENSE AGREEMENT, Copyright (c) 2026 Hangzhou Tongyi Laboratory Technology Co., Ltd. All Rights Reserved.

Downloads last month
-
Safetensors
Model size
4B params
Tensor type
BF16
Β·
F16
Β·
U8
Β·
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Model tree for WaveCut/Image21-Turbo-OrbitQuant-W4A4

Quantized
(1)
this model