Nodes/ComfyUI/Train LoRA
ComfyUI Node Runs on cloud

Train LoRA

ComfyUI's built-in trainer actually trains — and it's less scary than it looks

By Comfy-Org·Created 4 years ago·Updated 29 minutes ago· 129,853
Train LoRA
  • model
  • latents
  • positive
  • lora
  • loss_map
  • steps
batch_size1
grad_accumulation_steps1
steps16
learning_rate0
rank8
optimizerAdamW
loss_functionMSE
seed0
training_dtypebf16
lora_dtypebf16
quantized_backwardfalse
algorithmLoRA
gradient_checkpointingtrue
checkpoint_depth1
offloadingfalse
existing_lora[None]
bucket_modefalse
bypass_modefalse

This is the node that turns your ComfyUI from a generation tool into a training tool. Train LoRA doesn't load or apply a LoRA - it creates brand-new weights from scratch, using your latents and captions as the dataset. It ships inside ComfyUI core (no install, no second Python environment, no YAML config), and it's been quietly getting good since mid-2025.

The honest framing up front: if you're a serious trainer, the community default is still ai-toolkit, kohya, or OneTrainer, and you'll get told "the ComfyUI training stuff is not fully baked" if you ask. That's true in the sense that these nodes are still marked experimental and shift between releases. But baked enough - plenty of people train real, working LoRAs inside ComfyUI, and it's the only trainer that gets day-one support for whatever architecture just shipped.

How it actually works

Training is a diffusion objective, not a pixel-matching exercise. The node deep-copies your model, freezes the original weights, and bolts low-rank adapters on top (pick algorithm: LoRA by default, plus LoHa, LoKr, or OFT - LoKr is worth a try for character work on modern bases). Then it runs a loop where each step grabs a random latent from the dataset, adds noise at a random timestep, asks the model to predict the clean latent back, and measures the error. That error is what your loss_function scores - MSE by default, or L1, Huber, SmoothL1. Rinse and repeat steps times.

The inputs that matter

The first three are the dataset trio: model (the base model to train on), latents (pre-encoded images - wire them straight from Make Training Dataset or Load Training Dataset), and positive (the captions, one per image; give one and it repeats for all). Then the knobs:

  • steps - how many optimizer updates. The default of 16 is a smoke-test number, not a real run. Small character sets typically want a few thousand.
  • learning_rate - default 5e-4 is SDXL-era thinking. Modern bases want lower: the KB's rule of thumb is ~1e-4 ceiling for Flux-class models, lower still on big batches.
  • rank - the size of the adapter. 8 default; go higher for more capacity, lower for style.
  • batch_size and grad_accumulation_steps - accumulate gradients to fake a bigger batch on limited VRAM.
  • training_dtype - bf16 default. Set to none to keep the model's native compute dtype; fp16 models automatically get GradScaler.
  • existing_lora - pick one from models/loras to keep training it instead of starting fresh.
  • bucket_mode - flip this on when feeding pre-bucketed latents from Resolution Bucket, and bypass_mode for quantized models whose weights can't be modified directly.

What comes out

Three outputs: lora (the trained weights), loss_map (feed it to Plot Loss Graph), and steps (total step count). The lora output doesn't go back into a normal LoraLoader - it wires into Save LoRA Weights to write a .safetensors, or Load LoRA Model to test it immediately in the same graph.

Here's the workflow shape:

Load Image → Make Training Dataset → Train LoRA → Save LoRA Weights
                                     └──→ Plot Loss Graph

Where people get burned

  • The save node. People hunt for "Extract and Save LoRA" and find inputs called model_diff and text_encoder_diff that nothing connects to. That's a legacy node. The trainer's lora output goes into Save LoRA Weights (alias "export lora"), which drops a file like ComfyUI_trained_lora_2000_steps_00000_.safetensors under your output folder.
  • Macs. If you're on Apple silicon, the offloading toggle won't save you the way it does on CUDA - unified memory means there's no separate VRAM to spill into, and training Flux on an M4 Max has been known to OOM at 88 GB. Keep the memory budget small.
  • It's experimental. Settings and defaults move between ComfyUI releases. If a tutorial's knobs don't match what you see, trust the tooltips.
  • The 16-step default is a trap. Anyone who runs the default and concludes training is broken should read the loss graph first - it's learning, you just asked for almost no learning.
Categorymodel/training

Inputs (21)

NameTypeDefaultDescription
modelMODELThe model to train the LoRA on.
latentsLATENTThe Latents to use for training, serve as dataset/input of the model.
positiveCONDITIONINGThe positive conditioning to use for training.
batch_sizeINT11–10000The batch size to use for training.
grad_accumulation_stepsINT11–1024The number of gradient accumulation steps to use for training.
stepsINT161–100000The number of steps to train the LoRA for.
learning_rateFLOAT01e-7–1The learning rate to use for training.
rankINT81–128The rank of the LoRA layers.
optimizerCOMBOAdamWThe optimizer to use for training.
loss_functionCOMBOMSEThe loss function to use for training.
seedINT00–18446744073709550000The seed to use for training (used in generator for LoRA weight initialization and noise sampling)
training_dtypeCOMBObf16The dtype to use for training. 'none' preserves the model's native compute dtype instead of overriding it. For fp16 models, GradScaler is automatically enabled.
lora_dtypeCOMBObf16The dtype to use for lora.
quantized_backwardBOOLEANfalseWhen using training_dtype 'none' and training on quantized model, doing backward with quantized matmul when enabled.
algorithmCOMBOLoRAThe algorithm to use for training.
gradient_checkpointingBOOLEANtrueUse gradient checkpointing for training.
checkpoint_depthINT11–5Depth level for gradient checkpointing.
offloadingBOOLEANfalseOffload model weights to CPU during training to save GPU memory.
existing_loraCOMBO[None]The existing LoRA to append to. Set to None for new LoRA.
bucket_modeBOOLEANfalseEnable resolution bucket mode. When enabled, expects pre-bucketed latents from ResolutionBucket node.
bypass_modeBOOLEANfalseEnable bypass mode for training. When enabled, adapters are applied via forward hooks instead of weight modification. Useful for quantized models where weights cannot be directly modified.

Outputs (3)

NameTypeDescription
loraLORA_MODELLoRA weights
loss_mapLOSS_MAPLoss history
stepsINTTotal training steps