Simple LLM Caption (Advanced)
Same Joy Caption engine, now with sampling dials and a ready-made negative prompt
- pipeline
- image
- positive_prompt
- negative_prompt
When the basic node isn't enough
SimpleLLMCaptionAdvanced is SimpleLLMCaption with the training wheels off. Same Joy Caption Alpha Two pipeline, same seven caption types, same text processing - but you get control over the generation itself, and instead of one string you get two outputs: positive_prompt and negative_prompt. That pair is the whole point. You can build a caption-to-image loop where the caption this node writes is your prompt, and its negative_prompt output feeds the negative prompt input, no extra wiring.
The dials aren't just for tinkerers. Captioning a training set and want output that stays on the rails? Drop the temperature toward 0.5. Generating social media or MidJourney captions and want variety? Crank it up. Same engine, different temperament.
The inputs that changed
On top of the basic node's pipeline, image, caption_type, and caption_length, you get:
temperature(0.1-2.0, default 0.7) andtop_p(0.1-1.0, default 0.9) - the standard sampling knobs. The basic node doesn't even expose these; it just runs with defaults.max_new_tokens(50-1000, default 300) - the hard ceiling on caption length. The "very short" to "very long" enum works by steering the prompt text, not by capping tokens; this is your actual limit.append_to_caption- free text glued to the very end of the caption, after everything else. Handy for stamping a consistent suffix, like a style tag, onto every output.negative_prompt- a pass-through, not generated. Whatever you type here is returned verbatim on thenegative_promptoutput, and it's an empty string if you leave it blank, which is fine.
Plus the extras: prefix / suffix wrap the caption before append_to_caption is added, and you still get lora_trigger, the three replacement fields (gender_age_replacement, hair_replacement, body_size_replacement), and remove_tattoos / remove_jewelry.
Outputs: positive_prompt (STRING) and negative_prompt (STRING). Both wire straight into any checkpoint's prompt and negative inputs.
What stays the same
Mechanically it's the same pipeline: SigLIP features → image adapter → spliced into the Llama template → LoRA-tuned generation. It also unloads models from VRAM after each call and reloads before the next, and it force re-runs whenever you change an input (parameter hashing beats ComfyUI's cache). First use still triggers the multi-gigabyte auto-downloads - but if you've already run the basic node, the loader has everything cached and this one is instant.
Install
Same pack, same deal:
cd ComfyUI/custom_nodes
git clone https://github.com/Pixelailabs/Joy_Caption_Two_PixelaiLabs.git
cd Joy_Caption_Two_PixelaiLabs
pip install -r requirements.txt
Restart and it appears under image/captioning. ComfyUI Manager search "Joy Caption Two" works too.
Where people trip
- The Advanced node doesn't improve caption quality by default - temperature 0.7 and top_p 0.9 are close to what Joy Caption already uses. The gain is the negative-prompt output and the hard token cap, not magic.
- Crank temperature too high and training captions start hallucinating details. For dataset work, sit at 0.5-0.6 and keep
max_new_tokenstight. - Remember the negative output is your text or nothing - it is not the model telling you what to avoid. Beginners assume it's generated; it isn't.
Inputs (17)
| Name | Type | Default | Description |
|---|---|---|---|
| pipeline | LLM_PIPELINE | — | |
| image | IMAGE | — | |
| caption_type | COMBO | 7 options: Descriptive, Descriptive (Informal), Training Prompt, MidJourney, Booru Tags, Art Critic, +1 | |
| caption_length | COMBO | medium | 6 options: any, very short, short, medium-length, long, very long |
| temperature | FLOAT | 0.70.1–2 | — |
| top_p | FLOAT | 0.900.1–1 | — |
| max_new_tokens | INT | 30050–1000 | — |
| append_to_captionopt | STRING | — | |
| negative_promptopt | STRING | — | |
| lora_triggeropt | STRING | — | |
| gender_age_replacementopt | STRING | — | |
| hair_replacementopt | STRING | — | |
| body_size_replacementopt | STRING | — | |
| remove_tattoosopt | BOOLEAN | false | — |
| remove_jewelryopt | BOOLEAN | false | — |
| prefixopt | STRING | — | |
| suffixopt | STRING | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| positive_prompt | STRING | — |
| negative_prompt | STRING | — |