diff --git a/app/ui/features/settings/taste.js b/app/ui/features/settings/taste.js index 307b6cf8..bbc3e9a6 100644 --- a/app/ui/features/settings/taste.js +++ b/app/ui/features/settings/taste.js @@ -74,7 +74,7 @@ export const taste = (app) => function mount() { if (influence && influence.error) rows.push(c.banner.warn({ text: `Could not read the recording: ${influence.error}` })); // The switch is always here, even when the report could not be read: a failed read must not take away the way to turn recording off. rows.push(c.toggle.default({ label: "Record block influence", hint: "On: each run on a Taste key is measured, and kept once you rate it. Off: nothing is recorded.", - checked: influence && influence.state ? !!influence.state.enabled : true, + checked: influence && influence.state ? !!influence.state.enabled : false, onChange: async (on) => { try { await app.api.setBlockInfluence(on); } catch (err) { tell(err.message); } refreshResearch(); } })); if (influence && influence.state) { const { state, four } = influence; diff --git a/modules/sampling/block_influence/__init__.py b/modules/sampling/block_influence/__init__.py index d0f7e2ce..361db5ab 100644 --- a/modules/sampling/block_influence/__init__.py +++ b/modules/sampling/block_influence/__init__.py @@ -17,8 +17,8 @@ activity differed in the 4th decimal). That version averaged over steps before looking. Each block's push is averaged over the steps of a run, so a per-step signal that cancels within a run is lost (a known limit, not yet fixed). -Switched on from Settings > Refinement & Taste (on by default; it is research -data). The hooks sit on the model whenever a taste key is set and read the +Switched on from Settings > Refinement & Taste (off by default; it is optional +research data). The hooks sit on the model whenever a taste key is set and read the switch at the start of each run, because ComfyUI caches the node that installs them and a toggle must reach the next generation. """ diff --git a/modules/sampling/block_influence/measure.py b/modules/sampling/block_influence/measure.py index 2420e026..caaa1de1 100644 --- a/modules/sampling/block_influence/measure.py +++ b/modules/sampling/block_influence/measure.py @@ -8,7 +8,7 @@ from ..._core import config, dit_hooks, registry KIND = "block_influence" MIN_PER_GROUP = 2 # liked AND disliked before a difference is one -SWITCH = config.ROOT / "block_influence.enabled" # on disk: a fresh rental resumes recording +SWITCH = config.ROOT / "block_influence.enabled" # on disk: the choice survives a restart # Why recording cannot or did not store anything, for the panel (shown only while recording is on). @@ -16,11 +16,11 @@ problem = None def enabled() -> bool: - # On until someone turns it off: with no switch file yet (a fresh rental) recording runs. + # Off until someone turns it on: with no switch file yet nothing is recorded. try: - return SWITCH.read_text().strip() != "0" + return SWITCH.read_text().strip() == "1" except OSError: - return True + return False def set_enabled(on: bool) -> bool: diff --git a/modules/sampling/block_influence/tests/test_block_influence.py b/modules/sampling/block_influence/tests/test_block_influence.py index 7cca86a6..181603a6 100644 --- a/modules/sampling/block_influence/tests/test_block_influence.py +++ b/modules/sampling/block_influence/tests/test_block_influence.py @@ -387,3 +387,19 @@ def test_the_measurement_stays_out_of_comfys_memory_recorder_but_the_block_does_ tally.measure(0, {"img": torch.zeros(8, 4)}, block) assert paused["block_ran_paused"] is False, "the block must run inside the recorder, as it always did" assert paused["entered"] >= 1, "the measurement's own allocations must be paused" + + +def test_recording_is_off_until_the_user_turns_it_on(tiny_h3, tmp_path): + from modules.sampling.block_influence import measure + assert not (tmp_path / "switch").exists() # a fresh install: no switch file yet + assert measure.enabled() is False + base = tiny_h3.run() + patched, _ = _load(tiny_h3) + out = tiny_h3.sample(patched) + assert torch.equal(out[0], base[0]) and torch.equal(out[1], base[1]) + from modules.system.taste import store + assert not (store.ROOT / "fox" / "block_influence.pending.pt").exists() + measure.set_enabled(True) # the setting still works + assert measure.enabled() is True + (tmp_path / "switch").write_text("junk") # anything but "1" is off + assert measure.enabled() is False diff --git a/modules/sampling/block_influence/tests/test_groups.py b/modules/sampling/block_influence/tests/test_groups.py index ca108e6e..52ddc874 100644 --- a/modules/sampling/block_influence/tests/test_groups.py +++ b/modules/sampling/block_influence/tests/test_groups.py @@ -9,13 +9,16 @@ def _row(reward, axis, profile): return {"reward": reward, "axis": axis, "rows": {"ratio": torch.tensor(profile, dtype=torch.float32)}} -def test_recording_is_on_when_no_switch_file_exists(tmp_path, monkeypatch): +def test_recording_is_off_when_no_switch_file_exists(tmp_path, monkeypatch): monkeypatch.setattr(measure, "SWITCH", tmp_path / "switch") - assert measure.enabled() is True - measure.set_enabled(False) + assert not (tmp_path / "switch").exists() assert measure.enabled() is False measure.set_enabled(True) assert measure.enabled() is True + measure.set_enabled(False) + assert measure.enabled() is False + (tmp_path / "switch").write_text("junk") + assert measure.enabled() is False def test_groups_sort_dislikes_by_axis():