Revert "Revert long videos ref routing to release"
This reverts commit 00985b73b3.
This commit is contained in:
+22
-2
@@ -4586,6 +4586,26 @@ def resolve_tagged_refs(text, ref_list):
|
|||||||
return out.strip(), [ref_list[n - 1] for n in live], dropped
|
return out.strip(), [ref_list[n - 1] for n in live], dropped
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_prompt_refs(text, ref_list):
|
||||||
|
"""(rewritten text, refs, dropped) for the refs a shot actually carries.
|
||||||
|
|
||||||
|
Explicit <Picture N> tags still decide which slot numbers the prompt points at,
|
||||||
|
but named character matches must ride into the real ref-image list too. Without
|
||||||
|
that split, a shot could inherit the facts/context for "Mara" and "Jon" while
|
||||||
|
only carrying a tagged location image, which reads exactly like the names were
|
||||||
|
understood but the faces were ignored."""
|
||||||
|
rewritten, tagged_refs, dropped = resolve_tagged_refs(text, ref_list)
|
||||||
|
refs = list(tagged_refs)
|
||||||
|
seen = {id(ref) for ref in refs}
|
||||||
|
for _slot_number, ref in _named_character_refs_for_text(rewritten, ref_list):
|
||||||
|
marker = id(ref)
|
||||||
|
if marker in seen:
|
||||||
|
continue
|
||||||
|
seen.add(marker)
|
||||||
|
refs.append(ref)
|
||||||
|
return rewritten, refs, dropped
|
||||||
|
|
||||||
|
|
||||||
def shot_references(ref_list, ref_mode, shot_index, handoff):
|
def shot_references(ref_list, ref_mode, shot_index, handoff):
|
||||||
"""Pure: which reference images shot `shot_index` is conditioned on, or [] when
|
"""Pure: which reference images shot `shot_index` is conditioned on, or [] when
|
||||||
the shot should use the keyframe handoff instead.
|
the shot should use the keyframe handoff instead.
|
||||||
@@ -6750,7 +6770,7 @@ class H3LongVideos:
|
|||||||
for shot_index, gen in enumerate(gens):
|
for shot_index, gen in enumerate(gens):
|
||||||
shot_mode = beat_ref_mode_directive(beats[shot_index] if shot_index < len(beats) else "") or ref_mode
|
shot_mode = beat_ref_mode_directive(beats[shot_index] if shot_index < len(beats) else "") or ref_mode
|
||||||
if shot_mode in ("where tagged", "auto ref2v") and any_tags_anywhere:
|
if shot_mode in ("where tagged", "auto ref2v") and any_tags_anywhere:
|
||||||
if resolve_tagged_refs(gen, ref_slots)[1]:
|
if resolve_prompt_refs(gen, ref_slots)[1]:
|
||||||
on.append(shot_index + 1)
|
on.append(shot_index + 1)
|
||||||
tagged_used = True
|
tagged_used = True
|
||||||
else:
|
else:
|
||||||
@@ -6845,7 +6865,7 @@ class H3LongVideos:
|
|||||||
# The prompt itself says where each reference belongs: the shot whose
|
# The prompt itself says where each reference belongs: the shot whose
|
||||||
# text names <Picture N> gets image N, renumbered to match what that
|
# text names <Picture N> gets image N, renumbered to match what that
|
||||||
# shot actually carries. Every untagged shot keeps its handoff.
|
# shot actually carries. Every untagged shot keeps its handoff.
|
||||||
gen_prompt, shot_refs, dropped = resolve_tagged_refs(gen_prompt, ref_slots)
|
gen_prompt, shot_refs, dropped = resolve_prompt_refs(gen_prompt, ref_slots)
|
||||||
for n in dropped:
|
for n in dropped:
|
||||||
if n not in ref_missing:
|
if n not in ref_missing:
|
||||||
ref_missing.append(n)
|
ref_missing.append(n)
|
||||||
|
|||||||
@@ -423,6 +423,41 @@ class DumasH3LongVideosHelperTests(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
self.assertEqual(dropped, [4])
|
self.assertEqual(dropped, [4])
|
||||||
|
|
||||||
|
def test_resolve_prompt_refs_keeps_named_character_images_alongside_tagged_location(self):
|
||||||
|
refs = [
|
||||||
|
{"kind": "character", "image": "img1", "name": "Mara"},
|
||||||
|
{"kind": "character", "image": "img2", "name": "Jon"},
|
||||||
|
{"kind": "location", "image": "img3", "name": "Hangar"},
|
||||||
|
]
|
||||||
|
|
||||||
|
text, references, dropped = self.module.resolve_prompt_refs(
|
||||||
|
"Mara and Jon argue inside <Picture 3>.",
|
||||||
|
refs,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(text, "Mara and Jon argue inside <Picture 1>.")
|
||||||
|
self.assertEqual(
|
||||||
|
[self.module._reference_image(ref) for ref in references],
|
||||||
|
["img3", "img1", "img2"],
|
||||||
|
)
|
||||||
|
self.assertEqual(dropped, [])
|
||||||
|
|
||||||
|
def test_resolve_prompt_refs_where_tagged_mode_stays_tag_only(self):
|
||||||
|
refs = [
|
||||||
|
{"kind": "character", "image": "img1", "name": "Mara"},
|
||||||
|
{"kind": "location", "image": "img2", "name": "Hangar"},
|
||||||
|
]
|
||||||
|
|
||||||
|
text, references, dropped = self.module.resolve_prompt_refs(
|
||||||
|
"Mara waits in the hangar near <Picture 2>.",
|
||||||
|
refs,
|
||||||
|
include_named=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(text, "Mara waits in the hangar near <Picture 1>.")
|
||||||
|
self.assertEqual([self.module._reference_image(ref) for ref in references], ["img2"])
|
||||||
|
self.assertEqual(dropped, [])
|
||||||
|
|
||||||
def test_resolve_shot_references_uses_named_characters_without_picture_tags(self):
|
def test_resolve_shot_references_uses_named_characters_without_picture_tags(self):
|
||||||
refs = [
|
refs = [
|
||||||
{"kind": "character", "image": "img1", "name": "Mara"},
|
{"kind": "character", "image": "img1", "name": "Mara"},
|
||||||
@@ -444,6 +479,21 @@ class DumasH3LongVideosHelperTests(unittest.TestCase):
|
|||||||
self.assertFalse(shot_tag_driven)
|
self.assertFalse(shot_tag_driven)
|
||||||
self.assertEqual(mode_eff, "auto ref2v")
|
self.assertEqual(mode_eff, "auto ref2v")
|
||||||
|
|
||||||
|
def test_resolve_prompt_refs_prioritizes_characters_before_locations(self):
|
||||||
|
refs = [
|
||||||
|
{"kind": "location", "image": "img1", "name": "Hangar"},
|
||||||
|
{"kind": "character", "image": "img2", "name": "Mara"},
|
||||||
|
]
|
||||||
|
|
||||||
|
text, references, dropped = self.module.resolve_prompt_refs(
|
||||||
|
"[Generation 1] Mara waits in the hangar.",
|
||||||
|
refs,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(text, "[Generation 1] Mara waits in the hangar.")
|
||||||
|
self.assertEqual([self.module._reference_image(ref) for ref in references], ["img2", "img1"])
|
||||||
|
self.assertEqual(dropped, [])
|
||||||
|
|
||||||
def test_shot_references_uses_all_connected_sparse_slots(self):
|
def test_shot_references_uses_all_connected_sparse_slots(self):
|
||||||
refs = [
|
refs = [
|
||||||
None,
|
None,
|
||||||
@@ -697,6 +747,21 @@ class DumasH3LongVideosHelperTests(unittest.TestCase):
|
|||||||
self.assertIn("Persistent appearance for Mara: silver hair.", context)
|
self.assertIn("Persistent appearance for Mara: silver hair.", context)
|
||||||
self.assertNotIn("Persistent wardrobe/style for Mara: red jacket.", context)
|
self.assertNotIn("Persistent wardrobe/style for Mara: red jacket.", context)
|
||||||
|
|
||||||
|
def test_resolve_prompt_refs_adds_named_location_refs(self):
|
||||||
|
refs = [
|
||||||
|
{"kind": "location", "image": "img2", "name": "Hangar", "description": "wet concrete floor"},
|
||||||
|
]
|
||||||
|
|
||||||
|
rewritten, matched, dropped = self.module.resolve_prompt_refs(
|
||||||
|
"[Generation 1] They wait in the hangar.",
|
||||||
|
refs,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(rewritten, "[Generation 1] They wait in the hangar.")
|
||||||
|
self.assertEqual(dropped, [])
|
||||||
|
self.assertEqual(len(matched), 1)
|
||||||
|
self.assertEqual(matched[0]["name"], "Hangar")
|
||||||
|
|
||||||
def test_resolve_tagged_refs_drops_reference_without_image(self):
|
def test_resolve_tagged_refs_drops_reference_without_image(self):
|
||||||
refs = [
|
refs = [
|
||||||
{"kind": "character", "image": None, "name": "Mara"},
|
{"kind": "character", "image": None, "name": "Mara"},
|
||||||
|
|||||||
Reference in New Issue
Block a user