From 0ff74be52f83c8a739de4a64bae2fcb11faad17b Mon Sep 17 00:00:00 2001 From: Ethanfel Date: Tue, 7 Jul 2026 19:49:26 +0200 Subject: [PATCH] fix(inline): thread model-class arch hint into auto_tune so captured chains score under the right preset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Completes FIX #12: the hint reached optimize_merge but not auto_tune's _normalize_stack, so inline autotuner-mode candidate scoring + the community arch bucket used key-based detection (mis-tagging e.g. attention-only Qwen as ACE-Step). File-based stacks have no virtual items → hint unreachable → unchanged. Co-Authored-By: Claude Fable 5 --- lora_optimizer.py | 8 +++++++- tests/test_inline_optimizer.py | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/lora_optimizer.py b/lora_optimizer.py index e1e910c..2373cbc 100644 --- a/lora_optimizer.py +++ b/lora_optimizer.py @@ -11572,7 +11572,13 @@ class LoRAAutoTuner(LoRAOptimizer): lora_stack = clean_stack # --- Normalize & validate stack --- - normalized_stack = self._normalize_stack(lora_stack, normalize_keys=normalize_keys) + # Pass the model-class arch hint so captured (inline) chains score + # candidates under the correct preset (else key-based detection + # mis-tags e.g. attention-only Qwen as ACE-Step). File-based stacks + # have no virtual items, so the hint is unreachable — identical. + normalized_stack = self._normalize_stack( + lora_stack, normalize_keys=normalize_keys, + _arch_hint=self._model_class_arch(model)) active_loras = [item for item in normalized_stack if item["strength"] != 0] if not active_loras: return (model, clip, "No active LoRAs in stack.", "", None, None) diff --git a/tests/test_inline_optimizer.py b/tests/test_inline_optimizer.py index 8650eb1..c1263e8 100644 --- a/tests/test_inline_optimizer.py +++ b/tests/test_inline_optimizer.py @@ -1622,6 +1622,31 @@ class TestInlineAutoTunerDelegation(unittest.TestCase): "analysis report", {"td": 1}, {"ld": 2}) node._autotuner_delegate = types.SimpleNamespace(auto_tune=fake_auto_tune) + def test_autotune_threads_model_class_arch_hint(self): + """auto_tune must pass the model-class arch hint to _normalize_stack so + captured chains score candidates under the right preset (was hintless → + attention-only Qwen scored under the ACE-Step preset).""" + class QwenImage: # mirrors comfy.model_base.QwenImage + pass + model = _FakePatcher({}) + model.model = QwenImage() + delegate = lora_optimizer.LoRAAutoTuner() + seen = {} + + class _Stop(Exception): + pass + + def rec_normalize(stack, normalize_keys="disabled", _arch_hint=None): + seen["hint"] = _arch_hint + raise _Stop + + delegate._normalize_stack = rec_normalize + stack = [{"name": "chain lora #1 [x]", "lora": {"k": _adapter()}, + "strength": 1.0, "_precomputed_diffs": True}] + with self.assertRaises(_Stop): + delegate.auto_tune(model, stack, 1.0) + self.assertEqual(seen.get("hint"), "qwen_image") + def test_delegates_with_virtual_stack_and_stripped_model(self): model = self._model(_chain_patches( (0.8, {"a": _adapter()}), (0.5, {"a": _adapter()})))