Nodes/ComfyUI-FunPack/FunPack Train LoRA
ComfyUI Node

FunPack Train LoRA

A whole training run hidden in one output node

By digital-garbage·Created about a year ago·Updated 19 days ago· 20
FunPack Train LoRA
  • clip
  • vae
  • model
  • audio_vae
  • lora
◄set_name►
◄namefunpack_lora►
◄usenormal►
◄steps500►
◄learning_rate0►
◄rank16►
◄algorithmLoRA►
◄optimizerAdamW►
◄lossMSE►
◄batch_size1►
◄grad_accumulation1►
◄resolution512►
◄aspect_bucketsfalse►
◄frames33►
◄fps0.0►
◄startstart►
◄trigger►
◄seed0►
◄training_dtypebf16►
◄lora_dtypebf16►
◄gradient_checkpointingtrue►
◄offloadingfalse►
◄bypassfalse►
◄model_name►
◄weight_dtypedefault►
◄compute_dtypedefault►
◄postfix►
◄swap_blocks0►
◄preview_every0►
◄save_every0►
◄resume►

Most LoRA advice ends with "now go install ai-toolkit", and that's still the right answer for Flux or Z-Image. This node is for a different mood: your clips are already in ComfyUI, you don't want a second Python environment, and you want a .safetensors in ComfyUI/models/loras by dinner. FunPack Train LoRA is a training run you queue like any other graph.

Caveats first: one module of a one-person hobby pack, hidden behind a Settings toggle, verified on MiniMax H3 only. Everything else goes through ComfyUI's own trainer and is unproven.

What it actually does

Two code paths. On MiniMax H3 the pack runs its own loop, ported from the musubi-tuner H3 recipe - which layers get a LoRA, block swap, per-block checkpointing, ComfyUI still carrying the batches. That path is where Pause/Resume, mid-run previews and every-N-steps copies live.

On anything else it wraps TrainLoraNode from comfy_extras/nodes_train.py - the trainer that ships inside ComfyUI. FunPack's contribution there is the fiddly part: turning your set into latents and conditioning, then saving the result properly.

Either way the prep is cached: every item encoded to a latent, every caption to conditioning, written to custom_nodes/ComfyUI-FunPack/training/cache/ and keyed on the file's path, mtime and size, the size bucket, frames/fps, and a fingerprint of your VAE and text encoder. Re-run after a crash and the encoding is skipped - a real advantage over copy-pasting a kohya config.

The inputs you'll actually touch

set_name is a string, not a dropdown, and it has to name a set that already exists - those live as JSON under training/sets/, built in the pack's own Training window at /funpack/ (Data, Tags, Train, Results). A typo stops the run with "there is no training set called …".

Wire clip and vae; on H3 you also need audio_vae, because H3 learns picture and sound together and refuses without it. For the model, pick one: wire a MODEL into model, or leave it empty and type the filename into model_name, and the trainer loads that file itself, once, reusing the same object as its "fresh copy". GGUF is refused - use a .safetensors.

use is the interesting one. normal trains on liked results and your own media; avoid trains only on what you disliked, for a LoRA you apply at negative strength; all keeps everything. trigger is prepended to every caption, postfix appended - pick a rare nonsense token and reuse it at inference.

Then steps (default 500), learning_rate (1e-4), rank (16). The defaults are sane-ish, but 500 steps is thin for a character: a 15-25 image set on a modern architecture usually wants 1,500-3,000. Keep save_every above zero - the last epoch is regularly not the best one.

If the card complains, gradient_checkpointing is already on; then offloading; then swap_blocks, which parks N transformer blocks in system RAM. Lower resolution and frames before you touch rank. On H3, batch_size gets forced to 1 with a warning, aspect_buckets is ignored, and the shortest clip in the set caps frames for everyone.

One output: lora, a string with the saved file's name inside your loras folder. The node is an output node, so queueing the prompt is the run. Nothing gets overwritten; a second run with the same name writes name_2.safetensors.

Installing it

Through ComfyUI Manager, search the pack title; or:

cd ComfyUI/custom_nodes
git clone https://github.com/olivv-cs/ComfyUI-FunPack
cd ComfyUI-FunPack && pip install -r requirements.txt

The README still points at digital-garbage/ComfyUI-FunPack - same pack. requirements.txt only pins comfy-kitchen>=0.2.32 and gguf, neither of which training touches. What training needs is the lora_training add-on switched on in Settings > Modules, which installs onnxruntime on the next restart for the automatic tagger; until then the node raises "LoRA training is switched off." You also need a ComfyUI new enough to have comfy_extras/nodes_train.py.

Where people get burned

You installed 4.x. FunPack 5 is a from-scratch rewrite and the Training window is new in it; the old Cutting Room app lives on the v4-classic branch. No FunPack/Training category and no /funpack/ studio means Manager gave you the old one - check Settings > About. The registry copy lags the repo, so cloning is more reliable.

OOM on an H3 run. The likely one. H3's blocks modulate the stream in place, so each checkpointed block keeps its recompute alive through the backward pass, around 4 GiB a block at long sequence lengths. The node logs card usage at each setup stage and after the first backward recomputes, so the OOM tells you which stage filled the card.

resume isn't the LoRA's name. It wants the twelve-hex-character ID of a paused run.

"This model was loaded in a way the trainer cannot copy" means the MODEL you wired didn't come from a plain file loader - use FunPack's Diffusion Model Loader, or skip it and use model_name.

And the honest framing: for a production character LoRA on a current image model, go use ai-toolkit. Reach for this one when the data is your own H3 clips and the results you rated inside FunPack, and you'd rather not leave the graph.

CategoryFunPack/Training

Inputs (35)

NameTypeDefaultDescription
clipCLIPThe text encoder that turns the captions into conditioning.
vaeVAEThe VAE that turns pictures and clips into latents.
set_nameSTRINGThe training set to learn from.
nameSTRINGfunpack_loraFile name of the finished LoRA (no extension). An earlier file is never overwritten.
useCOMBOnormalnormal: liked results and your own media. avoid: only the disliked results, for a LoRA you apply at negative strength. all: everything.
stepsINT5001–100000How many training steps.
learning_rateFLOAT01e-7–1How big each learning step is. Lower is safer and slower.
rankINT161–128How much the LoRA can learn. Higher holds more detail and makes a bigger file.
algorithmCOMBOLoRAThe adapter kind. LoRA is the common one.
optimizerCOMBOAdamWHow the weights are updated.
lossCOMBOMSEHow the error is measured.
batch_sizeINT11–64Samples per step. Models that train one sample at a time (H3) lower it to 1.
grad_accumulationINT11–256Steps added up before the weights change: a bigger batch for less memory.
resolutionINT51264–2048Training size in pixels per side. Each item is fitted to about this area, keeping its shape.
aspect_bucketsBOOLEANfalseKeep each picture's own shape (a few size groups) instead of one shape for all. Not used for H3.
framesINT331–1025Frames taken from each clip, for video models. H3 rounds to its own grid (17 x n + 5).
fpsFLOAT0.00–120Frames per second to read the clips at. 0 uses each clip's own rate (H3: 24).
startCOMBOstartWhere in a clip to take the frames from.
triggerSTRINGThe prefix: text put at the start of every caption, for example a word to call the LoRA up later.
seedINT00–18446744073709550000Seed for the noise and the LoRA's starting weights.
training_dtypeCOMBObf16Precision used while training. bf16 is right for nearly everything.
lora_dtypeCOMBObf16Precision the LoRA is stored in.
gradient_checkpointingBOOLEANtrueTrades speed for a lot less memory.
offloadingBOOLEANfalseKeeps model weights in system memory while training: slower, for cards that cannot hold the model.
bypassBOOLEANfalseApply the LoRA by hooks instead of changing weights. For quantized models.
model_nameSTRINGThe diffusion model file to train on, as the loader lists it. The trainer loads it itself, once, with no loader node in front.
weight_dtypeCOMBOdefaultHow the model file's weights are stored when it is loaded here.
compute_dtypeCOMBOdefaultWhat the maths runs in when the model is loaded here.
postfixSTRINGText put at the end of every caption.
swap_blocksINT00–128How many transformer blocks keep their weights in system memory, fetched one layer at a time: slower, and each one frees about a block's weight on the card. 0 keeps the whole model on the card.
preview_everyINT00–100000Pause every this many steps so the pipeline can make a preview with the LoRA so far. 0 never pauses.
save_everyINT00–100000Save a copy of the LoRA so far to the loras folder every this many steps, named <name>_step<N>. 0 saves only the finished one.
resumeSTRINGThe name of a paused run to carry on. Empty starts a new run.
modeloptMODELA model already loaded to train on. Leave empty and give model_name to have the trainer load the file itself, once.
audio_vaeoptVAEOnly for models that learn sound with the picture (H3): turns the clips' sound into latents.

Outputs (1)

NameTypeDescription
loraSTRING—