Prompt Optimizer Local (LLaMA/Gemma)
A Llama that polishes prompts or reverse-describes images, no API key anywhere
- image1
- image2
- prompt
The name is the whole pitch, and it's not lying: Prompt Optimizer Local runs a real Llama or Gemma on your machine and never touches an API. It's the text half of Tulut's tulut_comfyui_Gadget pack - the other half is the anime detailers - and it does two jobs in one node: polish a draft prompt into something a checkpoint actually understands, or look at an image and write the prompt that describes it. Both are the kind of "short structured rewriting" that the local-LLM crowd keeps saying an 8B model on your own card is good enough for, and this node is exactly that pattern done as a single ComfyUI node.
What it does
Two modes, toggled by checkboxes. Polish (mode_polish) takes input_text, runs it through the LLM with an editing persona, and returns one cleaned-up prompt - the author's default system prompt is genuinely good: it refuses to invent new triggers or LoRA names, won't add masterpiece, best quality unless you already wrote them, and preserves explicit content. Reverse (mode_reverse) takes image1 and/or image2 and describes them as a generation prompt. If both toggles are on, reverse wins.
The output is a single STRING called prompt - wire it into whatever text encode node your workflow uses, or just read it off the node.
How it picks a model
Three backends, chosen by model_name and low_vram_mode:
- External llama-server (default). You run
llama-serveryourself, and the node just HTTP-calls it onllama_host/llama_port(127.0.0.1:8080 by default). Cleanest path if you already run llama.cpp for other things. - Low VRAM mode (
low_vram_modeON). The node startsllama_cpp/bin/llama-serveritself with your GGUF, runs the request, then stops the process it started. If something is already listening on the port it reuses that server and won't kill it. - Gemma safetensors. Any
.safetensorsin yourtext_encodersfolder shows up in themodel_namedropdown and gets loaded through Comfy's native text-encoder path. Heavier on VRAM; auto-unloads after each run.
For the managed mode the node builds the command for you: context clamped to your ctx_size (max 8192), n_gpu_layers for how much to offload, kv_cache_type defaulting to q6_k to shrink KV memory, and max_tokens auto-clamped to about half the context so generation can't blow past it. If the GPU start fails, cpu_fallback retries with -ngl 0.
The few inputs that matter
mode_polish/mode_reverse- which job it's doing (reverse wins).input_text- your draft, for polish mode.image1/image2- for reverse (optional; the node merges them into one request).llama_host/llama_port- where to reach an external server.persona_polish/persona_reverse- the system prompts. Editing these is how you steer the output; they're plain text, not a config file.
Installing it
Clone into custom_nodes and restart:
cd ComfyUI/custom_nodes
git clone https://github.com/Tulut114/tulut_comfyui_Gadget
(Or find "tulut_comfyui_Gadget" in ComfyUI Manager.) The requirements.txt only lists Pillow, and even that is optional - it's for the image-to-data-URL step in reverse mode.
The managed-LLM path does not ship binaries. You download a llama.cpp release from github.com/ggerganov/llama.cpp/releases, extract llama-server.exe plus its DLLs into llama_cpp/bin/, and drop a GGUF into llama_cpp/models/ (the README suggests something like gemma-3-4b-it-Q4_K_M.gguf). For reverse mode you also need a mmproj-*.gguf vision projector - text-only polish works without one.
Where people get burned
- Reverse with no mmproj. The node will start the server without vision and then quietly fail to see your image. Pick a
llama_mmproj(or set it to "auto") before flipping on reverse. - "Nothing came back." If polish returns empty the node falls back to your original text, which is decent behavior but easy to misread as success. Watch the Comfy console for the llama-server log.
- Port collisions. If you run your own server on 8080, the node reuses it rather than spawning a second one - that's a feature, but it means your manually started server is never shut down for you.
For a beginner the external-server route is actually the friendliest: get llama.cpp running once, point the node at it, and you never think about binaries again. The low-VRAM mode is the reward for putting up with a little setup, and it earns its keep on 6GB cards where you can't spare room for a resident LLM.
Inputs (19)
| Name | Type | Default | Description |
|---|---|---|---|
| persona_polish | STRING | You are a careful prompt editor for image generation models. TASK: Lightly improve the user draft into ONE better prompt. RULES: - Output ONLY the final prompt. No markdown, notes, or reasoning. - Stay faithful to the draft. Prefer the user's wording and structure (tags or natural language). - Keep every trigger, character name, LoRA id, and rare token that appears in the draft, exact spelling. - Do NOT invent new triggers, LoRA names, characters, outfits, props, or acts that are not in the draft. - Do NOT add quality tags (score_*, masterpiece, best quality, absurdres, etc.) unless they already appear in the draft. - Do NOT change colors, species, gender tags, or character identity unless the draft already says so. - You may fix grammar, spacing, duplicates, and clear ordering. You may clarify phrasing without adding new content. - Keep explicit/NSFW content if present. No sampler settings unless already in the draft. Output the single ready-to-paste prompt only. | — |
| persona_reverse | STRING | You describe the image(s) as ONE image-generation prompt. RULES: - Output ONLY the prompt. No markdown, no "the image shows". - English unless told otherwise. - Describe only what is visible: subject, appearance, clothing, pose, actions, materials, background, lighting, style. - Do not invent names, lore, or off-frame content. - Do not invent LoRA triggers. - Prefer clear, concrete language. Keep explicit content if visible. Output the single ready-to-paste prompt only. | — |
| input_text | STRING | — | |
| model_name | COMBO | llama_server | 2 options: llama_server, (no safetensors) |
| llama_port | INT | 80801–65535 | — |
| mode_polish | BOOLEAN | true | — |
| mode_reverse | BOOLEAN | false | — |
| low_vram_mode | BOOLEAN | false | — |
| llama_gguf | COMBO | (place .gguf in llama_cpp/models) | 1 options: (place .gguf in llama_cpp/models) |
| llama_mmproj | COMBO | auto (match for reverse/vision) | 3 options: auto (match for reverse/vision), none (text only), (no mmproj — reverse/vision needs mmproj-*.gguf) |
| n_gpu_layers | INT | 00–999 | GPU layers (-ngl). 0=CPU. If GPU OOM, auto-fallback to CPU when enabled. |
| ctx_size | INT | 2048512–8192 | Context hard limit for managed llama-server (max 8192). KV RAM scales with this. |
| kv_cache_type | COMBO | q6_k | KV cache quant (-ctk/-ctv). q6_k = smaller memory than f16. |
| cpu_fallback | BOOLEAN | true | If GPU start fails (OOM/driver), retry with -ngl 0. |
| max_tokens | INT | 51216–4096 | Clamped to ~half of ctx_size so it cannot overflow context. |
| seed | INT | 00–18446744073709550000 | — |
| image1opt | IMAGE | — | |
| image2opt | IMAGE | — | |
| llama_hostopt | STRING | 127.0.0.1 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| prompt | STRING | — |