Nodes/ComfyUI/Make Training Dataset
ComfyUI Node Runs on cloud

Make Training Dataset

The node that turns images and captions into something trainable

By Comfy-Org·Created 4 years ago·Updated about 19 hours ago· 129,495
Make Training Dataset
  • images
  • vae
  • clip
  • latents
  • conditioning
texts

Make Training Dataset is the front door of ComfyUI's built-in training pipeline. The Train LoRA node can't eat raw images - it trains on latents and conditioning. This node is the translation layer: it runs every image through a VAE to get latents, every caption through CLIP to get conditioning, and hands both back as parallel lists. Everything downstream - Save Training Dataset, Resolution Bucket, Train LoRA - expects exactly that shape.

It ships with ComfyUI core, no install, and it landed alongside the rest of the training family in late 2025. It's still marked experimental, so expect the occasional edge, but the mechanism itself is simple and stable.

How it works

Mechanically it's two loops doing exactly what the tooltips say. Each image gets vae.encoded into a latent dict; each caption gets tokenized and encoded into a conditioning list. One image, one caption, one aligned pair. The encoding is deterministic and architecture-specific - the latents you get are only meaningful to the base model whose VAE you used, which is the whole reason the node takes explicit vae and clip inputs rather than guessing.

The inputs that matter

  • images - your dataset as a list of images. Wire it from Load Image, or a batch from a Load Images From Folder node.
  • vae and clip - must match the model you'll train on. A Z-Image dataset made with the wrong VAE will produce garbage LoRAs no matter how good your captions are. Architecture lock-in is absolute.
  • texts - the only optional input, and the one with rules. It's a list of captions that must be either the same length as images (one caption per image), length 1 (repeated for every image), or omitted entirely (which silently uses empty strings - unconditional training with no prompt control at all).

A length mismatch - 5 texts for 10 images, say - raises an error rather than guessing. That's by design; silent misalignment is how you waste a training run.

Outputs and where they go

Two outputs, both lists: latents and conditioning. The straightforward wiring is straight into Train LoRA's latents and positive inputs. If you want bucketing, push them through Resolution Bucket first. If you'll be iterating on trainer settings, save them with Save Training Dataset and load later - re-encoding a dataset every time you tweak a learning rate is pure waste.

The part that's actually on you

Encoding is the cheap half of dataset work; curation is the expensive half, and the node doesn't help there. The KB's rules still apply and still matter more than any knob:

  • Caption what you want to vary, leave what should stay fixed undescribed. Describe clothing and lighting; don't describe the face.
  • Use a rare trigger token (ch9ractername, not "the character") so it doesn't collide with real words.
  • Small and clean beats big and sloppy. Twenty well-chosen images outperform two hundred careless ones, every time.
  • Character sets want 15–25 images; styles want 30–100.

And for the modern LLM-encoder bases - Flux, Z-Image, Qwen-Image - write natural-language captions, not tag soup. The clip input here is whatever text encoder the model uses; give it sentences it can actually understand.

Gotchas

Empty texts means unconditional training - fine for experiments, useless if you want a promptable LoRA. And remember the node encodes at whatever resolution your images arrive in; if your set mixes portrait and landscape, that's not a bug, that's what Resolution Bucket exists to handle.

Categorymodel/training

Inputs (4)

NameTypeDefaultDescription
imagesIMAGEList of images to encode.
vaeVAEVAE model for encoding images to latents.
clipCLIPCLIP model for encoding text to conditioning.
textsoptSTRINGList of text captions. Can be length n (matching images), 1 (repeated for all), or omitted (uses empty string).

Outputs (2)

NameTypeDescription
latentsLATENTList of latent dicts
conditioningCONDITIONINGList of conditioning lists