Commit Graph

315 Commits

Author SHA1 Message Date
Vladimir Mandic 22d01c7e6e lora load cache state_dict
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-07-01 18:43:48 +02:00
Vladimir Mandic 7eacfafa4a lora guard against param change on-the-fly
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-07-01 15:53:38 +02:00
CalamitousFelicitousness d95ea9e238 fix(lora): support embedding-target LoRA and companion bias deltas
Route nn.Embedding targets (and the SDNQEmbedding / ScaledWordEmbedding subclasses) through the linear LoRA path: the weight delta is up@down over the [vocab, dim] table, same shape and merge as a Linear.

Apply a companion bias delta (diff_b) as ex_bias on the same module rather than dropping it; collect diff_b into the LoRA group so it rides the existing module instead of a separate Full module that would collide on the network key.
2026-06-23 20:40:42 +01:00
CalamitousFelicitousness 48fad8524e feat(krea2): add Krea 2 (K2) image model support
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.
2026-06-23 04:41:54 +01:00
Vladimir Mandic 6cc2a9582f Merge pull request #4935 from QualiaRain/fix/lora-network-shape-guard
fix(lora): guard self.shape for modules without a weight attribute
2026-06-16 09:01:24 +02:00
QualiaRain 42a4b82c8e fix(lora): guard self.shape for modules without a weight attribute
NetworkModule.__init__ set self.shape only inside 'if hasattr(sd_module, weight)' but then used len(self.shape) unconditionally, raising AttributeError when a LoRA targets a weightless module. Default shape to None and skip the dora_norm_dims computation when absent.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 15:20:08 -04:00
QualiaRain ca730fa3e6 fix(lora-extract): stop overwriting the module selection list; fix dead no-LoRA guard
make_lora reassigned the 'modules' selection arg to a named_modules() generator, so the subsequent 'te'/'unet' in modules checks tested an exhausted generator and silently skipped TE2 + UNet extraction. Also 'loaded_lora() == ""' never matched a loaded model (returns a list), so the no-LoRA-detected guard never fired.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-15 15:20:06 -04:00
CalamitousFelicitousness 1be0867d1e refactor(lora): centralize universal passthrough prefixes in the shared resolver
transformer., bare-diffusers, and lora_transformer_ bases are already in
network-key form for every arch, yet each per-arch resolve_targets repeated the
same passthrough branch for them. Move that into a shared
PASSTHROUGH_PREFIXES_DEFAULT set consulted by resolve_group_targets, leaving each
arch's resolve_targets to only the prefixes it actually rewrites (kohya / BFL).
lycoris_ stays in flux2, the one arch that recognizes it.

Pure refactor: the same keys resolve to the same modules.
2026-06-14 18:22:41 +01:00
CalamitousFelicitousness 31c07dbaf9 fix(lora): load OneTrainer diffusers-format LoRAs via lora_transformer_ prefix
OneTrainer saves LoRAs against the diffusers layout, keying each module as
'lora_transformer_' + the underscore-flattened module path with QKV pre-split.
That is sdnext's own network_layer_mapping namespace, but the native loader did
not list it as a known prefix, so parse_key dropped every key and the network
loaded zero modules ("not loaded").

Add lora_transformer_ to KNOWN_PREFIXES_DEFAULT and resolve it in a shared
resolve_group_targets helper that passes the base through unchanged, with no
rename or chunking. Routing every family loader through the helper gives all
diffusers arches (chroma, flux2, zimage, ernie) OneTrainer support without
per-arch wiring.

Fixes #4877
2026-06-14 18:22:41 +01:00
QualiaRain 023c829179 fix model/vae: wrong quant_config var, getattr guards, remote-vae latent_copy shadowing + response handling
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-12 13:00:39 -04:00
Vladimir Mandic 5e99dee3c2 full codespell coverage
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-06-04 12:36:10 +02:00
CalamitousFelicitousness 55db15c213 docs: cleanup 2026-05-31 00:24:33 +01:00
CalamitousFelicitousness 5b321d2071 refactor(lora): update importers for native_adapter rename
5 pipeline files + 2 test files. Mechanical substitution. 141/141
adapter tests pass.
2026-05-31 00:24:33 +01:00
CalamitousFelicitousness 7cd6b6be79 refactor(lora): rename native_loader to native_adapter
Frees the name for pipelines/native_transformer. Module covers the full
LyCORIS adapter family (LoRA/LoKR/LoHA/OFT/IA3/GLoRA/Norm/Full), not
just LoRA.
2026-05-31 00:24:33 +01:00
CalamitousFelicitousness 9587972831 fix(lora): natural-filename lookup on windows and in subfolders
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.
2026-05-24 02:46:48 +01:00
CalamitousFelicitousness 84683a1d84 refactor(anima): migrate to generic native_loader
Replaces anima_lora.py's bespoke try_load_lora / group_keys /
resolve_network_key with thin wrappers binding native_loader's generics
to anima's prefix tuples and resolve_targets, mirroring flux2 / zimage /
chroma / ernie. The hand-rolled apply_lora_alphas bake-with-balance
pass goes away; alpha / scale / dora_scale flow through NetworkWeights.w
to NetworkModule.calc_scale at apply time.

native_loader gains an optional network_prefix kwarg (str or
Callable[[prefix_used], str], default "lora_transformer_") used when
constructing network_key. Anima passes a callable picking
lora_transformer_ / lora_llm_adapter_ / lora_te_ per matched prefix.
Single-component siblings keep the default and are unchanged.

network.NetworkModule.apply_weight_decompose grows a dual-path DoRA
convention detector. The pre-fix implementation only handled per-input
dora_scale (DoRA paper / kohya, shape (1, in)), silently broadcasting
per-output LyCORIS / PEFT dora_scale (shape (out, 1)) into an incoherent
element-wise rescaling. Detection is structural: (out, 1, ...) routes
to per-output; everything else (including the square-weight 1D ambiguity)
defaults to per-input for legacy compat. Pre-existing bug surfaced by
the LoKR+DoRA LyCORIS files Anima now loads.

Behavior changes:

- LoHA via the generic try_load_loha (NetworkModuleHada); covers
  scenery-anima-base and any other LyCORIS .hada_w* export.
- Kohya lora_te_ prefix recognized. The legacy resolver only matched
  BFL text_encoders.qwen3_06b.transformer.model. and silently dropped
  lora_te_layers_N_* keys (41% of BlueArcStyle's bases were unloaded).
- LoKR+DoRA LyCORIS files now apply correctly; the per-output dora_scale
  is honored instead of silently scrambled.

Adds test/test-anima-native-adapters.py: 37 offline tests across all
five prefixes (LoRA + LoHA), every COSMOS_2_FLAT_RENAME entry, DoRA
threading, marker disambiguation, try_load_chain dispatch, calc_updown
sanity, and both DoRA conventions (per-input / per-output / 1D ambiguous).
Adapter mock mirrors AnimaLLMAdapter's real module tree.
2026-05-22 00:22:32 +01:00
CalamitousFelicitousness 4c3f4db129 refactor(lora): collapse native dispatcher to a registry
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.
2026-05-18 23:38:37 +01:00
CalamitousFelicitousness 6ad67319de refactor(lora): add generic loaders for IA3/GLoRA/Norm/Full
Same parameterized shape as the core 4.

- IA3: .on_input is the marker disambiguator (.weight is too generic).
  Fused targets skipped.
- GLoRA: requires a1/a2/b1/b2 per group. Fused skipped (target-dependent
  term doesn't slice cleanly).
- Norm: never fused. Loader-local network_layer_name stamping bypasses
  lora_convert's transformer-norm guard without changing the carve-out.
- Full: fused skipped (no chunk class for diff tensors).
2026-05-18 23:18:51 +01:00
CalamitousFelicitousness d2fd08fe3c refactor(lora): add generic loaders for LoRA/LoKR/LoHA/OFT
Family loaders parameterized on per-arch resolve_targets callable and
prefix tuples. Build network keys as
"lora_transformer_" + path.replace(".", "_").

Fused-target handling:

- LoRA: chunk at load time, supports both equal and unequal ChunkSpec
- LoKR: dispatch to NetworkModuleLokrChunk (equal) or LokrSliceChunk
  (unequal), materialize kron(w1, w2) lazily
- LoHA: NetworkModuleHadaChunk for equal only; Tucker-on-fused and
  unequal skipped with warning
- OFT/BOFT: fused skipped with warning. Algorithm discriminated by
  oft_blocks.ndim (3-D OFT, 4-D BOFT)

Plus try_load_chain umbrella for per-arch family-iteration wrappers.
2026-05-18 23:18:41 +01:00
CalamitousFelicitousness cbaaf1c88c refactor(lora): move NetworkModuleLokrSliceChunk to network_lokr
Lifts the slice variant from chroma_lora into network_lokr so the generic
LoKR loader can dispatch to either NetworkModuleLokrChunk (equal chunks)
or NetworkModuleLokrSliceChunk (unequal ranges) based on ChunkSpec shape.

chroma_lora keeps the same slice path through an updated import.
2026-05-18 23:18:31 +01:00
CalamitousFelicitousness 7c32d97121 refactor(lora): extract native adapter scaffolding to native_loader
Lifts the parts of the per-arch native loaders that are byte-identical
across z-image, chroma, ernie, and flux2 into a new shared module.

- Suffix and marker tables for all nine families
- SUFFIX_NORMALIZE (lora_A/lora_B to lora_down/lora_up)
- KNOWN_PREFIXES_DEFAULT and BARE_DIFFUSERS_PREFIX_USED sentinel
- ChunkSpec dataclass for fused-weight slicing (equal idx+total or
  unequal start+end)
- unwrap_peft_wrapper and strip_peft_adapter_name
- has_marker, resolve_mapping, new_network, finalize_network, shapes_match
- Parameterized parse_key and group_by_suffixes
2026-05-18 23:18:22 +01:00
Disty0 c227d5fa10 SDNQ add Hadamard Rotation support 2026-05-18 17:06:11 +03:00
Disty0 297ab4bb60 SDNQ Lora fix dtype 2026-05-16 13:13:41 +03:00
Disty0 8e11971572 Fix SDNQ Lora 2026-05-15 21:25:08 +03:00
Vladimir Mandic c8d6fd5cf8 Revert "much stricter ruff linting"
This reverts commit 310dbf1574.
2026-05-11 08:13:57 +02:00
Vladimir Mandic 310dbf1574 much stricter ruff linting
Co-authored-by: Copilot <copilot@github.com>
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-05-11 07:15:37 +02:00
CalamitousFelicitousness 0c44b93b25 refactor(flux2): expose single try_load entry point for dispatcher
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.
2026-05-10 16:33:18 +01:00
CalamitousFelicitousness 69506551a7 feat(lora): surface method-selection reason in load logs
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.
2026-05-10 00:05:37 +01:00
CalamitousFelicitousness dda7bb7bbc feat(flux2): native BOFT (butterfly-OFT) support
Discriminated from OFT by 4-D oft_blocks shape (boft_m, block_num,
block_size, block_size), mirroring LyCORIS algo_check. The cascade
of log_2(block_num)+1 Cayley rotations is applied via the
unflatten/transpose/flatten reshape sequence in NetworkModuleBOFT,
porting LyCORIS make_weight verbatim.
2026-05-10 00:05:37 +01:00
CalamitousFelicitousness 4d3699bab6 refactor(flux2): align dispatcher with z-image/chroma native pattern
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.
2026-05-09 23:16:09 +01:00
CalamitousFelicitousness 7983c8ec72 feat(lora): add NetworkModuleHadaChunk for fused-weight LoHA targets
Slices w1a/w2a at the assigned chunk's row range and computes the
partial Hadamard product, mirroring NetworkModuleLokrChunk. Used
when LoHA targets a fused weight (e.g. img_attn.qkv) on models
that expose split Q/K/V modules.
2026-05-09 23:16:09 +01:00
CalamitousFelicitousness 1750a2881e fix(lora): use is-not-none check for ex_bias accumulation
Truthiness on a tensor raises when stacking multiple Norm/Full
adapters. Match the updown accumulation pattern five lines above.
2026-05-09 22:04:42 +01:00
CalamitousFelicitousness db4a345a1b fix(lora): set GLora dim so alpha scaling is applied
Without self.dim, NetworkModule.calc_scale returns 1.0 even when
alpha is present, silently dropping the trained scaling. Use
w1b.shape[0] as the rank, matching the network_lora and
network_hada conventions.
2026-05-09 22:04:42 +01:00
CalamitousFelicitousness 4aca63e841 fix(lora): guard OFT constraint for LyCORIS oft_diag files
LyCORIS files have self.constraint=None (only the kohya path
uses it). Wrap the .to() call to avoid the NoneType AttributeError.
2026-05-09 22:04:17 +01:00
Vladimir Mandic 4747ca2fc0 lora change detection improvements
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-05-09 09:38:54 +02:00
CalamitousFelicitousness 92df94a227 feat(chroma): native loader for chroma lora
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
2026-05-04 21:17:14 +01:00
CalamitousFelicitousness b37e275212 feat(lora): native loader for ernie-image
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.
2026-05-04 16:43:36 +01:00
CalamitousFelicitousness 450bf977e8 fix(lora): use native_active flag instead of applied_layers for restore trigger
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.
2026-05-01 01:38:56 +01:00
Vladimir Mandic ebc875d224 reorg control type
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-04-29 11:20:22 +02:00
CalamitousFelicitousness a028b56687 fix(lora): restore native weights when LoRA removed on diffusers-path models
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.
2026-04-29 02:00:33 +01:00
CalamitousFelicitousness 4af3a57741 feat(anima): native lora across transformer, llm_adapter, text encoder
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.
2026-04-25 03:16:03 +01:00
awsr 09f5fc6e03 Update concurrent.futures imports
Python 3.14 adds `concurrent.interpreters` and we don't need to import that here.
2026-04-23 16:49:31 -07:00
vladmandic ab7fd5b5e6 cleanup
Signed-off-by: vladmandic <mandic00@live.com>
2026-04-21 19:45:51 +02:00
vladmandic db670b8bca fix sdnq-lora
Signed-off-by: vladmandic <mandic00@live.com>
2026-04-21 19:44:18 +02:00
Vladimir Mandic f1304b3ba0 Merge pull request #4762 from awsr/hashcache
Update hash cache
2026-04-15 09:42:35 +02:00
CalamitousFelicitousness 65e59e7224 feat(lora): z-image native lokr, loha and oft loaders
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.
2026-04-14 21:48:19 +01:00
CalamitousFelicitousness c35adc4d0d feat(lora): native z-image lora loader
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.
2026-04-14 21:13:23 +01:00
awsr 6aff795985 Improve extensibility 2026-04-14 02:59:19 -07:00
vladmandic 456d17fcd3 cleanup bnb references
Signed-off-by: vladmandic <mandic00@live.com>
2026-04-12 19:06:08 +02:00
vladmandic 91bba59c0d fix lint
Signed-off-by: vladmandic <mandic00@live.com>
2026-04-12 19:06:08 +02:00