Spaces:
Runtime error
Runtime error
feat: build Qwen Image Editor app (Edit/Compose tabs, Fast/Quality, ZeroGPU + local CUDA) with tests
d713f9b | """Model constants, device helpers, and dimension utilities for Qwen Image Editor.""" | |
| from __future__ import annotations | |
| import math | |
| import os | |
| # --------------------------------------------------------------------------- | |
| # Model & LoRA identifiers | |
| # --------------------------------------------------------------------------- | |
| MODEL_ID = "Qwen/Qwen-Image-Edit-2511" | |
| LORA_REPO = "lightx2v/Qwen-Image-Edit-2511-Lightning" | |
| LORA_FILE = "Qwen-Image-Edit-2511-Lightning-4steps-V1.0-bf16.safetensors" | |
| LORA_ADAPTER_NAME = "lightning" | |
| # --------------------------------------------------------------------------- | |
| # Lightning scheduler configuration | |
| # Copied verbatim from diffusers-zerogpu-api.md §2. | |
| # The Lightning distillation was trained with shift=3 (log(3)) and | |
| # exponential time shifting — using the default scheduler gives degraded | |
| # results when combined with the Lightning LoRA. | |
| # --------------------------------------------------------------------------- | |
| LIGHTNING_SCHEDULER_CONFIG: dict = { | |
| "base_image_seq_len": 256, | |
| "base_shift": math.log(3), # shift=3 used during distillation | |
| "invert_sigmas": False, | |
| "max_image_seq_len": 8192, | |
| "max_shift": math.log(3), # same as base_shift for flat schedule | |
| "num_train_timesteps": 1000, | |
| "shift": 1.0, | |
| "shift_terminal": None, | |
| "stochastic_sampling": False, | |
| "time_shift_type": "exponential", | |
| "use_beta_sigmas": False, | |
| "use_dynamic_shifting": True, | |
| "use_exponential_sigmas": False, | |
| "use_karras_sigmas": False, | |
| } | |
| def on_spaces() -> bool: | |
| """Return True iff running inside a Hugging Face ZeroGPU Space.""" | |
| return bool(os.environ.get("SPACES_ZERO_GPU")) | |
| def auto_device() -> str: | |
| """Detect the best available compute device: cuda > mps > cpu.""" | |
| import torch | |
| if torch.cuda.is_available(): | |
| return "cuda" | |
| if torch.backends.mps.is_available(): | |
| return "mps" | |
| return "cpu" | |
| def fit_dimensions(image: object, max_pixels: int = 1024 * 1024, multiple: int = 16) -> tuple[int, int]: | |
| """Return (width, height) fitting within max_pixels, rounded down to `multiple`, min 256. | |
| Preserves aspect ratio as closely as the multiple constraint allows. | |
| Area is guaranteed <= max_pixels except in extreme aspect-ratio cases where | |
| the shorter dimension is clamped up to the 256 minimum. | |
| """ | |
| w, h = image.size | |
| if w * h > max_pixels: | |
| scale = (max_pixels / (w * h)) ** 0.5 | |
| w = int(w * scale) | |
| h = int(h * scale) | |
| # Floor to nearest multiple | |
| w = (w // multiple) * multiple | |
| h = (h // multiple) * multiple | |
| # Enforce minimum of 256 on each side | |
| w = max(256, w) | |
| h = max(256, h) | |
| return w, h | |
| def should_cpu_offload(device: str) -> bool: | |
| """Return True iff device is local CUDA with < 40 GB free VRAM. | |
| Always returns False on ZeroGPU Spaces (the runtime manages placement) | |
| and on mps/cpu (offload does not apply). Returns False gracefully when | |
| torch is not installed. | |
| """ | |
| if device != "cuda" or on_spaces(): | |
| return False | |
| try: | |
| import torch | |
| free_bytes, _total = torch.cuda.mem_get_info() | |
| return free_bytes / (1024**3) < 40.0 | |
| except Exception: | |
| return False | |