Commit Graph
345 Commits
Author SHA1 Message Date
EthanfelandClaude Opus 4.7 b161b13886 feat: tag community cache uploads with base_model_family
Threads the detected architecture family (zimage, wan, flux, qwen_image,
etc.) into the config payload so the 'dit' arch_preset bucket can be
filtered by sub-family downstream (estimator training, targeted cache
reuse). Existing 400 configs on HF were backfilled with zimage in a
separate dataset commit.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-21 11:08:52 +02:00
EthanfelandClaude Opus 4.6 d6c8bfbf73 fix: deep-convert JSON lists to tuples for cached target_keys
target_key can be a nested tuple like ("key", (dim, start, size)).
JSON round-trips flatten this to ["key", [dim, start, size]].
The shallow tuple() conversion only fixed the outer level, leaving
inner lists unhashable — causing TypeError in single_lora_keys.add().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-20 12:45:40 +02:00
EthanfelandClaude Opus 4.6 be1847cc37 fix: reduce analysis partial save log from info to debug
Fires on every prefix during analysis, spamming the console.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-20 10:30:27 +02:00
EthanfelandClaude Opus 4.6 a51580f9d9 fix: make combo progress seed-independent and prevent auto-randomization
Root cause: ComfyUI auto-randomizes INT inputs named "seed", generating
a new seed each queue run. Progress was keyed by seed, so each new seed
started from scratch.

- Rename "seed" input to "shuffle_order" to prevent auto-randomization
- Store completed combo hashes in a flat set instead of per-seed keys
  (combo hashes are already order-independent, so progress persists
  regardless of shuffle order)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 18:10:14 +02:00
EthanfelandClaude Opus 4.6 5318e48e8c feat: add diagnostic logging to LoRACombinationGenerator
Logs seed, pool size, combo count, completed count, progress file path
on entry, confirms save success/failure, and logs returned combo info.
Improves error message for insufficient LoRAs to show filtered list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 18:04:23 +02:00
Ethanfel 75076b4efe Merge branch 'speed/autotuner-loop-optimizations' into feat/acestep-merge-optimization 2026-04-19 13:01:40 +02:00
EthanfelandClaude Opus 4.6 3e03a048b9 feat: require folder_filter and support multiple comma-separated prefixes
Empty filter no longer allowed — there's no point merging across
incompatible architectures. Users must specify prefixes like
'zit/,zib/' to combine compatible LoRA pools.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 12:59:17 +02:00
EthanfelandClaude Opus 4.6 9d90ee728e feat: add folder_filter input to LoRA Combination Generator
Filters the LoRA pool by path prefix (e.g. "zimage/" or "sdxl/")
so users can generate combos only for compatible architectures.
Empty string includes all LoRAs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 12:56:07 +02:00
EthanfelandClaude Opus 4.6 663d782d26 fix: add missing log warning when skipping deleted LoRA combos
Design doc requires logging when a LoRA file is missing and a combo
is skipped. Follows existing project convention of logging.warning
with the [LoRA ...] prefix.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 12:40:24 +02:00
EthanfelandClaude Opus 4.6 4afbef2fc0 fix: use InterruptProcessingException for graceful stop when combinations exhausted
LoRACombinationGenerator previously raised RuntimeError when all combos
were done, showing a red error in ComfyUI's UI. Now uses ComfyUI's
InterruptProcessingException which sends an "execution_interrupted"
event — clean yellow stop instead of a scary error traceback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 12:37:34 +02:00
EthanfelandClaude Opus 4.6 f3a3cb4a5d fix: replace recursive retry with iterative loop in get_next_combo
The missing-LoRA handling used unbounded recursion via
`return self.get_next_combo(...)` which would hit Python's recursion
limit of 1000 when many LoRAs are deleted. Replaced with an iterative
while-loop that skips deleted-LoRA combos without growing the stack.

Also removed redundant `OUTPUT_NODE = False` (it's the default).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 12:33:38 +02:00
EthanfelandClaude Opus 4.6 f76b2d7a84 feat: add ComfyUI node interface to LoRACombinationGenerator
Add INPUT_TYPES, RETURN_TYPES, IS_CHANGED, __init__, and get_next_combo
methods so the class works as a ComfyUI node. Register in
NODE_CLASS_MAPPINGS and NODE_DISPLAY_NAME_MAPPINGS. Add 3 tests for the
node interface (input fields, return types, IS_CHANGED returns NaN).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 12:28:33 +02:00
EthanfelandClaude Opus 4.6 9c9c7390d4 fix: use string combo_size and seed_ prefix in LoRACombinationGenerator
combo_size now accepts ComfyUI dropdown strings ("2", "3", "2_and_3")
instead of integers. Progress JSON keys use "seed_42" format instead
of bare "42" for clarity.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 12:24:02 +02:00
EthanfelandClaude Opus 4.6 b56d973542 feat: add LoRACombinationGenerator with combo generation and progress tracking
Implements core static methods for generating, shuffling, hashing, and
tracking LoRA combinations (pairs/triples) with deterministic seeding
and JSON-based progress persistence. Includes 11 TDD tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 12:21:18 +02:00
EthanfelandClaude Opus 4.6 fe9becfe73 feat: add ACE-Step 1.5 merge optimization for voice preservation
Add dedicated architecture support for ACE-Step music generation model LoRAs
with optimizations informed by the v1.5 hybrid attention architecture — cross-
attention is the primary voice-identity pathway (always global, attending to
timbre+lyric+text conditioning), while self-attention alternates sliding window
(local timbre) and global GQA (long-range structure).

Changes:
- New `acestep_dit` preset: wider orthogonal band (0.30), higher TIES threshold
  (0.35), full magnitude preservation (floor 1.0) — biases toward SLERP over
  TIES to prevent voice signal trimming in cross-attn layers
- Fix `to_out` → `o_proj` normalization bug (was producing `out_proj`)
- Add v1.0 detection and normalization (transformer_blocks, speaker_embedder,
  lyric_encoder mapped to v1.5 canonical form)
- Refine WAN detection to exclude transformer_blocks (prevents v1.0 misdetect)
- Add `acestep_dit` to all architecture_preset UI dropdowns
- 25 new tests (detection, normalization, preset)
- Technical reference doc with architecture analysis and design rationale

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 12:59:13 +02:00
EthanfelandClaude Opus 4.6 96312042d1 fix: add SD 1.5 detection and fix SDXL diffusers key normalization
The SDXL normalizer's .replace('.', '_') was mangling LoRA weight
suffixes (.lora_down.weight → _lora_down_weight), breaking prefix
extraction for diffusers-format keys. Added _split_lora_suffix to
preserve suffixes. Also split SD 1.5 from SDXL detection so single-TE
LoRAs normalize to lora_te_ instead of lora_te1_.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 00:45:50 +02:00
EthanfelandClaude Opus 4.6 2bc4af3580 perf: cache single-LoRA merge results across Phase 2 candidates
Single-LoRA prefixes produce identical patches regardless of merge config
(forced to weighted_sum, early return at _merge_diffs). Cache results keyed
by (label_prefix, auto_strength) to skip diff recomputation for candidates
2+ sharing the same auto_strength value.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 00:52:01 +02:00
EthanfelandClaude Opus 4.6 cc1660710b fix: remove _target_key lambda — compare patch keys directly
Patch dict keys and single_lora_keys both store target_key values
from _group_target_key(). When target_key is a tuple (weight slices),
the lambda extracted k[0] (a string) which never matched the tuple
in the set. Direct comparison handles both string and tuple keys.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 00:27:27 +02:00
EthanfelandClaude Opus 4.6 7a2e838c11 refactor: move _target_key lambda outside Phase 2 loop
Avoid redefining the lambda on every iteration — it's a pure function.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 00:22:12 +02:00
EthanfelandClaude Opus 4.6 36334bbdbb perf: cache single-LoRA patch scoring across Phase 2 candidates
Single-LoRA patches bypass all merge strategies (early return at line
2868). Score them once on the first candidate and merge as baseline
for subsequent candidates. All composite_score components (norm_cv,
effective_rank, sparsity) are scale-invariant, so auto_strength
differences between candidates don't affect correctness.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 00:21:13 +02:00
EthanfelandClaude Opus 4.6 376f304b4c perf: cache LoRA format detection per lora_dict
A LoRA file uses one key format consistently. Caching the winning
format index (0-3) after first detection avoids up to 6 wasted
dict lookups per prefix on subsequent calls. Cache miss on stale
entries is safe — falls through to full cascade.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 00:17:28 +02:00
EthanfelandClaude Opus 4.6 19780e20f6 perf: transfer LoRA factors before float conversion in scoring
Moving fp16/bf16 tensors to score_device then converting to fp32
halves the PCIe transfer bandwidth vs converting first. For ~240
LoRAAdapter patches per candidate, saves meaningful transfer time.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 00:12:43 +02:00
EthanfelandClaude Opus 4.6 695441f3ff perf: gate psutil memory logging to first/last Phase 2 iteration
Memory diagnostics on every iteration adds overhead without value.
First and last iteration still show whether memory leaks occur.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 00:11:37 +02:00
EthanfelandClaude Opus 4.6 2f2848f271 perf: lighten GC in Phase 2 loop — gen-0 only, drop empty_cache
Replace full gc.collect() with gc.collect(0) (youngest generation only,
~10x faster). Remove torch.cuda.empty_cache() — CUDA allocator handles
block reuse, forced sync is pure overhead. Post-loop cleanup at line
9354-9356 still does full gc.collect() + empty_cache().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 00:10:58 +02:00
Ethanfel 023d9cf4f2 fix: skip conflict analysis chatter for single LoRA — clean decision log 2026-04-09 13:29:17 +02:00
EthanfelandClaude Sonnet 4.6 e2b6c94467 feat: add enabled_{i} toggle to LoRAStackDynamic — skips disabled slots in build_stack
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 11:57:26 +02:00
EthanfelandClaude Sonnet 4.6 8cc78a9be3 fix: reorder settings_source/tuner_data before decision_smoothing in INPUT_TYPES; upload candidates list in community cache
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 11:43:12 +02:00
EthanfelandClaude Sonnet 4.6 3b4a574355 feat: drop download_only — community cache is upload_and_download only
Removes the passive download_only option to encourage contribution.
Users who want community results need to also contribute back.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 15:27:19 +02:00
EthanfelandClaude Sonnet 4.6 5361a18de6 feat: upload config from memory hit path
Memory hits had content_hashes and the cached config available but
never uploaded. Now uploads the winning config to community cache on
memory hits too. lora/pair analysis entries are still only uploaded
after a full sweep (they require _run_group_analysis output).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 15:19:44 +02:00
EthanfelandClaude Sonnet 4.6 a031d7b027 fix: community cache blocked by memory hit — move before memory check
Community download block was inside Pass 1, after the memory check's
early return. Runs with memory_mode=auto never reached the community
code, so nothing was downloaded or uploaded despite community_cache
being set to upload_and_download.

Moved lora/pair cache init + community download block to before the
persistent memory lookup so community hits and uploads work regardless
of memory cache state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 15:15:19 +02:00
EthanfelandClaude Sonnet 4.6 7f63e610f8 fix: move "will run full analysis" log to after all cache checks
Previously fired before memory/community checks, causing misleading
"MISS — will run full analysis" followed by "Memory HIT". Now logs
"No cached results — running full sweep" only when all caches miss.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 15:07:46 +02:00
EthanfelandClaude Sonnet 4.6 a4f1a75a33 feat: improve community cache logging verbosity
- Show mode, LoRA count, and arch at start of check
- Report lora/pair cache hits as X/N (e.g. "2/3 lora hit, 2/3 pair hit")
- Log "No config found — will run full sweep" on config miss
- Log config version mismatch with both versions
- Log "Config HIT" with score and arch on success
- Log "COMMUNITY CACHE HIT" with score on replay
- Track and report upload counts (N lora, M pair, config score)
- Log when config not uploaded due to community score being higher

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 15:02:48 +02:00
EthanfelandClaude Sonnet 4.6 f1ddd4ae24 refactor: split AUTOTUNER_ALGO_VERSION into two separate versions
AUTOTUNER_ALGO_VERSION = "1.5.0"  — scoring formula, memory/config format
ANALYSIS_CACHE_VERSION = "1.6.0"  — per-prefix conflict math (lora/pair/analysis caches)

The clip_strength_multiplier fix only affects CLIP prefix entries.
Models without CLIP (Wan, etc.) had valid lora/pair caches that were
being incorrectly invalidated by the version bump. Now only analysis
caches are invalidated when conflict math changes, and only memory/
community configs are invalidated when scoring changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 14:59:00 +02:00
EthanfelandClaude Sonnet 4.6 3146aff22e fix: support huggingface-cli login for community cache uploads
Fall back to huggingface_hub stored token so users who ran
'huggingface-cli login' can upload without setting HF_TOKEN manually.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 14:02:49 +02:00
EthanfelandClaude Sonnet 4.6 b323d810a3 fix: community hit normalize_keys override user setting
Hardcoded "normalize_keys": "enabled" in reconstructed community
tuner_data was always overriding the user's normalize_keys param.
Removed the field so the fallback correctly uses the user's setting.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 13:55:22 +02:00
EthanfelandClaude Sonnet 4.6 e5c12561d1 fix: community cache arch key mismatch and misleading banner
- Download and upload now both resolve arch via _resolve_arch_preset,
  so config filenames are consistent (e.g. "dit" not "flux")
- Upload reuses _arch_key_for_community instead of tuner_preset_key
- Community hit banner no longer shows memory_mode hint

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 13:51:34 +02:00
EthanfelandClaude Sonnet 4.6 620399d3c1 feat: add community_cache — HF-backed shared analysis results
Replaces dead record_dataset param with community_cache dropdown
(disabled / download_only / upload_and_download).

Downloads are anonymous via urllib; uploads require HF_TOKEN and
huggingface_hub. LoRA filenames are never shared — content hashes
(SHA256[:16]) are used as keys. Per-LoRA/pair conflict metrics and
winning merge configs are shared; network errors fall back silently to
the full local sweep.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 13:39:56 +02:00
EthanfelandClaude Sonnet 4.6 23038f7e3c fix: include clip_strength_multiplier in lora cache magnitude unscaling
magnitude_samples in _analyze_target_group are built with eff_s =
strength * clip_strength_multiplier for CLIP prefixes without a per-LoRA
clip_strength. The extraction function was dividing by raw strength only,
so stored samples were off by csm. Reconstruction then rescaled without
csm, causing wrong magnitudes if csm changed between runs.

Fix: pass clip_strength_multiplier through _extract_for_lora_cache and
_reconstruct_from_pair_lora_cache, and use the same eff_s formula as
_prepare_group_diffs. Non-CLIP prefixes and models without CLIP are
unaffected (csm is never applied to them).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 12:17:19 +02:00
EthanfelandClaude Sonnet 4.6 453dfc8f04 feat: auto_ignore_strength falls back to highest-strength cached entry
When auto_ignore_strength misses on the names-only hash, scan existing
strength-sensitive entries with the same LoRA names and settings, and
use the one made with the highest total absolute strength (most reliable
strategy rankings). The result is then promoted to the names-only key
so future runs hit directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 23:19:36 +02:00
EthanfelandClaude Sonnet 4.6 4fabaf7417 feat: add auto_ignore_strength memory mode to AutoTuner
New memory_mode option that caches tuning results keyed by LoRA names
only (ignoring strengths). Useful when sweeping strengths on orthogonal
LoRAs where the optimal config (strategy, sparsification, refinement)
doesn't change with strength — avoids full Phase 2 re-run on each
strength change while still replaying the merge with current strengths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 23:17:03 +02:00
Ethanfel 490042fc7d fix: don't overwrite valid lora cache entries with None non-participant sentinel 2026-04-03 20:06:52 +02:00
Ethanfel 950c724817 fix: move pair/lora extraction outside cached_analysis guard in CPU path 2026-04-03 19:56:54 +02:00
Ethanfel 5d9e980667 fix: use eff_s for sign-flip check in pair/lora cache reconstruction (clip_strength support) 2026-04-03 19:39:45 +02:00
EthanfelandClaude Sonnet 4.6 e947decc73 feat: wire pair/lora cache load and save through auto_tune
Loads lora/pair caches before _run_group_analysis and merges new entries
back into on-disk cache files after successful analysis, completing the
analysis cache feature end-to-end.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 19:33:06 +02:00
Ethanfel c39b60c006 fix: rename lora_entry to pair_entry in pair cache extraction blocks 2026-04-03 19:31:15 +02:00
EthanfelandClaude Sonnet 4.6 2f29e6e727 feat: wire pair/lora cache hit/miss into _run_group_analysis
Add lora_caches/pair_caches/lora_hashes params to _run_group_analysis,
skip _analyze_target_group on full cache hit via _pair_lora_cache_hit,
and populate new_lora_entries/new_pair_entries in the return dict on miss.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 19:28:34 +02:00
Ethanfel df0f20da9b fix: use raw strength for display_l2 in pair/lora cache reconstruction 2026-04-03 19:25:45 +02:00
EthanfelandClaude Sonnet 4.6 d0746aad55 feat: add _reconstruct_from_pair_lora_cache
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 19:22:16 +02:00
Ethanfel b5db2bc6fa fix: remove dead guard and fix test docstring in extraction helpers 2026-04-03 19:20:08 +02:00
EthanfelandClaude Sonnet 4.6 4680f94c3f feat: add per-lora and per-pair cache extraction helpers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 18:34:05 +02:00