Baking a lora into a quantized weight requantizes it, and on low-bit
formats round-to-nearest erases sub-step deltas (uint4 retains roughly
2/group_size of the signal). Plain lora deltas now ride the sdnq svd
side-channel: factors append to svd_up/svd_down with the down factor
hadamard-rotated, applied by the dequantizer at full precision in every
forward mode. Apply and remove are exact and take no weight backup.
- non-factorable families (dora, lokr, loha, oft, cp mid, dense bias)
fall back to requantize with a per-pass summary warning
- native fuse now honors the quantized-model guard; fuse requantized in
place on every network swap and accumulated drift
- layers that fell back on a mixed set restore from backup before
re-entering the factor path; untargeted quantized layers are no
longer flagged
- test/test-sdnq-lora-factors.py pins the erasure law, factor-path
exactness, memory accounting and set transitions
NATIVE_DISPATCH is the documented registration surface for per-arch
native loaders and is read cross-module by the fidelity analyzer, so
the private marker signaled the opposite of its role and enforced
nothing.
Cached networks are shared objects, and network_load overwrote their
multipliers before network_deactivate ran, so fuse-mode removal recomputed
the subtraction delta with the new values: a strength edit froze at its
first applied value and a later removal left residue in the model weights.
network_load now stages the values on the net and network_activate promotes
them, so the removal pass always subtracts the delta that was applied.
Backup mode restores from stored tensors and was unaffected.
network_load seeded net.dyn_dim with extra_networks_default_multiplier
when no dyn_dims list was passed, so a float multiplier landed where
consumers expect a rank and slice with it. The prompt path always builds
a per-network list of ints or None, which is why the crash never fired
from the UI; any direct network_load caller hits it in both
rebuild_conventional and the sdnq factor path.
The native loader entry log repeated the name and full file path already
printed one line earlier by network_load. Remove it and fold cache-hit
status into the network_load announce line, so a native load emits one
starting line plus the result line instead of three with a duplicated
path.
Removing all loras never called set_adapters, so peft adapters stayed
active until model reload. Removal now uses disable_lora, which keeps
modules intact; unload_lora_weights would detach balanced offload hooks.
Load calls enable_lora after set_adapters since peft set_adapter does
not clear the disabled flag. Removal of fused diffusers loras remains
unhandled.
Network activation ran after prompt encoding, so text encoder lora
weights never affected embeds on the first generation and the stale
result was then served from the embed cache. The trailing unfiltered
activate in network_load also overrode the te exclude filter, so the
lora_apply_te setting was never honored.
- parse and activate networks in process_base before pipeline args are built
- activate_filtered gates text encoder components on per-request or global
lora_apply_te; used by base, hires, detailer and faceid call sites
- network_load accepts activate=False for callers that run their own
deactivate/activate sequence with include/exclude
- network_activate walks excluded components in restore-only mode so a
filtered text encoder reverts to backup instead of keeping stale deltas
- loaded_loras cache is single-entry since per-filter entries go stale when
the setting toggles
- prompt embed cache key includes the effective lora_apply_te value
Krea 2 is a 12.9B single-stream flow-matching DiT trained from scratch, using a Qwen3-VL-4B text encoder and the Qwen-Image VAE. The transformer is vendored as a diffusers ModelMixin whose module tree mirrors the checkpoint, so weights load with no key conversion; the pipeline ports the reference encode, flow-matching denoise, and VAE decode. The text encoder is shared at runtime via the existing dedup registry, so Base and Turbo reuse one Qwen3-VL-4B copy.
Covers text-to-image, image-to-image, native LoRA, and the single-file UNET override. Also completes SD.Next's partial Qwen-Image VAE support (5D decode input and TAESD preview mapping) that K2 shares.
NetworkOnDisk.fullname stripped only "/" from the post-lora_dir slice,
leaving a leading "\" on Windows. Every prompt typing the file's
natural dot-form name missed both registered aliases. On Linux,
dot-form lookup already missed when the file lived in any subfolder
because only the subfolder-prefixed form was registered.
- network.py: lstrip both separators and normalize backslashes to
forward slashes so fullname has one canonical shape per OS.
- lora_load.py: register a bare-basename-with-dots alias so typing
<lora:my.lora:1> resolves regardless of subfolder placement.
setdefault preserves explicit primary registrations on cross-subfolder
basename collisions.
Existing prompts using the legacy dots-to-underscores form continue
to resolve via entry.name unchanged.
Five if-blocks in lora_load.load_safetensors reduce to one lookup in
_NATIVE_DISPATCH, a string -> module-path map keyed by shared.sd_model_type.
Each entry's module exposes try_load(name, network_on_disk, lora_scale).
flux2 / zimage / chroma / ernie use the umbrella that binds native_loader's
generics via try_load_chain. Anima keeps its own try_load (aliased to
try_load_lora) since its multi-component routing doesn't fit the shared
suffix-table model.
New native archs land by adding one entry to the dict and shipping a
try_load.
Move the family-iteration loop into pipelines/flux/flux2_lora.try_load
so the f2 branch in lora_load.load_safetensors becomes a one-line call.
Per-family try_load_* entry points stay public for direct testing.
Addresses review feedback on PR #4841.
get_method now returns (method, reason). The reason distinguishes
user opt-in (lora_force_diffusers), class-forced, hash-forced, and
arch-unsupported routes from the default native path; surfaced in
the info-level "Network load: type=LoRA load=<method>(<reason>)"
line so users can tell why a given load took a particular path.
Adds 'f2' to allow_native and dispatches all eight native loaders
through load_safetensors. lora_force_diffusers continues to route
through lora_diffusers.load_diffusers as the explicit PEFT escape
hatch.
Add a per-model native LoRA path for Chroma that handles both PEFT-style
(diffusion_model.<dotted>.lora_A.weight, no alpha) and kohya-flat
(lora_unet_<flat> with .alpha) layouts, plus LoKR/LoHA/OFT/DoRA.
Resolves issue #4169 (ostris ai-toolkit Chroma LoRAs failed to load).
- new pipelines/chroma/chroma_lora.py with try_load_lora/lokr/loha/oft
- fused-QKV expansion: 3-way equal for img/txt qkv, 4-way unequal
[3072, 3072, 3072, 12288] for single linear1 (Q+K+V+proj_mlp)
- NetworkModuleLokrSliceChunk for unequal-row LoKR slicing
- path rewrite from Flux-source to ChromaTransformer2DModel naming
- lora_load.py: dispatch chroma to the native loader and narrow the
kohya-Flux convert gate to f1 only
Adds pipelines/ernie/ernie_lora.py with try_load_lora/lokr/loha/oft
entry points modeled on the z-image native loader, wires it into
lora_load.load_safetensors, and adds 'ernieimage' to allow_native.
ERNIE attention is not fused (separate to_q/to_k/to_v/to_out.0), so
the loader skips the qkv-split machinery the z-image loader needs and
supports all four families uniformly. Recognized prefixes are
diffusion_model., transformer., and lora_unet_; PEFT lora_A/lora_B
keys are normalized to lora_down/lora_up. Verified against PEFT, LoKR,
and Kohya/AIT files in the wild with zero unmapped or shape-mismatched
modules.
applied_layers is cleared and re-populated on every network_activate call.
With lora_apply_te=True the second activate (TE-only pass) finds all
modules already at the target state and skips them all, leaving
applied_layers empty and breaking the restore trigger on the next gen.
native_active is set from loaded_networks at the end of activate, so it
survives idempotent re-runs and only flips false after the restore call
clears loaded_networks.
Flux2/Klein loads LoRAs as native modules through the diffusers method
path. network_activate() was only called when new native modules existed,
so removing a LoRA from the prompt left backed-up weights unrestored.
Check applied_layers to detect previously active native modules and
trigger network_activate() for the restore path.
Dispatch anima loras through a dedicated native loader covering kohya,
bfl/ai-toolkit, and hybrid (bfl with alpha plus qwen3 text encoder)
formats. Cosmos 2.0 path rename is mirrored from diffusers in flat
(underscore) form so rewritten paths match network_layer_mapping keys
without further conversion.
Split model_type from cosmos to anima so a future base-cosmos2 lora
path stays separable. Update flow_models, taesd supported list, and the
taesd wanvideo bucket so samplers and preview decoding keep working
after the split.
Extend assign_network_names_to_compvis_modules to walk pipe.llm_adapter
under the lora_llm_adapter_ prefix, and add llm_adapter to
default_components so activate and deactivate include it for anima
models while staying inert elsewhere via the existing getattr guards.
Add three adapter families to the z-image native loader and chain them
with the existing lora path through load_safetensors. Mixed-family
files (for example gta6_amateur_photography_zimagebase_v2.safetensors,
which carries lora and lokr groups in the same file) now load
completely instead of having one family silently dropped.
Shared helpers in pipelines/z_image/zimage_lora.py parse keys by
suffix list, rename legacy attention.out and attention.wo to
attention.to_out.0, and split fused attention.qkv into to_q/k/v. For
lora the split chunks the up weight along dim 0. For lokr the split
emits three NetworkModuleLokrChunk entries that share the tensors and
slice the kronecker product at apply time.
Fused attention.qkv for loha and oft is skipped with a warning. No
NetworkModuleHadaChunk exists, oft rotations are tied to out_features
and cannot be cleanly split across q/k/v, and no real z-image adapter
in that layout exists today.
load_safetensors for zimage chains try_load_lora, try_load_lokr,
try_load_loha and try_load_oft and merges their module dicts into a
single Network so mixed files load every module.
Add zimage to allow_native so lora_force_diffusers picks between
native and diffusers. Before this, zimage always took the diffusers
path regardless of the setting.
pipelines/z_image/zimage_lora.py reads the safetensors and writes
directly into network_layer_mapping, so Z-Image LoRAs no longer go
through the diffusers PEFT converter that raised KeyError on
state dicts with partial alpha keys.
Key formats handled: ai-toolkit, kohya lora_unet_, bare transformer.
and no-prefix. Pre-refactor fused attention.qkv is split into
to_q/k/v; attention.out and attention.wo are renamed to
attention.to_out.0. Alpha and dora_scale are preserved.
Load Flux2/Klein LoRAs as native NetworkModuleLora objects, bypassing
diffusers PEFT. Handles kohya (lora_unet_), AI toolkit (diffusion_model.),
diffusers PEFT (transformer.), and bare BFL key formats with automatic
QKV splitting for double block fused attention weights.
Includes shape validation to reject architecture-mismatched LoRAs early.
Respects lora_force_diffusers setting to fall back to PEFT when needed.
- detect f2 model type for LoRAs via metadata, architecture, and filename/folder
- preprocess bare BFL-format keys with diffusion_model prefix for Flux2LoraLoaderMixin
- handle LoKR format via native NetworkModuleLokr with on-the-fly kron(w1, w2)
- add NetworkModuleLokrChunk for fused QKV split into separate Q/K/V modules
- activate native modules loaded via diffusers path
- improve error message for Flux1/Flux2 architecture mismatch