- Qwen_Image-2.1-MXFP4-Paiton
Qwen_Image-2.1-MXFP4-Paiton
Built with Qwen. This is a packed, mixed-precision derivative of Qwen-Image-2.1 prepared by EliovpAI. The recommended balanced checkpoint contains 8.67 GiB of weight tensors. It was benchmarked generating a 2048 × 2048 image on one 32 GB Radeon AI PRO R9700, with all model components resident on the GPU.
The recommended v1.0.2 runtime measured 103.29 seconds warm and 113.95 seconds for the first request, through PNG delivery, with a 25.55 GiB sampled whole-device peak at 2048 × 2048, 40 steps, guidance 1.0 and batch one. All model components remain GPU-resident: no CPU model offload, weight streaming during generation, VAE tiling or approximate denoiser caching.
The model weights are unchanged. This Hugging Face repository provides the
checkpoint and the original packaged loader. Use the current
Paiton integration
or its versioned container for the v1.0.2 runtime and results below. The default
runtime uses a mixed-precision schedule; it is not bit-exact. An exact
profile preserves the original denoiser arithmetic and measured about
134 seconds warm.
The package requires a compatible loader; it is not a drop-in
DiffusionPipeline.from_pretrained checkpoint. The complete image pipeline
still uses the pinned external Diffusers/PyTorch runtime alongside the Paiton
native libraries. These results do not claim native four-bit matrix
multiplication or a fully compiled, framework-independent diffusion pipeline.
Recommended setup: v1.0.2
Linux, Docker and a working AMD GPU driver are required. Use one model worker at a time; the launcher requires at least 30 GiB free VRAM before loading.
From an updated repository checkout, start the image API:
./models/Qwen-Image-2.1/serve-docker.sh
Without a checkout, start the same container directly:
docker run --rm --name paiton-qwen-image21 \
--device /dev/kfd --device /dev/dri --ipc=host \
-p 127.0.0.1:8191:8191 \
-v paiton-qwen-image21-cache:/cache \
ghcr.io/eliovp/paiton-vllm-plugin:qwen-image21-mxfp4-rdna4-v1.0.2
The first launch downloads and verifies 9.33 GB of checkpoint files.
The named volume preserves weights and runtime caches. Wait for
READY http://0.0.0.0:8191; the API is exposed only on the host's localhost.
With a repository checkout, generate and save a PNG from another terminal:
python3 models/Qwen-Image-2.1/request.py \
--prompt 'A neon shop sign that reads "QWEN IMAGE 2.1", rainy night, reflections on wet pavement' \
--size 2048 --seed 42 --output outputs/neon.png
Without a checkout, use the HTTP request example below. For the exact profile, use this instead of the default server command:
./models/Qwen-Image-2.1/serve-docker.sh serve --precision-profile exact
For the direct Docker form, append serve --precision-profile exact after the
image name. See the usage guide
for direct generation without a server, image editing, transparency and offline use.
This image API is separate from the repository's paiton serve language-model presets.
Latest R9700 results: v1.0.2
One 32 GB Radeon AI PRO R9700, 2048 × 2048, 40 steps, guidance 1.0 and batch one. The checkpoint and generation settings are unchanged between these releases.
| Published runtime | Warm request | First request | Peak whole-device VRAM | Sample count |
|---|---|---|---|---|
| v1.0.1 historical container repeat | 165.14 s | 179.32 s | 28.34 GiB | 3 processes |
| v1.0.2 exact profile | 133.74 s | 147.83 s | 25.33 GiB | 1 container |
v1.0.2 default (schedule-int8) |
103.29 s | 113.95 s | 25.55 GiB | 3 containers |
Timings cover the complete HTTP request through PNG delivery. The three-process figures are medians; the exact profile is a single validation run. Each process used seed 42 for its first request and seed 43 for its warm request. VRAM is the maximum sampled whole-device usage across that row's requests, sampled every 5 ms. Startup and model download are excluded; v1.0.2 default startup-to-ready median was about 65 seconds, with the checkpoint already cached.
The default reduces warm latency by about 37% compared with the documented v1.0.1 container repeat. These are separate release validation runs, not one interleaved comparison or a guarantee for every prompt. Earlier matched v1.0.2 source qualification measured 103.64 seconds warm / 115.37 seconds first request; those results are separate from the published-container measurements above.
Per-run results and methodology · Published measurement data
Runtime precision and quality
The default keeps the cached text-prefix pass and first seven denoising steps at the original precision, then uses int8 activations and int8/fp8 attention for steps 8–40. The downloaded MXFP4 checkpoint is unchanged.
Against this runtime's exact reference images, the default measured
41.8 dB PSNR / 0.00085 LPIPS on the 2048-square neon test and 50.2 dB PSNR
on the 1024-square teapot test. Generation, RGBA, editing and repeat-request
checks passed. The 2048-square RGBA case was close to the predefined acceptance
threshold (35.02 dB, with a 35 dB gate); use exact for the conservative
path, or schedule-int8-11 for the intermediate profile documented in the
usage guide.
These are bounded checks against the same quantized checkpoint's exact runtime,
not against the original unquantized model. The original weight-quantization
screen remains in Quality measurements.
The default does not promise identical output. For exact, bit-exactness was
checked on saved denoiser tensors; final PNGs can still show the documented
small differences across fresh processes from VAE/post-processing.
Hardware compatibility
The packed MXFP4 weight format is not tied to a GPU architecture. A compatible
loader can reconstruct these weights for BF16 computation on other hardware.
The supplied native HIP runtime binary, however, targets RDNA4 gfx1201.
The packaged launcher currently requires that architecture and at least 30 GiB
of free device memory, including when selecting its reference backend.
The R9700 is the benchmark and validation device, not part of the model's name. This release does not establish compatibility with every RDNA4 card or every GPU. A matching architecture alone does not establish sufficient VRAM. Other architectures require a compatible runtime and separate validation. AMD lists GPU architectures in its GPU specifications.
License
The upstream Qwen Research License permits noncommercial research and evaluation. Commercial use requires a separate upstream license. Quantizing the weights does not change those terms. Read LICENSE, NOTICE and third-party notices. This model's license is distinct from the Paiton plugin adapter's license and from commercial Paiton offerings.
What was quantized
| Component | Original BF16 inference weights | Recommended balanced weights |
|---|---|---|
| Diffusion transformer | 13.253 GiB | 3.706 GiB |
| Text and vision encoder | 16.330 GiB | 4.339 GiB |
| VAE | 0.629 GiB | 0.629 GiB |
| Total tensor payload | 30.212 GiB | 8.674 GiB |
The balanced profile quantizes 224 main diffusion matrices and 372 text/vision matrices, embedding tables and patch-convolution weights. It preserves the small diffusion input/output/conditioning layers and the VAE in BF16. Small normalization parameters and biases also remain BF16. The original runtime and v1.0.2 exact profile use BF16 activation arithmetic; the v1.0.2 default uses the precision schedule described above.
A separately measured compact conversion quantizes all 692 supported matrix, embedding and convolution weights, including the VAE, for an 8.027 GiB total payload. It also completed 2048-square generation on the R9700. The balanced profile is recommended because it improved the paired quality screen while still meeting the device-memory target. Compact is retained as an experimental alternative, not silently substituted for the recommended weights.
MXFP4 storage uses E2M1 values packed low nibble first, with an E8M0 scale for each group of 32 input columns. Scale storage and preserved BF16 tensors mean the complete checkpoint is not exactly four times smaller. Convolution weights are flattened by output channel and zero-padded to a multiple of 32 columns; the loader removes that padding before applying the original operation.
Memory: loading weights is not the complete request
All three components stay on the GPU in the qualified path. It uses no CPU model offload and no VAE tiling. Checkpoint loading streams individual tensors, so the R9700 host does not need a second full BF16 model copy in RAM.
The runtime avoids the large GEMM convolution workspace on the tested ROCm stack, removes unused temporal feature caches for asserted single-frame VAE calls, and releases completed condition-image caches before final decoding. Diffusion steps, guidance and resolution are preserved. BF16 activation arithmetic describes the original runtime and the exact profile; the current default uses the precision schedule above. The original loader expands weights temporarily for each operation.
The actual device exposes 31.86 GiB, despite its nominal 32 GB product label. Measurements distinguish live framework allocation, framework reservation and sampled whole-device usage. The original package measurements below used a 20 ms sampling interval; the v1.0.2 container measurements above use 5 ms. Sampling can miss very short transients; framework high-water marks are included in the result records.
The following table records the original packaged-runtime qualification, not the current v1.0.2 peak.
| R9700 configuration | 2048-square result |
|---|---|
| Original BF16, all components resident, full physical memory available | Out of memory during the first diffusion step: an additional 258 MiB was requested with 58 MiB free |
| Compact MXFP4, reference weight reconstruction | Completed; 29.06 GiB sampled peak |
| Balanced MXFP4, native Paiton weight reconstruction, local API | Completed; 29.74 GiB first / 28.68 GiB warm sampled peak |
The BF16 failure is specific to the tested fully resident configuration. It does not establish that BF16 can never run on an R9700 with offloading, staging, a smaller image or another memory strategy.
Complete-request latency comparison
Historical measurements of the original packaged runtime.
All rows below use the same balanced packed checkpoint, 2048² image, 40 steps, guidance 1.0, seed 42 and local HTTP/base64 PNG interface on the same R9700.
| Weight reconstruction backend | First request | Warm request |
|---|---|---|
| Generic framework reference | 242.73 s | 227.51 s |
| Original Quark HIP decoder | 196.62 s | 192.89 s |
| Paiton native HIP artifact | 200.10 s | 194.55 s |
The Quark HIP decoder was the strongest completed same-checkpoint baseline in this original screen. These historical measurements do not establish a Paiton speedup over it. The original Paiton artifact is an independently tested, framework-free weight decoder. Current v1.0.2 results use the updated runtime and are reported separately above; this historical table is retained for reproducibility.
Each process executed one first and one warm request. This is a bounded screen,
not a statistically powered throughput benchmark. The Paiton process took
58.59 s to become ready, including checkpoint integrity verification. Its first
response arrived about 258.68 s after process launch. These are process-cold
measurements with existing disk/kernel caches, not fresh-install timings.
The original Quark stable-ABI extension was loaded unchanged into the same
external pipeline; its identity and measurements are included in measurements/.
Tested operating limits
| Operation | Qualified settings |
|---|---|
| Text to image | 1024 × 1024 and 2048 × 2048, batch one |
| Transparent generation | 1024 × 1024 and 2048 × 2048; real alpha transparency checked |
| Image editing | One input image, at most 2048² input pixels; 1024 × 1024 output |
| Sampling | 40 steps, true guidance 1.0, prefix KV reuse enabled |
| Requests | One active request per worker; one fixed checkpoint per process |
| Runtime requirements | gfx1201 and at least 30 GiB free before startup |
| Benchmark hardware | Radeon AI PRO R9700 |
| Graphs | Native artifact graph replay qualified; full-pipeline graph capture unsupported |
Unsupported dimensions, batch sizes, step counts and guidance values are rejected before GPU execution. Multi-image editing, other aspect ratios, multiple simultaneous workers and other GPUs are not qualified by this package. Other applications using the GPU reduce available memory. Restart the worker to select another checkpoint or backend.
Start locally
Original packaged-runtime setup.
The following commands remain available for the original loader included in this Hugging Face repository. They do not select the v1.0.2 runtime or reproduce its timings; use the recommended container above for that release.
Use Python 3.12 and the tested ROCm Torch build in
environment.lock.json. The R9700 test used
torch==2.15.0.dev20260907+rocm10.0, HIP 7.15.26333, Transformers 5.17.0 and
Diffusers source commit 7263f3317f6b392d62f41e9d75ed9d7e21fc5a5c.
The requirements file pins the image dependencies and does not replace Torch.
Unrelated PyTorch/ROCm combinations have not been tested.
hf download EliovpAI/Qwen_Image-2.1-MXFP4-Paiton-RDNA4 \
--local-dir Qwen_Image-2.1-MXFP4-Paiton
cd Qwen_Image-2.1-MXFP4-Paiton
python3 -m pip install -r requirements.txt
./launch.sh --model-dir . generate \
--prompt 'A neon shop sign that reads "QWEN IMAGE 2.1", rainy night, reflections on wet pavement' \
--size 2048 --seed 42 --output outputs/neon.png
The checkpoint directory must contain result.json, the three component directories,
processor/ and scheduler/. The Hugging Face package puts these at its root.
Use that directory wherever /path/to/checkpoint appears below.
All checkpoint shard hashes are checked at startup; this
verification is included in the measured startup time. The worker requires no
Quark installation or compiler source. It loads the allowlisted native runtime
artifact after checking its hash and architecture.
./launch.sh --model-dir /path/to/checkpoint generate \
--mode rgba --prompt 'A cute cartoon dragon sticker.' \
--size 1024 --seed 52 --output outputs/dragon.png
./launch.sh --model-dir /path/to/checkpoint generate \
--mode edit --image inputs/teapot.png \
--prompt 'Change the blue teapot to bright red. Keep the table and composition.' \
--size 1024 --seed 53 --output outputs/red-teapot.png
The RGBA mode uses the upstream recommended transparency prompt wording. Save PNG to retain alpha. The measured stickers had 68.3% of pixels below alpha 128 at 1024² and 60.4% at 2048². The 2048² release-package CLI request took 197.95 s through PNG encoding and peaked at 29.74 GiB of sampled device memory. An RGBA file from an ordinary text prompt may have an almost opaque alpha channel; its file mode alone is not evidence of transparent generation.
Example files: 2048 text to image, 2048 transparent PNG, edit input, edited result.
Local API
The recommended container above exposes the image API on port 8191. To start the original packaged runtime instead, its existing command remains:
./launch.sh --model-dir /path/to/checkpoint serve --port 8191
The server binds to 127.0.0.1 by default. GET /health reports readiness and
checkpoint identity; GET /v1/models reports the supported tasks and limits.
Generation returns a base64 PNG plus full-request time and memory measurements.
curl http://127.0.0.1:8191/v1/images/generations \
-H 'Content-Type: application/json' \
-d '{"model":"paiton-image-2.1","prompt":"A blue ceramic teapot on a wooden table","size":"2048x2048","seed":42,"n":1}'
For POST /v1/images/edits, send JSON with prompt, image_b64 containing one
base64-encoded input image, size: "1024x1024" and seed. The API deliberately
accepts image bytes rather than fetching URLs or opening client-supplied file
paths. The edit endpoint is a JSON interface, not a multipart OpenAI API clone.
The request body limit is 32 MiB. A concurrent generation receives HTTP 409.
Quality measurements
This is the original checkpoint quantization versus BF16 screen. It is separate from the v1.0.2 runtime precision-profile checks above.
Eight fixed prompts with one seed each were generated at 2048², 40 steps and guidance 1.0. Each quantized result was paired with BF16 using the same hardware, software stack, model, scheduler and prompt settings. The suite covers a sign, portrait, product, wildlife, spatial relations, watercolor, landscape and poster.
| Metric | BF16 reference | Compact MXFP4 | Balanced MXFP4 |
|---|---|---|---|
| Mean CLIPScore, higher indicates stronger image/prompt alignment | 0.90313 | 0.85795 | 0.86839 |
| Mean paired LPIPS versus BF16, lower means closer | 0 | 0.26637 | 0.19177 |
CLIPScore uses OpenAI CLIP ViT-B/32, the A photo depicts prefix and
2.5 × max(cosine(image, text), 0), evaluated in float32 on CPU. LPIPS uses
AlexNet v0.1 through lpips==0.1.4, with RGB inputs resized to 512² using bicubic
sampling. This metric resize does not change the generated 2048² images.
See the pinned metric weights, per-prompt results and raw paired images in
evaluation/.
Balanced mean CLIPScore is approximately 3.85% below BF16 in this small suite. The neon-sign case accounts for much of the difference. This is a descriptive quality screen, not statistical equivalence, a general accuracy score, or a claim of unchanged quality. LPIPS measures changed composition as well as degradation. Neither metric guarantees correct spelling, counts or spatial relationships. No FID/KID is reported from eight images. This paired quality screen is separate from the R9700 memory and latency benchmarks. It does not establish identical images across different hardware or software stacks.
Metric references: CLIPScore, LPIPS.
Validation and reproduction
The checks and commands below describe the original packaged runtime and checkpoint. Current v1.0.2 runtime qualification is documented in the published benchmarks.
- Quark packing was checked against independently decoded E2M1/E8M0 values.
- The portable converter reproduced all 1,881 stored balanced-profile tensors bit-for-bit from the pinned original weights.
- Checkpoint shards, configs, indices and native artifacts have SHA-256 pins.
- The native artifact passed independent C++ arithmetic, every nibble/scale encoding, bounds, non-default streams and A-B-A graph replay tests without PyTorch or Triton.
- Real packed tensors were checked against the native decoder, including full matrices at the three dominant diffusion projection shapes.
- Native/reference denoising latents matched bit-for-bit. After preserving the compact cropped convolution-weight layout, the complete 2048² VAE decoder also matched bit-for-bit.
- Real HTTP tests covered repeated 2048 generation, RGBA, editing, rejected unsupported settings, a dedicated non-default stream and an A-B-A request sequence spanning different tasks. The repeated A PNGs were identical.
- The standalone staged release loaded its sanitized checkpoint manifest and completed a separate 2048² RGBA CLI request, including real alpha validation.
The exact latent and isolated VAE checks above concern the compact diagnostic profile. Separately loaded balanced full pipelines were not PNG-bitwise equal across backends: Paiton versus Quark differed by RGB MAE 0.084 on a 0–255 scale and PSNR 58.86 dB. Each backend's own repeated PNG was identical. These separate findings must not be combined into a claim of bitwise full-pipeline equivalence.
The local evidence also retains failures: default VAE convolution workspace exhaustion, allocator fragmentation, the initial padded-weight layout mismatch, and the slower experiment retaining all expanded diffusion weights. Successful microbenchmarks are not substituted for complete-request measurements.
Use --backend reference before the generate or serve command for the
generic framework weight-reconstruction control. Both backends use the same
packed checkpoint and BF16 inference settings. Matched API comparison records
are included separately from the quality table.
# Offline integrity and independent native artifact checks
python3 tools/verify_package.py --package .
python3 -m unittest discover -s tests -p 'test_*.py'
python3 tests/check_native.py
# About ten minutes: two 2048 requests, editing, transparency and cache isolation
timeout --signal=TERM --kill-after=15s 900s python3 tools/validate_api.py \
--model-dir . --output validation/native
# Same two-request timing control, using generic framework reconstruction
timeout --signal=TERM --kill-after=15s 690s python3 tools/validate_api.py \
--model-dir . --backend reference --benchmark-only --output validation/reference
To reproduce the strongest control, supply _C.cpython-312-x86_64-linux-gnu.so
from quark/torch/kernel/hw_emulation/ in the pinned Quark wheel to
tools/validate_api.py --backend quark-hip --quark-extension /path/to/_C.cpython-312-x86_64-linux-gnu.so.
Also supply --model-dir, --output and --benchmark-only as above. The tool
checks the extension hash before loading it. This optional test does not add
Quark to the normal inference requirements.
The paired metric screen can be reproduced on CPU in the pinned evaluation
environment, with lpips==0.1.4 installed:
python3 tools/prepare_metrics.py --output /path/to/metric-cache
python3 tools/evaluate.py \
--reference evaluation/images/bf16 --candidate evaluation/images/balanced \
--clip-dir /path/to/metric-cache/clip \
--torch-hub-dir /path/to/metric-cache/torch-hub --output /path/to/new-metrics
Metric model files are pinned and verified by SHA-256. The portable evaluation script reproduced all recorded balanced per-prompt scores exactly.
Offline conversion uses the separately pinned Quark environment:
python3 tools/quantize.py --snapshot /path/to/original/pinned/snapshot \
--output /path/to/new-balanced-checkpoint --profile balanced
--profile compact converts all supported matrix/convolution/embedding weights.
The converter checks original source hashes and creates a new output directory.
It does not overwrite the upstream checkpoint. Conversion is weight-only
round-to-nearest; it uses no activation calibration, GPTQ, learned correction or
quality-aware retraining. The native compiler implementation is intentionally
absent from this runtime distribution.
Model tree for EliovpAI/Qwen_Image-2.1-MXFP4-Paiton-RDNA4
Base model
Qwen/Qwen-Image-2.1