Nodes/CaptionForge/ JLC CaptionForge Joy Caption
ComfyUI Node

 JLC CaptionForge Joy Caption

Joy Caption is the witness you'll reach for first

By Damkohler·Created 3 months ago·Updated 2 months ago· 1
 JLC CaptionForge Joy Caption
  • image
  • pipeline_plan
  • template_options
  • image_out
  • pipeline_plan_out
  • template_options_out
  • caption
  • resolved_prompt
modelllama-joycaption-beta-one-hf-llava
memory_modeBalanced (8-bit)
keep_loadedtrue
caption_template_modetrue
caption_typeJLC LoRA Literal
caption_lengthany
custom_prompt_modefalse
prompt_presetdefault_literal
system_promptYou are a helpful image-captioning assistant. Describe only what is visible in the image. Do not invent unseen context.
custom_prompt
max_new_tokens384
temperature0.75
top_p0.90
top_k50
repetition_penalty1.00
max_size1024
forbidden_phrases
replace_pairs
download_probe_onlyfalse
seed

JoyCaption is the LoRA crowd's default captioner for a reason: it's the uncensored vision-language model built for training captions, and it's been the community favorite for years. This node is that model wrapped for ComfyUI, and inside CaptionForge it plays the role of the first "witness" - the Pass A caption engine whose account gets weighed against the others later. It's also a perfectly good standalone JoyCaption if you never touch the rest of the pack.

Here's the thing you should know first: CaptionForge is a brand-new, still-labeled-v0.1.x project (2026, MIT, by J. L. Córdova), so googling "CaptionForge" will mostly turn up an unrelated folder-tracking tool with the same name. Make sure you're on Damkohler/CaptionForge before you clone.

How it works

Under the hood it's a Python/Hugging Face engine running the JoyCaption/LLaVA-family model. Models are expected in ComfyUI/models/LLM/JLC_JoyCaption/, and if the folder's empty the node will download the weights from Hugging Face on first use - that's a multi-GB pull, not a typo on your part. The download_probe_only toggle, sitting at the very bottom of the widget list by design, fetches just the lightweight metadata and returns a status message instead of captioning. Use it to check your wiring before committing to a full download.

The node has two personalities. With nothing connected it's a standalone captioner. Plug a pipeline_plan in and it switches into Pass A evidence mode: the Pipeline Planner takes over image routing, per-run seeds, sampling schedules, and shared output paths, and your caption gets appended to the run's JSONL evidence file. Most of the sampling widgets stop mattering in that mode - the planner overrides them.

Inputs and outputs that matter

The few you'll actually touch:

  • model - defaults to llama-joycaption-beta-one-hf-llava. There's a model registry, so the dropdown may grow as models get added.
  • memory_mode - Balanced (8-bit) is the default and the author's recommendation for 16 GB VRAM. It's bitsandbytes load-time quantization. If you can't load the 8-bit version, Default is your fallback.
  • caption_type / caption_length - the structured template path. Joy has thirteen caption styles (Descriptive, MidJourney, Danbooru tag list, Art Critic…) and a length target from "very short" to explicit token counts.
  • custom_prompt_mode - overrides the template path when enabled; custom_prompt wins over prompt_preset if non-empty.
  • forbidden_phrases / replace_pairs - a cheap cleanup filter. One phrase per line to drop captions containing it, or old=>new lines for replacements.

Outputs: caption (the text you actually want), resolved_prompt (what was actually sent to the model - handy for debugging), plus passthroughs image_out, pipeline_plan_out, and template_options_out so you can chain nodes cleanly. Wire caption into a text display or into the capstone's JSONL feed.

Install

One install serves the whole pack. ComfyUI Manager, search "CaptionForge", or:

git clone https://github.com/Damkohler/CaptionForge.git ComfyUI/custom_nodes/CaptionForge

Restart ComfyUI, then make sure the Python deps are in your ComfyUI environment:

cd ComfyUI/custom_nodes/CaptionForge
pip install -e .

The repo ships no weights - Joy downloads itself into ComfyUI/models/LLM/JLC_JoyCaption/. Optional 8-bit support needs pip install bitsandbytes.

Common issues

First run downloads a big model, so give it time or use download_probe_only to test the graph first. On 16 GB systems keep memory_mode on Balanced (8-bit). And if you're running the full pipeline, know that Joy and Qwen are process-local Python models while the distillation stages live in Ollama - CaptionForge clears the Python models before handing work to Ollama, so don't be alarmed if the next image feels like a fresh load. That eviction dance is the pack trying to fit two model ecosystems in one GPU.

CategoryCaptioning/CaptionForge/Captioning Nodes

Inputs (23)

NameTypeDefaultDescription
modelCOMBOllama-joycaption-beta-one-hf-llavaJoyCaption/LLaVA-family model. Models are loaded from ComfyUI/models/LLM/JLC_JoyCaption/. Missing models may be downloaded automatically unless download_probe_only is enabled.
memory_modeCOMBOBalanced (8-bit)Joy model memory mode. Balanced (8-bit) uses bitsandbytes load-time quantization and is the recommended CaptionForge default for 16 GB VRAM systems.
keep_loadedBOOLEANtrueKeep the model cached after captioning for faster repeated runs. CaptionForge cache policy may still evict it when another caption model must load.
caption_template_modeBOOLEANtrueUse the structured CaptionForge template path: caption_type, caption_length, and optional Template Options from the template_options pin. If custom_prompt_mode is also enabled, custom_prompt_mode takes precedence.
caption_typeCOMBOJLC LoRA LiteralCaption template style used when caption_template_mode is active.
caption_lengthCOMBOanyTarget caption length used when caption_template_mode is active.
custom_prompt_modeBOOLEANfalseUse custom_prompt when non-empty, otherwise use prompt_preset. This overrides caption_template_mode when both toggles are enabled.
prompt_presetCOMBOdefault_literalBuilt-in prompt preset used only in custom_prompt_mode when custom_prompt is blank.
system_promptSTRINGYou are a helpful image-captioning assistant. Describe only what is visible in the image. Do not invent unseen context.Joy/LLaVA system prompt. Kept next to custom_prompt because both control the instruction envelope. Pipeline Planner does not currently override this.
custom_promptSTRINGCustom prompt used only when custom_prompt_mode is enabled. Overrides prompt_preset when non-empty.
max_new_tokensINT38416–4096Standalone token budget. When a Pipeline Planner is connected, this is overridden by the Planner's shared max_new_tokens.
temperatureFLOAT0.750–2Standalone sampling temperature. When a Pipeline Planner is connected, this is overridden by the Planner temperature schedule.
top_pFLOAT0.900–1Standalone top-p sampling value. When a Pipeline Planner is connected, this is overridden by the Planner top-p schedule.
top_kINT500–500Standalone top-k sampling limit. When a Pipeline Planner is connected, this is overridden by the Planner top-k schedule.
repetition_penaltyFLOAT1.001–2Penalty applied to repeated tokens. Kept with the core captioning parameters. This is not currently overridden by the Pipeline Planner.
max_sizeINT10240–4096Maximum longest-side image size for standalone captioning. The image is resized in memory only. Pipeline Planner overrides this in planned runs.
forbidden_phrasesSTRINGOptional cleanup filter: remove lines/captions containing any listed phrase, one per line.
replace_pairsSTRINGOptional cleanup replacements, one per line: old=>new.
download_probe_onlyBOOLEANfalseAt the very bottom by design. Probe/download lightweight model metadata only, then return a status message without captioning.
imageoptIMAGEImage or batch of images to caption. The image is passed through unchanged for clean node-to-node pipeline chaining.
pipeline_planoptCAPTIONFORGE_PIPELINE_PLANConnect the CaptionForge Pipeline Planner output here. When connected, this node switches into Pass A evidence mode: Planner image routing, per-run seeds, sampling schedules, shared output paths, and internal JSONL evidence append.
template_optionsoptCAPTIONFORGE_EXTRA_OPTIONSConnect the CaptionForge Template Options node here. Works in standalone and Pipeline modes. This is the only source for template modifiers and name input.
seedoptINTOptional standalone seed input. Ignored when a Pipeline Planner supplies a seed schedule.

Outputs (5)

NameTypeDescription
image_outIMAGE
pipeline_plan_outCAPTIONFORGE_PIPELINE_PLAN
template_options_outCAPTIONFORGE_EXTRA_OPTIONS
captionSTRING
resolved_promptSTRING