Keep curator auxiliary refs input-aligned
This commit is contained in:
@@ -58,7 +58,7 @@
|
|||||||
- Outputs: `prompt`, `ref_image_1` through `ref_image_9`, `reference_count`, `debug`, `anchor`, `sounds`, `bgm`, `original_ref_1` through `original_ref_9`, `compiled_ref_description_1` through `compiled_ref_description_9`
|
- Outputs: `prompt`, `ref_image_1` through `ref_image_9`, `reference_count`, `debug`, `anchor`, `sounds`, `bgm`, `original_ref_1` through `original_ref_9`, `compiled_ref_description_1` through `compiled_ref_description_9`
|
||||||
- Builds one standalone MiniMax H3 prompt from your final action text plus structured character/location references.
|
- Builds one standalone MiniMax H3 prompt from your final action text plus structured character/location references.
|
||||||
- The action text can mention references by character/location name, alias, `<Picture N>`, or `<refN>`. Only mentioned references are emitted, and the output images are compacted/renumbered so skipped inputs do not leave gaps.
|
- The action text can mention references by character/location name, alias, `<Picture N>`, or `<refN>`. Only mentioned references are emitted, and the output images are compacted/renumbered so skipped inputs do not leave gaps.
|
||||||
- Extra component outputs expose the cleaned anchor, sounds, BGM, and each selected original reference image plus its compiled reference description in compacted order.
|
- Extra component outputs expose the cleaned anchor, sounds, BGM, and each connected input reference image plus its compiled reference description in original socket order. These inspection/reuse outputs are not trimmed by the action text; only the final prompt and `ref_image_*` H3 reference outputs are trimmed.
|
||||||
- Adds curated reference context, anatomy guard text, optional subject-count guard text, anchor/style text, `overall_soundscape:` text, and `background_music:` text while respecting MiniMax H3's reference-generation shape: one prompt plus up to nine reference images.
|
- Adds curated reference context, anatomy guard text, optional subject-count guard text, anchor/style text, `overall_soundscape:` text, and `background_music:` text while respecting MiniMax H3's reference-generation shape: one prompt plus up to nine reference images.
|
||||||
|
|
||||||
- `Dumas H3 Shot Length`
|
- `Dumas H3 Shot Length`
|
||||||
@@ -266,7 +266,7 @@ decr -> use index - 1
|
|||||||
|
|
||||||
`Dumas H3 Plan Attach Scene Images` and `Dumas H3 Plan Extract Scene Images` are a companion pair for `ComfyUI-MiniMaxH3-Contex-Loop` and the local `ref2v` lane. The upstream H3 plan node cannot dynamically grow nine new image sockets for every JSON-defined scene, so Dumas stores scene image bindings beside the plan using a lightweight token and an in-memory registry. That keeps `plan.json` archiving intact while still letting you wire up nine IMAGE sockets per scene through chained helper nodes.
|
`Dumas H3 Plan Attach Scene Images` and `Dumas H3 Plan Extract Scene Images` are a companion pair for `ComfyUI-MiniMaxH3-Contex-Loop` and the local `ref2v` lane. The upstream H3 plan node cannot dynamically grow nine new image sockets for every JSON-defined scene, so Dumas stores scene image bindings beside the plan using a lightweight token and an in-memory registry. That keeps `plan.json` archiving intact while still letting you wire up nine IMAGE sockets per scene through chained helper nodes.
|
||||||
|
|
||||||
`Dumas Character Helper` is the restored two-image/text helper for general H3 workflows, and `Dumas Location Helper` mirrors it for scene/environment references. Both helpers also emit structured `REFERENCE` sockets for the curator. The structured `Dumas Character Reference` and `Dumas Location Reference` nodes remain available separately for workflows that want a single `REFERENCE` socket. `Dumas H3 Prompt Curator` consumes those structured references plus optional anchor, soundscape, and BGM strings, assigns the final `<Picture N>` numbering, and outputs only the compacted images the prompt actually mentions.
|
`Dumas Character Helper` is the restored two-image/text helper for general H3 workflows, and `Dumas Location Helper` mirrors it for scene/environment references. Both helpers also emit structured `REFERENCE` sockets for the curator. The structured `Dumas Character Reference` and `Dumas Location Reference` nodes remain available separately for workflows that want a single `REFERENCE` socket. `Dumas H3 Prompt Curator` consumes those structured references plus optional anchor, soundscape, and BGM strings, assigns the final `<Picture N>` numbering, and outputs compacted `ref_image_*` sockets for only the references the prompt actually mentions. Its `original_ref_*` and `compiled_ref_description_*` outputs mirror the connected input sockets for reuse/debugging even when a reference is not mentioned in the final prompt.
|
||||||
|
|
||||||
`Dumas Strip Iteration Suffix` keeps the part before the first underscore and drops the rest. Names like `char123_pose_final.png` become `char123.png`, while names with no underscore such as `char123.png` are left untouched.
|
`Dumas Strip Iteration Suffix` keeps the part before the first underscore and drops the rest. Names like `char123_pose_final.png` become `char123.png`, while names with no underscore such as `char123.png` are left untouched.
|
||||||
|
|
||||||
|
|||||||
+15
-8
@@ -1253,13 +1253,13 @@ def curate_h3_prompt(
|
|||||||
soundscape_text = _reference_text(soundscape)
|
soundscape_text = _reference_text(soundscape)
|
||||||
bgm_text = _reference_text(bgm)
|
bgm_text = _reference_text(bgm)
|
||||||
reference_description = ""
|
reference_description = ""
|
||||||
individual_reference_descriptions = []
|
selected_reference_descriptions = []
|
||||||
if selected:
|
if selected:
|
||||||
individual_reference_descriptions = [
|
selected_reference_descriptions = [
|
||||||
_reference_context(ref, picture_number)
|
_reference_context(ref, picture_number)
|
||||||
for picture_number, (_slot, ref) in enumerate(selected, 1)
|
for picture_number, (_slot, ref) in enumerate(selected, 1)
|
||||||
]
|
]
|
||||||
reference_description = " ".join(individual_reference_descriptions)
|
reference_description = " ".join(selected_reference_descriptions)
|
||||||
|
|
||||||
prompt_parts = []
|
prompt_parts = []
|
||||||
_append_prompt_section(prompt_parts, "Scene anchor", anchor_text)
|
_append_prompt_section(prompt_parts, "Scene anchor", anchor_text)
|
||||||
@@ -1279,9 +1279,16 @@ def curate_h3_prompt(
|
|||||||
prompt = prompt[: _H3_PROMPT_MAX_CHARS - 3].rstrip() + "..."
|
prompt = prompt[: _H3_PROMPT_MAX_CHARS - 3].rstrip() + "..."
|
||||||
images = [_reference_image(ref) for _slot, ref in selected]
|
images = [_reference_image(ref) for _slot, ref in selected]
|
||||||
images.extend([None] * (_H3_PROMPT_REF_SLOTS - len(images)))
|
images.extend([None] * (_H3_PROMPT_REF_SLOTS - len(images)))
|
||||||
individual_reference_descriptions.extend(
|
original_images = [
|
||||||
[""] * (_H3_PROMPT_REF_SLOTS - len(individual_reference_descriptions))
|
_reference_image(ref) if ref is not None else None
|
||||||
)
|
for ref in normalized_refs
|
||||||
|
]
|
||||||
|
original_images.extend([None] * (_H3_PROMPT_REF_SLOTS - len(original_images)))
|
||||||
|
input_reference_descriptions = [
|
||||||
|
_reference_context(ref, slot_number) if ref is not None else ""
|
||||||
|
for slot_number, ref in enumerate(normalized_refs, 1)
|
||||||
|
]
|
||||||
|
input_reference_descriptions.extend([""] * (_H3_PROMPT_REF_SLOTS - len(input_reference_descriptions)))
|
||||||
debug = (
|
debug = (
|
||||||
f"Selected {len(selected)} reference(s): "
|
f"Selected {len(selected)} reference(s): "
|
||||||
+ ", ".join(
|
+ ", ".join(
|
||||||
@@ -1299,8 +1306,8 @@ def curate_h3_prompt(
|
|||||||
anchor_text,
|
anchor_text,
|
||||||
soundscape_text,
|
soundscape_text,
|
||||||
bgm_text,
|
bgm_text,
|
||||||
*images[:_H3_PROMPT_REF_SLOTS],
|
*original_images[:_H3_PROMPT_REF_SLOTS],
|
||||||
*individual_reference_descriptions[:_H3_PROMPT_REF_SLOTS],
|
*input_reference_descriptions[:_H3_PROMPT_REF_SLOTS],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -503,13 +503,50 @@ class DumasImageNodeTests(unittest.TestCase):
|
|||||||
self.assertEqual(result[13], "steady rain")
|
self.assertEqual(result[13], "steady rain")
|
||||||
self.assertEqual(result[14], "low suspense music")
|
self.assertEqual(result[14], "low suspense music")
|
||||||
self.assertIs(result[15], dave_image)
|
self.assertIs(result[15], dave_image)
|
||||||
self.assertIs(result[16], cafe_image)
|
self.assertIs(result[16], van_image)
|
||||||
self.assertIsNone(result[17])
|
self.assertIs(result[17], cafe_image)
|
||||||
self.assertIn("<Picture 1> Dave", result[24])
|
self.assertIn("<Picture 1> Dave", result[24])
|
||||||
self.assertNotIn("<Picture 2> Coffee Shop", result[24])
|
self.assertNotIn("<Picture 2> Coffee Shop", result[24])
|
||||||
self.assertIn("<Picture 2> Coffee Shop", result[25])
|
self.assertIn("<Picture 2> Blue Van", result[25])
|
||||||
self.assertIn("Location context for <Picture 2> Coffee Shop", result[25])
|
self.assertIn("scuffed blue delivery van", result[25])
|
||||||
self.assertEqual(result[26], "")
|
self.assertIn("<Picture 3> Coffee Shop", result[26])
|
||||||
|
self.assertIn("Location context for <Picture 3> Coffee Shop", result[26])
|
||||||
|
self.assertNotIn("Blue Van", prompt)
|
||||||
|
|
||||||
|
def test_h3_prompt_curator_aux_reference_outputs_follow_input_sockets(self):
|
||||||
|
node = self.image_nodes.DumasH3PromptCuratorNode()
|
||||||
|
used_image = FakeTensorBatch()
|
||||||
|
unused_image = FakeTensorBatch()
|
||||||
|
used = self.image_nodes.make_reference(
|
||||||
|
kind="character",
|
||||||
|
image=used_image,
|
||||||
|
name="Maya",
|
||||||
|
description="short silver hair",
|
||||||
|
)
|
||||||
|
unused = self.image_nodes.make_reference(
|
||||||
|
kind="location",
|
||||||
|
image=unused_image,
|
||||||
|
name="Unused Warehouse",
|
||||||
|
description="rusted loading bay doors",
|
||||||
|
)
|
||||||
|
|
||||||
|
result = node.curate_prompt(
|
||||||
|
action_prompt="Maya waits in the rain.",
|
||||||
|
anatomy_guard="off",
|
||||||
|
subject_count_guard="off",
|
||||||
|
ref_1=used,
|
||||||
|
ref_2=unused,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertIs(result[1], used_image)
|
||||||
|
self.assertIsNone(result[2])
|
||||||
|
self.assertEqual(result[10], 1)
|
||||||
|
self.assertNotIn("Unused Warehouse", result[0])
|
||||||
|
self.assertIs(result[15], used_image)
|
||||||
|
self.assertIs(result[16], unused_image)
|
||||||
|
self.assertIn("<Picture 1> Maya", result[24])
|
||||||
|
self.assertIn("<Picture 2> Unused Warehouse", result[25])
|
||||||
|
self.assertIn("rusted loading bay doors", result[25])
|
||||||
|
|
||||||
def test_h3_prompt_curator_renumbers_explicit_reference_tags(self):
|
def test_h3_prompt_curator_renumbers_explicit_reference_tags(self):
|
||||||
node = self.image_nodes.DumasH3PromptCuratorNode()
|
node = self.image_nodes.DumasH3PromptCuratorNode()
|
||||||
|
|||||||
Reference in New Issue
Block a user