Merge remote-tracking branch 'origin/diffusion-lora' into diffusion-controlnet
This commit is contained in:
commit
582e2dcf39
5 changed files with 205 additions and 39 deletions
|
|
@ -191,9 +191,18 @@ def _is_trusted_diffusion_repo(repo_id: str) -> bool:
|
|||
on an arbitrary repo, which fetches and deserialises third-party weights. So the
|
||||
non-GGUF paths are gated to the ``unsloth/*`` org (the curated safetensors models) and
|
||||
to local paths the user explicitly pointed at (already on their disk). The GGUF path
|
||||
is unchanged and stays open to any repo, as before."""
|
||||
if Path(repo_id).expanduser().exists():
|
||||
return True
|
||||
is unchanged and stays open to any repo, as before.
|
||||
|
||||
A bare ``owner/name`` HF id is never a real filesystem path, and an id with invalid
|
||||
characters makes ``Path.exists()`` raise OSError; treat any such failure as "not a
|
||||
local path" so the trust decision falls through to the unsloth/ check (the loader's
|
||||
validate_load_request raises the clear FileNotFoundError for a genuinely missing
|
||||
local pick)."""
|
||||
try:
|
||||
if Path(repo_id).expanduser().exists():
|
||||
return True
|
||||
except OSError:
|
||||
pass
|
||||
return repo_id.strip().lower().startswith("unsloth/")
|
||||
|
||||
|
||||
|
|
@ -1313,6 +1322,15 @@ class DiffusionBackend:
|
|||
)
|
||||
|
||||
resolved = diffusion_lora.resolve_specs(specs, hf_token = state.hf_token, cancel_event = cancel)
|
||||
# The shared catalog scans both .safetensors and .gguf, but diffusers'
|
||||
# load_lora_weights only takes safetensors; a .gguf adapter would otherwise fail
|
||||
# deep in generation. Reject it here as a clean 400 before touching the pipe.
|
||||
bad = [r.id for r in resolved if r.fmt != "safetensors"]
|
||||
if bad:
|
||||
raise ValueError(
|
||||
"GGUF LoRA adapters are not supported on the diffusers engine "
|
||||
f"({', '.join(bad)}); use a .safetensors adapter, or the native engine."
|
||||
)
|
||||
# Unique adapter names (diffusers requires distinct names; sanitized stems can collide).
|
||||
uniq: list[tuple[str, str, float]] = []
|
||||
seen: set[str] = set()
|
||||
|
|
@ -1422,6 +1440,22 @@ class DiffusionBackend:
|
|||
control_pil = None
|
||||
cn_scale = cn_gstart = cn_gend = cn_mode = None
|
||||
ref_extra: list = []
|
||||
# Validate parameter dependencies up front: mask / upscale / reference all
|
||||
# need an input image, and reference conditioning needs a family that
|
||||
# supports it. Without these guards an unsupported combination would be
|
||||
# silently ignored and quietly fall back to txt2img / img2img.
|
||||
if init_image is None:
|
||||
if mask_image is not None:
|
||||
raise ValueError("mask_image requires an input image (init_image).")
|
||||
if upscale is not None and upscale > 1.0:
|
||||
raise ValueError("upscale requires an input image (init_image).")
|
||||
if reference_images:
|
||||
raise ValueError("reference_images require an input image (init_image).")
|
||||
if reference_images and not getattr(state.family, "reference", False):
|
||||
raise ValueError(
|
||||
f"Reference images are not supported for the '{state.family.name}' "
|
||||
"model family."
|
||||
)
|
||||
if getattr(state.family, "edit", False):
|
||||
# Instruction editing: the loaded pipe is the edit pipeline. It always
|
||||
# needs an input image; the prompt is the edit instruction. No mask, no
|
||||
|
|
@ -1721,13 +1755,13 @@ class DiffusionBackend:
|
|||
if state.eager_patched:
|
||||
uninstall_patches()
|
||||
uninstall_arch_patches()
|
||||
# Drop any LoRA adapters applied to the pipe so a later reference-path load is
|
||||
# bit-identical and the freed transformer carries no adapter layers. Idempotent.
|
||||
try:
|
||||
if getattr(state.pipe, "_unsloth_loras", ()):
|
||||
state.pipe.unload_lora_weights()
|
||||
except Exception: # noqa: BLE001 -- best-effort cleanup on teardown
|
||||
pass
|
||||
# NOTE: we deliberately do NOT call state.pipe.unload_lora_weights() here. unload()
|
||||
# sets the cancel event but does not take _generate_lock, so a LoRA-backed denoise
|
||||
# can still be running on this same pipe for up to one more callback; mutating its
|
||||
# adapter layers now would race that in-flight generation. The whole pipe is dropped
|
||||
# just below (self._state = None; del state; clear_gpu_cache()), so the adapter
|
||||
# tensors are freed with it -- no explicit unload is needed for memory or for a
|
||||
# later load (which builds a fresh pipe).
|
||||
# Drop the workflow pipes built around this load's modules so they don't pin the
|
||||
# freed pipeline (they only re-wire its components, but holding the wrappers
|
||||
# would keep the modules alive past unload).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue