236 Commits
Author SHA1 Message Date
Vladimir Mandic c6bf7b4368 samplers expose base/max seq len, improve sampler options save, copy defaults
Signed-off-by: Vladimir Mandic <[email protected]>
2026-09-30 18:37:05 +02:00
CalamitousFelicitousness d1d3c7c438 feat(lora): pdd exports with a trained sigma grid and replaced weights
Inference-only PDD exports such as alibaba-pai's Qwen-Image-2.1-Fun-Acc-4Step carry no pdd_num_steps: the grid is pdd_sigmas in the metadata or in the pdd_config.json the release keeps beside the weights, and the file replaces norm weights outright. Those parameters are set with the heads, blended toward the loaded value by strength and restored on removal. The pin passes the grid's block boundaries as sigmas and turns off dynamic shifting, static shift and terminal stretch on that generation's scheduler, which would otherwise reshape them, and leaves num_timesteps alone where the pipeline exposes it as a read-only property. Qwen-Image 2.1 gets an ArchSpec and the PDD loader in its chain; a file with heads but no grid warns and loads its backbone only.
2026-09-30 08:09:08 +01:00
CalamitousFelicitousness c5c09d6cc9 feat(lora): native loading for qwen-image 2.1
QwenImage21Transformer2DModel keeps attention and the SwiGLU split, while ComfyUI checkpoints fuse the SwiGLU input as img_mlp.gate_up with rows [gate_layer; proj], the layout ai-toolkit and musubi-tuner train against. pipelines/qwen/qwen21_lora.py splits that projection by row halves for LoRA, DoRA, LoKr and LoHA in dotted and kohya-flattened form and binds every other key verbatim; qwen21 joins allow_native and NATIVE_DISPATCH. The diffusers path loads none of the fused files and fails on transformer.-prefixed files that carry alpha tensors. The tests map every layout found on CivitAI and the Hub against the real class, check the split against the fused SwiGLU forward, and refuse Qwen-Image 1.x files.
2026-09-30 08:08:46 +01:00
CalamitousFelicitousness 55b0442e7c fix(civitai): name files from the /models payload
/model-versions can still report a fresh upload by its storage key
(VAPA5E3KPBRRJZ2PMTCMW8WSE0.safetensors) while /models already carries
the uploader name, and it drops GGUF quantType; /models is also what
the UIs list from. The names route and id-based download therefore take
their file entries from /models whenever it answers, and keep the
version's own files only when it does not.
2026-09-30 03:48:49 +01:00
CalamitousFelicitousness 803583c6f4 fix(civitai): drop redundant variant and role suffixes from save names
A suffix only adds what the CivitAI name lacks: the variant is skipped
when the name already spells that token (ideogram4INT8_...UncondINT8
stays as is, x_fp8 still gains -fp8_e4m3fn once the header names the
exact dtype), header-derived expert roles obey the same file-name guard
as title-derived ones (ideogram4_fp8Uncond no longer ends in -uncond),
and companions never take a role, since the text encoder of a
high-noise version is the same file the low-noise version ships.
2026-09-30 03:34:50 +01:00
CalamitousFelicitousness f49595da0a feat(civitai): name gguf downloads by their header quant
A GGUF's variant is its quant, never metadata.fp, which is the dtype it
was quantized from (a Q4_K_M upload tagged fp8 was saved as -fp8). The
name route now reads the GGUF header the way it reads safetensors
headers: general.file_type gives the exact quant (Q4_K_M) and files
without it, such as Ideogram 4 GGUFs with an empty KV block, fall back
to the dominant tensor type (Q4_0). When the header cannot be read the
metadata or url quantType still applies; fp never does.

- peek_civitai gains a v2/v3 GGUF reader over a 1 MB ranged read, with
  the same id-keyed cache and the quant token in the "quant" field
- peek_headers dispatches by extension, so .gguf siblings are probed
  alongside .safetensors ones
2026-09-30 03:22:02 +01:00
CalamitousFelicitousness 87e62e6545 feat(civitai): choose download file names server-side
Enso, the Gradio CivitAI tab and API callers share one naming rule in
modules/civitai/names_civitai.py. The variant token (metadata.fp,
quantType, or the quantType url parameter) is suffixed unconditionally
so names stay stable when a creator adds variants; dual-transformer
expert roles (Wan 2.2 A14B high/low noise, Ideogram 4 uncond) join it
from the version title or the file header; remaining collisions cascade
to the size class, then the file id. Header peeks upgrade a bare fp8
claim to the dtype-exact token.

- GET /sdapi/v2/civitai/version/{id}/names lists save name, route type,
  variant and role per file
- POST /sdapi/v2/civitai/download takes version_id + file_id and
  resolves url, name, sha256 and companion type; url + filename callers
  are unchanged
- /model-versions drops GGUF quantType, so such versions take their
  files from /models
- civitai_save_precision (Settings > Huggingface) drops the
  unconditional suffix; roles stay and names remain unique per version
- header peek moves to peek_civitai.py; failed reads are never cached
- ui/civitai.ts passes file ids instead of computing names
- test/test-civitai-names.py replays recorded /model-versions, /models
  and header responses under both toggle states
2026-09-30 03:01:02 +01:00
CalamitousFelicitousness 9f705b263e test(api): add multi-image condition set tests
Cases: two images on img2img, an aligned first image with a different requested size, a batch size above the image count, a request over max_condition_images, and two control inputs. With --log each case also reads the Base log line for the image count and call size the pipeline received; a call sized from the first image returns the requested size with scrambled content.
2026-09-26 18:47:37 +01:00
Vladimir Mandic 484e6acae7 Merge pull request #5110 from QualiaRain/fix/video-load-failure
Avoid default image-model reload after video load failure
2026-09-25 07:59:11 +02:00
Blood b7e8d73681 Create test-video-load-failure.py 2026-09-24 22:26:06 -04:00
Blood 514ed9540c Create test-refiner-prompt-restore.py 2026-09-24 21:58:05 -04:00
CalamitousFelicitousness c67b4f499f fix(lora): read the pdd grid from the file header when the cache lacks it
The metadata cache keeps a failed read forever and --no-metadata returns
nothing, and in both cases the head loader returned None silently while
the backbone still applied. The grid is now read from the file's own
header when the cached metadata lacks it, and head-shaped tensors
without a grid log a warning.
2026-09-16 19:26:21 +01:00
Vladimir Mandic 059ccbaf0b Merge pull request #5091 from CalamitousFelicitousness/feat/lora-pdd
feat(lora): parallel decoding heads and minimax schedule controls
2026-09-16 07:45:57 +02:00
CalamitousFelicitousness b259a48448 fix(lora): give replaced pdd projections their own memory
The projection a parallel head replaces waits out of the module tree,
so nothing moves it, and a weight still viewing its checkpoint shard
keeps the whole shard mapped. The stash now clones the projection's
tensors.
2026-09-16 03:23:03 +01:00
CalamitousFelicitousness 09e861157f fix(offload): hand back the loaded cpu tensors on no-stream offload
Group hooks on the no-stream path and the on-demand hook return a
component to cpu through a device copy, so a memory-mapped text encoder
sits in memory twice, as the mapped file its never-run vision tower
keeps alive and as the copies, and every encode pays a device-to-host
transfer of unchanged weights. The engine now records the cpu tensors
at onload and hands them back at offload; a component moved by any
other path still takes the copy.
2026-09-16 01:57:23 +01:00
CalamitousFelicitousness 726907dd5b fix(video): count minimax steps as transformer evaluations
MiniMaxH3Scheduler counts the terminal sigma in num_inference_steps, so
Steps N ran N-1 evaluations while every other model runs N. The shim
hands the scheduler p.steps + 1, the slider starts at 1, and the PDD
pin records the evaluation count while passing the scheduler its grid
argument. Metadata written before this change counted grid points.
2026-09-16 00:47:46 +01:00
CalamitousFelicitousness 29fe895c0b feat(video): absolute per-request minimax shift on every path
Shift is a property of the trained schedule, not of the step count, so
the tab sliders take absolute values, defaulting to the shipped 12 and
3. video_minimax resolves each request from the request value or the
scheduler config inside apply_overrides, which the tab, the api and
the still path all call, so a request without values lands on the
shipped schedule. The api maps sampler_shift onto the video schedule
and gains audio_shift. Applied values are recorded as Video shift and
Audio shift; the PDD pin records what it enforces.
2026-09-15 23:01:41 +01:00
CalamitousFelicitousness 57328dc615 fix(lora): bind minimax extraction residuals
Layer-wise extractions (FastH3) ship diff_b on every projection and
diff on the norms; final_layer.norm had no rename onto norm_out.norm,
so its residual went unmapped.
2026-09-15 03:52:04 +01:00
CalamitousFelicitousness a800fe59cf fix(lora): accept lowercase lora_a and lora_b factor names
TaoLive adapters save the factors as lora_a and lora_b without the
.weight suffix, which no suffix table knew, so the file bound nothing.
2026-09-15 03:52:04 +01:00
CalamitousFelicitousness a0f0097e52 refactor(lora): make the fused chunk slicer public
The fidelity CLI slices fused saves the way try_load_lora does.
2026-09-15 03:52:04 +01:00
CalamitousFelicitousness 5860ea9153 feat(lora): parallel decoding heads for pdd acceleration files
PDD files pair a backbone LoRA with the output projections repeated per
interval of a training grid; each step fuses the heads of its block
into one projection. network_pdd reads the grid from the metadata,
swaps a ParallelHead in for each projection, fuses from the scheduler's
step_index and pins the step count and shift while heads are
installed. The MiniMax loader declares which scheduler each head
follows.
2026-09-15 00:23:27 +01:00
CalamitousFelicitousness 3e705bc4af feat(lora): project adaln deltas onto the pruned minimax basis
The pruned transformer stores W @ P for each AdaLN projection against
the rank-8 basis in time_embedder.basis, so deltas trained at the
released width failed the shape check. try_load_lora gains an
adapt_weights hook and the MiniMax loader refits lora_down as down @ P,
which is exact.
2026-09-15 00:23:09 +01:00
CalamitousFelicitousness 6d5c63d9fe fix(hashes): snapshot the stores under a lock before saving the cache
save_cache handed writefile the live HashStore objects, so an add_hash
from another thread during the deep copy raised "dictionary changed
size during iteration" and dropped the save. The stores are now copied
under a lock that also covers the write, so a later save never lands
under an earlier snapshot.
2026-09-13 20:35:37 +01:00
CalamitousFelicitousness 68c64fb4bc fix(json_helpers): write atomically by default and warn on empty reads
Every caller writes a whole JSON document, and a plain open/write can
leave a torn or empty file when the process dies or another writer
overlaps, which readfile then returns as {}. Writes now go through the
temp file and replace unless atomic=False or the mode is append. A read
waits out an open that Windows refuses while a replace of the same name
is in flight, and an empty file is reported when the read is not
silent, since a zero-byte config.json otherwise resets settings without
a trace.
2026-09-13 19:20:10 +01:00
CalamitousFelicitousness b39639ce2e fix(json_helpers): serialize file access per path within the process
The fasteners lock is inter-process only. On Linux fcntl record locks
belong to the process, so two threads writing the same file were never
serialized and could tear it; on Windows they were, until the lock
switched itself off. Every writer of these files runs inside one
multi-threaded process, so that is the case that matters.

readfile(lock=True) and writefile now take a re-entrant lock per
normalized path, held from the snapshot through the replace so writes
to one path land in call order. Other processes are covered by the
atomic replace. A .lock file left next to a JSON file by the old lock
is removed the first time that path is used.
2026-09-13 19:20:10 +01:00
CalamitousFelicitousness cdc76c25c6 fix(json_helpers): make atomic saves work on windows, keep lock file
writefile(atomic=True) renamed the temp file while it was still open,
which Windows refuses, so every atomic save failed there and left a temp
file behind. The temp file is now created with mkstemp, closed before
os.replace and removed when the save fails; the replace retries briefly
when another handle holds the target, which Windows reports as a
permission error.

Both helpers removed the .lock file after releasing it. That removal
raced other holders on both platforms, and any failure switched locking
off for the whole process without a log line. The lock file now stays in
place; a failed release or a lock timeout is logged instead.

writefile deep-copied and validated the live object in Python, so a
concurrent insert into a shared dict raised "dictionary changed size
during iteration" and dropped the save. dict.copy and list.copy run
under the GIL, so the deep copy and the per-key validation now walk that
snapshot; nested containers remain the caller's responsibility.

test/test-json-helpers.py covers all three on Linux and Windows.
2026-09-13 18:41:33 +01:00
Vladimir Mandic da5d934f1f Merge branch 'dev' into feat/filter-sampler-upscaler-choices 2026-09-13 07:41:53 +02:00
Yifan Chen bae986e90b address selection filter review feedback 2026-09-12 00:08:08 -07:00
CalamitousFelicitousness 619a25eea6 fix(offload): key the group stats report by component
A checkpoint-name key survives unload, so a reload of the same checkpoint
never printed the per-module stats block again, even with a different
quantization. Each component now carries its own reported stamp: a task
switch rebuilds the pipe around the same modules and stays quiet, while a
reload or a component swap brings new modules and reports them.
2026-09-07 22:35:38 +01:00
CalamitousFelicitousness 8619dbc0af test(offload): address the split offload modules in the placement role tests
The group offload functions live in sd_offload_group, sd_offload_utils and
sd_offload_state rather than modules.sd_offload, so the tests and their
monkeypatches now import and patch those modules directly.
2026-09-07 22:32:54 +01:00
Yifan Chen a174e94183 feat(ui): filter generated sampler and upscaler lists 2026-09-07 08:29:37 -07:00
CalamitousFelicitousness b434eb0c1b refactor(lora): route every bare key through the resolver
The parser no longer takes reference-name prefixes to tell bare
reference keys from bare diffusers keys. Any bare key carries the
sentinel and the arch resolver renames what it knows and passes the rest
through. Flux2 keeps its list for file-format detection only.
2026-09-06 04:25:44 +01:00
CalamitousFelicitousness 783b66c3be refactor(lora): offer unknown bare keys to the resolver
A bare key that matches no known prefix is parsed with the
bare-diffusers sentinel and handed to the resolver instead of being
dropped at parse time. The per-arch lists of bare diffusers prefixes are
gone, and a path that names no live module counts as unmapped.
2026-09-06 04:25:44 +01:00
CalamitousFelicitousness 1c91fb2047 refactor(lora): make the fused row reorder a chunk capability
A ChunkSpec can reorder equal row blocks of the rows it selects, so an
arch declares a swapped SwiGLU projection on the target instead of
permuting the state dict first. Only the LoRA family applies it; the
others skip a reordered target with a warning.
2026-09-06 04:25:44 +01:00
CalamitousFelicitousness 4a5dc98cb2 fix(lora): match the diffusers minimax lora converter
The reference fc1 is a fused [gate; value] SwiGLU projection and the
diffusers port stores [value; gate]. The native mapping did not swap the
halves, so gate and value deltas landed on each other's rows. The
mapping now also renames the standalone projections, reads a
metadata-only alpha, and accepts the musubi, peft dit and diffusers-named
layouts.
2026-09-06 04:25:44 +01:00
CalamitousFelicitousness cd88d2ae34 fix(lora): route codebook layers on the mean level gap
SDNQ codebook layers keep their Lloyd levels in the scale slot, so reading
scale.mean() as the grid step returned the levels' near-zero mean and sent
sub-step deltas to requantize, where the grid erases them. grid_step returns
the mean adjacent-level gap for those layers and the plain scale mean otherwise.
2026-09-05 18:39:04 +01:00
CalamitousFelicitousness 5875cdd29e feat(lora): remap anima 1.0 lora block indices onto depth-expanded checkpoints
Anima 2.9B interleaves twelve new blocks among the 28 of Anima 1.0, so a block
index trained against 1.0 names a different block on the expanded model. Every
such key still resolves, since blocks 0 to 27 exist either way, so the
mismatch was silent. The Anima loader now shifts base-depth indices onto the
blocks that carry those weights, keyed by (base depth, expanded depth) and
applied only when the transformer is expanded and the LoRA stays inside the
base depth. Transformer keys move; llm_adapter and text encoder keys keep
their own numbering.
2026-09-05 02:24:04 +01:00
CalamitousFelicitousness 6b92f2ba03 feat(model): add anima 2.9b as a base reference model
Anima-2.9B is a depth-expanded finetune of Anima 1.0 Base carrying 40
transformer blocks against the base repo's 28. The reference entry points at
the Diffusers conversion. Single-file releases load through the native loader:
TransformerSpec gains an infer_config hook, the Anima spec uses it to size
num_layers to the block indices in the file, and model_anima routes a
checkpoint-selected safetensors through the loader with the remaining
components from the base repo.
2026-09-05 01:45:49 +01:00
nan f895b72863 Fix VDM trailing timestep spacing 2026-09-02 00:13:20 +08:00
CalamitousFelicitousness 35b935204b test(lora): assert every dispatched arch is native eligible
Two tables decide the native path: one says which architectures may take
it, the other says which loader they get. An entry in the second without
one in the first is a loader nothing can reach, and nothing checked that.
2026-08-30 06:23:07 +01:00
CalamitousFelicitousness 4886761980 fix(lora): finish the activation pass when it aborts
The error limiter halts a pass by raising, and nothing between the raise
and the caller put the model back. A halted pass left group offload hooks
stripped from every component the walk had reached, left a sequential
model on the cpu with offload disabled, and left the counters other
modules read describing the pass before it.

The epilogue moves into finish_pass under a finally, so the model returns
to its offload mode and the counters describe the pass that just ran. The
abort still reaches the caller.

Pass state is reset in one place in lora_sdnq now. Two of the six
accumulators were not being cleared at the start of a pass, and a stale
routed layer suppresses the fallback count for that layer next time.
2026-08-30 06:22:43 +01:00
CalamitousFelicitousness 3f86973bc6 refactor(lora): split the activation ladder into atomic mechanisms
The per-module walk carried four mechanisms inline, each repeating the
same tail: count the layer, stamp the pair that marks it current, advance
the bar, continue. Five copies of that tail and three of the backup probe
put the deepest arm nine levels in.

Each mechanism is now a function that either takes the layer or declines
to the next, and the walk reads as the four of them in order. The pass
state they share moves onto one object built before the walk starts, with
the accept tail, the stamp and the bar tick as its methods. That takes
network_activate from 218 lines to 55, none of it deeper than the module
loop.

Two shapes are deliberately not folded into that tail: the weight path
counts weights and bias separately and tracks what the module refused,
and the factor-strip restore stamps without counting. Hosting hands a
declined delta back rather than leaving it in a flag, so a pair of Nones
still reads as assembled and no layer is calculated twice.
2026-08-30 06:21:13 +01:00
CalamitousFelicitousness 88d263ba14 fix(lora): let stack degradation warnings recur after a settings change
The keys that mark a degradation as reported lived for the life of the
process, so a user who saw "flip=skipped weight=offloaded", changed the
offload mode and hit the same wall again was told nothing the second
time. Tie the set to the settings the warnings speak about: the stack
signature, the offload mode, the host rank and the checkpoint. Repeating
under one context still says it once.
2026-08-30 06:04:09 +01:00
CalamitousFelicitousness 2db573d283 fix(lora): bind 4-d oft files to the boft module type
The generic loader never offered a file to the boft type, so butterfly
OFT adapters reached the oft type instead, which claims any oft_blocks
key without checking its rank and then reads the block count as the lora
dim. Register boft ahead of oft; files with 3-d blocks still land on oft.
2026-08-30 06:04:02 +01:00
CalamitousFelicitousness fd2e082be5 fix(lora): keep the loaded-network type contract under nunchaku
The nunchaku path replaced the loaded network list with the on-disk
entries it composed from, so reading a loaded network back hit an object
without the fields it expects: choosing the reported method reads
len(net.modules) and raised on every set change, costing that generation
its infotext and trigger tags. The adapter was already composed by then,
so the image was unaffected. Wrap the composed set in Network objects
and mutate the list in place.
2026-08-30 06:03:54 +01:00
Vladimir Mandic 62bedf8834 update attention handlers and settings
Signed-off-by: Vladimir Mandic <[email protected]>
2026-08-29 13:05:20 +02:00
Vladimir Mandic da856522a8 Merge branch 'dev' into feat/lora-sdnq-stack 2026-08-29 09:46:42 +02:00
CalamitousFelicitousness 5cfa07fb5e test(lora): extend apply-method coverage to select riding
The mechanism gate tests assert select_candidate declines under
requantize, and the apply-method hint names the cache option among
those the requantize choice disables.
2026-08-28 13:09:26 +01:00
CalamitousFelicitousness 999224e91a test(lora): pin the upstream fixes in the campaign suite
The in-place weight installs, the promote-after-deactivate fuse
ordering, and the dynamo reset at model unload live in the shared
loader code; their regression pins belong in the campaign suite beside
the paths they protect.
2026-08-28 13:09:26 +01:00
CalamitousFelicitousness 2620b0cc5b feat(lora): per-block strength
<lora:name:1.0:lbw=VALUE> scales each targeted layer's delta by a slot of a
per-architecture block vector. VALUE is a preset name, a scalar, or a comma
vector; presets stretch onto the block count of the current model and the
a1111 17-slot and 12-slot layouts are accepted on sd and sdxl. The factor
enters through the module multiplier, so every apply path carries it: the
exact factor channel, hosting, requantize routing, dense stack combines and
select scoring.

- modules/lora/lora_blocks.py: slot classification from network_layer_mapping
  (namespace-first, anchored chain prefixes), preset resolution reusing the
  merge block-weight tables with BASE forced neutral, generated classic
  segment names plus DOUBLE/SINGLE chain names, per-model memoization
- the raw spec stages through pending_config and promotes with the other
  multipliers, keeping fuse removal consistent
- block weights join the activation signature, the per-module apply stamp
  and the factor cache identity; entries without block weights keep their
  existing signature bytes
- non-native load methods warn once and ignore the argument
2026-08-28 13:09:26 +01:00