FLUX.3 Klein Prompt Upsampler ๐
FLUX.3 Klein was trained on upsampler captions โ this node writes them
- llm_service_connector
- reference_images
- elements
- canvas_preview
- upsampled_prompt
- caption
- bbox_json
Most prompt-enhancer nodes are a nice-to-have. This one is closer to a required accessory, because Black Forest Labs' own documentation for FLUX.3 Klein says do not use Klein without the prompt upsampler. Klein is fine-tuned on the long captions its upsampler writes, so handing it your typed sentence is feeding it an input distribution it wasn't trained on.
Flux3KleinPromptUpsampler|Mie is that upsampler, reproduced with an LLM you supply.
What it actually does
It doesn't ship a model. It ships the prompt. The pack contains a byte-for-byte snapshot of BFL's official system prompts - the short pack from the HF repo black-forest-labs/flux-3-image-klein-pup (a full fine-tune of a Qwen3.5-9B on its own captions) and the far longer external-VLM pack from inference repo PR #5. The node takes your short request, wraps it in the right official system prompt for the mode you picked, sends it to whatever connector you wired, and returns the reply.
That reply is the point: upsampled_prompt is the model's answer verbatim, because that's the string Klein is trained to receive. You're not paraphrasing an idea into a better prompt - you're running the preprocessing step the checkpoint expects, on someone else's GPU.
The usual use is a chain: a rough caption in, upsampled_prompt out, straight into your positive conditioning.
Inputs that matter
llm_service_connector is required, and that's the real gate on this node. It's any Set*LLMServiceConnector from the same pack - a cloud provider key, or local Ollama if you'd rather not pay per call. Put keys in mie_llm_keys.json next to the pack's README rather than in the node.
mode has four values. t2i is the default and needs nothing else. i2i edits against reference images and needs a vision-capable connector - its system prompt literally opens with "You see the reference image(s)". t2i_bbox and i2i_bbox also plan a layout on a 0โ1000 grid.
prompt_pack picks the short pack (default; shipped with the PUP weights, which upstream nominates for any other LLM) or the long pack from PR #5, which carries many more few-shot examples and is roughly an order of magnitude longer. Same purpose, two official publications - worth a side-by-side test, because the difference is style, not correctness.
prompt accepts any language. The caption always comes back in English; only text you asked the model to render in the image (inside double quotes) keeps its original language. seed is there for reproducibility.
Then the optional half. reference_images takes up to 10 images, in order, and is mandatory for i2i / i2i_bbox. target_canvas (16:9, 1:1, or auto) steers composition only - the system prompt instructs the model never to mention the ratio, so you won't find "16:9" leaking into your caption. bboxes_json is your own element table for the *_bbox modes; the model is told to preserve it exactly, and leaving it empty lets the model plan the layout. temperature defaults to 0.2 (official PUP decodes greedily; APIs get pushed near-zero instead of a true 0 because some backends reject that). max_tokens defaults to 16384 against upstream's 3584, and timeout offers 60/120/300/600.
Outputs: upsampled_prompt (the verbatim reply - wire it to your conditioning), caption and bbox_json. Those last two are the reply split deterministically for the bbox modes so each half can drive its own node; on t2i and i2i they come back empty.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/MieMieeeee/ComfyUI-MieNodes
cd ComfyUI-MieNodes && pip install -r requirements.txt
Restart, or install MieNodes via ComfyUI Manager (registry publisher mie). No weights to download for this node - the prompt packs ship in the repo and there's nothing to fetch from HuggingFace. What you do need is an LLM: a cloud key through the matching connector, or Ollama running locally.
Where it bites
Turn Klein's own upsampler off. If you leave ComfyUI's enable_prompt_upsampler on and run this node, your prompt gets expanded twice and the second pass is working on a caption, not a request. Same story for the CLI's --no-pup.
Empty replies. Reasoning models spend the max_tokens budget thinking and hand you a 200 with nothing in it. The node raises rather than passing an empty string downstream - the fix is to raise max_tokens, which is exactly why the default is four times upstream's.
The editing-voice contradiction. BFL's Comfy tutorial says "write the result, not the change", while the PUP i2i system prompt, the single-reference guide and the official examples say to describe the change and close with what stays the same. Official sources disagree. This node follows the PUP convention, because that's what the bundled prompt was trained for - so if you're writing i2i requests in result-style and getting mush, that's why.
The long pack is enormous. Its system prompt alone is around 12k tokens. On a slow backend, 300 seconds can genuinely be tight - push timeout to 600 rather than assuming the call failed.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| llm_service_connector | LLMServiceConnector | โ | |
| mode | COMBO | t2i - ๆ็ๅพ(้ป่ฎค) | 4 options: t2i - ๆ็ๅพ(้ป่ฎค), i2i - ๅพ็ๅพ็ผ่พ(้ๅ่ๅพ), t2i_bbox - ๆ็ๅพ+ๅธๅฑๆก, i2i_bbox - ็ผ่พ+ๅธๅฑๆก(้ๅ่ๅพ) |
| prompt_pack | COMBO | short - ็ญ็(HF ๆ้ๅๆบ,้ป่ฎค) | 2 options: short - ็ญ็(HF ๆ้ๅๆบ,้ป่ฎค), long - ้ฟ็(PR#5 ๅค้จVLM,็คบไพๆดๅค) |
| prompt | STRING | Short request to upsample. Any language is fine โ the caption is always written in English, and only text the model is asked to render (inside double quotes) keeps its original language. Required, except in the *_bbox modes when an element table is supplied โ then the table's own descriptions serve as the request. ็ญๆ็คบ่ฏ๏ผๅฏไธญๆ๏ผ่พๅบๆไธบ่ฑๆ๏ผไป ๅผๅทๅ ๅพ ๆธฒๆๆๅญไฟ็ๅๆใ*_bbox ๆจกๅผไธ่ฅๅทฒๅกซๅ ็ด ่กจ๏ผๅๅฏ็็ฉบใ | |
| seed | INT | 00โ18446744073709550000 | โ |
| reference_imagesopt | IMAGE | Reference images, attached in order (up to 10). Required by i2i / i2i_bbox โ those prompts open with "You see the reference image(s)", so they run on a vision-capable connector. ๆๅบ้ไธ็ๅ่ๅพ๏ผๆๅค 10 ๅผ ๏ผใi2i / i2i_bbox ๅฟ ๅกซ๏ผ้ไฝฟ็จๆฏๆ่ง่ง็่ฟๆฅๅจใ | |
| elementsopt | ARRAY | Element table from Create Bounding Boxes' elements output. Boxes arrive already normalized to the official [y_min, x_min, y_max, x_max] on a 0-1000 grid, so no JSON is needed. *_bbox modes only. To MOVE something, draw two boxes and label their descriptions 'src' and 'tgt', then name those labels in the instruction ('Move the bird from src to tgt'). ็ดๆฅๆฅ Create Bounding Boxes ็ elements ่พๅบ๏ผๅๆ ๅทฒๆฏๅฎๆน 0-1000 ็ฝๆ ผ็ [y_min, x_min, y_max, x_max]๏ผๆ ้ๆๅ JSONใ่ฆ็งปๅจ็ฉไฝ๏ผๅฐฑ็ปไธคไธชๆก๏ผdesc ๅๅซๅ src ๅ tgt๏ผๆไปค้ๅผ็จ่ฟไธคไธช่ฏใ | |
| canvas_previewopt | IMAGE | Create Bounding Boxes' preview output. Its dimensions ARE the canvas, so the aspect ratio is taken from here instead of being typed โ the canvas and the prompt can never disagree. The official box grid normalizes each axis independently, so the frame's proportions cannot be recovered from the boxes alone; without this, objects are sized as if the frame were square. Only the t2i modes use it (the editing modes take the frame from the reference image). ๆฅ Create Bounding Boxes ็ preview ่พๅบ๏ผ็ปๅธๆฏไพ่ชๅจๅ่ช่ฟ้๏ผๆ ้ๆๅกซโโๅฎๆน็ฝๆ ผไธค่ฝดๅ่ชๅฝไธๅ๏ผๅช็ๆกๆ ๆณ็ฅ้็ปๅน ๅฎฝ้ซๆฏใ | |
| temperatureopt | FLOAT | 0.200โ2 | โ |
| max_tokensopt | INT | 1638464โ32768 | โ |
| timeoutopt | COMBO | 300 | 4 options: 60, 120, 300, 600 |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| upsampled_prompt | STRING | โ |
| caption | STRING | โ |
| bbox_json | STRING | โ |