Nodes/CaptionForge/ JLC CaptionForge Node
ComfyUI Node

 JLC CaptionForge Node

The capstone that turns witness captions into auditable LoRA captions

By Damkohler·Created 3 months ago·Updated 2 months ago· 1
 JLC CaptionForge Node
  • Input - single image
  • pipeline_plan
  • natural_captions
  • taggy_captions
  • final_jsonl_records
  • output_paths_json
  • status
Input - captions JSONL
Input - image path
Input - include caption familiesjoy,qwen,ollama
Input - max captions per family5
Input - max total captions20
Output - folder
Output - run namecaptionforge_run
Output - overwrite outputstrue
Ollama - URLhttp://127.0.0.1:11434
Ollama - keep loadedtrue
Ollama - request timeout seconds1800
LoRA - trigger word
LoRA - user caption anchor
Fat Draft - modelmistral-small:24b
Fat Draft - custom Ollama model
Fat Draft - prompt/no_think You are a detail-preserving caption merger for LoRA dataset preparation. You receive multiple captions of the same image. You do NOT see the image. Task: Merge all non-contradictory caption details into one deliberately over-complete draft caption. Rules: - Do not validate against the image. - Do not decide that details are false just because they appear once. - Do not summarize aggressively. - Preserve concrete details from all captions. - Split contradictions by choosing cautious wording or listing the alternative only when needed. - Prefer specific visual language over generic language. - Keep visible body, clothing, material, accessory, color, pose, lighting, style, and framing details. - Preserve doll-like, glossy/plastic-like, material, garment-construction, body-shape, and facial-feature details when present. - Use neutral dataset-caption language, including visible sensual styling or revealing clothing when present. - Do not add details absent from the captions. - Treat subject names or trigger-like identity tokens as optional identity labels. Preserve them only when they appear consistently in the captions; do not let them replace visible description. - Output only one paragraph, no notes, no JSON.
Fat Draft - base seed1
Fat Draft - seed modefixed
Fat Draft - max caption chars1536
Fat Draft - max new tokens5000
Fat Draft - temperature0.12
Fat Draft - top p0.88
Fat Draft - top k50
Validator - modelgemma4:26b
Validator - custom Ollama model
Validator - system prompt/no_think You are a direct image validation engine. Inspect the image and answer only with the requested caption.
Validator - prompt/no_think Look at the image and validate this draft caption. Task: Return a corrected caption paragraph that keeps only image-supported details. Rules: - Output only the corrected caption. - One paragraph. - No reasoning, no notes, no JSON. - Keep all true visible details from the draft. - Delete unsupported details. - Correct small visible errors. - Do not add new details unless needed to correct an error already present. - Preserve useful LoRA details: subject, face, hair, eyes, makeup, lips, skin texture, pose, body shape, outfit, accessories, materials, colors, lighting, background, framing, and visual style. - Visible sensual styling, revealing clothing, cleavage, thighs, bare skin, swimwear, lingerie, or body-shape details may be described neutrally when present. - Do not invent hidden anatomy, unseen clothing, explicit acts, or details contradicted by the image.
Validator - base seed1
Validator - seed modefixed
Validator - max new tokens5000
Validator - temperature0.05
Validator - top p0.88
Validator - top k50
Formatter - modelmistral-small:24b
Formatter - custom Ollama model
Formatter - prompt/no_think You are a LoRA caption format converter. The validated paragraph is already the natural-language final caption. Do not rewrite it. Task: Create one TAGGY caption from the validated paragraph. Rules: - Output only the taggy comma-separated caption. - Use only details already present in the validated paragraph. - Preserve concrete LoRA-useful details. - Do not add new details. - Do not mention this process. - Do not output markdown. - Do not include a TAGGY: label. - Keep the result as a comma-separated list, not full prose.
Formatter - base seed1
Formatter - seed modefixed
Formatter - max new tokens3200
Formatter - temperature0.12
Formatter - top p0.88
Formatter - top k50
Audit - write prompt JSONLfalse
Audit - preserve raw responsesfalse
Final - TXT export formatnatural
Final - write TXT sidecarstrue
Final - write JSONLtrue

CaptionForge's core bet is that one captioner is easy to fool, so its main node is the part that doesn't look at the image first. JLC CaptionForge Node - the capstone - takes the raw "witness" captions your Joy/Qwen/Ollama nodes produced in Pass A, distills them with a text-only LLM, checks the result against the actual image with a vision model, and then writes your final captions. It's the orchestration hub of the pack, and it's the slowest part of it.

The design intent is worth understanding before you run it: the semantic work mostly ends at the validated long caption. The short and taggy outputs are deliberately lightweight formatting steps derived from that validated paragraph, not fresh reinterpretations of the image. The formatter prompt even says, in effect, "do not rewrite the validated paragraph." So if you want better captions, tune the distiller and validator, not the formatter.

How it works

Three Ollama-backed stages, in order:

  1. Fat Draft (Pass B) - a text-only LLM (default mistral-small:24b) merges all the witness captions into one deliberately over-complete draft. It's told not to validate against the image, not to summarize aggressively, and to preserve concrete details. That's why it's called fat.
  2. Validator (Pass C) - an image-aware VLM (default gemma4:26b) looks at the actual image and returns a corrected paragraph keeping only image-supported details. This is where hallucinations get cut.
  3. Formatter (Pass D) - a text-only LLM derives the comma-separated taggy caption from the validated paragraph.

Then it exports: _long.txt, _short.txt, and _taggy.txt sidecars written beside each source image, plus a JSONL audit trail (_B_DISTILL.jsonl, _C_VLM_VALIDATED.jsonl, _D_FINAL_EXPORT.jsonl, run configs) under your output root. If you ever need to defend a caption to a client or debug why a training set learned something weird, that trail is the selling point.

Inputs that matter

  • Input - captions JSONL - the Pass A raw captions your caption nodes appended to. This is the node's primary fuel.
  • Input - image path - the folder/file root the validator uses to resolve source images. It has to be findable, or Pass C can't do its job.
  • Input - include caption families - joy,qwen,ollama by default; use all or * for everything.
  • LoRA - trigger word and LoRA - user caption anchor - your trigger token and any identity/style anchor passed through to distiller and validator.
  • Fat Draft / Validator / Formatter - model - dropdowns loaded from config/captionforge_ollama_models.json; pick Custom to type any installed Ollama tag.
  • Final - TXT export format - natural, taggy, or both_separate.
  • Ollama - URL - defaults to http://127.0.0.1:11434. Nothing happens until that server is up.

Outputs: natural_captions, taggy_captions, final_jsonl_records, output_paths_json, and status. The JSONL/paths outputs are the audit trail in string form if you want to inspect or re-export.

Install

Same as every node in this pack - clone and restart:

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

Then the real requirement: a working local Ollama with the stage models pulled.

ollama pull mistral-small:24b
ollama pull gemma4:26b

The pack ships no weights and pulls nothing for this node by itself - it's pure Ollama calls.

Common issues

If you see connection errors, Ollama isn't running or the URL is wrong - check ollama serve. It's slow by design: three model passes per image, and a 24B Ollama model can churn for a while on a 16 GB card (the author's own dev box is an RTX 4090 Laptop). The request timeout default is a generous 1800 seconds because large models may still be pulling on first call. And remember: this node clears the resident Joy/Qwen Python models before it calls Ollama, so the GPU handoff can feel like a reload. The fat draft is supposed to contain conflicting details - the validator is the one that trims them, so don't panic when Pass B looks overstuffed.

CategoryCaptioning/CaptionForge

Inputs (49)

NameTypeDefaultDescription
Input - captions JSONLSTRINGPass A raw caption JSONL produced by CaptionForge Caption nodes.
Input - image pathSTRINGImage file/folder root used by the VLM validator to resolve source images.
Input - include caption familiesSTRINGjoy,qwen,ollamaComma-separated model_family values to use from Pass A. Use all or * to include everything.
Input - max captions per familyINT50–50Maximum selected Pass A captions per model family. 0 means no per-family cap.
Input - max total captionsINT200–100Maximum selected Pass A captions per image. 0 means no total cap.
Output - folderSTRINGOutput folder. Planner value overrides this when pipeline_plan is connected.
Output - run nameSTRINGcaptionforge_runRun-root used for B/C/D/E JSONL and TXT artifacts.
Output - overwrite outputsBOOLEANtrue
Ollama - URLSTRINGhttp://127.0.0.1:11434Local Ollama server URL.
Ollama - keep loadedBOOLEANtruePass keep_alive to Ollama. Ollama ultimately owns model residency.
Ollama - request timeout secondsINT180010–7200HTTP patience for Ollama calls. This does not affect caption quality.
LoRA - trigger wordSTRING
LoRA - user caption anchorSTRING
Fat Draft - modelCOMBOmistral-small:24b6 options: mistral-small:24b, VladimirGav/gemma4-26b-16GB-VRAM-Uncensored, deepseek-r1:32b, tarruda/neuraldaredevil-8b-abliterated:fp16, gpt-oss:20b, Custom
Fat Draft - custom Ollama modelSTRINGUsed only when Fat Draft - model is Custom.
Fat Draft - promptSTRING/no_think You are a detail-preserving caption merger for LoRA dataset preparation. You receive multiple captions of the same image. You do NOT see the image. Task: Merge all non-contradictory caption details into one deliberately over-complete draft caption. Rules: - Do not validate against the image. - Do not decide that details are false just because they appear once. - Do not summarize aggressively. - Preserve concrete details from all captions. - Split contradictions by choosing cautious wording or listing the alternative only when needed. - Prefer specific visual language over generic language. - Keep visible body, clothing, material, accessory, color, pose, lighting, style, and framing details. - Preserve doll-like, glossy/plastic-like, material, garment-construction, body-shape, and facial-feature details when present. - Use neutral dataset-caption language, including visible sensual styling or revealing clothing when present. - Do not add details absent from the captions. - Treat subject names or trigger-like identity tokens as optional identity labels. Preserve them only when they appear consistently in the captions; do not let them replace visible description. - Output only one paragraph, no notes, no JSON.Instructions for the text-only fat draft LLM. Captions are appended automatically.
Fat Draft - base seedINT1-1–4294967295
Fat Draft - seed modeCOMBOfixed4 options: fixed, increment, decrement, random
Fat Draft - max caption charsINT15360–12000
Fat Draft - max new tokensINT500064–12000Maps to Ollama num_predict.
Fat Draft - temperatureFLOAT0.120–2
Fat Draft - top pFLOAT0.880–1
Fat Draft - top kINT500–500
Validator - modelCOMBOgemma4:26b4 options: gemma4:26b, qwen3.6:35B-A3B, huihui_ai/gemma-4-abliterated:26b, Custom
Validator - custom Ollama modelSTRINGUsed only when Validator - model is Custom.
Validator - system promptSTRING/no_think You are a direct image validation engine. Inspect the image and answer only with the requested caption.System prompt for the image-aware VLM validator.
Validator - promptSTRING/no_think Look at the image and validate this draft caption. Task: Return a corrected caption paragraph that keeps only image-supported details. Rules: - Output only the corrected caption. - One paragraph. - No reasoning, no notes, no JSON. - Keep all true visible details from the draft. - Delete unsupported details. - Correct small visible errors. - Do not add new details unless needed to correct an error already present. - Preserve useful LoRA details: subject, face, hair, eyes, makeup, lips, skin texture, pose, body shape, outfit, accessories, materials, colors, lighting, background, framing, and visual style. - Visible sensual styling, revealing clothing, cleavage, thighs, bare skin, swimwear, lingerie, or body-shape details may be described neutrally when present. - Do not invent hidden anatomy, unseen clothing, explicit acts, or details contradicted by the image.Instructions for the image-aware VLM validator. The fat draft is appended automatically.
Validator - base seedINT1-1–4294967295
Validator - seed modeCOMBOfixed4 options: fixed, increment, decrement, random
Validator - max new tokensINT500064–12000Maps to Ollama num_predict.
Validator - temperatureFLOAT0.050–2
Validator - top pFLOAT0.880–1
Validator - top kINT500–500
Formatter - modelCOMBOmistral-small:24b5 options: mistral-small:24b, VladimirGav/gemma4-26b-16GB-VRAM-Uncensored, gpt-oss:20b, deepseek-r1:32b, Custom
Formatter - custom Ollama modelSTRINGUsed only when Formatter - model is Custom.
Formatter - promptSTRING/no_think You are a LoRA caption format converter. The validated paragraph is already the natural-language final caption. Do not rewrite it. Task: Create one TAGGY caption from the validated paragraph. Rules: - Output only the taggy comma-separated caption. - Use only details already present in the validated paragraph. - Preserve concrete LoRA-useful details. - Do not add new details. - Do not mention this process. - Do not output markdown. - Do not include a TAGGY: label. - Keep the result as a comma-separated list, not full prose.Instructions for the text-only taggy formatter. The validated paragraph is appended automatically.
Formatter - base seedINT1-1–4294967295
Formatter - seed modeCOMBOfixed4 options: fixed, increment, decrement, random
Formatter - max new tokensINT320064–12000Maps to Ollama num_predict.
Formatter - temperatureFLOAT0.120–2
Formatter - top pFLOAT0.880–1
Formatter - top kINT500–500
Audit - write prompt JSONLBOOLEANfalse
Audit - preserve raw responsesBOOLEANfalse
Final - TXT export formatCOMBOnatural3 options: natural, taggy, both_separate
Final - write TXT sidecarsBOOLEANtrue
Final - write JSONLBOOLEANtrue
Input - single imageoptIMAGEOptional IMAGE passthrough/reference for planned single-image workflows.
pipeline_planoptCAPTIONFORGE_PIPELINE_PLANConnect the CaptionForge Pipeline Planner pipeline_plan output here.

Outputs (5)

NameTypeDescription
natural_captionsSTRING
taggy_captionsSTRING
final_jsonl_recordsSTRING
output_paths_jsonSTRING
statusSTRING