fix: H3 picture found in the packed model output; latent steering was off on every real run

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
digital-garbage
2026-09-27 19:01:13 +03:00
co-authored by Claude Opus 5.5
parent 169e8a6a1e
commit 0bb7e3a01a
12 changed files with 124 additions and 43 deletions
+1 -1
View File
@@ -188,7 +188,7 @@ def install(patcher, values, key):
out = executor(x, t, *args, **kwargs)
named = streams.model_args(args, kwargs)
to = named.get("transformer_options")
split = streams.video_of(out)
split = streams.video_of(out, named)
if split is None:
_say("off this run: could not find the picture in this model's latent")
return out
@@ -51,7 +51,6 @@ def test_nothing_banked_at_this_resolution_changes_nothing():
def test_it_banks_the_last_step_and_steers_once_rated(tiny_h3, monkeypatch):
from comfy.nested_tensor import NestedTensor
from comfy.patcher_extension import WrappersMP
from modules.sampling.modifiers.nodes import FunPackLoadModifiers
from modules.system.taste import store
@@ -66,12 +65,13 @@ def test_it_banks_the_last_step_and_steers_once_rated(tiny_h3, monkeypatch):
torch.manual_seed(1)
bad = torch.randn(1, 4, 3, 8, 8)
audio = torch.randn(1, 8, 5)
x0 = NestedTensor([bad, audio])
from conftest import packed_av, unpacked
x0, shapes = packed_av(bad, audio)
for i, rating in enumerate(["disliked", "disliked"]):
monkeypatch.setattr(store, "current_prompt_id", lambda i=i: f"run-{i}")
wrap, outer, status = load()
for o in outer:
o(lambda: wrap(lambda *a, **k: x0, x0, None, None, None, None, _to(3)))
o(lambda: wrap(lambda *a, **k: x0, x0, None, None, None, None, _to(3), latent_shapes=shapes))
assert store.rate(f"run-{i}", rating)["recorded"] == ["dynashift"]
wrap, outer, _status = load()
@@ -80,8 +80,8 @@ def test_it_banks_the_last_step_and_steers_once_rated(tiny_h3, monkeypatch):
for o in outer:
o(lambda: None) # a run starts: the bank is read
assert any("2 disliked, 0 liked banked" in e["message"] for e in log.history())
early = wrap(lambda *a, **k: x0, x0, None, None, None, None, _to(1))
early = wrap(lambda *a, **k: x0, x0, None, None, None, None, _to(1), latent_shapes=shapes)
assert early is x0 # first half: untouched
late = wrap(lambda *a, **k: x0, x0, None, None, None, None, _to(3))
assert not torch.allclose(late.tensors[0], bad)
assert late.tensors[1] is audio # sound untouched
late = wrap(lambda *a, **k: x0, x0, None, None, None, None, _to(3), latent_shapes=shapes)
assert not torch.allclose(unpacked(late, shapes)[0], bad)
assert torch.equal(unpacked(late, shapes)[1], audio) # sound untouched
+1 -1
View File
@@ -74,7 +74,7 @@ def install(patcher, values, key):
out = executor(x, t, *args, **kwargs)
named = streams.model_args(args, kwargs)
to = named.get("transformer_options")
split = streams.video_of(out)
split = streams.video_of(out, named)
if split is None:
_say("off this run: could not find the picture in this model's latent")
return out
@@ -42,9 +42,9 @@ def _teach(kind, names):
def _x0():
from comfy.nested_tensor import NestedTensor
from conftest import packed_av
torch.manual_seed(3)
return NestedTensor([torch.randn(1, 4, 3, 8, 8), torch.randn(1, 8, 5)])
return packed_av(torch.randn(1, 4, 3, 8, 8), torch.randn(1, 8, 5))
def _start(outer):
@@ -55,16 +55,17 @@ def _start(outer):
def test_late_guidance_banks_the_final_picture_and_steers_only_late(tiny_h3, monkeypatch):
from modules.system.taste import store
monkeypatch.setattr(store, "current_prompt_id", lambda: "run-1")
x0 = _x0()
x0, shapes = _x0()
wrap, outer = _load(tiny_h3, "output_guidance")
for o in outer:
o(lambda: wrap(lambda *a, **k: x0, x0, None, None, None, None, _to(3)))
o(lambda: wrap(lambda *a, **k: x0, x0, None, None, None, None, _to(3), latent_shapes=shapes))
assert store.rate("run-1", "liked")["recorded"] == ["x0_final"]
_teach("x0_final", ["final"])
wrap, outer = _load(tiny_h3, "output_guidance")
_start(outer)
assert wrap(lambda *a, **k: x0, x0, None, None, None, None, _to(1)) is x0
late = wrap(lambda *a, **k: x0, x0, None, None, None, None, _to(3))
assert not torch.allclose(late.tensors[0], x0.tensors[0])
assert late.tensors[1] is x0.tensors[1]
from conftest import unpacked
assert wrap(lambda *a, **k: x0, x0, None, None, None, None, _to(1), latent_shapes=shapes) is x0
late = wrap(lambda *a, **k: x0, x0, None, None, None, None, _to(3), latent_shapes=shapes)
assert not torch.allclose(unpacked(late, shapes)[0], unpacked(x0, shapes)[0])
assert torch.equal(unpacked(late, shapes)[1], unpacked(x0, shapes)[1])
+3 -3
View File
@@ -120,12 +120,12 @@ def install(patcher, values, key):
return base
size = torch.linalg.vector_norm(c[:, words], dim=-1, dtype=torch.float32).mean()
step = (d.to(c.device) * STEP * size).to(c.dtype) * words.view(1, -1, 1)
split = streams.video_of(base)
split = streams.video_of(base, named)
if split is None:
_say("off this run: could not find the picture in this model's latent")
return base
plus = streams.video_of(executor(x, t, **{**named, "c_crossattn": c + step}))
minus = streams.video_of(executor(x, t, **{**named, "c_crossattn": c - step}))
plus = streams.video_of(executor(x, t, **{**named, "c_crossattn": c + step}), named)
minus = streams.video_of(executor(x, t, **{**named, "c_crossattn": c - step}), named)
video, rebuild = split
return rebuild(video + (plus[0] - minus[0]) * amount)
@@ -44,7 +44,7 @@ def test_similar_prompts_pick_their_own_direction():
def test_late_steps_combine_three_passes_on_the_picture_words_only(tiny_h3):
from comfy.nested_tensor import NestedTensor
from conftest import packed_av, unpacked
from comfy.patcher_extension import WrappersMP
from modules.sampling.modifiers.nodes import FunPackLoadModifiers
from modules.system.taste import store
@@ -68,19 +68,20 @@ def test_late_steps_combine_three_passes_on_the_picture_words_only(tiny_h3):
def executor(x, t, c_concat=None, c_crossattn=None, control=None, transformer_options=None, **kw):
seen.append(c_crossattn.clone())
return NestedTensor([torch.full((1, 2, 1, 2, 2), float(c_crossattn[0, :, 0].sum())), audio])
return packed_av(torch.full((1, 2, 1, 2, 2), float(c_crossattn[0, :, 0].sum())), audio)[0]
c = torch.ones(1, 4, dim)
tags = torch.tensor([1, 1, 0, 1]) # row 2: a reference image's token
x0 = executor(None, None, c_crossattn=c)
shapes = packed_av(torch.zeros(1, 2, 1, 2, 2), audio)[1]
seen.clear()
early = wrap(executor, x0, None, None, c, None, _to(0), minimax_payload={"text_token_tags": tags})
assert len(seen) == 1 and torch.equal(early.tensors[0], x0.tensors[0])
early = wrap(executor, x0, None, None, c, None, _to(0), minimax_payload={"text_token_tags": tags}, latent_shapes=shapes)
assert len(seen) == 1 and torch.equal(early, x0)
seen.clear()
late = wrap(executor, x0, None, None, c, None, _to(3), minimax_payload={"text_token_tags": tags})
late = wrap(executor, x0, None, None, c, None, _to(3), minimax_payload={"text_token_tags": tags}, latent_shapes=shapes)
assert len(seen) == 3
plus = seen[1]
assert torch.equal(plus[0, 2], c[0, 2]) and not torch.equal(plus[0, 0], c[0, 0])
assert not torch.equal(late.tensors[0], x0.tensors[0])
assert late.tensors[1] is audio
assert not torch.equal(unpacked(late, shapes)[0], unpacked(x0, shapes)[0])
assert torch.equal(unpacked(late, shapes)[1], audio)
@@ -80,7 +80,7 @@ def install(patcher, values, key):
out = executor(x, t, *args, **kwargs)
named = streams.model_args(args, kwargs)
q = quarter(named.get("transformer_options"))
split = streams.video_of(out)
split = streams.video_of(out, named)
if q is None or split is None:
_say("off this run: could not place this step on the schedule or find the picture")
return out
@@ -42,9 +42,9 @@ def _teach(kind, names):
def _x0():
from comfy.nested_tensor import NestedTensor
from conftest import packed_av
torch.manual_seed(3)
return NestedTensor([torch.randn(1, 4, 3, 8, 8), torch.randn(1, 8, 5)])
return packed_av(torch.randn(1, 4, 3, 8, 8), torch.randn(1, 8, 5))
def _start(outer):
@@ -56,17 +56,18 @@ def test_early_guidance_steers_in_the_first_quarter_and_banks_every_quarter(tiny
from modules.system.taste import store
_teach("x0_quarters", ["q0", "q1", "q2", "q3"])
monkeypatch.setattr(store, "current_prompt_id", lambda: "run-2")
x0 = _x0()
x0, shapes = _x0()
wrap, outer = _load(tiny_h3, "trajectory_guidance")
def run():
return [wrap(lambda *a, **k: x0, x0, None, None, None, None, _to(i)) for i in range(4)]
return [wrap(lambda *a, **k: x0, x0, None, None, None, None, _to(i), latent_shapes=shapes) for i in range(4)]
results = {}
for o in outer:
o(lambda: results.setdefault("steps", run()))
first = results["steps"][0]
assert not torch.allclose(first.tensors[0], x0.tensors[0])
assert not torch.allclose(first[..., :4 * 3 * 8 * 8], x0[..., :4 * 3 * 8 * 8])
assert torch.equal(first[..., 4 * 3 * 8 * 8:], x0[..., 4 * 3 * 8 * 8:])
pending = torch.load(store.ROOT / "fox" / "x0_quarters.pending.pt")["rows"]
assert sorted(pending) == ["q0", "q1", "q2", "q3"]