Expand character helper fact fields
This commit is contained in:
@@ -28,10 +28,10 @@
|
|||||||
- Reads back the seven optional images for a selected MiniMax H3 plan scene, for example by connecting the current `clip_index`.
|
- Reads back the seven optional images for a selected MiniMax H3 plan scene, for example by connecting the current `clip_index`.
|
||||||
|
|
||||||
- `Dumas Character Helper`
|
- `Dumas Character Helper`
|
||||||
- Inputs: `image1`, `image2`, `image1_picture_id`, `image2_picture_id`, `character_id`, `name`, `height_feet`, `height_inches`, `accent`, `general`
|
- Inputs: `image1`, `image2`, `image1_picture_id`, `image2_picture_id`, `character_id`, `name`, `alias`, `pronouns`, `age`, `nationality`, `occupation`, `height_feet`, `height_inches`, `accent`, `general`
|
||||||
- Outputs: `image1`, `image2`, `character_text`
|
- Outputs: `image1`, `image2`, `character_text`
|
||||||
- Passes both images through unchanged and builds a character reference string such as `<Picture 2> and <Picture 3> reference the same character who is called Dave.`
|
- Passes both images through unchanged and builds a character reference string such as `<Picture 2> and <Picture 3> reference the same character who is called Dave.`
|
||||||
- Appends optional sentences for character ID, height, accent, and freeform notes only when those fields are filled in.
|
- Appends optional sentences for non-visual facts such as ID, alias, pronouns, age, nationality, occupation, height, accent, and freeform notes only when those fields are valid and filled in.
|
||||||
|
|
||||||
- `Dumas JSON String to Object`
|
- `Dumas JSON String to Object`
|
||||||
- Input: `json_string`
|
- Input: `json_string`
|
||||||
@@ -189,7 +189,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`. The upstream H3 plan node cannot dynamically grow six 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 six 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`. The upstream H3 plan node cannot dynamically grow six 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 six IMAGE sockets per scene through chained helper nodes.
|
||||||
|
|
||||||
`Dumas Character Helper` lives in `Dumas/String`. Use the picture ID dropdowns to decide which `<Picture N>` tags get mentioned in the generated text, while the two IMAGE sockets continue downstream unchanged.
|
`Dumas Character Helper` lives in `Dumas/String`. Use the picture ID dropdowns to decide which `<Picture N>` tags get mentioned in the generated text, while the two IMAGE sockets continue downstream unchanged. The node is tuned for useful non-visible facts rather than visual descriptions already obvious from the reference images.
|
||||||
|
|
||||||
`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.
|
||||||
|
|
||||||
|
|||||||
+98
-1
@@ -290,11 +290,36 @@ def _ensure_sentence(value):
|
|||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_positive_int(value):
|
||||||
|
text = str(value or "").strip()
|
||||||
|
if not text:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
parsed = int(text)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
return None
|
||||||
|
if parsed <= 0:
|
||||||
|
return None
|
||||||
|
return parsed
|
||||||
|
|
||||||
|
|
||||||
|
def _indefinite_article(value):
|
||||||
|
text = _normalize_free_text(value).lower()
|
||||||
|
if not text:
|
||||||
|
return "a"
|
||||||
|
return "an" if text[0] in "aeiou" else "a"
|
||||||
|
|
||||||
|
|
||||||
def _build_character_helper_text(
|
def _build_character_helper_text(
|
||||||
primary_picture_id,
|
primary_picture_id,
|
||||||
secondary_picture_id,
|
secondary_picture_id,
|
||||||
character_id,
|
character_id,
|
||||||
name,
|
name,
|
||||||
|
alias,
|
||||||
|
pronouns,
|
||||||
|
age,
|
||||||
|
nationality,
|
||||||
|
occupation,
|
||||||
height_feet,
|
height_feet,
|
||||||
height_inches,
|
height_inches,
|
||||||
accent,
|
accent,
|
||||||
@@ -304,8 +329,13 @@ def _build_character_helper_text(
|
|||||||
secondary_picture = int(secondary_picture_id)
|
secondary_picture = int(secondary_picture_id)
|
||||||
character_name = _normalize_free_text(name)
|
character_name = _normalize_free_text(name)
|
||||||
character_id = _normalize_free_text(character_id)
|
character_id = _normalize_free_text(character_id)
|
||||||
|
alias = _normalize_free_text(alias)
|
||||||
|
pronouns = _normalize_free_text(pronouns)
|
||||||
|
nationality = _normalize_free_text(nationality)
|
||||||
|
occupation = _normalize_free_text(occupation)
|
||||||
accent = _normalize_free_text(accent)
|
accent = _normalize_free_text(accent)
|
||||||
general = _ensure_sentence(general)
|
general = _ensure_sentence(general)
|
||||||
|
age_value = _parse_positive_int(age)
|
||||||
character_label = _label_for_character(character_name, character_id)
|
character_label = _label_for_character(character_name, character_id)
|
||||||
|
|
||||||
if character_name:
|
if character_name:
|
||||||
@@ -333,12 +363,29 @@ def _build_character_helper_text(
|
|||||||
if character_id:
|
if character_id:
|
||||||
lines.append(f'The character ID string is "{character_id}".')
|
lines.append(f'The character ID string is "{character_id}".')
|
||||||
|
|
||||||
|
if alias:
|
||||||
|
lines.append(f"{character_label} is also known as {alias}.")
|
||||||
|
|
||||||
|
if pronouns:
|
||||||
|
lines.append(f"{character_label} uses {pronouns} pronouns.")
|
||||||
|
|
||||||
|
if age_value is not None:
|
||||||
|
lines.append(f"{character_label} is {age_value} years old.")
|
||||||
|
|
||||||
|
if nationality:
|
||||||
|
lines.append(f"{character_label} is {nationality}.")
|
||||||
|
|
||||||
|
if occupation:
|
||||||
|
lines.append(f"{character_label} works as {occupation}.")
|
||||||
|
|
||||||
height_text = _format_height_text(height_feet, height_inches)
|
height_text = _format_height_text(height_feet, height_inches)
|
||||||
if height_text:
|
if height_text:
|
||||||
lines.append(f"{character_label} is {height_text} tall.")
|
lines.append(f"{character_label} is {height_text} tall.")
|
||||||
|
|
||||||
if accent:
|
if accent:
|
||||||
lines.append(f"{character_label} has a {accent} accent.")
|
lines.append(
|
||||||
|
f"{character_label} speaks in {_indefinite_article(accent)} {accent} accent."
|
||||||
|
)
|
||||||
|
|
||||||
if general:
|
if general:
|
||||||
lines.append(general)
|
lines.append(general)
|
||||||
@@ -798,6 +845,46 @@ class DumasCharacterHelperNode:
|
|||||||
"tooltip": "Character name used in the main reference sentences.",
|
"tooltip": "Character name used in the main reference sentences.",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
"alias": (
|
||||||
|
"STRING",
|
||||||
|
{
|
||||||
|
"default": "",
|
||||||
|
"multiline": False,
|
||||||
|
"tooltip": "Optional alternate name, codename, or nickname.",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
"pronouns": (
|
||||||
|
"STRING",
|
||||||
|
{
|
||||||
|
"default": "",
|
||||||
|
"multiline": False,
|
||||||
|
"tooltip": "Optional pronouns such as he/him or she/her.",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
"age": (
|
||||||
|
"STRING",
|
||||||
|
{
|
||||||
|
"default": "",
|
||||||
|
"multiline": False,
|
||||||
|
"tooltip": "Optional numeric age. Invalid values are omitted.",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
"nationality": (
|
||||||
|
"STRING",
|
||||||
|
{
|
||||||
|
"default": "",
|
||||||
|
"multiline": False,
|
||||||
|
"tooltip": "Optional nationality, origin, or cultural background.",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
"occupation": (
|
||||||
|
"STRING",
|
||||||
|
{
|
||||||
|
"default": "",
|
||||||
|
"multiline": False,
|
||||||
|
"tooltip": "Optional job, role, or function that is not visually obvious.",
|
||||||
|
},
|
||||||
|
),
|
||||||
"height_feet": (
|
"height_feet": (
|
||||||
["", "3", "4", "5", "6", "7", "8"],
|
["", "3", "4", "5", "6", "7", "8"],
|
||||||
{
|
{
|
||||||
@@ -839,6 +926,11 @@ class DumasCharacterHelperNode:
|
|||||||
image2_picture_id,
|
image2_picture_id,
|
||||||
character_id,
|
character_id,
|
||||||
name,
|
name,
|
||||||
|
alias,
|
||||||
|
pronouns,
|
||||||
|
age,
|
||||||
|
nationality,
|
||||||
|
occupation,
|
||||||
height_feet,
|
height_feet,
|
||||||
height_inches,
|
height_inches,
|
||||||
accent,
|
accent,
|
||||||
@@ -849,6 +941,11 @@ class DumasCharacterHelperNode:
|
|||||||
image2_picture_id,
|
image2_picture_id,
|
||||||
character_id,
|
character_id,
|
||||||
name,
|
name,
|
||||||
|
alias,
|
||||||
|
pronouns,
|
||||||
|
age,
|
||||||
|
nationality,
|
||||||
|
occupation,
|
||||||
height_feet,
|
height_feet,
|
||||||
height_inches,
|
height_inches,
|
||||||
accent,
|
accent,
|
||||||
|
|||||||
@@ -251,9 +251,14 @@ class DumasImageNodeTests(unittest.TestCase):
|
|||||||
image2_picture_id="3",
|
image2_picture_id="3",
|
||||||
character_id="char_dave",
|
character_id="char_dave",
|
||||||
name="Dave",
|
name="Dave",
|
||||||
|
alias="The Locksmith",
|
||||||
|
pronouns="he/him",
|
||||||
|
age="41",
|
||||||
|
nationality="English",
|
||||||
|
occupation="a detective",
|
||||||
height_feet="6",
|
height_feet="6",
|
||||||
height_inches="2",
|
height_inches="2",
|
||||||
accent="northern English",
|
accent="English",
|
||||||
general="wears a long grey coat",
|
general="wears a long grey coat",
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -266,8 +271,13 @@ class DumasImageNodeTests(unittest.TestCase):
|
|||||||
"<Picture 2> is the primary full-body reference for Dave.\n"
|
"<Picture 2> is the primary full-body reference for Dave.\n"
|
||||||
"<Picture 3> is a frontal facial reference for Dave.\n"
|
"<Picture 3> is a frontal facial reference for Dave.\n"
|
||||||
'The character ID string is "char_dave".\n'
|
'The character ID string is "char_dave".\n'
|
||||||
|
"Dave is also known as The Locksmith.\n"
|
||||||
|
"Dave uses he/him pronouns.\n"
|
||||||
|
"Dave is 41 years old.\n"
|
||||||
|
"Dave is English.\n"
|
||||||
|
"Dave works as a detective.\n"
|
||||||
"Dave is 6 feet 2 inches tall.\n"
|
"Dave is 6 feet 2 inches tall.\n"
|
||||||
"Dave has a northern English accent.\n"
|
"Dave speaks in an English accent.\n"
|
||||||
"wears a long grey coat."
|
"wears a long grey coat."
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -284,6 +294,11 @@ class DumasImageNodeTests(unittest.TestCase):
|
|||||||
image2_picture_id="6",
|
image2_picture_id="6",
|
||||||
character_id="",
|
character_id="",
|
||||||
name="",
|
name="",
|
||||||
|
alias="",
|
||||||
|
pronouns="",
|
||||||
|
age="unknown",
|
||||||
|
nationality="",
|
||||||
|
occupation="",
|
||||||
height_feet="",
|
height_feet="",
|
||||||
height_inches="",
|
height_inches="",
|
||||||
accent="",
|
accent="",
|
||||||
|
|||||||
Reference in New Issue
Block a user