Compare commits

..
2 Commits
3 changed files with 65 additions and 5 deletions
+2 -2
View File
@@ -58,10 +58,10 @@
- `Dumas H3 Prompt Curator` - `Dumas H3 Prompt Curator`
- Inputs: `action_prompt`, `anatomy_guard`, `subject_count_guard`, optional `anchor`, optional `soundscape`, optional `bgm`, optional `ref_1` through `ref_9` - Inputs: `action_prompt`, `anatomy_guard`, `subject_count_guard`, optional `anchor`, optional `soundscape`, optional `bgm`, optional `ref_1` through `ref_9`
- Outputs: `prompt`, `ref_image_1` through `ref_image_9`, `reference_count`, `debug`, `anchor`, `sounds`, `bgm`, `original_ref_1` through `original_ref_9`, `reference_description` - Outputs: `prompt`, `ref_image_1` through `ref_image_9`, `reference_count`, `debug`, `anchor`, `sounds`, `bgm`, `original_ref_1` through `original_ref_9`, `reference_description`, `original_ref_description_1` through `original_ref_description_9`, `compiled_ref_image_1` through `compiled_ref_image_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, selected structured references in compacted order, and the compiled reference-description block used inside the prompt. - Extra component outputs expose the cleaned anchor, sounds, BGM, selected structured references in compacted order, the compiled reference-description block used inside the prompt, and plain image/compiled-description socket pairs for each selected reference.
- 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`
+40 -2
View File
@@ -1253,11 +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 = []
if selected: if selected:
reference_description = " ".join( individual_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)
prompt_parts = [] prompt_parts = []
_append_prompt_section(prompt_parts, "Scene anchor", anchor_text) _append_prompt_section(prompt_parts, "Scene anchor", anchor_text)
@@ -1279,6 +1281,9 @@ def curate_h3_prompt(
images.extend([None] * (_H3_PROMPT_REF_SLOTS - len(images))) images.extend([None] * (_H3_PROMPT_REF_SLOTS - len(images)))
selected_refs = [ref for _slot, ref in selected] selected_refs = [ref for _slot, ref in selected]
selected_refs.extend([None] * (_H3_PROMPT_REF_SLOTS - len(selected_refs))) selected_refs.extend([None] * (_H3_PROMPT_REF_SLOTS - len(selected_refs)))
individual_reference_descriptions.extend(
[""] * (_H3_PROMPT_REF_SLOTS - len(individual_reference_descriptions))
)
debug = ( debug = (
f"Selected {len(selected)} reference(s): " f"Selected {len(selected)} reference(s): "
+ ", ".join( + ", ".join(
@@ -1298,6 +1303,9 @@ def curate_h3_prompt(
bgm_text, bgm_text,
*selected_refs[:_H3_PROMPT_REF_SLOTS], *selected_refs[:_H3_PROMPT_REF_SLOTS],
reference_description, reference_description,
*individual_reference_descriptions[:_H3_PROMPT_REF_SLOTS],
*images[:_H3_PROMPT_REF_SLOTS],
*individual_reference_descriptions[:_H3_PROMPT_REF_SLOTS],
) )
@@ -2691,6 +2699,9 @@ class DumasH3PromptCuratorNode:
+ ("INT", "STRING", "STRING", "STRING", "STRING") + ("INT", "STRING", "STRING", "STRING", "STRING")
+ (_REFERENCE_TYPE,) * _H3_PROMPT_REF_SLOTS + (_REFERENCE_TYPE,) * _H3_PROMPT_REF_SLOTS
+ ("STRING",) + ("STRING",)
+ ("STRING",) * _H3_PROMPT_REF_SLOTS
+ ("IMAGE",) * _H3_PROMPT_REF_SLOTS
+ ("STRING",) * _H3_PROMPT_REF_SLOTS
) )
RETURN_NAMES = ( RETURN_NAMES = (
"prompt", "prompt",
@@ -2718,6 +2729,33 @@ class DumasH3PromptCuratorNode:
"original_ref_8", "original_ref_8",
"original_ref_9", "original_ref_9",
"reference_description", "reference_description",
"original_ref_description_1",
"original_ref_description_2",
"original_ref_description_3",
"original_ref_description_4",
"original_ref_description_5",
"original_ref_description_6",
"original_ref_description_7",
"original_ref_description_8",
"original_ref_description_9",
"compiled_ref_image_1",
"compiled_ref_image_2",
"compiled_ref_image_3",
"compiled_ref_image_4",
"compiled_ref_image_5",
"compiled_ref_image_6",
"compiled_ref_image_7",
"compiled_ref_image_8",
"compiled_ref_image_9",
"compiled_ref_description_1",
"compiled_ref_description_2",
"compiled_ref_description_3",
"compiled_ref_description_4",
"compiled_ref_description_5",
"compiled_ref_description_6",
"compiled_ref_description_7",
"compiled_ref_description_8",
"compiled_ref_description_9",
) )
FUNCTION = "curate_prompt" FUNCTION = "curate_prompt"
CATEGORY = "Dumas/MiniMax" CATEGORY = "Dumas/MiniMax"
+23 -1
View File
@@ -510,6 +510,19 @@ class DumasImageNodeTests(unittest.TestCase):
self.assertIn("<Picture 1> Dave", result[24]) self.assertIn("<Picture 1> Dave", result[24])
self.assertIn("<Picture 2> Coffee Shop", result[24]) self.assertIn("<Picture 2> Coffee Shop", result[24])
self.assertIn("Location context for <Picture 2> Coffee Shop", result[24]) self.assertIn("Location context for <Picture 2> Coffee Shop", result[24])
self.assertIn("<Picture 1> Dave", result[25])
self.assertNotIn("<Picture 2> Coffee Shop", result[25])
self.assertIn("<Picture 2> Coffee Shop", result[26])
self.assertIn("Location context for <Picture 2> Coffee Shop", result[26])
self.assertEqual(result[27], "")
self.assertIs(result[34], dave_image)
self.assertIs(result[35], cafe_image)
self.assertIsNone(result[36])
self.assertIn("<Picture 1> Dave", result[43])
self.assertNotIn("<Picture 2> Coffee Shop", result[43])
self.assertIn("<Picture 2> Coffee Shop", result[44])
self.assertIn("Location context for <Picture 2> Coffee Shop", result[44])
self.assertEqual(result[45], "")
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()
@@ -647,11 +660,20 @@ class DumasImageNodeTests(unittest.TestCase):
def test_h3_prompt_curator_uses_documented_reference_limits(self): def test_h3_prompt_curator_uses_documented_reference_limits(self):
node = self.image_nodes.DumasH3PromptCuratorNode() node = self.image_nodes.DumasH3PromptCuratorNode()
self.assertEqual(len(node.RETURN_TYPES), 25) self.assertEqual(len(node.RETURN_TYPES), 52)
self.assertEqual(node.RETURN_NAMES[1:10], tuple(f"ref_image_{i}" for i in range(1, 10))) self.assertEqual(node.RETURN_NAMES[1:10], tuple(f"ref_image_{i}" for i in range(1, 10)))
self.assertEqual(node.RETURN_NAMES[12:15], ("anchor", "sounds", "bgm")) self.assertEqual(node.RETURN_NAMES[12:15], ("anchor", "sounds", "bgm"))
self.assertEqual(node.RETURN_NAMES[15:24], tuple(f"original_ref_{i}" for i in range(1, 10))) self.assertEqual(node.RETURN_NAMES[15:24], tuple(f"original_ref_{i}" for i in range(1, 10)))
self.assertEqual(node.RETURN_NAMES[24], "reference_description") self.assertEqual(node.RETURN_NAMES[24], "reference_description")
self.assertEqual(
node.RETURN_NAMES[25:34],
tuple(f"original_ref_description_{i}" for i in range(1, 10)),
)
self.assertEqual(node.RETURN_NAMES[34:43], tuple(f"compiled_ref_image_{i}" for i in range(1, 10)))
self.assertEqual(
node.RETURN_NAMES[43:52],
tuple(f"compiled_ref_description_{i}" for i in range(1, 10)),
)
def test_normalize_reference_upgrades_generic_summary_with_socket_picture_id(self): def test_normalize_reference_upgrades_generic_summary_with_socket_picture_id(self):
image = FakeTensorBatch() image = FakeTensorBatch()