Anima Save Llama-cpp Captions
Turns the VLM's words into real caption .txt files
- TASK_LIST
- IMAGE_RECORDS
- TASK_LIST
- caption_log
The llama-cpp nodes in this workflow produce a list of strings - raw VLM output with FINAL: prefixes, thinking blocks, and tag soup. That is not a training set. AnimaSaveLlamaCppCaptions is the node that makes it one: it takes the VLM's output_list, matches each caption to the image it came from via IMAGE_RECORDS, runs the pack's caption cleaner, and writes a trigger_word, anime illustration, tags... .txt file next to every image. This is where the llama-cpp caption path ends and real LoRA data begins.
How it works
The node is marked INPUT_IS_LIST, meaning it receives the VLM's per-image output list (not a joined blob). It zips that list against the IMAGE_RECORDS from AnimaLoadCaptionImageBatch - so caption N pairs with image N - and for each pair it derives the trigger word, cleans the caption through clean_caption (strip markdown and model chatter, drop masterpiece/watermark/artist-name pollution, dedupe, lowercase, force the trigger first and anime illustration second), and writes image.txt. It also handles the case where you accidentally fed it a single joined string: if the text contains ====== Image chunk markers it splits them back apart, which is a genuinely nice touch.
After writing, it refreshes the caption counts in the task list so downstream nodes (like AnimaCaptionPrepare and the trainer) see accurate numbers.
The inputs
- TASK_LIST - passed through from the folder loader.
- IMAGE_RECORDS - from AnimaLoadCaptionImageBatch; this is what maps captions back to files.
- caption_list - the VLM's output. Connect
output_list, not a joined output - if the counts don't match, the node returnsERROR: caption count mismatch. records=N, captions=M. Connect llama-cpp output_list, not the joined output.It's telling you exactly what you did. - overwrite_existing_caption (true) - whether to replace an existing non-empty caption. The caption-API path defaults the other way; here it defaults to overwrite, which is right for a first captioning run.
Outputs: TASK_LIST (refreshed) and caption_log, with a per-file OK: / SKIP: / ERROR: line and a Saved llama-cpp captions. saved=N, skipped=N, failed=N summary.
Installing it
Part of the AnimaForge Windows pack: ComfyUI Manager → "ComfyUI-AnimaForge-Windows", or
cd C:\ComfyUI\custom_nodes
git clone https://github.com/AI-KSK/ComfyUI-AnimaForge-Windows.git
cd ComfyUI-AnimaForge-Windows
powershell -ExecutionPolicy Bypass -File .\scripts\install_windows.ps1
Its only Python deps are requests and pillow; the VLM half of the workflow needs ComfyUI-llama-cpp_vlm plus a Gemma-class GGUF and mmproj in ComfyUI\models\LLM. Restart ComfyUI after install.
Common issues
The count-mismatch error above is by far the most common - everyone tries to drag in the instruct node's text output instead of its list output at least once. Second: forgetting IMAGE_RECORDS entirely gives ERROR: IMAGE_RECORDS is empty, so the node can't know which file a caption belongs to. And because overwrite_existing_caption defaults to true here, re-running after fixing the model can stomp captions you hand-corrected - flip it off once you start editing .txt files by hand. Worth knowing from the community side: AnimaForge auto-captions run long (users have seen 1200+ characters, mostly natural language) and still train fine, but this cleaner normalizes them into the trigger-first hybrid format regardless - which is exactly what Anima's training data looks like.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| TASK_LIST | TASK_LIST | — | |
| IMAGE_RECORDS | IMAGE_RECORDS | — | |
| caption_list | STRING | — | |
| overwrite_existing_caption | BOOLEAN | true | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| TASK_LIST | TASK_LIST | — |
| caption_log | STRING | — |