EntroPack: Fit Qwen-Image & H3 to Your Exact VRAM

Introduction
ModelScope just open-sourced EntroPack, an Apache 2.0 PyTorch library that compresses model weights at any bits-per-parameter you ask for, not just the usual 4-bit or 8-bit steps. The announcement landed on Oct 14 (about 18:00 MYT) alongside ready-to-load packs for three models creators actually run locally: Z-Image-Turbo, Qwen-Image-2.1, and MiniMax-H3. Today they load through DiffSynth-Studio; ModelScope's post also names ComfyUI as a target.
The pitch is simple and very local-rig friendly: instead of a fixed quant that either overshoots your card or leaves VRAM on the table, you dial a bitrate like 4.8 bpp and fill the GPU you actually own.
Code: modelscope/entropack on GitHub · Packs: EntroPackPreQuants on ModelScope · Report: EntroPack technical report
What shipped
- Library:
entropack(Python 3.10+, CUDA build of PyTorch 2.10+,cuda13orcuda12extras), Apache 2.0. - Lossy mode:
EntroPackLossyConfig(target_bpp=...)takes any target from 0.001 to 11 bpp, fractions included. No activation calibration or fine-tuning. - Lossless modes:
DFloat11Config()for exact BF16 recovery andTileANSConfig()for BF16, FP16, FP32, FP8, INT8, and more. - Drop-in layers:
CompressedLinear.from_linearswaps a normaltorch.nn.Linearfor a compressed one you call the same way. - Decoding: E8 lattice quantization plus entropy coding, decoded and reconstructed in one fused GPU kernel. ModelScope reports over 340 GB/s on a single BF16 tensor test.
The 16 GB headline
ModelScope's showcase number is the one most of us care about. In a Qwen-Image-2.1 test at 1024×1024, targeting 4.8 bpp peaked at 15.86 GiB, so it fits a 16 GB card, while cutting weight reconstruction error from NF4's 9.40% to 4.26%.
Speed cost looks small too. On one NVIDIA H20, compressing all 276 linear layers of Z-Image-Turbo's DiT at 4 bpp took 3.5 seconds, and a denoising step ran at 544.7 ms versus 505.7 ms for the original BF16 model, about 7.7% slower.
The pre-quantized packs
Every model gets DiT and text-encoder files at 4, 5, 6, 7, and 8 bpp, an fp8@5 pack (FP8 W8A8 codes stored at 5 bpp, running FP8 GEMM), and an "extreme" mixed-bit pack that keeps sensitive layers higher and squeezes the rest. You can mix DiT and text-encoder rates freely, for example an 8 bpp DiT with a 4 bpp text encoder.
Z-Image-Turbo DiT sizes from the model card:
- 8 bpp: 5.78 GB, 0.53% reconstruction error
- 6 bpp: 4.34 GB, 1.85% error
- 4 bpp: 2.88 GB, 7.01% error
- Extreme 2.3 bpp: 1.66 GB, 24.0% error (about one-seventh of BF16)
Qwen-Image-2.1 DiT sizes:
- 8 bpp: 6.68 GB, 0.54% error
- 5 bpp: 4.19 GB, 3.66% error
- 4 bpp: 3.34 GB, 7.06% error
- Extreme 3.0 bpp: 2.50 GB, 14.2% error
MiniMax-H3 ships both FL2VA and Ref2VA DiTs plus a shared text encoder and video VAE:
- DiT 8 bpp: 31.16 GB each, 0.50% error
- DiT 5 bpp: 19.54 GB each, 3.39% error
- DiT 4 bpp: 15.58 GB each, 6.57% error
- DiT extreme 3.0 bpp: 11.68 GB each, 13.2% error
- Video VAE: 1.47 GB at 4 bpp up to 2.61 GB at 8 bpp
A quick read of those error numbers: 6 to 8 bpp is close to lossless territory, 4 to 5 bpp is the sweet spot for tight cards, and the extreme packs are for "I just want it to run" experiments. Check the validation images and videos under assets/ on the model card before you commit a rig to the low end.
Try it
Install both pieces from source, picking the CUDA extra that matches your setup:
git clone https://github.com/modelscope/DiffSynth-Studio.git
cd DiffSynth-Studio && pip install -e .
cd ..
git clone https://github.com/modelscope/entropack.git
cd entropack && pip install -e '.[cuda13]'Then point DiffSynth-Studio at a pack. Each .safetensors file has a same-named .json sidecar that registers it, so the Z-Image-Turbo example only needs the package paths:
import json
import torch
from diffsynth.configs import MODEL_CONFIGS
from diffsynth.pipelines.z_image import ZImagePipeline, ModelConfig
repo = "DiffSynth-Studio/EntroPackPreQuants"
def prequant(path):
pkg = ModelConfig(model_id=repo, origin_file_pattern=path)
pkg.download_if_necessary()
side = ModelConfig(model_id=repo, origin_file_pattern=path.replace(".safetensors", ".json"))
side.download_if_necessary()
with open(side.path) as f:
MODEL_CONFIGS.append(json.load(f))
return pkg
pipe = ZImagePipeline.from_pretrained(
torch_dtype=torch.bfloat16,
device="cuda",
model_configs=[
prequant("models/Z-Image-Turbo/dit_4bpp.safetensors"),
prequant("models/Z-Image-Turbo/text_encoder_4bpp.safetensors"),
ModelConfig(model_id="Tongyi-MAI/Z-Image-Turbo", origin_file_pattern="vae/diffusion_pytorch_model.safetensors"),
],
tokenizer_config=ModelConfig(model_id="Tongyi-MAI/Z-Image-Turbo", origin_file_pattern="tokenizer/"),
)
image = pipe(prompt="a lantern-lit night market in the rain, cinematic, shallow depth of field", seed=42, rand_device="cuda")
image.save("z-image-turbo-entropack.jpg")For Qwen-Image-2.1 or MiniMax-H3, swap in that model's pipeline and package paths. The extreme and fp8@5 packs load the same way.
Good to know
- The library is Apache 2.0. The packs inherit each base model's own license, so check Qwen-Image-2.1, Z-Image-Turbo, and MiniMax-H3 terms before commercial use.
- The model card documents DiffSynth-Studio loading today. ModelScope's announcement also mentions ComfyUI, so watch for a node or loader before assuming a drag-and-drop workflow.
- You can compress your own checkpoints too:
ep.compress(tensor, config)andCompressedLinearwork on any 2D weight, which is handy for fine-tunes and LoRA-merged bases.
Original Source
Conclusion
EntroPack turns quantization from a menu of fixed sizes into a slider, and the first packs already cover the image and video models local creators lean on hardest. If a 16 GB card has been your ceiling for Qwen-Image-2.1, this is the one to test tonight.
—Aurelia ♡
