Spaces:
Running on Zero
Revert NF4 quantization: this checkpoint's weights are stored fp8-native
Browse filesSpace startup crashed: RuntimeError: Blockwise 4bit quantization only
supports 16/32-bit floats, but got torch.float8_e4m3fn.
The transformer safetensors index reports ~19GB total for a 20B-param
model (~1 byte/param), confirming prithivMLmods/Qwen-Image-Edit-Rapid-
AIO-V23 already ships as fp8, not bf16. bitsandbytes' 4-bit quantizer
requires a 16/32-bit source tensor to quantize from and cannot operate
on fp8-stored weights directly — and since nothing in this vendored
qwenimage code has fp8 compute kernels, the weights still need to be
upcast to bf16 for the forward pass to work at all, which is exactly
what the pre-quantization code already did. So NF4-on-load isn't a
drop-in fix here; doing it properly would mean manually materializing
the model in bf16 first and then hand-converting nn.Linear modules to
Linear4bit, which needs real GPU verification to get right.
Reverting app.py to the pre-quantization state (926cf86) to restore a
working Space. The requirements.txt fix pinning diffusers==0.39.0
(unrelated to quantization — it fixed a real huggingface-hub version
conflict against the transformers==4.57.1 pin) is kept since it's
still correct and needed regardless of the quantization approach.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- app.py +21 -33
- requirements.txt +0 -1
|
@@ -72,7 +72,7 @@ print("[startup] TF32 enabled", flush=True)
|
|
| 72 |
print("[startup] importing dimensions...", flush=True)
|
| 73 |
from dimensions import compute_output_dimensions, max_dim_for_mode
|
| 74 |
print("[startup] importing diffusers...", flush=True)
|
| 75 |
-
from diffusers import
|
| 76 |
print("[startup] importing QwenImageEditPlusPipeline...", flush=True)
|
| 77 |
from qwenimage.pipeline_qwenimage_edit_plus import QwenImageEditPlusPipeline
|
| 78 |
print("[startup] importing QwenImageTransformer2DModel...", flush=True)
|
|
@@ -97,31 +97,13 @@ def _start_heartbeat(label: str) -> threading.Event:
|
|
| 97 |
_t0_load = time.perf_counter()
|
| 98 |
print("[startup] loading transformer from_pretrained (prithivMLmods/Qwen-Image-Edit-Rapid-AIO-V23)...", flush=True)
|
| 99 |
_hb = _start_heartbeat("transformer")
|
| 100 |
-
# NF4-quantize the transformer (~20B params, ~40GB in bf16) to fit the pipeline
|
| 101 |
-
# comfortably inside this Space's 47GB MIG slice. bitsandbytes only quantizes
|
| 102 |
-
# on an actual CUDA device (it rejects device_map="cpu"/"disk" for a fresh,
|
| 103 |
-
# not-yet-quantized config), so this loads straight onto cuda:0 instead of the
|
| 104 |
-
# CPU-first pattern used below for the rest of the pipeline. That pays the
|
| 105 |
-
# once-per-boot "ZeroGPU disk packing" cost the CPU-first load was added to
|
| 106 |
-
# avoid, but only once at startup rather than never.
|
| 107 |
-
_quant_config = BitsAndBytesConfig(
|
| 108 |
-
load_in_4bit=True,
|
| 109 |
-
bnb_4bit_quant_type="nf4",
|
| 110 |
-
bnb_4bit_compute_dtype=dtype,
|
| 111 |
-
bnb_4bit_use_double_quant=True,
|
| 112 |
-
) if torch.cuda.is_available() else None
|
| 113 |
_transformer = QwenImageTransformer2DModel.from_pretrained(
|
| 114 |
"prithivMLmods/Qwen-Image-Edit-Rapid-AIO-V23",
|
| 115 |
torch_dtype=dtype,
|
| 116 |
-
device_map=
|
| 117 |
-
quantization_config=_quant_config,
|
| 118 |
)
|
| 119 |
_hb.set()
|
| 120 |
print(f"[startup] transformer loaded in {time.perf_counter()-_t0_load:.1f}s", flush=True)
|
| 121 |
-
try:
|
| 122 |
-
print(f"[startup] transformer memory footprint: {_transformer.get_memory_footprint()/1024**3:.2f}GB", flush=True)
|
| 123 |
-
except Exception as e:
|
| 124 |
-
print(f"[startup] transformer memory footprint: unavailable ({e})", flush=True)
|
| 125 |
|
| 126 |
_t1_load = time.perf_counter()
|
| 127 |
print("[startup] loading pipeline from_pretrained (FireRedTeam/FireRed-Image-Edit-1.1)...", flush=True)
|
|
@@ -422,21 +404,27 @@ def _infer_gpu(pil_images, prompt, seed, guidance_scale, steps, width, height, m
|
|
| 422 |
|
| 423 |
# Each ZeroGPU call runs in a fresh worker (hooks are always unset here),
|
| 424 |
# so cpu_offload buys no cross-call reuse — it only trades one bulk
|
| 425 |
-
# to(device) transfer for several slower hook-managed ones.
|
| 426 |
-
#
|
| 427 |
-
#
|
| 428 |
-
#
|
| 429 |
-
#
|
|
|
|
|
|
|
| 430 |
if getattr(pipe.transformer, "_hf_hook", None) is None:
|
| 431 |
-
|
| 432 |
-
|
| 433 |
-
|
| 434 |
-
|
| 435 |
-
|
| 436 |
-
|
| 437 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 438 |
pipe.enable_model_cpu_offload(device=device)
|
| 439 |
-
print(f"[infer] enabled cpu offload on {device} (
|
| 440 |
print(f"[infer] {_gpu_mem_str(_cuda_ok)} — t={time.perf_counter()-t0:.1f}s")
|
| 441 |
|
| 442 |
print(f"[infer] {len(pil_images)} image(s) pre-decoded, output={width}x{height}, seed={seed}")
|
|
|
|
| 72 |
print("[startup] importing dimensions...", flush=True)
|
| 73 |
from dimensions import compute_output_dimensions, max_dim_for_mode
|
| 74 |
print("[startup] importing diffusers...", flush=True)
|
| 75 |
+
from diffusers import FlowMatchEulerDiscreteScheduler
|
| 76 |
print("[startup] importing QwenImageEditPlusPipeline...", flush=True)
|
| 77 |
from qwenimage.pipeline_qwenimage_edit_plus import QwenImageEditPlusPipeline
|
| 78 |
print("[startup] importing QwenImageTransformer2DModel...", flush=True)
|
|
|
|
| 97 |
_t0_load = time.perf_counter()
|
| 98 |
print("[startup] loading transformer from_pretrained (prithivMLmods/Qwen-Image-Edit-Rapid-AIO-V23)...", flush=True)
|
| 99 |
_hb = _start_heartbeat("transformer")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
_transformer = QwenImageTransformer2DModel.from_pretrained(
|
| 101 |
"prithivMLmods/Qwen-Image-Edit-Rapid-AIO-V23",
|
| 102 |
torch_dtype=dtype,
|
| 103 |
+
device_map="cpu",
|
|
|
|
| 104 |
)
|
| 105 |
_hb.set()
|
| 106 |
print(f"[startup] transformer loaded in {time.perf_counter()-_t0_load:.1f}s", flush=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 107 |
|
| 108 |
_t1_load = time.perf_counter()
|
| 109 |
print("[startup] loading pipeline from_pretrained (FireRedTeam/FireRed-Image-Edit-1.1)...", flush=True)
|
|
|
|
| 404 |
|
| 405 |
# Each ZeroGPU call runs in a fresh worker (hooks are always unset here),
|
| 406 |
# so cpu_offload buys no cross-call reuse — it only trades one bulk
|
| 407 |
+
# to(device) transfer for several slower hook-managed ones. On a
|
| 408 |
+
# generously-sized allocation, move the full ~37GB pipeline to GPU in one
|
| 409 |
+
# shot (fast); but the 47GB 2g.48gb MIG slice this Space actually gets
|
| 410 |
+
# measured a peak of 46.82GB and still OOM'd on that path, wasting ~40s
|
| 411 |
+
# before falling back — so only attempt it when there's real headroom
|
| 412 |
+
# above that, otherwise go straight to enable_model_cpu_offload.
|
| 413 |
+
_FAST_PATH_MIN_GB = 60
|
| 414 |
if getattr(pipe.transformer, "_hf_hook", None) is None:
|
| 415 |
+
if _cuda_ok and p.total_memory / 1024**3 >= _FAST_PATH_MIN_GB:
|
| 416 |
+
try:
|
| 417 |
+
pipe.to(device)
|
| 418 |
+
print(f"[infer] moved full pipe to {device} — t={time.perf_counter()-t0:.1f}s")
|
| 419 |
+
except torch.cuda.OutOfMemoryError:
|
| 420 |
+
print(f"[infer] OOM moving full pipe to {device}, falling back to cpu offload")
|
| 421 |
+
pipe.to("cpu")
|
| 422 |
+
torch.cuda.empty_cache()
|
| 423 |
+
pipe.enable_model_cpu_offload(device=device)
|
| 424 |
+
print(f"[infer] enabled cpu offload on {device} (fallback)")
|
| 425 |
+
else:
|
| 426 |
pipe.enable_model_cpu_offload(device=device)
|
| 427 |
+
print(f"[infer] enabled cpu offload on {device} (slice too small for fast path)")
|
| 428 |
print(f"[infer] {_gpu_mem_str(_cuda_ok)} — t={time.perf_counter()-t0:.1f}s")
|
| 429 |
|
| 430 |
print(f"[infer] {len(pil_images)} image(s) pre-decoded, output={width}x{height}, seed={seed}")
|
|
@@ -2,7 +2,6 @@ git+https://github.com/huggingface/accelerate.git
|
|
| 2 |
diffusers==0.39.0
|
| 3 |
git+https://github.com/huggingface/peft.git
|
| 4 |
transformers==4.57.1
|
| 5 |
-
bitsandbytes
|
| 6 |
huggingface_hub
|
| 7 |
pyarrow
|
| 8 |
sentencepiece
|
|
|
|
| 2 |
diffusers==0.39.0
|
| 3 |
git+https://github.com/huggingface/peft.git
|
| 4 |
transformers==4.57.1
|
|
|
|
| 5 |
huggingface_hub
|
| 6 |
pyarrow
|
| 7 |
sentencepiece
|