Prompt Perfect (ChatGPT)
ChatGPT writes your product photo prompt — and it costs a few cents per run
- prompt
- negative
- debug_json
Prompt Perfect (ChatGPT) is the rare ComfyUI node whose name isn't lying: it really does call the ChatGPT API, it really does need a key, and every run costs you a fraction of a cent. The pitch is simple - you fill in structured fields about the shot you want, it hands them to an OpenAI model, and out come two clean strings you wire straight into your text encoders. If you've ever spent twenty minutes banging a product shot prompt into shape, you'll see the appeal.
What it's actually built for is narrow, and worth knowing up front. The bundled system prompt turns the LLM into a "senior prompt engineer and advertising art director" whose job is a single, hyper-realistic, production-grade product photography prompt - one scene, one moment, the product's packaging and logo treated as immutable. It's tuned around Qwen Image 2511 and speaks Qwen's language: it emits a structured block-style paragraph - medium, product, environment, lighting, camera, composition, realism controls - rather than a tag soup. That's exactly where 2026 prompting lives: camera and lens names are the highest-leverage phrase there is, and block-structured prompts read far better on LLM-encoded models than comma-separated tags. So for a hero product shot on Qwen, this is a genuinely good writing partner. Want a generic prompt booster for an anime SDXL checkpoint? Wrong tool - it will keep dragging you back to "premium product photography."
How it works
Under the hood it's a thin wrapper around the OpenAI Python SDK. Your fields are serialized to JSON and sent with the fixed system prompt; the model is told to reply with valid JSON containing prompt, negative, and notes. The node parses that, appends anything you put in negatives_extra to the negative, and returns three STRING outputs: prompt, negative, and debug_json (a dump of the fields it sent plus the model's notes, so you can see what it decided). If the model ever returns something unparseable, there's a graceful fallback: the raw text becomes the prompt and your extra negatives get returned as-is, so it never hard-crashes a queue.
The inputs that actually matter
Eight required fields read like a client brief: subject, environment, lighting, camera, composition, constraints, plus style and negatives_extra. The defaults are placeholders, so plan to fill most of them. The three that move the needle are:
subject- the product (or character) itself; the system prompt treats this as immutable, so describe it precisely.camera- lens mm, framing, angle. This gets the strongest, most deterministic instructions.constraints- the consistency rules ("same product, exact label, correct scale"), and where you put anything the system prompt wouldn't guess.
Leave lighting, camera, or composition blank and the model picks conservative defaults (50mm, eye-level, soft diffused key) rather than asking questions. On the optional side: api_key (or the OPENAI_API_KEY environment variable - it checks both), model (default gpt-4.1-mini), and temperature (default 0.1; keep it low - this is drafting, not a creative free-for-all).
Installing it
It's a one-node pack, so install is as trivial as the README claims. Either use ComfyUI Manager and search for ComfyUI-PromptPerfect, or:
cd ComfyUI/custom_nodes
git clone https://github.com/Pedreiro-Digital-Studio-Ltda/ComfyUI-PromptPerfect
Restart ComfyUI. The one real dependency is openai>=1.40.0, which the bundled install.py pulls in automatically - no model files to download, no local weights at all. Then set your key before first use:
export OPENAI_API_KEY="sk-..."
Where people get burned
The key error. If you hit OPENAI_API_KEY not found, that's it - the node found no key in the input or the environment. Set the env var (or paste the key into api_key) and restart.
The model_hint trap. The optional model_hint field defaults to a literal qwen / flux / wan / sd and looks like a selector, but it doesn't retarget the model - the system prompt is hard-coded for Qwen Image 2511 and model_hint is just passed through as a JSON field. Pick "flux" all you want; it's still writing an advertising Qwen prompt. Set your expectations (or just leave it alone).
The negative output is less useful than it looks. The node goes to real trouble building a strong negative paragraph, but if you're on Qwen or Flux - the models this prompt is aimed at - negative prompting is largely inert at CFG 1. It's worth its weight on SDXL-lineage models and close to decoration on LLM-encoded ones; don't expect it to carry the shot, the structured positive prompt is the real deliverable.
It costs money. Every run is a live API call. At gpt-4.1-mini with a strict output format it's cheap, but a queue of a couple hundred variations is a couple hundred calls, not zero. There's no local fallback - if your OpenAI balance is empty, so is the node.
Verdict
A small, opinionated, niche node that does one job - structured product-photography prompts via ChatGPT - very specifically. If you already pay for an OpenAI key and shoot products on Qwen, it's a legit timesaver. If you wanted a free, local prompt assistant, this isn't that; you'd be better served by an LLM node running a local Qwen with this pack's system prompt as inspiration.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| style | STRING | photoreal premium product photography | — |
| subject | STRING | main subject | — |
| environment | STRING | environment / set / context | — |
| lighting | STRING | lighting description | — |
| camera | STRING | camera + lens + framing | — |
| composition | STRING | composition + focus priorities | — |
| constraints | STRING | consistency constraints, scale, realism rules | — |
| negatives_extra | STRING | extra negatives (optional) | — |
| model_hintopt | STRING | qwen / flux / wan / sd | — |
| api_keyopt | STRING | — | |
| modelopt | STRING | gpt-4.1-mini | — |
| temperatureopt | FLOAT | 0.100–1 | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| prompt | STRING | — |
| negative | STRING | — |
| debug_json | STRING | — |