From 71b9a1f5149bb8a30e79c816c80b1832a6dda391 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 25 Oct 2026 20:44:59 +0000 Subject: [PATCH] A rating re-runs the same seed for every learner, not only the Attention explorer The taste module now fingerprints rated rows into the load node's cache key. Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01RnrTBt9b8CdJwub5roffF3 --- modules/sampling/attention_bandit/__init__.py | 14 +------------- .../tests/test_attention_bandit.py | 11 ++++++----- modules/system/taste/__init__.py | 17 ++++++++++++++++- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/modules/sampling/attention_bandit/__init__.py b/modules/sampling/attention_bandit/__init__.py index 9f9f745b..f48af4fe 100644 --- a/modules/sampling/attention_bandit/__init__.py +++ b/modules/sampling/attention_bandit/__init__.py @@ -219,16 +219,4 @@ def install(patcher, values, key): return f"{len(groups)} depth groups over {len(blocks)} blocks, {size}" -def cache_key(): - """Changes whenever a rating reaches this kind. ComfyUI skips a graph whose inputs did not - change, and a rating is not an input: the same seed rated and sent again would run nothing.""" - try: - ask = registry.current().ask - key = ask("taste_latest_key") - stat = ask("taste_kind", key, KIND).path().stat() if key else None - return f"{stat.st_mtime_ns}:{stat.st_size}" if stat else "" - except Exception: # noqa: BLE001 -- a fingerprint must never fail a run - return "" - - -PROVIDES = {"modifier": install, "cache_key": cache_key} +PROVIDES = {"modifier": install} diff --git a/modules/sampling/attention_bandit/tests/test_attention_bandit.py b/modules/sampling/attention_bandit/tests/test_attention_bandit.py index 2b4e5161..57c0804a 100644 --- a/modules/sampling/attention_bandit/tests/test_attention_bandit.py +++ b/modules/sampling/attention_bandit/tests/test_attention_bandit.py @@ -138,17 +138,18 @@ def test_a_block_list_with_nothing_usable_is_refused(tiny_h3): assert "attention_bandit: failed to install" in status -def test_a_rating_changes_the_cache_key_so_the_same_seed_runs_again(tiny_h3, monkeypatch): +def test_a_rating_changes_the_taste_cache_key_so_the_same_seed_runs_again(tiny_h3, monkeypatch): from modules.sampling import attention_bandit as m - from modules.system.taste import store + from modules.system.taste import cache_key, store patched, _ = _load(tiny_h3, blocks="0-3") - assert m.cache_key() == "" + assert cache_key() == "" monkeypatch.setattr(m, "draw", lambda table, rng=random: [0] * len(table)) _run(_outer(patched), lambda: tiny_h3.run(patched)) + assert cache_key() == "" # a waiting capture is not a rating store.rate("run-1", "liked") - first = m.cache_key() + first = cache_key() assert first monkeypatch.setattr(store, "current_prompt_id", lambda: "run-2") _run(_outer(patched), lambda: tiny_h3.run(patched)) store.rate("run-2", "liked") - assert m.cache_key() != first + assert cache_key() != first diff --git a/modules/system/taste/__init__.py b/modules/system/taste/__init__.py index c2f92a73..36873b7d 100644 --- a/modules/system/taste/__init__.py +++ b/modules/system/taste/__init__.py @@ -151,6 +151,21 @@ def taste_latest_key(): return store.latest_key() +def cache_key(): + """Changes whenever a rating reaches the latest key. ComfyUI skips a graph whose inputs did not + change, and a rating is not an input: the same seed rated and sent again would run nothing, for + every module that learns from ratings. Waiting captures are left out: every run writes one.""" + try: + key = store.latest_key() + folder = store._dir(key) if key else None + if folder is None or not folder.is_dir(): + return "" + return "|".join(f"{p.name}:{p.stat().st_mtime_ns}:{p.stat().st_size}" + for p in sorted(folder.glob("*.pt")) if ".pending." not in p.name) + except Exception: # noqa: BLE001 -- a fingerprint must never fail a run + return "" + + def taste_kind(key, kind): return Kind(key, kind) @@ -298,4 +313,4 @@ def routes(table, base, web): return web.json_response({"imported": name, "kinds": count, "keys": store.keys()}) -PROVIDES = {"modifier": install, "taste_store": taste_store, "taste_kind": taste_kind, "taste_latest_key": taste_latest_key, "routes": routes} +PROVIDES = {"modifier": install, "taste_store": taste_store, "taste_kind": taste_kind, "taste_latest_key": taste_latest_key, "cache_key": cache_key, "routes": routes}