Commit graph

6,276 commits

Author SHA1 Message Date
Daniel Han
e3d8e5ef0f Merge remote-tracking branch 'origin/diffusion-lora-ux' into diffusion-lora-training 2026-07-02 04:34:48 +00:00
Daniel Han
9ca4b9ee3a Merge remote-tracking branch 'origin/diffusion-sdxl' into diffusion-lora-ux 2026-07-02 04:34:47 +00:00
Daniel Han
939ba33b1d Merge branch 'diffusion-sdxl' of https://github.com/unslothai/unsloth into diffusion-sdxl 2026-07-02 04:34:21 +00:00
Daniel Han
5987caf940 Align the VAE to the denoiser's first FLOATING dtype, not its first parameter
A GGUF-quantized transformer's leading parameters are packed uint8 storage,
so reading next(parameters()).dtype handed nn.Module.to() an integer dtype
and every image-conditioned generation on a GGUF model (Qwen-Image-Edit)
failed with a 500. Probe the parameters for the first floating dtype, treat
an all-integer module as a no-op, and also catch TypeError so an unexpected
dtype can never break generation. Regression test included.
2026-07-02 04:34:21 +00:00
Daniel Han
3e4469bb9f Merge remote-tracking branch 'origin/diffusion-lora-ux' into diffusion-lora-training 2026-07-02 04:01:44 +00:00
Daniel Han
61b12676b9 Merge remote-tracking branch 'origin/diffusion-sdxl' into diffusion-lora-ux 2026-07-02 04:01:42 +00:00
pre-commit-ci[bot]
57c6e11c36 [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2026-07-02 04:01:09 +00:00
Daniel Han
9e3aa584c6 Merge remote-tracking branch 'origin/diffusion-controlnet' into diffusion-sdxl
# Conflicts:
#	studio/backend/core/inference/diffusion.py
2026-07-02 04:00:09 +00:00
Daniel Han
23b2c13c75 Merge remote-tracking branch 'origin/diffusion-lora' into diffusion-controlnet
# Conflicts:
#	studio/backend/core/inference/diffusion.py
2026-07-02 03:57:51 +00:00
Daniel Han
89ff99475d Merge remote-tracking branch 'origin/diffusion-image-workflows' into diffusion-lora 2026-07-02 03:56:32 +00:00
Daniel Han
c58856709a Merge remote-tracking branch 'origin/image-generation' into diffusion-image-workflows
# Conflicts:
#	studio/backend/core/inference/diffusion.py
2026-07-02 03:55:35 +00:00
Daniel Han
a4277a01e4 Honor memory_mode over legacy cpu_offload and prefetch dense-quant transformer shards
plan_diffusion_memory only applies the legacy cpu_offload override when no
memory_mode was supplied, matching the documented API contract that
memory_mode overrides cpu_offload when set; an explicit fast request now
stays resident even if the old flag is also enabled.

The transformer-quant dense path fetches the base repo's transformer/
shards inside the locked finalize phase, where unload and cancellation
cannot preempt the multi-GB download. The load worker now widens the
preemptible prefetch to include those shards when that path can actually
run: quant requested and supported for the device, scheme resolvable, and
no pre-quantized checkpoint shortcutting the dense build.
2026-07-02 03:51:53 +00:00
Daniel Han
370544c8ee Merge remote-tracking branch 'origin/diffusion-lora-ux' into diffusion-lora-training 2026-07-02 03:38:52 +00:00
Daniel Han
8af8db0b8b Merge remote-tracking branch 'origin/diffusion-sdxl' into diffusion-lora-ux 2026-07-02 03:38:50 +00:00
Daniel Han
4dbd3e538d Merge remote-tracking branch 'origin/diffusion-controlnet' into diffusion-sdxl 2026-07-02 03:38:49 +00:00
Daniel Han
d06b68c83a Merge remote-tracking branch 'origin/diffusion-lora' into diffusion-controlnet 2026-07-02 03:38:46 +00:00
Daniel Han
ecb797ab42 Merge remote-tracking branch 'origin/diffusion-image-workflows' into diffusion-lora 2026-07-02 03:36:58 +00:00
Daniel Han
c800e89206 Merge remote-tracking branch 'origin/image-generation' into diffusion-image-workflows
# Conflicts:
#	studio/backend/core/inference/diffusion.py
#	studio/frontend/src/features/images/images-page.tsx
2026-07-02 03:36:50 +00:00
pre-commit-ci[bot]
dd792c6312 [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2026-07-02 03:30:16 +00:00
Daniel Han
a9e5a80654 Address the round of Codex review findings on the merged diffusion phases
Memory planning and dense-quant path: size a local diffusers base's
resident companions from its on-disk VAE and text-encoder weights instead
of folding them to zero, feed the distilled variant hint into the runtime
headroom estimate so turbo and schnell models are not over-reserved, place
group-offload companions resident before attaching the transformer hooks
so a failed placement falls back to whole-module offload instead of
crashing, and bail out of the dense transformer download before it starts
when the requested quant scheme is unsupported so the load falls back to
GGUF cleanly.

sd.cpp stack: scrub the native path lease secret from sd-cli child env,
redact native load-progress errors, forward the resolved accelerator when
auto-installing a forced-native binary, release stale diffusion GPU
ownership on CPU-native loads, and remove the sd.cpp install tree on
uninstall.

Prequant and scripts: reject prequant artifacts missing base_model_id
when a base is requested, expanduser before checkpoint existence checks,
record and validate the int8 exclusion filter and fp8 fast-accum in
checkpoint metadata, make verify_prequant_backend allowlist its local
checkpoint and fail on missing or bad LPIPS and on load-peak regressions,
average only finite PSNR values in diffusion_quality, and reset the
process-wide attention backend between perf probe variants.

API and UI: normalize attention_backend casing before Literal validation,
close hidden popovers when leaving the Images page, and clear the stale
quant label when loading a direct local GGUF file.
2026-07-02 03:29:18 +00:00
Daniel Han
b33418e14a Merge remote-tracking branch 'origin/diffusion-image-workflows' into diffusion-lora 2026-07-02 02:39:00 +00:00
Daniel Han
2aa379d9cc Merge remote-tracking branch 'origin/image-generation' into diffusion-image-workflows 2026-07-02 02:37:52 +00:00
Daniel Han
22f49b5ac2 Merge remote-tracking branch 'origin/main' into image-generation
# Conflicts:
#	scripts/scan_packages_baseline.json
2026-07-02 02:36:18 +00:00
Daniel Han
2ce0bdbdf6 Merge remote-tracking branch 'origin/diffusion-lora-ux' into diffusion-lora-training 2026-07-02 02:31:18 +00:00
Daniel Han
8c5cdeb331 Merge remote-tracking branch 'origin/diffusion-sdxl' into diffusion-lora-ux 2026-07-02 02:30:23 +00:00
Daniel Han
e6bf4c4cd6 Merge remote-tracking branch 'origin/diffusion-controlnet' into diffusion-sdxl 2026-07-02 02:28:33 +00:00
Daniel Han
c3196cb8bd Merge remote-tracking branch 'origin/diffusion-lora' into diffusion-controlnet 2026-07-02 02:27:40 +00:00
Daniel Han
b9b80a4c83 Merge remote-tracking branch 'origin/diffusion-image-workflows' into diffusion-lora
# Conflicts:
#	studio/backend/core/inference/diffusion.py
2026-07-02 02:26:46 +00:00
Daniel Han
a4d02dda73 Merge remote-tracking branch 'origin/image-generation' into diffusion-image-workflows
# Conflicts:
#	studio/backend/core/inference/diffusion.py
#	studio/frontend/src/features/images/images-page.tsx
2026-07-02 02:25:16 +00:00
Daniel Han
a8f7b3de57 Address review findings on the image-generation PR
Backend:
- Sanitize a blank hf_token to None in begin_load and load_pipeline, so the
  default empty Studio token loads anonymously instead of 401ing as an explicit
  empty credential.
- Free the ACTIVE diffusion engine before LLM training and in the delete-cached
  guard: on a native (sd_cpp) selection the diffusers singleton reports
  unloaded, so training could start against a live sd-cli generation and
  delete-cached could remove a GGUF the native engine is using. Both now go
  through diffusion_engine_router.get_active_diffusion_engine().
- Refuse delete-cached while a background image load is downloading the repo
  (or its companion base): status().loaded is False in that window, but the
  delete would yank blobs from under the in-flight assembly. Both engines
  expose the in-flight ids via a new loading_repo_ids().
- Cap request seeds at 2**53-1: seeds round-trip through JSON gallery recipes,
  where JavaScript rounds larger integers, so a restored recipe generated a
  different image. Random seeds were already masked to this range.
- Add the task field to CachedModelRepo: the handler sets it for cached
  diffusers image repos but response_model silently dropped it, letting
  image-only repos pass the chat picker's task gate.

Frontend:
- Offset sequential run seeds by the batch size: the native engine seeds image
  j of a run at seed+j, so a +1 run offset regenerated the previous run's
  batch-mates.
- Revert the optimistic quant selection when a load fails to start.
- Stop disabling the Images page on chat-only hosts: the native sd.cpp engine
  exists exactly for the no-GPU route.
2026-07-02 02:17:57 +00:00
Daniel Han
7f59cd6c1e Review pass over the merged diffusion phases: seven correctness fixes
Re-reviewed each merged phase PR against this branch's tip and fixed what is
still real:

- A superseded background load no longer cancels the current model's in-flight
  generation: the load-token check now runs BEFORE the cancel signal, with a
  re-check under the generate lock (Phase 1 review).
- enable_model_cpu_offload / enable_sequential_cpu_offload now forward the
  resolved target device; diffusers defaults to CUDA, which broke offloaded
  loads on non-CUDA accelerators such as Intel XPU (Phase 2 review).
- build_sd_cpp_command rejects a None prompt (str(None) previously slipped
  into argv as the literal "None") and a mask without an init image, which
  is an invalid sd-cli inpaint invocation (Phase 4/6 review).
- The dense-quant OOM fallback drops the caught exception before
  clear_gpu_cache(): the traceback pinned the partially built dense
  transformer, so the VRAM this cleanup exists to reclaim stayed allocated
  through the GGUF rebuild (Phase 8 review).
- Pre-quantized transformers (built via from_config) are eval()'d to match
  the from_pretrained paths, so train-mode layers cannot make prequant
  inference nondeterministic (Phase 9 review).
- FBCache state is reset before each generation when a step cache is engaged:
  diffusers never clears the stateful first-block residuals on the resident
  transformer, so a resolution or batch change on the next request hit a
  shape mismatch, and an unchanged request could reuse stale residuals
  (Phase 12 review).

Each fix carries a regression test; the full diffusion battery passes.
2026-07-02 02:06:08 +00:00
Daniel Han
49ea887312 CI: baseline the fastapi/gguf scan findings for the studio dependency set
The pip scan-packages job keys its baseline on the matched-code hash (main's
scanner). This branch's dependency set resolves a newer fastapi (its routing
while-True loop hashes differently than the baselined one) and adds gguf,
whose HF_TOKEN-authenticated download helper trips the env+network check.
Both reviewed benign: the fastapi hit is its own websocket routing loop and
the gguf hit is the official package's Hub download path. Sync the scanner
and baseline from main and add the two reviewed entries.
2026-07-02 02:04:28 +00:00
Daniel Han
e0db8f4612 Merge remote-tracking branch 'origin/diffusion-lora-ux' into diffusion-lora-training 2026-07-02 01:23:23 +00:00
Daniel Han
76b5ee354d Merge diffusion-sdxl into diffusion-lora-ux; keep options-only LoRA catch
The catalog-refresh .catch from the lower branch clears the selected adapters
too, which is right for its catalog-only picker but wrong here: this picker
holds free-text HF repo ids that are valid without being in the catalog, so a
transient refresh failure must not wipe them. Family swaps still clear the
selection and hidden LoRAs are never sent.
2026-07-02 01:23:15 +00:00
Daniel Han
2ac1e77dfc Merge remote-tracking branch 'origin/diffusion-sdxl' into diffusion-lora-ux 2026-07-02 01:21:52 +00:00
Daniel Han
74c3aa8a6d Merge remote-tracking branch 'origin/diffusion-controlnet' into diffusion-sdxl
# Conflicts:
#	studio/backend/core/inference/diffusion.py
2026-07-02 01:21:41 +00:00
Daniel Han
582e2dcf39 Merge remote-tracking branch 'origin/diffusion-lora' into diffusion-controlnet 2026-07-02 01:18:40 +00:00
Daniel Han
bb78742718 Merge remote-tracking branch 'origin/diffusion-image-workflows' into diffusion-lora 2026-07-02 01:17:02 +00:00
pre-commit-ci[bot]
dcf6cf5117 [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2026-07-02 01:14:22 +00:00
Daniel Han
e05c9cc947 Images: preserve restored LoRAs through model load and never send hidden LoRAs
- The LoRA effect cleared the selection on every load->capable transition, which
  wiped adapters restored from a gallery recipe before the model finished loading.
  Track the previously-loaded family in a ref and clear only on a real family swap;
  keep the selection on the initial load and on unload.
- Gate the generate payload's loras on loraCapable so a restored selection that is
  hidden (loaded model does not support LoRA) is never sent to the backend.
2026-07-02 01:13:39 +00:00
Daniel Han
a4fb348f9f SDXL: reject GGUF up front, skip unused base weights, drop refiner, and harden helpers
Addresses review findings on the SDXL family:
- Reject a GGUF load for single_file_is_pipeline families (SDXL) in validate_load_request,
  before the route evicts the current model; SDXL has no transformer-only GGUF variant.
- Skip base-repo weight files when a whole-pipeline single file is loaded: from_single_file
  (config=base) needs only the base config/tokenizer/scheduler, so a local .safetensors no
  longer triggers a multi-GB base download.
- Remove the SDXL refiner from the non-GGUF trust allowlist: it is an img2img-only pipeline
  but this backend loads every sdxl repo as the base txt2img pipeline.
- Normalize a blank/whitespace hf_token to None once in load_pipeline so every load branch
  degrades to anonymous instead of erroring on a malformed token.
- Read the denoiser dtype from a parameter (compile-wrapped modules may lack .dtype) and
  access state.family.denoiser_attr directly.

Adds/updates regression tests for the trust allowlist, GGUF rejection, and base-config filter.
2026-07-02 01:13:18 +00:00
Daniel Han
94d74e8bbe Diffusion: guard trust check against OSError and validate conditioning inputs
- _is_trusted_diffusion_repo: wrap Path.exists() so a repo id with invalid
  characters (or a bare owner/name id) can't raise OSError; treat any failure as
  not-a-local-path and fall through to the unsloth/ allowlist. validate_load_request
  still raises the clear FileNotFoundError for a genuinely missing local pick.
- generate(): reject mask_image / upscale / reference_images supplied without an
  input image, and reject reference_images on a family that does not support
  reference conditioning, instead of silently degrading to txt2img / img2img.
2026-07-02 01:13:04 +00:00
pre-commit-ci[bot]
1d4461b23b [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2026-07-02 01:12:15 +00:00
Daniel Han
50a313f93d Diffusion LoRA: harden resolution, native tag precedence, and diffusers teardown
Address review findings on the LoRA path:
- resolve_one: normalise a blank/whitespace hf_token to None (anonymous access)
  and reject a client-supplied weight file with traversal / absolute path.
- resolve_specs: convert FileNotFoundError from an unknown/stale id to ValueError
  so the route returns 400 instead of a generic 500.
- _scan_local: disambiguate local adapters that share a stem (foo.safetensors vs
  foo.gguf) so each is uniquely addressable.
- inject_prompt_tags: the backend-validated weight now wins over a user-typed
  <lora:ALIAS:...> for a selected adapter; unselected user tags are left alone.
- diffusers _apply_loras: reject a .gguf adapter with a clear error before touching
  the pipe (diffusers loads safetensors only).
- _unload_locked: drop the explicit unload_lora_weights() on teardown; the pipe is
  dropped wholesale (freeing adapters), so the previous call could race an in-flight
  denoise on the same pipe.
- Images page: use a stable LoRA key and clear the selection (not just the options)
  when the catalog refresh fails.
2026-07-02 01:11:07 +00:00
pre-commit-ci[bot]
c898473620 [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2026-07-02 01:08:47 +00:00
Daniel Han
cdfc6f0f56 ControlNet: address review findings on the diffusers path
- resolve_controlnet enforces catalog family compatibility so a direct API call
  cannot load a ControlNet built for another family through the wrong pipeline.
- Unknown ControlNet ids now surface as a 400 (call site maps FileNotFoundError
  to ValueError) instead of a generic 500.
- strength 0 disables ControlNet entirely, so a no-op selection never pays the
  download / VRAM cost; the control image is decoded and validated BEFORE the
  ControlNet is resolved or built, so a malformed image fails fast for the same reason.
- ControlNet loads use the base compute dtype (state.dtype is a display string,
  not a torch.dtype, so it silently fell back to float32) and honor the base
  offload policy via group offloading instead of forcing the module resident.
- Empty/malformed HF token coerced to anonymous access.
- Flux Union ControlNet control_mode mapped from the selected control type.
- resolve_controlnet drops the unused hf_token/cancel_event params.
- ControlNetSpec validates guidance_start <= guidance_end (clean 422).
- Images UI ControlNet Select shows its placeholder when nothing is selected.

Adds regression tests for family enforcement and the union control-mode map.
2026-07-02 01:08:02 +00:00
pre-commit-ci[bot]
f28be14639 [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2026-07-02 01:07:40 +00:00
Daniel Han
af638f98c3 Diffusion LoRA training: harden config handling, cancellation, SDXL conditioning, and safety
Addresses review findings on the SDXL LoRA trainer:
- Gate the base model with the same trust check as inference (unsloth/*, allowlisted
  official bases, or a local path) before from_pretrained, so an untrusted remote repo
  is never fetched or deserialised.
- Check the stop signal before the (slow) model load, not only between steps, so a
  cancel during download is honoured; a stop may carry save=False to cancel without
  leaving a partial adapter.
- Per-sample SDXL add_time_ids from the actual crop (original size + crop offset, with
  the offset mirrored on horizontal flip) instead of a fixed uncropped-square tensor.
- Apply EXIF orientation before resize/crop so rotated photos train upright.
- Skip gradient clipping when max_grad_norm <= 0 (the Studio 'disable' value) instead
  of scaling every gradient to zero.
- Coerce Studio config strings/blanks: learning_rate string to float, blank hf_token to
  anonymous, gradient_checkpointing 'none'/'true'/'unsloth' to bool; reject a zero/negative
  lora_alpha or learning_rate.
- Alias the generic Studio training payload keys (model_name/max_steps/batch_size/lora_r/
  lr_scheduler_type/random_seed) onto the diffusion field names.
- Mirror the trained adapter into loras/diffusion so the Images LoRA picker discovers it.
- Report worker exceptions in both message and error keys so the failure is not lost.

Adds regression tests for the config coercion/validation and aliasing.
2026-07-02 01:06:42 +00:00
Daniel Han
e77ae6fecf Merge remote-tracking branch 'origin/diffusion-lora-ux' into diffusion-lora-training 2026-07-01 23:57:39 +00:00
Daniel Han
3c37299180 Merge remote-tracking branch 'origin/diffusion-sdxl' into diffusion-lora-ux 2026-07-01 23:57:26 +00:00