Nodes/ComfyUI-FunPack/FunPack Apply Prompt Markup
ComfyUI Node

FunPack Apply Prompt Markup

Putting (word:1.5) back on models that toss it

By digital-garbage·Created about a year ago·Updated about 14 hours ago· 20
FunPack Apply Prompt Markup
  • model
  • clip
  • positive
  • latent
  • markup
  • model
  • positive
  • status

If you came from SD 1.5 or SDXL, you have muscle memory for (word:1.5). You type it, the encoder listens, the word gets heavier. Then you move to a 2026 model with a language-model encoder and the same syntax does nothing at all - or worse, it goes in as literal punctuation. FunPack Apply Prompt Markup exists because the pack's author hit that wall on MiniMax H3 and decided to fix it one layer down, at attention, instead of hoping the text encoder would cooperate.

Why the weights vanish in the first place

On CLIP-encoded models the weighting syntax is part of the wrapper. On LLM-encoded models the encoder wrapper passes disable_weights=True and your (word:1.3) is discarded - that's the mechanism, not a bug, and it's why the weighting habit supposedly died in 2026. The usual advice is "stop weighting, write instructions instead." That's good advice. It's also unsatisfying when you want one phrase to land harder and the model has decided to be a poet.

This node takes the other road: strip the markup out of the text so the encoder sees clean prose, then re-apply the effect on the transformer's attention, where weights still mean something.

How it actually works

The markup is produced by its twin, FunPack Prompt Markup - that node eats your prompt, pulls out (word:1.5) weights, [phrase@2-4] timed phrases and [a|b] blends, and gives you back clean text plus a FUNPACK_MARKUP blob. You encode the clean text with your CLIP Text Encode, and this node does the rest:

  • Weights and timed phrases are applied by patching the model. The node clones the model, strips any previous funpack_markup. patch, and installs an override on the packed self-attention that scales or masks the token rows belonging to your phrase. Timed phrases are masked to a frame window in the video latent - that's why latent is a required input, and why [walking@2-4] can make a phrase matter only for seconds two through four.
  • Blends are done in conditioning space instead: the node re-encodes the alternative phrasing, measures its rows against the original, and adds (1-s)*A + s*B over the prompt span.

If it can't do a thing, it says so rather than guessing. Three real refusals live in the source: "this text encoder is not one a model module can place words in", "the encoded prompt does not match this text - was the clean text from Prompt Markup what got encoded?", and a timed window that misses the clip, which is logged and skipped.

Inputs and outputs worth knowing

Required: model, clip, positive, latent, markup. That's the whole node - no numeric dials, because all the intent lives in the markup text.

Outputs: model and positive go straight into your sampler, and status is the string you should actually read. It reports "no markup", or which parts landed ("2 weight(s), 1 timed phrase(s)"), or "not applied: …" with the reason. There is no silent failure mode here, which is rare and welcome.

Install

Same as the rest of the pack - it's one repo, so install once and you get all of it.

cd ComfyUI/custom_nodes
git clone https://github.com/digital-garbage/ComfyUI-FunPack
cd ComfyUI-FunPack && pip install -r requirements.txt

Then restart ComfyUI. ComfyUI Manager works too if you search ComfyUI-FunPack, but the README is explicit that Manager and comfy node install serve whatever is on the Comfy Registry, so check Settings ▸ About FunPack in the /funpack/ UI afterwards to confirm you got 5.0 and not an older publish. Dependencies are light: comfy-kitchen>=0.2.32 (compiled, so never let pip casually upgrade it) and gguf for the loaders. No model download is needed for this node.

Troubleshooting

Status says "not applied". Nine times out of ten you encoded the raw prompt instead of the clean output. The node locates your phrases by character offsets in the clean text; if the conditioning came from a different string, the token spans don't line up and it refuses.

Status says "no markup". The markup blob is empty - you probably fed it text with no weights, timings or blends. Also check you're on the Apply node and not the Markup node, which is the one that parses.

The right node isn't in the menu. FunPack v5 loads features as modules, and a module that fails to load is dropped while the rest keeps working. If these two Conditioning nodes are missing entirely, read ComfyUI's console output at startup rather than reinstalling.

It works on H3 and rough elsewhere. The pack's own position is that MiniMax H3 is what v5 is built and tested around; SD 1.5 is labelled experimental and LTX 2.x is explicitly untested. Weight placement depends on a model module that knows your encoder's token layout. Treat anything outside H3 as a coin flip and watch the status string.

CategoryFunPack/Conditioning

Inputs (5)

NameTypeDefaultDescription
modelMODEL—
clipCLIP—
positiveCONDITIONING—
latentLATENT—
markupFUNPACK_MARKUP—

Outputs (3)

NameTypeDescription
modelMODEL—
positiveCONDITIONING—
statusSTRING—