Commit Graph
413 Commits
Author SHA1 Message Date
EthanfelandClaude Sonnet 4.6 aae488bc00 feat: add _extract_lora_svd helper for LoRA extraction
Adds module-level _extract_lora_svd() that SVD-decomposes a weight
delta into (lora_up, lora_down, alpha), supporting fixed-rank and
auto-rank (energy threshold) modes with a singular value noise floor.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 23:27:23 +02:00
EthanfelandClaude Sonnet 4.6 02daae172e test: add failing tests for _extract_lora_svd helper
Adds TestExtractLoRAFromDelta test class and _load_module() helper
to support TDD for the upcoming LoRAExtractFromModel node.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 17:49:57 +02:00
EthanfelandClaude Opus 4.6 5133fa3dd0 fix: cap diff cache RAM at 16GB to prevent OOM on video models
The diff cache was using 50% of available RAM with no absolute cap,
causing 54GB+ usage on WAN. Now capped at 16GB — excess spills to
disk automatically. First candidate is still slow but subsequent
ones benefit from disk-cached diffs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 14:52:39 +01:00
EthanfelandClaude Opus 4.6 b756a344f5 fix: move del measured after results.append to avoid UnboundLocalError
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 14:48:21 +01:00
EthanfelandClaude Opus 4.6 d224156fd9 fix: add memory logging per Phase 2 candidate + free measured dict
Log process RSS and diff cache size after each Phase 2 candidate
to diagnose RAM growth on large models. Also del measured dict
to free metric temporaries sooner.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 14:45:17 +01:00
EthanfelandClaude Opus 4.6 ffc92a9d78 fix: reduce scoring memory pressure for large model patches
Free tensor references eagerly in scoring loop, reorder sparsity
before SVD, avoid unnecessary intermediate allocations. Helps
prevent RAM accumulation during Phase 2 on video models.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 14:36:11 +01:00
EthanfelandClaude Opus 4.6 2862fd1459 fix: eliminate persistent fp32 copy in merge_quality scoring
Avoid keeping a full fp32 copy of each diff tensor for the entire
scoring iteration. Norm and sparsity now work on original dtype,
fp32 conversion only happens inside the SVD block and is freed
immediately after Gram matrix computation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 14:27:40 +01:00
EthanfelandClaude Opus 4.6 e914aa3550 fix: reduce RAM usage for merge_quality SVD scoring on large models
Use Gram matrix + eigvalsh instead of full SVD for tensors with
min dimension > 32. Same effective rank result but much smaller
memory footprint, critical for video models like WAN.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 14:22:28 +01:00
EthanfelandClaude Opus 4.6 f460dab546 chore: bump version to 1.5.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 13:52:18 +01:00
ethanfel 44ac674275 Add files via upload 2026-03-26 13:50:59 +01:00
EthanfelandClaude Opus 4.6 07bffa28cc docs: mention Triton acceleration in scoring_svd tooltip
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 13:45:15 +01:00
EthanfelandClaude Opus 4.6 88c203ba77 feat: show rank variation hint suggesting SVD scoring modes
When LoRAs have significantly different ranks (2x+ ratio), the analysis
report now suggests trying scoring_svd='lora_rank' or 'full'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 13:43:53 +01:00
55d10b895c feat: add Procrustes alignment, batched eigvalsh, and SVD scoring modes
- Procrustes alignment as faster alternative to KnOTS SVD alignment
  (pure rotation via batched_procrustes from kernel.py, whiten=False)
- Batched deferred eigvalsh for LoRA effective rank computation
  (group by rank, single eigvalsh per group vs 240 individual SVDs)
- Unified scoring_svd dropdown: disabled/merge_quality/lora_rank/full
- Import batched_procrustes from kernel.py with graceful fallback

Based on PR #4.

Co-Authored-By: Ethanfel <ethan.fel@ts-pc.fr>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 13:37:44 +01:00
marduk191andClaude Opus 4.6 bc8e1a9349 feat: add Triton fallback logging in kernel.py
Log info message when Triton is not available so users know
fused N=2/N=3 kernels are disabled.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 13:37:34 +01:00
EthanfelandClaude Opus 4.6 ce0a756a86 fix: show LoRA filename instead of full path in stack nodes
Override _displayValue getter on combo widgets to strip directory
paths, showing only the filename for readability.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 12:13:44 +01:00
EthanfelandClaude Opus 4.6 168fa1311c feat: wire Triton SVD kernel into optimizer
Integrate kernel.py into scoring and rank estimation pipelines.
Based on PR #4 approach, with hardening:
- _triton_svdvals helper with internal transpose and kernel dispatch
- Cap at N<=32 to avoid eigh serialization cliff
- Warning log when kernel.py exists but fails to load
- NameError guard for frozen/zipimport environments
- Fix >2D tensor fallback slice axis

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 12:13:39 +01:00
marduk191 feceb5e96e feat: add Triton SVD kernel for batched thin-matrix SVD
Fused Triton kernels for N=2,3 (3850-5488x faster than torch),
Gram-eigh hybrid for N>=4, Newton-Schulz inverse sqrt, and
subspace-preserving Procrustes alignment.

From PR #4.
2026-03-26 12:13:33 +01:00
EthanfelandClaude Opus 4.6 39c09ed123 fix: include memory_mode in autotuner cache key
When switching memory_mode (e.g. auto → disabled), the in-memory
cache key was unchanged, causing stale memory-hit results to be
returned instead of running a fresh sweep.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 11:09:55 +01:00
EthanfelandClaude Opus 4.6 65eba9df7f feat: add selection input to AutoTuner node
Allows picking which ranked config to apply (default=1, top-ranked)
directly on the AutoTuner node, without needing a separate Merge
Selector node. Changing selection skips the full sweep — only the
final merge is re-run.

Also bumps version to 1.4.7.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 20:46:38 +01:00
EthanfelandClaude Opus 4.6 ba9b3c239a feat: default memory_mode to auto
Memory is transparent and safe — no reason to require opt-in.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 11:27:38 +01:00
EthanfelandClaude Opus 4.6 f83f828d18 chore: bump version to 1.4.6
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 11:26:08 +01:00
EthanfelandClaude Opus 4.6 920cc5a976 feat: add persistent memory system for AutoTuner results
Skip expensive parameter sweeps (30-120s) by caching tuning results
to disk and replaying the best config in a single merge (~2-5s).

Memory is keyed by LoRA combo (order-independent hash) + tuning
settings + algorithm version. Stored as individual JSON files in
models/autotuner_memory/ with atomic writes for crash safety.

Adds memory_mode input (disabled/auto/read_only/clear_and_run) to
LoRAAutoTuner, LoRAAutoTunerSettings, and LoRAOptimizerSimple nodes.
Defaults to disabled for backward compatibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 11:16:25 +01:00
EthanfelandClaude Opus 4.6 4ddb2cbd21 chore: bump version to 1.4.5
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 13:14:20 +01:00
EthanfelandClaude Opus 4.6 98adbc389b docs: update workflow notes — fix misleading tips, fill empty notes
- Additional notes (Optimizer): rewrote strategy_set and merge_refinement
  tips to explain they're different toolboxes, not quality rankings
- Merge Formula note (782): added formula syntax explanation
- Merge Formula note (783): added description of what the node does

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 13:13:38 +01:00
Ethanfel 33e3cb986d Merge branch 'feat/merge-formula' 2026-03-11 13:11:50 +01:00
EthanfelandClaude Opus 4.6 78f46b0a0d chore: bump version to 1.4.3
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 22:50:28 +01:00
EthanfelandClaude Opus 4.6 c30b56481e fix: add missing smooth_slerp_gate parameter to legacy optimizer execute_node
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 22:49:10 +01:00
EthanfelandClaude Opus 4.6 a479f6dc49 fix: add missing smooth_slerp_gate parameter to legacy optimizer execute_node
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 22:48:50 +01:00
EthanfelandClaude Opus 4.6 b0dc9d5273 fix: skip exact linear patch fast path when virtual LoRAs present
The _build_exact_linear_patch fast path concatenates LoRA factors
directly without expanding to dense diffs. It looks up patches via
aliases (string prefixes), but virtual LoRAs from sub-merges store
patches keyed by target keys (tuples). The alias lookup silently
missed virtual LoRAs, producing patches containing only the non-virtual
LoRA — making sub-merged characters invisible in the output.

Also removes diagnostic logging added in the previous commit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 22:46:15 +01:00
EthanfelandClaude Opus 4.6 1c124cd24c debug: add diagnostic logging for virtual LoRA key matching in formula merge
Traces sub-merge patch extraction, target group resolution, and diff
lookup to diagnose why character LoRAs have zero visible effect in
(1+2)+3 formula output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 22:34:21 +01:00
EthanfelandClaude Opus 4.6 63a6658f82 fix: restore _detected_arch in single-LoRA formula path, guard autotuner cache for sub-merges
- _detected_arch was not restored when formula resolved to single item,
  causing wrong architecture preset in the fall-through path
- saved_arch moved before _autotune_resolve_tree so both >= 2 and == 1
  paths can restore it
- Single-LoRA path uses resolved preset_key when coming from formula
- Sub-merge auto_tune no longer overwrites _autotuner_cache, preventing
  loss of cached results from prior runs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 21:58:04 +01:00
EthanfelandClaude Opus 4.6 69e2d97d59 fix: reset _skip_qkv_refusion for final merge and save/restore _detected_arch in tree executor
- _skip_qkv_refusion=True from sub-merges was leaking into the final
  merge in _execute_merge_tree, causing Z-Image models to output
  unfused QKV patches that ComfyUI cannot apply
- Sub-merges may overwrite _detected_arch (e.g. all-virtual stacks);
  save and restore it around _resolve_tree_to_stack

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 21:50:16 +01:00
EthanfelandClaude Opus 4.6 5ab9ec3e2d test: add sub-merge flags, single-item passthrough, and nested formula tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 21:39:30 +01:00
EthanfelandClaude Opus 4.6 723e0f0ccf fix: forward _is_sub_merge/_suppress_pbar to outer recursive call, use normalized_stack for single-LoRA path
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 21:37:55 +01:00
EthanfelandClaude Opus 4.6 7f6df901d5 feat: integrate formula detection into AutoTuner with reviewed bug fixes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 21:30:48 +01:00
EthanfelandClaude Opus 4.6 285f4e7080 feat: add _autotune_resolve_tree for per-sub-merge AutoTuner
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 21:23:53 +01:00
EthanfelandClaude Opus 4.6 4b97d7cacf docs: update AutoTuner sub-merge plan with reviewed bug fixes
Incorporates 7 fixes from code review:
- Bug 1: normalize_keys="disabled" for recursive outer call
- Bug 2: clip_strength_multiplier in at_kwargs
- Bug 4: update active_loras when formula resolves to single item
- Bug 6: _suppress_pbar for sub-merge progress bars
- Bug 7: document evaluator exclusion from sub-merges
- Bug 8: save/restore _detected_arch around recursive call
- Bug 9: _skip_qkv_refusion on single-LoRA path

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 21:17:55 +01:00
EthanfelandClaude Opus 4.6 c197f21444 docs: add AutoTuner per sub-merge implementation plan
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 21:10:05 +01:00
EthanfelandClaude Opus 4.6 557b532556 docs: add AutoTuner per sub-merge design document
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 21:07:47 +01:00
EthanfelandClaude Opus 4.6 267e33d7de fix: count skipped keys per-LoRA not per-alias in _prepare_group_diffs
When a target group has multiple aliases (e.g., virtual LoRA target key +
real LoRA prefix), a miss on one alias but hit on another was incorrectly
counted as a skip. Now skip_count only increments when ALL aliases fail
for a given LoRA, fixing inflated "Skipped keys" in merge formula reports.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 20:37:48 +01:00
EthanfelandClaude Opus 4.6 12a77c318d fix: skip Z-Image QKV re-fusion in formula sub-merges
Sub-merge virtual LoRA patches must stay unfused (to_q/to_k/to_v) so
the outer merge can pair them with other LoRAs' unfused keys. Re-fusion
only happens in the final merge. Fixes 150 skipped keys from shape
mismatch when merging fused virtual patches with unfused style LoRA.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 20:20:37 +01:00
EthanfelandClaude Opus 4.6 27f5a967c8 fix: move virtual LoRA diffs to compute device before analysis
Sub-merge patches are stored on CPU but the final merge's analysis runs
on CUDA. Move precomputed diffs to the compute device in all three diff
lookup paths (_prepare_group_diffs, _process_prefix, _analyze_prefix)
to prevent device mismatch in subspace overlap computation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 20:10:22 +01:00
EthanfelandClaude Opus 4.6 8fec563108 fix: preserve native dtype for virtual LoRA storage_dtype
Use raw tensor dtype (e.g. fp16) instead of post-.float() dtype (fp32)
to avoid 2x memory overhead in final merge patches.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 20:01:39 +01:00
EthanfelandClaude Opus 4.6 d26cd8fae6 fix: pass resolved architecture preset to formula sub-merges
Prevents all-virtual final merges (e.g. (1+2)+(3+4)) from falling back
to sd_unet preset when auto-detection finds no real LoRAs to detect from.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 19:49:27 +01:00
EthanfelandClaude Opus 4.6 3007042d79 fix: handle single-LoRA sub-merge fallback and tuple-key alias collision
- When sub-merge hits single-LoRA fast path (lora_data=None), pass
  sub-stack items through directly instead of creating empty virtual LoRA
- Generate canonical prefix from target_key when all aliases are tuples
  (Flux/WAN all-virtual merges) to prevent group collision at ordered[""]

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 19:37:02 +01:00
EthanfelandClaude Opus 4.6 cbd253196b fix: prevent None diff leaks, preserve tuple keys, restore final cache
- Guard aggregated[i] assignment in _prepare_group_diffs to skip when
  virtual LoRA has no matching key (prevents None diff crashes)
- Keep tuple target keys intact in _collect_lora_prefixes for correct
  Flux/sliced-weight group resolution
- Handle mixed string/tuple sorting in prefix collection and alias lists
- Restore original cache_patches setting for the final merge while
  keeping sub-merges uncached

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 19:29:10 +01:00
EthanfelandClaude Opus 4.6 24970c8b88 fix: correct formula index mapping and remaining pipeline gaps
- Parse formula against full normalized stack, not filtered active_loras,
  so indices match user-specified positions regardless of zero-strength items
- Add string components of tuple target keys to _build_target_groups sets
  for Flux/WanVideo sliced-weight compatibility
- Preserve inner weights in parenthesized expressions (parser fix)
- Handle virtual LoRAs in _analyze_prefix with precomputed diff lookup
- Deep-copy metadata dict in _resolve_tree_to_stack to prevent mutation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 19:14:40 +01:00
EthanfelandClaude Opus 4.6 a59a18071d fix: handle polymorphic return types and edge cases in merge formula
- Handle 3-tuple vs 5-tuple from WanVideoLoRAOptimizer.optimize_merge
- Normalize tuple target keys to strings in _collect_lora_prefixes
  to prevent mixed-type sorting crashes on Flux architectures
- Add tuple fallback in precomputed diff lookups
- Preserve clip_strength through re-normalization
- Free sub-merge model clones after extracting patches

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 18:21:26 +01:00
EthanfelandClaude Opus 4.6 d8410db206 fix: integrate virtual LoRAs into full merge pipeline
- Preserve _precomputed_diffs flag through _normalize_stack
- Handle virtual LoRA model-space keys in _collect_lora_prefixes
  and _build_target_groups
- Use full target_key (including tuples) for virtual LoRA lookup
- Skip _normalize_keys for virtual LoRAs (model-space keys)
- Skip architecture detection for virtual LoRAs
- Avoid dense expansion of compressed patches in _model_to_virtual_lora
- Disable cache_patches for sub-merges to prevent cache thrashing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 18:08:45 +01:00
EthanfelandClaude Opus 4.6 926490bf7c fix: address code quality issues in merge formula executor
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 16:29:05 +01:00