EzFlex-PromptHelper
Prompt Cards, Merged Output, and an Optional LLM Rewrite
- media_in_1
- media_in_2
- media_in_3
- media_in_4
- media_in_5
- media_in_6
- media_in_7
- media_in_8
- media_in_9
- media_in_10
- media_in_11
- media_in_12
- media_in_13
- media_in_14
- media_in_15
- media_in_16
- Merged prompt
- Card 1
- Card 2
- Card 3
- Card 4
- Card 5
- Card 6
- Card 7
- Card 8
- Card 9
- Card 10
- Card 11
- Card 12
- Card 13
- Card 14
- Card 15
- Card 16
- Card 17
- Card 18
- Card 19
- Card 20
- Card 21
- Card 22
- Card 23
- Card 24
- Card 25
- Card 26
- Card 27
- Card 28
- Card 29
- Card 30
- Card 31
- Card 32
A prompt in ComfyUI is a text box. Which is fine until you're maintaining four of them - a character block, a style block, a negative, a block of camera terms - and trying a second version of one means pasting over the good one.
EzFlex-PromptHelper turns the prompt into a stack of cards. Each card is a small rich-text editor with a Default and an Optimized tab, a merge switch, and its own output port. The node emits a Merged prompt plus one STRING per card. Compose, toggle, and nothing gets destroyed.
Inputs
Beyond the panel-written config (multiline STRING, default "{}"), this node has no CLIP input - deliberately. Instead it has two families of dynamic optional sockets:
media_in_1…media_in_16- any-type: images, video, audio, 3D models, with a new empty slot appearing when you connect one. These are reference media. The node reads the media ports of generator nodes on the canvas and numbers them, and you reference them in text as@图片1/@视频1/@音频1- or pick them from the reference-media window, grouped by the node that produces them.card_in_1…card_in_32- STRING, one per card. Connect external text and it overrides that card's panel content, and the card greys out. This is how you drive the stack from a wildcard processor or a generated prompt.
Outputs
Merged prompt first, then Card 1 … Card 32 - all STRING. Wire the merged output into your CLIP Text Encode; wire an individual card when one encoder wants only the character block.
The thing to internalize is that the card slider and the overall slider are separate layers with separate slots. A card's "Optimized" result lives in that card's slot and only affects that card's port; the overall result only affects the merged prompt. They never overwrite each other. Point a slider at an empty slot and you get an empty string - no fallback, no padding. Strict, and it has saved a few people from silently sampling an empty prompt.
Merge is a per-card switch: green means the card joins the merged prompt, gray means it only travels through its own port.
The optimize layer, where the opinion lives
There's a Tools dropdown offering three ways to have a model rewrite your prompt: API (a vendor endpoint), TextGenerate (a local CLIP/text-generation path you point at a model file in the settings), and llama (a llama.cpp/Ollama-style server, or llama-cpp-python running in process). Fire one manually, or flip a runtime auto-optimize switch. The three auto switches are mutually exclusive, and if a call fails it errors out rather than quietly using the unoptimized text. Good.
What gets sent to the model is your original text with the @图片1 markers intact - the system prompt asks it to leave them alone - and the vendor-specific syntax (<Picture 1>, @image1) is only compiled at the output ports. So if the model rewrites your marker into "the first image", the mapping is gone and no amount of spec compilation brings it back. If you lean on reference media, prefer a local model. The KB's LLM-in-ComfyUI notes make the same point from the other end: local, uncensored models are why this category exists, since API providers filter exactly the prompts people buy these tools to write. And a node holding your API key is a node to install deliberately, not because a workflow told you to.
The other stuff it does
The editor is Word-flavoured - bold, alignment, font size, colour, highlight, find & replace, a skill button that inserts a *.md file line by line at the caret, a tag panel with a bundled tag library and random-tag generator, card presets saved to user_data/prompts/<name>.json. Since v1.2.5, ModelsCombo can auto-read a loaded LoRA's trigger words and show them live here - the same "where did my trigger word go" problem rgthree's Power Lora Loader is famous for solving, from a different direction.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/blackbossokok/Comfyui-EzFlex-Presets
pip install -r requirements.txt # mutagen
Manager: search EzFlex, restart. Optional extras are manual on purpose: pip install llama-cpp-python for in-process llama mode (kept out of requirements.txt so Manager doesn't try to compile it, which regularly fails on Windows) and pip install gguf onnx for metadata cards elsewhere in the pack. One thing you may have to add yourself: the local llama.cpp / Ollama server address is registered when you save settings rather than being open by default, so a node that can't reach your own localhost server just needs its address added. ComfyUI 0.3.13+ per pack metadata.
Common issues
Merged output is empty. Slider on Optimized with an empty optimized slot - strict by design. Flip to Default, or run the optimize.
A card is greyed out and ignores your edits. Something is connected to its card_in_N socket, and external text wins.
Auto-optimize errors the whole run. That's intended; failures are loud. Fix the API key, the TextGenerate model path or the llama server address, or turn the switch off. Also check only one of the three switches is on - the panel enforces it, but a hand-edited config gets a hard error.
Your @图片1 came out as prose. The optimize model rewrote the marker. Use a more literal model, or skip optimization on cards that carry references.
Inputs (49)
| Name | Type | Default | Description |
|---|---|---|---|
| config | STRING | {} | Config JSON generated by the Prompt Cards panel (card list). |
| media_in_1opt | * | Any media 1: images / video / audio / 3D models are accepted (a new empty slot is added when connected). | |
| media_in_2opt | * | Any media 2: images / video / audio / 3D models are accepted (a new empty slot is added when connected). | |
| media_in_3opt | * | Any media 3: images / video / audio / 3D models are accepted (a new empty slot is added when connected). | |
| media_in_4opt | * | Any media 4: images / video / audio / 3D models are accepted (a new empty slot is added when connected). | |
| media_in_5opt | * | Any media 5: images / video / audio / 3D models are accepted (a new empty slot is added when connected). | |
| media_in_6opt | * | Any media 6: images / video / audio / 3D models are accepted (a new empty slot is added when connected). | |
| media_in_7opt | * | Any media 7: images / video / audio / 3D models are accepted (a new empty slot is added when connected). | |
| media_in_8opt | * | Any media 8: images / video / audio / 3D models are accepted (a new empty slot is added when connected). | |
| media_in_9opt | * | Any media 9: images / video / audio / 3D models are accepted (a new empty slot is added when connected). | |
| media_in_10opt | * | Any media 10: images / video / audio / 3D models are accepted (a new empty slot is added when connected). | |
| media_in_11opt | * | Any media 11: images / video / audio / 3D models are accepted (a new empty slot is added when connected). | |
| media_in_12opt | * | Any media 12: images / video / audio / 3D models are accepted (a new empty slot is added when connected). | |
| media_in_13opt | * | Any media 13: images / video / audio / 3D models are accepted (a new empty slot is added when connected). | |
| media_in_14opt | * | Any media 14: images / video / audio / 3D models are accepted (a new empty slot is added when connected). | |
| media_in_15opt | * | Any media 15: images / video / audio / 3D models are accepted (a new empty slot is added when connected). | |
| media_in_16opt | * | Any media 16: images / video / audio / 3D models are accepted (a new empty slot is added when connected). | |
| card_in_1opt | STRING | Text of prompt card 1 (when connected it overrides that card panel content). | |
| card_in_2opt | STRING | Text of prompt card 2 (when connected it overrides that card panel content). | |
| card_in_3opt | STRING | Text of prompt card 3 (when connected it overrides that card panel content). | |
| card_in_4opt | STRING | Text of prompt card 4 (when connected it overrides that card panel content). | |
| card_in_5opt | STRING | Text of prompt card 5 (when connected it overrides that card panel content). | |
| card_in_6opt | STRING | Text of prompt card 6 (when connected it overrides that card panel content). | |
| card_in_7opt | STRING | Text of prompt card 7 (when connected it overrides that card panel content). | |
| card_in_8opt | STRING | Text of prompt card 8 (when connected it overrides that card panel content). | |
| card_in_9opt | STRING | Text of prompt card 9 (when connected it overrides that card panel content). | |
| card_in_10opt | STRING | Text of prompt card 10 (when connected it overrides that card panel content). | |
| card_in_11opt | STRING | Text of prompt card 11 (when connected it overrides that card panel content). | |
| card_in_12opt | STRING | Text of prompt card 12 (when connected it overrides that card panel content). | |
| card_in_13opt | STRING | Text of prompt card 13 (when connected it overrides that card panel content). | |
| card_in_14opt | STRING | Text of prompt card 14 (when connected it overrides that card panel content). | |
| card_in_15opt | STRING | Text of prompt card 15 (when connected it overrides that card panel content). | |
| card_in_16opt | STRING | Text of prompt card 16 (when connected it overrides that card panel content). | |
| card_in_17opt | STRING | Text of prompt card 17 (when connected it overrides that card panel content). | |
| card_in_18opt | STRING | Text of prompt card 18 (when connected it overrides that card panel content). | |
| card_in_19opt | STRING | Text of prompt card 19 (when connected it overrides that card panel content). | |
| card_in_20opt | STRING | Text of prompt card 20 (when connected it overrides that card panel content). | |
| card_in_21opt | STRING | Text of prompt card 21 (when connected it overrides that card panel content). | |
| card_in_22opt | STRING | Text of prompt card 22 (when connected it overrides that card panel content). | |
| card_in_23opt | STRING | Text of prompt card 23 (when connected it overrides that card panel content). | |
| card_in_24opt | STRING | Text of prompt card 24 (when connected it overrides that card panel content). | |
| card_in_25opt | STRING | Text of prompt card 25 (when connected it overrides that card panel content). | |
| card_in_26opt | STRING | Text of prompt card 26 (when connected it overrides that card panel content). | |
| card_in_27opt | STRING | Text of prompt card 27 (when connected it overrides that card panel content). | |
| card_in_28opt | STRING | Text of prompt card 28 (when connected it overrides that card panel content). | |
| card_in_29opt | STRING | Text of prompt card 29 (when connected it overrides that card panel content). | |
| card_in_30opt | STRING | Text of prompt card 30 (when connected it overrides that card panel content). | |
| card_in_31opt | STRING | Text of prompt card 31 (when connected it overrides that card panel content). | |
| card_in_32opt | STRING | Text of prompt card 32 (when connected it overrides that card panel content). |
Outputs (33)
| Name | Type | Description |
|---|---|---|
| Merged prompt | STRING | — |
| Card 1 | STRING | — |
| Card 2 | STRING | — |
| Card 3 | STRING | — |
| Card 4 | STRING | — |
| Card 5 | STRING | — |
| Card 6 | STRING | — |
| Card 7 | STRING | — |
| Card 8 | STRING | — |
| Card 9 | STRING | — |
| Card 10 | STRING | — |
| Card 11 | STRING | — |
| Card 12 | STRING | — |
| Card 13 | STRING | — |
| Card 14 | STRING | — |
| Card 15 | STRING | — |
| Card 16 | STRING | — |
| Card 17 | STRING | — |
| Card 18 | STRING | — |
| Card 19 | STRING | — |
| Card 20 | STRING | — |
| Card 21 | STRING | — |
| Card 22 | STRING | — |
| Card 23 | STRING | — |
| Card 24 | STRING | — |
| Card 25 | STRING | — |
| Card 26 | STRING | — |
| Card 27 | STRING | — |
| Card 28 | STRING | — |
| Card 29 | STRING | — |
| Card 30 | STRING | — |
| Card 31 | STRING | — |
| Card 32 | STRING | — |