Skip to content

feat(model-manager): identify UNet-only SDXL LoRAs (e.g. slider LoRAs)#9383

Open
Pfannkuchensack wants to merge 1 commit into
invoke-ai:mainfrom
Pfannkuchensack:feat/sdxl-unet-only-lora-detection
Open

feat(model-manager): identify UNet-only SDXL LoRAs (e.g. slider LoRAs)#9383
Pfannkuchensack wants to merge 1 commit into
invoke-ai:mainfrom
Pfannkuchensack:feat/sdxl-unet-only-lora-detection

Conversation

@Pfannkuchensack

Copy link
Copy Markdown
Collaborator

Summary

Self-attention-only SDXL LoRAs (e.g. Civitai "slider" LoRAs) patch only the UNet and contain no cross-attention (attn2) or text-encoder (lora_te*) keys. lora_token_vector_length() reads the base's context dimension from exactly those keys, so it returns None for such LoRAs and identification fails with "unrecognized token vector length None".

Add a structural fallback: SDXL's UNet has a deep transformer stack (up to 10 transformer blocks) in its lower-resolution attention blocks, so transformer_blocks indices reach >= 2, whereas SD1.x/SD2.x only ever have a single transformer block (index 0) per attention. _state_dict_looks_like_sdxl_unet_lora() detects SDXL from that structure alone. The regex is anchored on the UNet down/up/mid-block + attentions grouping so it won't false-positive on DiT LoRAs (FLUX/Qwen/Z-Image) that also use transformer_blocks.

The fallback only runs after the normal token-vector detection returns None, so existing LoRAs are unaffected. Wired into both the LyCORIS and Diffusers base configs.

Related Issues / Discussions

Closes #7709

QA Instructions

  1. Grab a UNet-only SDXL "slider" LoRA whose keys are all lora_unet_..._attn1_... (no attn2/lora_te*), e.g. Dramatic Lighting Slider.
  2. On main, installing/scanning it fails to identify with "unrecognized token vector length None".
  3. On this branch, install it via the model manager and confirm it is identified as LoRA / StableDiffusionXL / LyCORIS.
  4. Use the LoRA in an SDXL generation and confirm it applies correctly.
  5. Regression: install a normal SDXL LoRA (with cross-attention + text-encoder keys) and an SD1.5 LoRA and confirm their bases are still detected correctly (unchanged path).

Automated coverage: tests/backend/model_manager/configs/test_sdxl_slider_lora_identification.py — unit tests for the structural heuristic (positive: self-attention-only slider + diffusers dot-format; negative: SD1.5 shallow stack, Qwen, FLUX, empty/non-string keys) plus end-to-end identification through the LyCORIS configs (SDXL matches, SD1/SD2 reject).

uv run --extra cuda --extra test python -m pytest tests/backend/model_manager/configs/ tests/backend/patches/lora_conversions/ --no-cov -q

Merge Plan

Standard merge — no DB schema or redux changes.

Checklist

  • The PR has a short but descriptive title, suitable for a changelog
  • Tests added / updated (if applicable)
  • ❗Changes to a redux slice have a corresponding migration
  • Documentation added / updated (if applicable)
  • Updated What's New copy (if doing a release after this PR)

Self-attention-only SDXL LoRAs (e.g. Civitai "slider" LoRAs) patch only the
UNet and contain no cross-attention (attn2) or text-encoder (lora_te*) keys.
lora_token_vector_length() reads the base's context dimension from exactly
those keys, so it returns None for such LoRAs and identification fails with
"unrecognized token vector length None".

Add a structural fallback: SDXL's UNet has a deep transformer stack (up to 10
transformer blocks) in its lower-resolution attention blocks, so
transformer_blocks indices reach >= 2, whereas SD1.x/SD2.x only ever have a
single transformer block (index 0) per attention. _state_dict_looks_like_sdxl_unet_lora()
detects SDXL from that structure alone. The regex is anchored on the UNet
down/up/mid-block + attentions grouping so it won't false-positive on DiT
LoRAs (FLUX/Qwen/Z-Image) that also use transformer_blocks.

The fallback only runs after the normal token-vector detection returns None,
so existing LoRAs are unaffected. Wired into both the LyCORIS and Diffusers
base configs.
@github-actions github-actions Bot added python PRs that change python files backend PRs that change backend files python-tests PRs that change python tests labels Jul 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend PRs that change backend files python PRs that change python files python-tests PRs that change python tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[enhancement]: Unable to import LORA

1 participant