- Port the studio from gradio.Server + custom index.html to gr.Workflow (89d839fdd6111bc4099555393ec91981c9560d44)
Co-authored-by: AK <akhaliq@users.noreply.huggingface.co>
[Admin] Add NCII prompt guard for image-conditioned generations (#4)
h3_lora.py now loads both turbo LoRAs and switches the folded set in
place per request (unfold old / fold new, one bf16 rounding, AoTI-safe).
The lightx checkpoint is PEFT-style against the diffusers tree (rank
128, alpha 8 -> fold scale 0.0625); the larry one keeps the reference
key conversion. The UI checkbox becomes a LoRA dropdown (larry / lightx
/ off) that suggests each design point in steps (6 / 4 / 28), and the
API gains a 'lora' string parameter — the legacy use_lora bool still
works.
Stage moves above the control deck on narrow screens, the deck becomes a
full-width scrolling panel with a sticky Generate button, the transport
bar wraps with the progress bar on its own row, the header collapses to
logo + status pill, dropzones/sliders get bigger touch targets, and
inputs use 16px to stop iOS focus zoom.
ckpt850 is the final checkpoint of the round and sharp at 4 steps per
the updated card, so the UI/API default drops 8 -> 4. Also adds
H3_LORA_STRENGTH (default 1.0), the card's sharpness/artifact dial,
applied at fold time and in the per-request toggle.
Default steps 6 -> 8 (better quality at the ckpt500 weights)
set_enabled now iterates _delta_targets directly. The frontend uses
client.submit with data+status events: the transport bar shows queue
position, then fills against the queue's ETA blended with the elapsed
timer, indeterminate while conditioning.
- H3_LORA default is now minimax_h3_turbo_4step_ckpt500.safetensors, the
model card's recommended default (newest, sharpest, non-EMA)
- the low-rank factors stay resident after the startup fold, so
h3_lora.set_enabled() folds/unfolds B@A in place per request; the AoTI
blocks read the same live storage. UI gets a 'Turbo LoRA' checkbox
(default on), the API a use_lora parameter (default true)
- default steps 4 -> 6 per the card's updated guidance (comfort zone is
6-8 at this checkpoint; 4 is softer)
Back to @gradio/client: ZeroGPU requires its HF iframe auth headers
The Server-mode docs are explicit that plain fetch/EventSource calls do
not forward the iframe auth headers ZeroGPU quota handling needs, so
bookings landed on the pod IP's shared quota. The earlier fn_index crash
was a stale tab from the pre-Server build. Keeps the tuple unwrap and
FileData path fallback.
Pass the caller's x-ip-token to the conditioner explicitly
LocalContext-based token forwarding is unreliable in Server mode, so the
conditioner's ZeroGPU booking fell back to this Space's pod IP and its
shared quota ('quota exceeded' despite the caller having quota). Extract
the header from the injected Request and hand it to a per-request
gradio_client, per the gradio ZeroGPU docs.
Call the v2 named-endpoint API directly, unwrap the single-Api-output tuple
- @gradio/client resolves a legacy fn_index that Server mode's internal
Blocks does not have (KeyError on queue join); the v2 API
(POST /gradio_api/call/v2/generate + SSE) addresses endpoints by name
- the tuple return is one 'Api' output, so it arrives nested one level
- whitelist OUTPUT_DIR for the /gradio_api/file= route
Resolve returned FileData without a url through /gradio_api/file= (Server mode can return only path)
Rename /config to /studio-config: Gradio's own client-discovery route lives at /config, and shadowing it broke @gradio/client ('Could not get API info')
Server mode: @app.api(name="generate") keeps the queue / ZeroGPU /
gradio_client contract (same name and signature), @app.get("/") serves a
self-contained index.html — dark studio layout with a control deck
(prompt, keyframe dropzones, canvas / duration / steps / seed), a preview
monitor, and a transport-style report bar, driven by the @gradio/client
JS package. /status and /config feed the readiness pill and the canvas
list. Keyframe cover-crop moved server-side into generate so API callers
get it too.
Fold the 4-step Turbo LoRA into the transformer, default to 4 steps
Downloads larryvrh/MiniMax-H3-Turbo-Lora at startup and merges W + B@A
into the bf16 weights, mirroring the diffusers key conversion (fused-QKV
thirds, SwiGLU gate/value swap, shared AdaLN row layout). Folded before
the AoTI package is patched in so compiled blocks carry the update.
H3_LORA / H3_LORA_REPO configure it, H3_LORA=off disables.
get_duration is refit on the measured AoTI per-step table, AoTI is opt-in behind H3_AOTI with a card and torch check before it loads, and the duration slider starts at 2 s again by lowering the pipeline's own floor.
Start the duration slider at the 5 s the model actually generates