Nodes/FLUX 3 PE GGUF (T8)/FLUX 3 Prompt Enhancement
ComfyUI Node

FLUX 3 Prompt Enhancement

A local prompt upsampler that never phones home

By T8mars·Created 15 days ago·Updated 12 days ago· 5
FLUX 3 Prompt Enhancement
  • pe_model
  • images
  • enhanced_prompt
  • details_json
◄promptA man walking with his dog, afternoon sun►
◄keep_loadedfalse►
◄use_cachetrue►
◄max_tokens3584►
◄canvas_width0►
◄canvas_height0►
◄boxes_json►
◄retry_invalid_outputtrue►

"A man walking with his dog, afternoon sun" is the default sitting in the prompt box, and it's the perfect illustration of why this node exists. That sentence is a vibe, not a caption. This node turns it into a paragraph the image model can actually work with - locally, no API key, nothing uploaded.

That's the real selling point, and it isn't marketing. Most prompt enhancement happens by pasting your idea into a browser chat model and copying the paragraph back - censored, metered per call, useless offline. Here the enhancer is BFL's own prompt upsampler for FLUX 3, running in the graph instead of a chat window.

Know what it isn't. Not a writer: a Q4_K_M upsampler removes the blank page and sharpens vague requests, and nobody should expect frontier prose out of 5.63 GB. And it doesn't make pictures - FLUX 3 image generation needs its own diffusion weights, a Qwen3-VL encoder and the FLUX.2 VAE, none of which ship here.

Four modes, picked by what you wire

No mode dropdown, which confuses people for about thirty seconds. The node decides from your inputs, shipping four separate system prompts: prompt alone is text-to-image upsampling; prompt plus images is editing instructions; prompt plus boxes_json is layout mode with an element table; both is reference-editing annotation - source boxes, target boxes, what moved or went away.

Decoding isn't free-form chat either: temperature 0, thinking disabled, stop on <|im_end|>, a presence penalty on the text path so it stops padding. Then the output is validated before you see it - fenced markdown rejected, <think> leakage rejected, truncation errors instead of handing you half a caption, and in layout mode every box id must be cited in the prose or the whole thing fails.

That strictness is the feature. An enhancer that returns "Here is your enhanced prompt:" has put chat scaffolding into your conditioning, which is worse than no enhancer at all.

The inputs and outputs worth touching

prompt is your rough idea. images is an autogrow input with up to ten slots; wiring any image flips the node into editing-instruction mode, and slot order is the order the model sees. Fewer is better - the pack scales one reference to about a 1024² budget, two to 724², three or more to 512² each.

boxes_json is only for layout work, normalized [y_min, x_min, y_max, x_max]:

[{"id":"balloon","desc":"a red balloon","bbox":[0.1,0.1,0.6,0.4]}]

canvas_width / canvas_height default to 0, meaning "say nothing"; set both and the request gains a TARGET CANVAS: W:H line so a wide canvas spreads instead of stacks.

keep_loaded is the one to get right - the author's tooltip: "Disable before running an image model on a small GPU." max_tokens caps at 3584. use_cache reuses an identical request. retry_invalid_output allows exactly one recovery attempt when the model loops or returns malformed layout bindings.

Two strings come out. enhanced_prompt goes to your text encoder - or to Preview as Text for the first few runs, because reading the rewrites is how you learn what the thing wants to be asked. details_json reports mode, reference sizes, backend, timings, token usage, cache hits and whether recovery fired.

Installing it

Same pack as the loader - Manager, search FLUX 3 PE GGUF (T8), or:

cd ComfyUI/custom_nodes
git clone https://github.com/T8mars/Comfyui-Flux3-PE-GGUF-T8.git Comfyui-Flux3-PE

You need the three model files (flux3-klein-pup-Q4_K_M.gguf, the mmproj projector, manifest.json) plus a llama-cpp-python 0.3.36 wheel in ComfyUI's Python - requirements.txt is only requests and Pillow. Then wire the loader here and start from one of the pack's examples/*.json workflows.

Common issues

"PE generation did not finish normally (length)." It ran out of tokens mid-caption. Push max_tokens toward 3584, or simplify the request and drop references. The error is deliberate - a cut-off caption is worse than a retry.

Your diffusion model vanishes from VRAM. Expected. Before loading the PE, this node unloads every ComfyUI model and empties the cache, because llama.cpp allocations are invisible to Comfy's memory manager and would otherwise collide. With keep_loaded=false the PE releases itself after one enhancement and your image model gets the card back - that release is why the round trip works on a mid-size GPU.

Layout mode keeps failing on bindings. Every locked id must appear in the caption text, not just the JSON table, and zero-width boxes or references to unwired images get rejected. retry_invalid_output buys you one recovery; past that, simplify the box table.

Nothing changed when you queued again. The node re-executes on purpose, then answers from its result cache with cache_hit: true and zeroed timings. Turn use_cache off while iterating, on when you're done.

Last thing: the output is a caption, not a weighted prompt. (rim light:1.4) means nothing to a Qwen3-class encoder - it gets tokenized as literal punctuation. Write constraints in words and let the upsampler phrase them.

CategoryFLUX3/Prompt Enhancement

Inputs (10)

NameTypeDefaultDescription
pe_modelFLUX3_PE_MODEL—
promptSTRINGA man walking with his dog, afternoon sun—
imagesCOMFY_AUTOGROW_V3—
keep_loadedBOOLEANfalseKeep PE in GPU memory for repeated enhancement. Disable before running an image model on a small GPU.
use_cacheBOOLEANtrue—
max_tokensINT35841–3584—
canvas_widthINT00–16384—
canvas_heightINT00–16384—
boxes_jsonoptSTRINGOptional normalized boxes: [{"id":"obj_1","desc":"a red balloon","bbox":[0.1,0.1,0.5,0.4]}]
retry_invalid_outputoptBOOLEANtrueRetry once if the model loops or returns invalid layout bindings. The details output reports recovery.

Outputs (2)

NameTypeDescription
enhanced_promptSTRING—
details_jsonSTRING—