Nodes/CaptionForge/ JLC CaptionForge Pipeline Planner
ComfyUI Node

 JLC CaptionForge Pipeline Planner

Where a CaptionForge run actually gets planned

By Damkohler·Created 4 months ago·Updated a day ago· 1
 JLC CaptionForge Pipeline Planner
  • Input - single image
  • single_image
  • pipeline_plan
  • pipeline_plan_json
Planner - enabledtrue
Input - image path
Input - recursivetrue
Input - filename glob*
Output - folder/tmp/ComfyUI/output/CaptionForge
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
Caption - Joy runs/image2
Caption - Qwen runs/image1
Caption - Ollama runs/image1
Caption - base seed-1
Caption - seed modefixed
Caption - temperature schedule0.90
Caption - top p schedule0.60
Caption - top k schedule80
Caption - max image size1024
Caption - max new tokens4096
Distiller - modelmistral-small:24b
Distiller - custom Ollama model
Distiller - 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.
Distiller - seed-1
Distiller - max caption chars for LLM1536
Distiller - num predict3096
Distiller - temperature0.24
Distiller - top p0.90
Distiller - top k60
Distiller - write prompt JSONLfalse
Distiller - preserve raw responsefalse
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 - seed-1
Validator - num predict2112
Validator - temperature0.00
Validator - top p0.92
Validator - top k80
Validator - write prompt JSONLfalse
Validator - preserve raw VLM responsefalse
Formatter - modelmistral-small:24b
Formatter - custom Ollama model
Formatter - prompt/no_think You are a LoRA caption format converter. The validated paragraph is your only source of truth. Output exactly two labeled lines: SHORT: <a concise natural-language caption, typically around 100 words, that preserves all LoRA-useful validated details> TAGGY: <one compact comma-separated caption> SHORT must preserve the image's distinctive training identity across the whole source: 1. subject, defining face/hair/body traits, and every major outfit piece/material; 2. pose/action and key accessories or unusual visible details; 3. setting, lighting, framing, and visual medium/style. Omit a category only when absent. Use only source details; never add, infer, euphemize, or correct. Compress wording, not category coverage. Do not copy only the source opening. Aim for roughly 100 words. Keep it concise, but allow modest variation when needed to preserve important information and finish the caption naturally. Do not cut off a sentence merely to satisfy a word-count target. TAGGY must preserve all concrete LoRA-useful source details as compact comma-separated phrases. No markdown, reasoning, notes, or other labels.
Formatter - seed-1
Formatter - num predict3200
Formatter - temperature0.12
Formatter - top p0.88
Formatter - top k50
Formatter - write prompt JSONLfalse
Formatter - preserve raw responsefalse
Final - write TXT sidecarstrue
Final - write JSONLtrue
Dataset - export image and captionfalse
Dataset - output folder
Dataset - max image size0
Dataset - dimension divisor16
Dataset - image formatPNG
Dataset - JPEG quality95
Dataset - captionshort

CaptionForge's real workflow is batch captioning a folder of images for LoRA training, and that workflow is run by JLC CaptionForge Pipeline Planner. It's the front door: you point it at an image folder (or a single image), tell it how many witness captions to generate per image and from which engines, pick the distiller and validator models, set your LoRA trigger word, and it produces a pipeline_plan that every downstream CaptionForge node reads. Change the plan, and the whole run changes with it - that's the point of having one planning node instead of forty widgets scattered across the graph.

The output layout is worth knowing before you run anything: final TXT sidecars get written beside each source image, run artifacts (JSONL audit trails, run config, output paths) land in a run-specific working folder under your output root, and direct IMAGE inputs get copied into an opt_images/ folder so the validator can find them.

How it works

The planner emits a CAPTIONFORGE_PIPELINE_PLAN (also available as pipeline_plan_json, a string) that caption nodes and the capstone consume through their pipeline_plan pins. When connected, it overrides the standalone sampling settings on those nodes - shared seed schedules, temperature/top-p/top-k schedules, max image size, max new tokens. It does recursive folder traversal and filename glob filtering, so *.png over a nested directory is a normal day at the office.

The Planner - enabled toggle is a neat escape hatch: disable it and the node just passes through your optional IMAGE with an empty plan, so downstream nodes run in standalone mode without you having to bypass widgets by hand.

Inputs that matter

  • Input - image path - image file or folder root; doubles as the validator's image root in planned runs.
  • Input - recursive / Input - filename glob - how deep you go and which files count.
  • Output - folder / Output - run name - where artifacts go (default /tmp/ComfyUI/output/CaptionForge) and the prefix on every JSONL.
  • Caption - Joy / Qwen / Ollama runs/image - witness counts per image. The dropdowns cap at 5 on purpose, "to prevent accidental giant runs" per the author. Three witnesses at 5 runs each is 15 raw captions per image to distill - think before you max it out.
  • Caption - base seed / seed mode - fixed, increment, decrement, or random across the run.
  • Caption - temperature / top p / top k schedule - comma-separated schedules; the last value repeats if you run out.
  • Caption - max new tokens - the shared token budget all witnesses get.
  • Distiller - model / Validator - model - the Ollama tags for Pass B and Pass C (dropdowns from config/captionforge_ollama_models.json, with Custom for arbitrary tags).
  • Final - caption style - narrative, comma, or both.
  • LoRA - trigger word / LoRA - user caption anchor - threaded through distiller and validator.

Outputs: single_image (your IMAGE passthrough), pipeline_plan, and pipeline_plan_json.

Install

Same pack install as everything else:

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

Restart ComfyUI. The planner itself loads no models, but the run it plans needs Ollama up with the distiller/validator tags pulled (ollama pull mistral-small:24b, ollama pull gemma4:26b).

Common issues

This node is where runs get misconfigured, so read your settings like a checklist: witness counts, seed mode, output folder, trigger word. If a caption node seems to ignore your standalone settings, check that the planner's overrides aren't stomping them - that's by design. And if a run produces nothing, the usual cause is a typo in Input - image path or a glob that matches zero files. Start with one image and low witness counts before you point it at a 10,000-image dataset, because the pack is unapologetically heavy.

CategoryCaption/CaptionForge

Inputs (64)

NameTypeDefaultDescription
Planner - enabledBOOLEANtrueEnable CaptionForge Pipeline Planner mode. If disabled, this node passes through the optional IMAGE and emits an empty/falsy plan so downstream nodes can run in standalone mode without GUI bypassing.
Input - image pathSTRINGImage file or image folder/root for ordinary folder/file workflows. This is also used as the validator image root. For quick single-image workflows, connect IMAGE to the optional Input - single image socket.
Input - recursiveBOOLEANtrueWhether captioning nodes should recurse when Input - image path is a folder.
Input - filename globSTRING*Filename glob for folder captioning, e.g. *.png, *.jpg, or *.
Output - folderSTRING/tmp/ComfyUI/output/CaptionForgeOutput root folder. CaptionForge creates a run-specific working directory inside this folder for JSON/JSONL/audit artifacts. Final TXT sidecars are written beside their resolved source images.
Output - run nameSTRINGcaptionforge_runRun-root used to name config JSON, output path JSON, caption JSONL, distiller JSONL, prompt JSONLs, validator JSONL, and final JSONL.
Output - overwrite outputsBOOLEANtrueOverwrite generated run artifacts during capstone execution.
Ollama - URLSTRINGhttp://127.0.0.1:11434Planner-owned local Ollama server URL for Passes B, C, and D.
Ollama - keep loadedBOOLEANtruePlanner-owned keep_alive policy for Passes B, C, and D.
Ollama - request timeout secondsINT180010–7200Planner-owned HTTP patience for Passes B, C, and D; does not affect caption quality.
LoRA - trigger wordSTRINGOptional shared LoRA trigger token/string preserved through the pipeline.
LoRA - user caption anchorSTRINGOptional persistent semantic caption anchor supplied by the user, for example 'doll-like quasi-3D render'. CaptionForge encourages compatible anchor content to persist through refinement and final caption generation.
Caption - Joy runs/imageCOMBO2Joy Caption runs per image. Set to Disabled to omit Joy from this run. Dropdown is capped at 5 to prevent accidental giant runs.
Caption - Qwen runs/imageCOMBO1Qwen Caption runs per image. Set to Disabled to omit Qwen from this run. Dropdown is capped at 5 to prevent accidental giant runs.
Caption - Ollama runs/imageCOMBO1Ollama Caption runs per image for each connected JLC CaptionForge Ollama Caption node. The actual Ollama model tag is selected in each Ollama Caption node. Connecting multiple Ollama Caption nodes multiplies runtime, memory pressure, and raw-caption count.
Caption - base seedINT-1-1–4294967295Base seed for the reusable Pass-A run schedule. -1 means intentionally unseeded.
Caption - seed modeCOMBOfixedHow the base seed changes across witness runs: fixed reuses it, increment/decrement step by one, and random creates a repeatable hash-derived schedule. A base seed of -1 remains unseeded in every mode.
Caption - temperature scheduleSTRING0.90Comma-separated caption temperature schedule; final value repeats if needed.
Caption - top p scheduleSTRING0.60Comma-separated nucleus-sampling values for Pass-A runs. Lower values limit choices to more likely tokens; the final value repeats as needed.
Caption - top k scheduleSTRING80Comma-separated token-choice limits for Pass-A runs. Lower values are more restrictive; the final value repeats as needed.
Caption - max image sizeINT10240–4096Maximum longest image side sent to Pass-A captioners. Larger images are resized proportionally; 0 keeps their original size.
Caption - max new tokensINT409616–4096Maximum Pass-A generation budget. CaptionForge supports up to 4096 tokens.
Distiller - modelCOMBOmistral-small:24bConcrete Ollama text model tag for the distiller. Use custom to enter any other installed Ollama text model.
Distiller - custom Ollama modelSTRINGUsed only when Distiller - model is custom, e.g. my-model:latest.
Distiller - 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.Planner-owned instructions for the text-only fat draft LLM. Pass A captions are appended automatically.
Distiller - seedINT-1-1–4294967295Fixed seed used by the distiller for every image. -1 means omit seed.
Distiller - max caption chars for LLMINT15360–12000Maximum characters retained from each Pass-A source caption before building the Pass-B prompt. 0 keeps the complete caption.
Distiller - num predictINT309664–12000Planner token budget for Pass B; maps to Ollama num_predict.
Distiller - temperatureFLOAT0.240–2Pass-B variation level. Lower values are steadier; higher values permit more varied wording.
Distiller - top pFLOAT0.900–1Pass-B nucleus-sampling limit. Lower values restrict the model to more likely tokens.
Distiller - top kINT600–500Pass-B token-choice limit. Lower values are more restrictive; 0 lets the backend disable top-k filtering.
Distiller - write prompt JSONLBOOLEANfalseWrite the complete Pass-B prompt to a separate JSONL audit file. This can substantially increase output size.
Distiller - preserve raw responseBOOLEANfalseKeep the unparsed Pass-B model response in audit records for troubleshooting.
Validator - modelCOMBOgemma4:26bConcrete Ollama vision model tag for the image-aware validator. Use custom to enter any other installed Ollama vision model.
Validator - custom Ollama modelSTRINGUsed only when Validator - model is custom, e.g. gemma4:e4b or another installed VLM tag.
Validator - system promptSTRING/no_think You are a direct image validation engine. Inspect the image and answer only with the requested caption.Planner-owned 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.Planner-owned instructions for the image-aware VLM validator. The fat draft is appended automatically.
Validator - seedINT-1-1–4294967295Fixed seed used by the VLM validator for every image. -1 means omit seed.
Validator - num predictINT211264–12000Planner token budget for Pass C; maps to Ollama num_predict.
Validator - temperatureFLOAT0.000–2Pass-C variation level. Zero requests the most deterministic image-validation result.
Validator - top pFLOAT0.920–1Pass-C nucleus-sampling limit. Lower values restrict the validator to more likely tokens.
Validator - top kINT800–500Pass-C token-choice limit. Lower values are more restrictive; 0 lets the backend disable top-k filtering.
Validator - write prompt JSONLBOOLEANfalseWrite the complete image-validation prompt to a separate JSONL audit file.
Validator - preserve raw VLM responseBOOLEANfalseKeep the unparsed Pass-C VLM response in audit records for troubleshooting.
Formatter - modelCOMBOmistral-small:24bConcrete Ollama text model tag for the SHORT + TAGGY formatter. Use custom to enter any other installed Ollama text model.
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 your only source of truth. Output exactly two labeled lines: SHORT: <a concise natural-language caption, typically around 100 words, that preserves all LoRA-useful validated details> TAGGY: <one compact comma-separated caption> SHORT must preserve the image's distinctive training identity across the whole source: 1. subject, defining face/hair/body traits, and every major outfit piece/material; 2. pose/action and key accessories or unusual visible details; 3. setting, lighting, framing, and visual medium/style. Omit a category only when absent. Use only source details; never add, infer, euphemize, or correct. Compress wording, not category coverage. Do not copy only the source opening. Aim for roughly 100 words. Keep it concise, but allow modest variation when needed to preserve important information and finish the caption naturally. Do not cut off a sentence merely to satisfy a word-count target. TAGGY must preserve all concrete LoRA-useful source details as compact comma-separated phrases. No markdown, reasoning, notes, or other labels.Planner-owned SHORT + TAGGY instructions for the text-only formatter. The validated LONG caption is appended automatically.
Formatter - seedINT-1-1–4294967295Fixed seed used by the SHORT/TAGGY formatter for every image. -1 means omit seed.
Formatter - num predictINT320064–12000Planner token budget for Pass D; maps to Ollama num_predict.
Formatter - temperatureFLOAT0.120–2Pass-D variation level. Lower values make SHORT/TAGGY formatting more consistent.
Formatter - top pFLOAT0.880–1Pass-D nucleus-sampling limit. Lower values restrict the formatter to more likely tokens.
Formatter - top kINT500–500Pass-D token-choice limit. Lower values are more restrictive; 0 lets the backend disable top-k filtering.
Formatter - write prompt JSONLBOOLEANfalseWrite the complete Pass-D SHORT/TAGGY prompt to a separate JSONL audit file.
Formatter - preserve raw responseBOOLEANfalseKeep the unparsed Pass-D model response in audit records for troubleshooting.
Final - write TXT sidecarsBOOLEANtrueFinal TXT sidecars use the associated image filename stem and .txt extension.
Final - write JSONLBOOLEANtrueWrite the final run-level JSONL containing LONG, SHORT, and TAGGY captions for every processed image.
Dataset - export image and captionoptBOOLEANfalseExport a resized image and matching training TXT. Planner owns these controls when connected.
Dataset - output folderoptSTRINGParent folder for training_dataset. Blank uses Output - folder. Originals are never replaced.
Dataset - max image sizeoptINT00–8192Maximum long edge; never enlarges. 0 follows the configured Validator size (Planner Caption - max image size).
Dataset - dimension divisoroptINT161–512Round both dimensions DOWN to this multiple after resizing. 1 disables alignment. Images too small for the divisor fail export without enlargement.
Dataset - image formatoptCOMBOPNGFormat of the exported RGB training image.
Dataset - JPEG qualityoptINT951–100JPEG quality; ignored for PNG.
Dataset - captionoptCOMBOshortCaption written to the matching plain .txt file. Other caption variants remain available.
Input - single imageoptIMAGEOptional IMAGE passthrough for quick single-image workflows. The planner does not process this image; it simply returns it as output.

Outputs (3)

NameTypeDescription
single_imageIMAGE
pipeline_planCAPTIONFORGE_PIPELINE_PLAN
pipeline_plan_jsonSTRING