Character Prompt Merger πβ€
Reassemble a character prompt from just the parts you want β no API keys, no network
- character
- tags
The Character Prompt Merger is the quiet half of the PromptPrism pack, and it's the half you'll actually live in. The Parser does the clever - and paid - work of splitting a prompt into categories. The Merger takes that structured character object and reassembles exactly the categories you want into one flat tag string. No API keys, no network, no per-run cost. Just string math over whatever the parser handed you.
What it's for
Think character-sprite or Visual Novel work. You build a "base character" once - hair, eyes, face, body, species - then per scene you toggle on pose, background, composition and whatever outfit that scene needs, and leave the rest off. Or parse two characters and merge pieces of each. The README's example is exactly that second move: parse a second prompt and pull only the elements you want from it to combine with the first. That's the pattern this node exists to make painless.
How it works
It walks the 15 categories from the character object. For each one: if its enable_ toggle is on, it takes the tags from the object - unless you've wired an override_ input, which replaces them outright. Empty tags get dropped. If the category's weight isn't 1.0, every tag in that category gets a tag:1.2-style weight appended. Then everything is joined with the delimiter plus a space, and your prefix is stuck on the front.
The inputs that matter
- character - the CHARACTER socket from the Parser. This is the one beginners trip on: the Merger does not work standalone. Drag one in without a parser feeding it and there's nothing to merge.
- delimiter - default
,. Tags come outtag1, tag2, tag3. - enable_<category> and weight_<category> - 15 of each. Toggles decide whether a category appears at all; weights (0β10, default 1) scale its tags. Use a weight below 1 to downplay a category instead of deleting it.
- override_<category> (optional) - wire a string node in and it replaces the parsed tags for that category. Handy for "same character, but this scene she's wearing X."
- prefix (optional) - a string prepended to the whole result, if you want something like
solo,before the assembled tags.
The output
One tags string, nothing more. It feeds a CLIPTextEncode (or any string-combining node) and from there into your sampler. Because the merger is pure text assembly, you can batch variations without touching the parser or spending another API call.
Two quirks worth knowing (both real, both in the source)
- Leave prefix empty and your output starts with a stray
", ". The code unconditionally emitsprefix + delimiter + tags, so with no prefix you get a leading comma. Feed a prefix or strip it downstream - cosmetic, but it'll confuse you the first time. - The weight syntax is CLIP-style attention weighting:
blue_hair:1.2. Exactly right for Pony/Illustrious/NoobAI, and meaningless on LLM-encoded models, where the colon passes through as literal punctuation. Know which lineage your checkpoint is on before you bother with weights.
And if you toggle every category off, the output is a bare ", " - an empty prompt in disguise. Keep at least one category on.
Install
Same pack as the Parser - ComfyUI Manager (search "PromptPrism"), or:
cd ComfyUI/custom_nodes
git clone https://github.com/Bewinxed/PromptPrism.git
cd PromptPrism
pip install -r requirements.txt
Then restart ComfyUI. The Merger itself adds no extra dependencies and downloads no models; the install cost is the pack's shared LiteLLM/Instructor stack, which the Parser needs anyway.
Worth the setup? If you're doing character-consistent batch work on a tag-based model, yes - it turns "same girl, different scene" from a copy-paste chore into a toggle. If you only generate one-off images, skip it: the Merger is useless without a parser upstream, and the parser is the part that costs you money per run.
Inputs (48)
| Name | Type | Default | Description |
|---|---|---|---|
| character | CHARACTER | β | |
| delimiter | STRING | , | β |
| enable_quality | BOOLEAN | true | β |
| weight_quality | FLOAT | 1.00β10 | β |
| enable_clothes | BOOLEAN | true | β |
| weight_clothes | FLOAT | 1.00β10 | β |
| enable_hair | BOOLEAN | true | β |
| weight_hair | FLOAT | 1.00β10 | β |
| enable_eyes | BOOLEAN | true | β |
| weight_eyes | FLOAT | 1.00β10 | β |
| enable_face | BOOLEAN | true | β |
| weight_face | FLOAT | 1.00β10 | β |
| enable_expression | BOOLEAN | true | β |
| weight_expression | FLOAT | 1.00β10 | β |
| enable_body | BOOLEAN | true | β |
| weight_body | FLOAT | 1.00β10 | β |
| enable_pose | BOOLEAN | true | β |
| weight_pose | FLOAT | 1.00β10 | β |
| enable_accessories | BOOLEAN | true | β |
| weight_accessories | FLOAT | 1.00β10 | β |
| enable_background | BOOLEAN | true | β |
| weight_background | FLOAT | 1.00β10 | β |
| enable_composition | BOOLEAN | true | β |
| weight_composition | FLOAT | 1.00β10 | β |
| enable_gender | BOOLEAN | true | β |
| weight_gender | FLOAT | 1.00β10 | β |
| enable_species | BOOLEAN | true | β |
| weight_species | FLOAT | 1.00β10 | β |
| enable_age | BOOLEAN | true | β |
| weight_age | FLOAT | 1.00β10 | β |
| enable_name | BOOLEAN | true | β |
| weight_name | FLOAT | 1.00β10 | β |
| override_quality πopt | STRING | β | |
| override_clothes πopt | STRING | β | |
| override_hair πopt | STRING | β | |
| override_eyes πopt | STRING | β | |
| override_face opt | STRING | β | |
| override_expression πopt | STRING | β | |
| override_body π€opt | STRING | β | |
| override_pose πΊopt | STRING | β | |
| override_accessories πΆοΈopt | STRING | β | |
| override_background ποΈopt | STRING | β | |
| override_composition πΌοΈopt | STRING | β | |
| override_gender π»opt | STRING | β | |
| override_species πΎopt | STRING | β | |
| override_age opt | STRING | β | |
| override_name opt | STRING | β | |
| prefixopt | STRING | β |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| tags | STRING | β |