Nodes/FiL_Design_ImageMind/📚 LoRA Dataset Forge
ComfyUI Node

📚 LoRA Dataset Forge

A batch of images in, a kohya-ready LoRA dataset out — captions included

By FiL-Design-Ai·Created 2 months ago·Updated 8 days ago· 8
📚 LoRA Dataset Forge
  • image
  • config
  • preview
  • report
  • dataset_path
  • manifest
dataset_namemy_lora
trigger_word
class_token
base_resolution1024
layoutkohya
repeats10
caption_modenatural
crop_modecenter
dry_runfalse
write_modeappend
caption_max_words60
caption_languageen
bucket_step64
caption_extension.txt
image_formatpng
jpg_quality95
seed-1
captions
dont_caption
caption_instruction

Training a LoRA has two miserable parts: wrangling the images into aspect-ratio buckets, and captioning them all. FiLDatasetForge kills both in one run. Feed it a whole image batch (Load Image with a folder of frames), tell it your trigger word, and it buckets the images at the target resolution, writes one LLM caption per frame, and lays the whole thing out as a folder kohya_ss or sd-scripts can eat directly - plus a dataset.toml if you pick the kohya layout. It's the kind of node you reach for when a dataset has been sitting half-built in your head for a month.

How it works

The pipeline is: bucket → crop → caption → write. Buckets are built around base_resolution (1024 for SDXL/Flux, 512–768 for SD 1.5), with bucket_step (64 default) as the side divisor - the standard kohya bucketing math. Each frame is cropped into its bucket with crop_mode center, or entropy if you want the crop pulled toward the most detailed region instead of the middle.

Captioning is where the LLM comes in. With config from the Provider Loader connected, each image gets a caption in caption_mode: natural prose (Flux/SDXL), comma tags (SD 1.5/Pony), hybrid, or none (trigger word only, no API call). You can also bypass the LLM entirely by wiring the captions input with manual captions separated by lines containing only --- - it accepts Optic Scanner output as-is, which is a nice pairing for auditing a small set by hand.

The inputs that decide whether your LoRA generalizes

  • trigger_word - the rare token that activates the LoRA, prepended to every caption. Use something like ohwx, not a real word.
  • class_token - the class the subject belongs to (woman, car). It follows the trigger in captions and in the kohya folder name (img/<repeats>_<trigger> <class>/).
  • base_resolution and caption_mode - match both to your base model.
  • dont_caption - the underrated one. List the invariants you never want described ("her face, red hair"); the caption prompt forbids them explicitly.

That last input encodes the single most important rule in LoRA captioning, and the README states it plainly: describe what varies - pose, clothing, background, lighting - and never describe the invariant. The invariant belongs to the trigger word; if your captions describe it, the LoRA learns it as something you'll have to fight at inference time. That rule is why dont_caption exists, and it's the difference between a LoRA that generalizes and one that's welded to your exact dataset.

Outputs and gotchas

Four outputs: preview (the bucketed frames letterboxed onto one square canvas), report (a human-readable summary - read this first), dataset_path (absolute path of what was written), and manifest (per-image bucket, crop, caption and hash). dry_run computes everything and writes nothing - use it, always, the first time.

Two honest warnings. First, the node never upscales: sources smaller than their bucket are still written, but they're flagged in the report's upscaled_count. Small images in a dataset quietly hurt training, so run stragglers through FiL Upscaler Simple first. Second, multi-subject attribution is the known weak spot of every captioning VLM - if your set has multiple people doing different things, audit those captions by hand rather than trusting the LLM. Manual captioning is still the gold standard for small sets, and the captions input makes that easy.

Install is pack-standard: Manager search FiL_Design_ImageMind, or clone + pip install -r requirements.txt + restart. No captioning requires no config at all; LLM captions need a provider.

Category🎨 FiL Design/📁 Dataset

Inputs (22)

NameTypeDefaultDescription
imageIMAGEImages to turn into a dataset. The whole batch is processed, one file per frame.
dataset_nameSTRINGmy_loraDataset folder name under ComfyUI/output/datasets. Sanitized to a safe path segment.
trigger_wordSTRINGUnique token that activates the LoRA, prepended to every caption (e.g. 'ohwx'). Leave empty for a style LoRA.
class_tokenSTRINGClass the subject belongs to (e.g. 'woman', 'car'). Follows the trigger word in captions and in the kohya folder name.
base_resolutionCOMBO1024Training resolution. Buckets are built around this area — 1024 for SDXL/Flux, 512-768 for SD 1.5.
layoutCOMBOkohyakohya: <name>/img/<repeats>_<trigger> <class>/ plus dataset.toml. flat: images and captions directly in <name>/.
repeatsINT101–1000Repeats per image per epoch — encoded in the kohya folder name and dataset.toml. Fewer images means more repeats.
caption_modeCOMBOnaturalnatural: prose for Flux/SDXL. tags: comma tags for SD 1.5/Pony. hybrid: short comma phrases. none: trigger word only, no LLM call.
crop_modeCOMBOcenterHow the frame is cropped into its bucket. entropy keeps the most detailed region instead of the middle.
dry_runBOOLEANfalseCompute buckets, captions and file names but write nothing. Read the report to check the plan first.
write_modeCOMBOappendappend: keep existing files and continue numbering. overwrite: delete this node's image/caption pairs in the folder first (other files are left alone).
caption_max_wordsINT604–400Hard word limit per caption. Captions longer than this are truncated.
caption_languageCOMBOenCaption language. Trainers expect English unless the base model was trained otherwise.
bucket_stepINT648–256Bucket side divisor. 64 is the kohya default and fits SD/SDXL/Flux latents.
caption_extensionCOMBO.txtExtension of the caption sidecar files. kohya defaults to .txt.
image_formatCOMBOpngpng keeps the crop lossless; jpg saves disk space on large sets.
jpg_qualityINT9550–100JPEG quality when image_format is jpg. Below ~90 the artifacts start training too.
seedINT-1-1–999999999999Provider-side caption seed. -1 lets the provider pick one; a fixed value makes captions reproducible.
configoptFIL_PROVIDER_CONFIGProvider Loader config. Required for LLM captioning — leave unconnected when captions come from the captions input or caption_mode is 'none'.
captionsoptSTRINGManual captions, one per image, separated by a line containing only '---'. Accepts Optic Scanner output as-is. When filled, no LLM call is made.
dont_captionoptSTRINGInvariants the captions must never mention (e.g. 'her face, red hair'). These belong to the trigger word — describing them stops the LoRA from learning them.
caption_instructionoptSTRINGExtra instruction appended to every caption request.

Outputs (4)

NameTypeDescription
previewIMAGEBucketed frames letterboxed onto a square canvas so the batch can be previewed. The files on disk keep their real bucket size.
reportSTRINGHuman-readable summary: buckets, captions, warnings, target path.
dataset_pathSTRINGAbsolute path of the dataset folder that was written.
manifestDICTFull manifest dict — per-image bucket, crop, caption and hash.