Spaces:
Running on Zero
Running on Zero
Commit History
-
refactor(upscale): drop LoRA support per spec
Unverified signatureCLAUDE.md and docs/superpowers/specs marked LoRA on the Upscale refinement pass as out-of-scope for v1, but the UI + handler still exposed it. In practice the upscale flow is RealESRGAN x2 -> 5 step Z-Image-Turbo img2img at 0.33 denoising — a window so tight that style LoRAs (Toon5, DarkGhibly, etc.) have almost no purchase on the output. Worse, users expect "Use a LoRA" to actually do something visible. Remove: - LoRA checkbox / file / strength group from ui.build_upscale_tab - lora_enabled/lora_path/lora_strength params + _coerce_lora call in app.on_upscale_generate - The lora_enabled.change visibility wiring in build_app - applied_lora wrapper + lora/lora_strength meta fields in modes.call_upscale Test coverage: - Update existing call_upscale tests to drop the no-longer-accepted lora_path / lora_strength params. - Add test_build_upscale_tab_has_no_lora_components to lock the UI surface against regression. The lora module + the T2I/ControlNet LoRA paths are untouched.7953225 -
fix(lora): accept diffusion_model.* prefix and use pipe.load_lora hotload
Unverified signatureThe sniff allowlist only had transformer./dit./model.transformer., so any CivitAI / Kohya LoRA whose keys started with diffusion_model.* (Toontastic, DarkGhibly, etc.) was rejected before reaching the pipeline. The bigger issue: _apply_lora_impl was calling diffsynth.utils.lora.merge_lora (loras: List[Dict], alpha) as if it were a state_dict-to-module fuser. It isn't — it's an image2lora list-merger — so even the LoRAs we did accept never actually patched the DiT. Swapped to pipe.load_lora(module=pipe.dit, ...) which routes through GeneralLoRALoader.convert_state_dict (strips the diffusion_model. prefix natively) and hotloads into AutoWrappedLinear, reverted at exit via pipe.clear_lora(). Verified live with Toon5_E10 (Z-Image-Turbo) and DarkGhiblyZBase (Z-Image Base) on local MPS.2e18e13
-
fix(upscale): crop upscaled image to multiple-of-16 dims before refinement
Unverified signatureDiffSynth allocates the noise tensor at ceil-multiple-of-16 but its VAE encodes at floor-multiple-of-16, so a 1240x728 ESRGAN output produced a 156-wide noise latent against a 154-wide input latent and add_noise crashed with 'tensor a (154) must match tensor b (156) at dim 3'. Floor-crop to mod 16 in modes.call_upscale so both paths agree.9514256 -
test: update _on_model_change asserts for new 3-tuple return shape
Unverified signaturee3764fc -
fix(upscale): pass post-upscale dims to pipe + LoRA label hints model compat
Unverified signatureTwo coupled UX fixes from live testing: 1. Upscale generation crashed with 'size of tensor a (256) must match size of tensor b (128) at non-singleton dimension 3' in DiffSynth's add_noise. RealESRGAN x4 + 0.5 resize yields a 2x image (1024 -> 2048). The VAE- encoded input latents were 256x256 but DiffSynth's noise initializer used the default 1024 height/width, producing 128x128 noise. call_upscale now passes height=upscaled.size[1], width=upscaled.size[0] — mirrors what call_controlnet already did for the preprocessed control image. 2. The LoRA toggle didn't say which model's LoRA it accepts. Now reads 'Use a LoRA (compatible with Z-Image-Turbo)' by default. On the T2I tab, _on_model_change updates the label to 'Use a LoRA (compatible with Z-Image)' when the user picks Base. ControlNet + Upscale stay Turbo-locked.296faa9 -
feat(ui): soft dark restraint redesign — native gr.Radio + accordion + lora toggle
Unverified signatureDrops the custom model-card grid, the popover tooltip pattern, the JS shim, and the decorative CSS. Uses Gradio-native shapes throughout (gr.Radio for Base/Turbo, gr.Checkbox to toggle LoRA visibility, gr.Accordion for advanced width/height/seed, info= subtitle text in place of the (i) icon). Adds the ControlNet preprocessor preview slot (Canny / Depth / Pose render live as the user changes the dropdown). Single output meta under the image (the prior mockup duplicated it inside Advanced).af844a1 -
feat(progress): gradio progress(track_tqdm=True) on all three handlers
Unverified signatureDiffSynth uses tqdm for the diffusion step loop and RealESRGAN uses it for the tile pass. Adding gr.Progress(track_tqdm=True) as a keyword parameter on the three on_*_generate handlers lets Gradio auto-capture both without threading a progress object through backend/modes.aa2a834 -
fix: pool-stashed transformer swap + MPS-safe vram + corrected model-zoo anchor
Unverified signatureThree coupled fixes uncovered by the first real Generate click locally: 1. AttributeError: 'ZImagePipeline' object has no attribute 'model_pool' DiffSynth's from_pretrained builds a fresh ModelPool, attaches pipe.dit/ pipe.text_encoder/etc. from it, then discards the pool. My _swap_transformer in modes.py assumed pipe.model_pool persisted. Replace from_pretrained call with a manual replication that stashes the pool on pipe._zis_pool, then index into pool.model for the two z_image_dit entries (Base loaded first, Turbo second per MODEL_CONFIGS order). fetch_model can't distinguish them since both register under the same name. 2. AttributeError: module 'torch.mps' has no attribute 'mem_get_info' DiffSynth's AutoWrappedModule.forward gates module load on check_free_vram (vram/layers.py:195), which calls torch.<device>.mem_get_info — CUDA-only. The escape hatch is vram_limit=None, which short-circuits the gate. Update models.vram_limit_for('mps') -> None (…0cf8ffc -
fix(deploy): switch model lookups to HF + fix ZeroGPU build
Unverified signatureMultiple issues caught in the HF Space build cycle: 1. DiffSynth defaults to ModelScope, not HF. Set DIFFSYNTH_DOWNLOAD_SOURCE= huggingface in app.py before imports so preload_from_hub + HF cache work. 2. PAI/Z-Image-Turbo-Fun-Controlnet-Union-2.1 is the ModelScope slug. On HF the mirror is alibaba-pai/... — update models.py + README + spec + test. 3. ZeroGPU build appends spaces==0.50.0 to the install line, conflicting with our spaces==0.30.0 pin. Drop the pin entirely — HF provides the right one. 4. DiffSynth resolves models at ./models/<repo>/, not ~/.cache/huggingface/hub. Add models.symlink_hf_cache_to_diffsynth_layout() that creates symlinks from cache snapshots to that layout. Wire into _bootstrap() so the preload weights are actually findable at runtime (otherwise the Space re-downloads all 30 GB on first call). 5. Set DIFFSYNTH_MODEL_BASE_PATH=<repo>/models in _bootstrap(). 6. Add models/ to .gitignore. 7. _bootstrap() now also runs locally (just th…99302bc -
fix(realesrgan): switch repo from xinntao/Real-ESRGAN to lllyasviel/Annotators
Unverified signaturexinntao/Real-ESRGAN doesn't exist on HF (returns 401) — the canonical weights live in GitHub releases. lllyasviel/Annotators mirrors the same 67 MB RealESRGAN_x4plus.pth and serves it cleanly via HF Hub. Caught when the HF Space build hit RUNTIME_ERROR on preload. Updates: README preload_from_hub, app._esrgan_path(), spec, plan.213bf15 -
fix: post-review polish — slider defaults, error handling, comment
Unverified signature- I5: t2i steps/cfg sliders update via gr.change() when model selector toggles base/turbo (was: stuck at turbo defaults, base generations silently used cfg=1 steps=8 → bad output). - I3: controlnet preprocessor wraps in try/except with raw-input fallback + stderr warning. - I1: zerogpu 'gpu task aborted' retries once with 2x duration via __retry_multiplier__ in params. duration_for honors it. - I4: 'Eager backend boot' comment renamed to 'Lazy backend singleton' to match the actual lazy get_backend() behavior. - bonus: fix pre-existing ruff failures in test_smoke_gpu.py (unused meta vars, unsorted local imports).76862de -
test: l3 gpu smoke (t2i base/turbo + controlnet + upscale)
Unverified signatureAdd pytest.mark.gpu smoke tests for real-weight end-to-end validation. Also add addopts=-m 'not gpu' to pyproject.toml so CI auto-deselects these tests; run with `pytest -m gpu` to opt in on a GPU box.5ac741c -
ci: ruff + pytest on push/pr (l1+l2, no gpu deps)
Unverified signatureAdd .github/workflows/ci.yml running ruff format, ruff check, and pytest against a minimal dep set (no torch/diffsynth/realesrgan/controlnet_aux). Fix all ruff format + lint violations found during CI replication (import order, unused imports, EN-dash RUF001, RUF059 unused unpack variables). Skip auto_device test when torch is absent so CI passes without a GPU.9a5065c -
feat(ui): per-tab gradio builders with labeled_label + custom model selector
Unverified signature14b904e -
feat(backend): ZImageStudioBackend with @spaces.GPU and mode dispatch
Unverified signature3b83775 -
feat(backend): zerogpu duration estimator (clamped 60-180s)
Unverified signature8894ed9 -
feat(modes): upscale handler (realesrgan + z-image-turbo refinement)
Unverified signature84d00fe -
feat(modes): controlnet handler (turbo + union 2.1 + preprocessor)
Unverified signature3762756 -
feat(modes): t2i handler (base + turbo) with transformer swap and lora ctx
Unverified signature8f6ce7f -
feat(upscale): realesrgan x4 wrapper with 0.5-resize bridge
Unverified signatureb855333 -
feat(preprocessors): canny/depth/pose via controlnet_aux (lazy imports)
Unverified signature036940b -
feat(lora): applied_lora ctx manager — validate, apply, revert on exit
Unverified signature8759971 -
feat(lora): safetensors header sniff + zimage key validation
Unverified signaturebc2513c -
feat(models): hf cache mirror (hardlink blobs, preserve snapshot symlinks, copy refs)
Unverified signature261639d -
feat(ui): labeled_label and model_selector_html helpers
Unverified signaturea7d0a44 -
feat(theme): css rules for param info tooltips and custom model selector
Unverified signature1a3b62d -
refactor(tooltips): rename copy.py → tooltips.py to avoid stdlib shadow
Unverified signatureThe original copy.py shadowed Python's stdlib copy module, requiring a fragile conftest hack to pre-import torch/pydantic/fastapi/gradio so they captured the real stdlib before sys.modules['copy'] was swapped. That coupling — every new dep with a lazy 'from copy import deepcopy' would silently break tests — is bad enough to avoid entirely. Rename to tooltips.py. conftest.py reverts to a simple sys.path insert. Spec and plan amendments updated.0592951 -
feat(copy): tooltip strings dict — one source of truth for param descriptions
Unverified signatureAlso fix conftest.py to pre-load torch/gradio/pydantic before swapping sys.modules["copy"] with the project module, preventing stdlib shadow breakage in tests that import those packages.232f8d6 -
feat(models): device autodetect, vram-limit helpers, model config registry
Unverified signature613dab3 -
fix(theme): preserve gradio's --font / --font-mono css vars
Unverified signatureThe _OnyxAmberBase override redirected self.font into font_str, which broke _get_theme_css emission of --font / --font-mono. Expose iterable access via .font_list / .font_mono_list instead, and add a regression assertion on the generated CSS.fd0ad15 -
feat(theme): onyx amber palette + gr.themes.Base + glow CSS
Unverified signature170a904 -
chore: project scaffolding (pyproject, requirements, license, claude.md, tests)
Unverified signature322b245