unsloth/studio/backend/models
Daniel Han-Chen c1f9aac510 Fix/adjust diffusion: round 8 async unloads + tighter handoffs for PR #5754
Round 8 reviewer surfaced event-loop stalls (blocking unload from
async routes), incomplete VRAM handoff coverage (is_active /
loading_models / is_export_active not checked), token leaks via
exception messages, /v1 exposure, and several fail-open paths.

Async / event-loop
  * routes/inference.py /images/unload, GGUF chat-load handoff,
    safetensors chat-load handoff: blocking DiffusionBackend.unload
    pushed onto asyncio.to_thread. unload takes _load_lock +
    _generate_lock and can block for the full duration of an
    in-flight load / generation, which was freezing the FastAPI
    worker, SSE stream, and hardware poller for minutes.
  * routes/export.py + routes/training.py: same to_thread wrap on
    diffusion unload during checkpoint / training start.

GPU-owner handoff completeness
  * core/inference/diffusion.py _release_chat_backend_for_diffusion:
    llama-server now also unloaded when is_active=True (mid-download
    / startup), not only when is_loaded; flushed in-flight
    safetensors loads from loading_models too.
  * core/inference/diffusion.py _release_other_gpu_owners_for_
    diffusion: export shutdown now also fires when
    is_export_active() returns True (checkpoint not yet assigned).

Security / scrubbing
  * core/inference/diffusion.py: load failure paths now scrub
    hf_token from both _last_error AND the raised RuntimeError
    message (the previous scrub only cleared frame locals).
    Falls back to a regex strip of hf_[A-Za-z0-9]{20,} to
    catch tokens that came in via huggingface_hub default caching.
  * routes/inference.py: image lifecycle endpoints moved from
    router to studio_router so they no longer answer under
    the /v1 OpenAI-compat prefix. Studio-only side effects
    (download multi-GB GGUFs, unload chat, etc.) should not be
    reachable via an OpenAI-compat client.
  * models/inference.py: control-char validator now also rejects
    tab. Some log sinks split fields on tab; allowing it left a
    log-injection surface.

Fail-closed delete guards
  * routes/models.py /delete-cached: llama.cpp and safetensors
    branches now fail closed with 503 when their status check
    raises (matches the diffusion-side guard added earlier).
  * routes/export.py: split the try/except around the training
    backend so import failure falls back to 'skip' (no
    core.training in this build) while a runtime failure of
    get_training_backend()/is_training_active() fails closed.
  * routes/models.py /delete-finetuned: diffusion guard now also
    compares against relative path candidates (Path.resolve() works
    on relative input). Previously a load with a relative repo_id
    bypassed the guard.

CUDA cleanup ordering
  * core/inference/diffusion.py: split _release() (drops local +
    gc.collect) from _drain_cuda_cache() (torch.cuda.empty_cache).
    Callers now drain AFTER nulling every reference so the
    allocator actually reclaims the freed slabs (previously
    empty_cache ran while caller still held a local, which left
    the cache pinned).

Generate response (P2 #16)
  * routes/inference.py: response uses status()['active_repo_id']
    instead of the UI-facing repo_id, so a queued /images/load
    promoting a pending model cannot mislabel the just-rendered
    image with the new model's identity.

Test wiring
  * tests/test_diffusion_routes.py: mount inf.studio_router on the
    test app so /images/* routes are reachable now that they live
    on the Studio-only router.
2026-05-25 02:48:00 +00:00
..
.gitkeep fix: restore models directory files deleted during restructure 2026-02-02 19:36:30 +00:00
__init__.py Studio: Dark theme refactor, right sidebar redesign, and chat UI polish (#5150) 2026-05-07 14:33:31 +04:00
auth.py studio: security and hardening pass (auth rate-limit, sandbox, path containment, schema validation, headers) (#5375) 2026-05-13 06:12:18 -07:00
data_recipe.py feat(studio): multi-file unstructured seed upload with better backend extraction (#4468) 2026-03-20 13:22:42 -07:00
datasets.py Final cleanup 2026-03-12 18:28:04 +00:00
export.py studio: security and hardening pass (auth rate-limit, sandbox, path containment, schema validation, headers) (#5375) 2026-05-13 06:12:18 -07:00
inference.py Fix/adjust diffusion: round 8 async unloads + tighter handoffs for PR #5754 2026-05-25 02:48:00 +00:00
models.py Studio: add folder browser modal for Custom Folders (#5035) 2026-04-15 08:04:33 -07:00
providers.py Studio: make API key optional for local providers (llama.cpp/vLLM/Ollama) (#5457) 2026-05-15 23:33:22 +04:00
responses.py Final cleanup 2026-03-12 18:28:04 +00:00
training.py studio: drop unused max_grad_value schema + route plumbing (#5424) 2026-05-14 05:43:58 -07:00
users.py fix: remove old comments (#4292) 2026-03-14 16:50:13 +04:00