ComfyUI Node

Train SDXL LoRA

Train An SDXL LoRA Without Leaving The Graph (It Shells Out To Kohya)

By alchemine·Created about a year ago·Updated 2 days ago· 5
Train SDXL LoRA
    • lora_path
    • run_dir
    ◄namemy_lora►
    ◄versionv1.0.0►
    ◄ckpt_name▾►
    ◄train_unit▾►
    ◄train_length20►
    ◄learning_rate1.0000►
    ◄network_type▾►
    ◄r32►
    ◄lora_alpha16►
    ◄loraplus_lr_ratio0►
    ◄resolution1024►
    ◄batch_size1►
    ◄optim▾►
    ◄lr_scheduler_type▾►
    ◄warmup_ratio0.05►
    ◄shuffle_captiontrue►
    ◄keep_tokens1►
    ◄gradient_checkpointingfalse►
    ◄gradient_accumulation_steps1►
    ◄network_dropout0.00►
    ◄scale_weight_norms0.0►
    ◄noise_offsettrue►
    ◄noise_offset_value0.0357►
    ◄seed42►
    ◄save_steps200►
    ◄sample_steps200►
    ◄logging_steps25►
    ◄sample_prompts1girl, solo --n worst quality, low quality --w 832 --h 1216 --s 28 --l 5 --d 42►

    What it actually is

    This is a kohya wrapper wearing a node costume. You give it a dataset folder and a checkpoint, it writes two TOML configs, shells out to kohya's sdxl_train_network.py in a subprocess, streams that process's log into your ComfyUI console, and waits.

    Which matters, because the tooling story is confusing right now. kohya's mentions roughly halved over eighteen months while ai-toolkit grew nearly fivefold, so "use ai-toolkit" is the honest advice for a fresh Flux LoRA. But that advice is architecture-specific. SDXL-lineage bases - Illustrious, Pony, NoobAI - are still kohya territory, and the settings tables everyone quotes for them were written against it.

    My honest read: if you already have kohya_ss's GUI open or ai-toolkit installed, this won't convert you - you'd be trading a real UI for thirty widgets. It earns its place when you want one graph from folder to .safetensors on a Linux box with an NVIDIA card, and no second training install to maintain.

    What it runs

    Everything lives under output/train/<name>/<version>/. train/ holds your images with same-name .txt captions, read in place. mask/, if it exists, switches on sd-scripts' masked loss - white trains, black is ignored. Each run gets a timestamp folder under checkpoints/ (the LoRA files) and runs/ (configs, samples, TensorBoard logs).

    Some settings are hardcoded: UNet-only training, min_snr_gamma = 5, bf16, cached latents, SDPA, bucketing with no upscale, one repeat. The node parses sd-scripts' progress lines to drive a live loss chart, and blocks until the process exits - a non-zero return raises and points you at run_dir.

    The inputs worth touching

    name and version are just folder names. ckpt_name is your base checkpoint from models/checkpoints.

    train_unit plus train_length decide how long: epochs multiplies by ceil(images / batch_size), steps is taken literally. Do the arithmetic yourself - the default 20 epochs on a 20-image set at batch 1 is 400 steps, and the old SDXL rule of thumb is 100–200 steps per image. So that default is a short run, not a medium one. Set 100 epochs for a character and keep save_steps on; the last checkpoint is regularly not the best one.

    learning_rate is the trap in this node. Default is 1.0, which is correct for Prodigy - with an adaptive optimizer the learning rate is a multiplier on an estimated step size, and 1.0 is the point. Switch optim to AdamW or AdamW8bit and leave it at 1.0 and you'll blow the run up in the first fifty steps. AdamW on SDXL wants something around 1e-4.

    network_type is LoRA or LoKr, and r/lora_alpha default to 32/16 - which happens to match the SDXL community's favourite pairing (32/16 or 16/16, both widely reported as the sweet spot for people). Leave them.

    resolution, batch_size, gradient_checkpointing and gradient_accumulation_steps are your VRAM dials. noise_offset defaults on at 0.0357, the value SDXL base was trained with; the README is explicit that you should turn it off for AnyIllustrious-XL. sample_prompts takes sd-scripts' one-line-per-prompt format (--n, --w, --h, --s, --l, --d) - the stock prompt is an 832×1216 anime portrait, which tells you who the author was testing against.

    Outputs are lora_path (the final .safetensors) and run_dir (configs, samples, logs). Both are strings, mostly there so you can print or log where things landed.

    Installing sd-scripts first

    The pack installs like any other: ComfyUI Manager → search ComfyUI-Alchemine-Pack → install → restart, or git clone into custom_nodes. But the node refuses to run until kohya lives at <ComfyUI>/sd-scripts with its own .venv:

    cd ComfyUI
    git clone https://github.com/kohya-ss/sd-scripts.git
    cd sd-scripts
    python3 -m venv .venv
    .venv/bin/pip install --upgrade pip
    .venv/bin/pip install torch torchvision --index-url https://download.pytorch.org/whl/cu124
    .venv/bin/pip install -r requirements.txt
    .venv/bin/pip install prodigyopt    # the default optimizer needs it
    

    That last line isn't decoration: kohya's Prodigy support has always needed prodigyopt in the training environment separately, and this node defaults optim to Prodigy.

    The same loss curve is in TensorBoard:

    sd-scripts/.venv/bin/tensorboard --logdir output/train/<name>/<version>/runs
    

    Where people get burned

    The LoRA isn't in models/loras. Training writes to output/train/<name>/<version>/checkpoints/<timestamp>/<name>.safetensors. It won't show up in a LoraLoader until you move or symlink it there, and nobody finds that out from the success message.

    sd-scripts is not installed: … before anything starts. The node checks two exact paths: sdxl_train_network.py and .venv/bin/accelerate. If your venv is elsewhere, or your sd-scripts lives under a different ComfyUI root, the run dies at the door.

    Windows and older cards are both out. .venv/bin/accelerate is the POSIX venv layout - a Windows venv puts executables in .venv/Scripts/ - and bf16 is hardcoded with no fp16 fallback, so a pre-Ampere card is going to have a bad time.

    Your queue is blocked for the duration. The node waits on the child process, so ComfyUI is busy until the run finishes. The real progress output is in the console as [sd-scripts] lines - that's where optimiser errors, OOM kills and the actual step count live if the chart looks stuck.

    A missing train/ folder fails loudly. Put images and same-name .txt captions in place before you queue, and check the node's path display above the chart - it shows the output_dir and mask_dir it will use as you type.

    CategoryAlcheminePack/Lora

    Inputs (28)

    NameTypeDefaultDescription
    nameSTRINGmy_lora—
    versionSTRINGv1.0.0—
    ckpt_nameCOMBO0 options:
    train_unitCOMBO2 options: epochs, steps
    train_lengthINT201–100000—
    learning_rateFLOAT1.00000–1—
    network_typeCOMBO2 options: LoRA, LoKr
    rINT321–256—
    lora_alphaINT161–256—
    loraplus_lr_ratioFLOAT00–32—
    resolutionINT1024512–2048—
    batch_sizeINT11–16—
    optimCOMBO4 options: Prodigy, AdamWScheduleFree, AdamW8bit, AdamW
    lr_scheduler_typeCOMBO2 options: cosine, constant
    warmup_ratioFLOAT0.050–0.5—
    shuffle_captionBOOLEANtrue—
    keep_tokensINT10–16—
    gradient_checkpointingBOOLEANfalse—
    gradient_accumulation_stepsINT11–64—
    network_dropoutFLOAT0.000–0.5—
    scale_weight_normsFLOAT0.00–10—
    noise_offsetBOOLEANtrue—
    noise_offset_valueFLOAT0.03570–0.2—
    seedINT420–4294967295—
    save_stepsINT2000–100000—
    sample_stepsINT2000–100000—
    logging_stepsINT251–100000—
    sample_promptsSTRING1girl, solo --n worst quality, low quality --w 832 --h 1216 --s 28 --l 5 --d 42—

    Outputs (2)

    NameTypeDescription
    lora_pathSTRING—
    run_dirSTRING—