Prompt Enhancer (API: edit config.json)
It doesn't need to be Qwen, it needs an endpoint
- image_1
- image_2
- image_3
- image_4
- rewritten_prompt
- wh_ratio
- width
- height
- ratio_follow
- thinking
The class is called QwenImagePromptEnhancer and the display name is just "Prompt Enhancer," which is fair - the Qwen part refers to the system prompts, copied from Qwen-Image 2.1's own T2I and I2I prompt guides. Behind the URL, any OpenAI-compatible text LLM works. It defaults to llama.cpp on 127.0.0.1:8080.
The job is the classic one: you type a rough idea, a small local model rewrites it into a structured, detailed prompt and - this is the part most enhancers skip - also tells you what aspect ratio the composition wants, in pixels.
Inputs
Four widgets, all required: user_prompt (multiline, the rough idea), mode (T2I or I2I - this selects which system prompt is used), temperature (0.7), and thinking_mode.
thinking_mode is a real switch, not a cosmetic one. Ours (8-step), the default, sends the full shipped system prompt with enable_thinking false - in the author's own measurements that produces roughly 1600 characters of output. Model native throws your system prompt away and uses a built-in minimal instruction that just describes the JSON shape, with enable_thinking true, and yields around 550 characters. Both is for future Qwen3-class models that can do the full instruction and think. If a server rejects enable_thinking with a 400, the node retries once without it. There are no other inputs - no api_key widget, deliberately.
Outputs, and the one that surprises people
Six outputs: rewritten_prompt, wh_ratio, width, height, ratio_follow, thinking.
rewritten_prompt goes into your text encoder. width and height are real INTs ready for Empty Latent Image - the model isn't guessing pixels. The node takes the ratio the LLM returned, looks it up in a table of common 2K-ish sizes (so 2:1 is 2048×1024, 7:3 is 2352×1008, 18:39 is 1056×2288, 5:7 is 1280×1792), and for anything not in the table computes from a 1536×1536 target pixel count, clamped to ratios between 0.25 and 4.0 so a hallucinated 100:1 can't hand you a 40,000-pixel-wide latent. Everything is then rounded to a multiple of 16.
ratio_follow is the model's own notes about why it picked that ratio. Most people will ignore it, and it's genuinely useful the first few times your output keeps coming out 1:1 - because that's the tell. In T2I the code seeds wh_ratio with 3:2 before the call, so a model that says nothing gets the landscape default; in I2I it starts empty, and an unparseable or missing ratio falls back to 1:1, i.e. a 1536×1536 latent. If every run is square, the answer is in ratio_follow.
thinking is the model's reasoning, either from the API's reasoning_content field or pulled out of inline <think> tags. Wire it to a Show Text node while you're tuning; leave it unconnected after.
Configuring it
api_base, api_key and model come from config.json in the pack folder - there is no widget for them, and no environment variable is read anywhere in this pack (not OPENAI_API_KEY, not proxy vars). That's on purpose: a key typed into a panel gets written verbatim into every saved workflow and every image's metadata. Per-node overrides live under per_node:
{
"api_base": "http://127.0.0.1:8080",
"model": "",
"per_node": { "QwenImagePromptEnhancer": { "model": "Qwen3-8B-Q4_K_M" } }
}
Leave api_key empty for llama.cpp, which needs none. The file is re-read on every run, so edits apply immediately without restarting ComfyUI. Host root or full /v1 URL both work - the code normalises to /v1 for the chat-completions call and strips it back off for a /completion fallback if your server doesn't speak the OpenAI route.
Install
ComfyUI Manager → ComfyUI-FeiFei, or:
cd ComfyUI/custom_nodes
git clone https://github.com/aifeifei798/ComfyUI-FeiFei.git
pip install openai # optional; a urllib fallback handles the request without it
No model files ship with the pack. The LLM is yours to run - llama.cpp, Ollama, vLLM, or a cloud endpoint, as long as it exposes an OpenAI-compatible chat API.
What to watch for
API Error:as your output. Errors come back as strings instead of exceptions, so a dead endpoint doesn't kill the run - it just hands you an error message where a prompt should be. Fixconfig.jsonand re-run.- The enhancer adding things you didn't ask for. Every one of these nodes does this; it's the job description. Keep the prompt short and specific and check the first few outputs before you trust it in a batch.
- A model that doesn't follow JSON. The node expects one JSON object and extracts it, but a chatty model leaks preamble into the prompt. Small and obedient beats large and clever here.
- Bilingual output is a feature, not a bug. The Qwen-Image system prompt is happy to write Chinese, which is native territory for LLM-encoded image models and wasted tokens on a tag-based SDXL checkpoint. If you're on an old model, this is the wrong enhancer - the pack's Prompt Director has an explicit
model_styleswitch for exactly that reason.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| user_prompt | STRING | Tokyo Japanese girl walking in the rain with umbrella | — |
| mode | COMBO | T2I | 2 options: T2I, I2I |
| temperature | FLOAT | 0.700.1–1.5 | — |
| thinking_mode | COMBO | Ours (8-step) | 3 options: Ours (8-step), Model native, Both |
| prompt_set | COMBO | Qwen-Image-2.1 | Qwen-Image-2.1 replies with JSON and a wh_ratio; Flux-3-Klein-PUP replies with the bare caption (or instruction) the image model consumes. |
| timeoutopt | INT | 12010–600 | Request timeout in seconds. |
| bboxopt | BOOLEAN | false | Flux set only: use the _bbox prompt (caption/instruction plus a JSON element table). |
| canvasopt | STRING | Flux T2I only: target canvas as W:H, sent as a TARGET CANVAS line and echoed to wh_ratio / width / height. Leave empty to let the model compose freely. | |
| image_1opt | IMAGE | — | |
| image_2opt | IMAGE | — | |
| image_3opt | IMAGE | — | |
| image_4opt | IMAGE | — |
Outputs (6)
| Name | Type | Description |
|---|---|---|
| rewritten_prompt | STRING | — |
| wh_ratio | STRING | — |
| width | INT | — |
| height | INT | — |
| ratio_follow | STRING | — |
| thinking | STRING | — |