Nodes/Comfyui-EzFlex-Presets/EzFlex-PromptHelper
ComfyUI Node

EzFlex-PromptHelper

Prompt Cards, Merged Output, and an Optional LLM Rewrite

By blackbossokok·Created 20 days ago·Updated about 15 hours ago· 1
EzFlex-PromptHelper
  • 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
config{}
card_in_1
card_in_2
card_in_3
card_in_4
card_in_5
card_in_6
card_in_7
card_in_8
card_in_9
card_in_10
card_in_11
card_in_12
card_in_13
card_in_14
card_in_15
card_in_16
card_in_17
card_in_18
card_in_19
card_in_20
card_in_21
card_in_22
card_in_23
card_in_24
card_in_25
card_in_26
card_in_27
card_in_28
card_in_29
card_in_30
card_in_31
card_in_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_1media_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_1card_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 1Card 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.

CategoryEzFlex

Inputs (49)

NameTypeDefaultDescription
configSTRING{}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_1optSTRINGText of prompt card 1 (when connected it overrides that card panel content).
card_in_2optSTRINGText of prompt card 2 (when connected it overrides that card panel content).
card_in_3optSTRINGText of prompt card 3 (when connected it overrides that card panel content).
card_in_4optSTRINGText of prompt card 4 (when connected it overrides that card panel content).
card_in_5optSTRINGText of prompt card 5 (when connected it overrides that card panel content).
card_in_6optSTRINGText of prompt card 6 (when connected it overrides that card panel content).
card_in_7optSTRINGText of prompt card 7 (when connected it overrides that card panel content).
card_in_8optSTRINGText of prompt card 8 (when connected it overrides that card panel content).
card_in_9optSTRINGText of prompt card 9 (when connected it overrides that card panel content).
card_in_10optSTRINGText of prompt card 10 (when connected it overrides that card panel content).
card_in_11optSTRINGText of prompt card 11 (when connected it overrides that card panel content).
card_in_12optSTRINGText of prompt card 12 (when connected it overrides that card panel content).
card_in_13optSTRINGText of prompt card 13 (when connected it overrides that card panel content).
card_in_14optSTRINGText of prompt card 14 (when connected it overrides that card panel content).
card_in_15optSTRINGText of prompt card 15 (when connected it overrides that card panel content).
card_in_16optSTRINGText of prompt card 16 (when connected it overrides that card panel content).
card_in_17optSTRINGText of prompt card 17 (when connected it overrides that card panel content).
card_in_18optSTRINGText of prompt card 18 (when connected it overrides that card panel content).
card_in_19optSTRINGText of prompt card 19 (when connected it overrides that card panel content).
card_in_20optSTRINGText of prompt card 20 (when connected it overrides that card panel content).
card_in_21optSTRINGText of prompt card 21 (when connected it overrides that card panel content).
card_in_22optSTRINGText of prompt card 22 (when connected it overrides that card panel content).
card_in_23optSTRINGText of prompt card 23 (when connected it overrides that card panel content).
card_in_24optSTRINGText of prompt card 24 (when connected it overrides that card panel content).
card_in_25optSTRINGText of prompt card 25 (when connected it overrides that card panel content).
card_in_26optSTRINGText of prompt card 26 (when connected it overrides that card panel content).
card_in_27optSTRINGText of prompt card 27 (when connected it overrides that card panel content).
card_in_28optSTRINGText of prompt card 28 (when connected it overrides that card panel content).
card_in_29optSTRINGText of prompt card 29 (when connected it overrides that card panel content).
card_in_30optSTRINGText of prompt card 30 (when connected it overrides that card panel content).
card_in_31optSTRINGText of prompt card 31 (when connected it overrides that card panel content).
card_in_32optSTRINGText of prompt card 32 (when connected it overrides that card panel content).

Outputs (33)

NameTypeDescription
Merged promptSTRING
Card 1STRING
Card 2STRING
Card 3STRING
Card 4STRING
Card 5STRING
Card 6STRING
Card 7STRING
Card 8STRING
Card 9STRING
Card 10STRING
Card 11STRING
Card 12STRING
Card 13STRING
Card 14STRING
Card 15STRING
Card 16STRING
Card 17STRING
Card 18STRING
Card 19STRING
Card 20STRING
Card 21STRING
Card 22STRING
Card 23STRING
Card 24STRING
Card 25STRING
Card 26STRING
Card 27STRING
Card 28STRING
Card 29STRING
Card 30STRING
Card 31STRING
Card 32STRING