Nodes/Nova Audio Player/Nova ACE LoRA Trainer ๐ŸŽ“
ComfyUI Node

Nova ACE LoRA Trainer ๐ŸŽ“

Train a music LoRA without parking your ComfyUI for three hours

By NovaFemmeยทCreated 20 days agoยทUpdated 2 days agoยท 0
Nova ACE LoRA Trainer ๐ŸŽ“
    • lora_dir
    • output_dir
    • exit_code
    • console
    โ—„tensor_dirโ–บ
    โ—„output_dirโ–บ
    โ—„checkpoint_dirโ–บ
    โ—„variantxl_sftโ–บ
    โ—„presetrecommendedโ–บ
    โ—„rank0โ–บ
    โ—„alpha0โ–บ
    โ—„learning_rate0.0000โ–บ
    โ—„epochs0โ–บ
    โ—„batch_size0โ–บ
    โ—„gradient_accumulation0โ–บ
    โ—„save_every0โ–บ
    โ—„optimizerfrom presetโ–บ
    โ—„gradient_checkpointingfrom presetโ–บ
    โ—„deviceautoโ–บ
    โ—„precisionbf16โ–บ
    โ—„dry_runfalseโ–บ
    โ—„warmup_steps0โ–บ
    โ—„acestep_repo_pathโ–บ
    โ—„resume_fromโ–บ

    Training anything takes hours, and the usual local-audio route is ACE-Step's own Gradio app in a second terminal - which works, and which the community's own thread on it describes as "you can create a LoRA for now only with their gradio app." Fine until you want it in the same workflow as everything else.

    Nova ACE LoRA Trainer ๐ŸŽ“ runs ACE-Step's training loop over the tensors Preprocess produced, as a separate process. That's the design decision worth caring about: cancel it from the ComfyUI UI, and it can't take the server down with it. All VRAM comes back when it exits. Per-epoch progress goes to the terminal, not the node.

    The inputs that matter

    Twenty-odd widgets, but the ones that decide your afternoon:

    • tensor_dir - wired from Preprocess.
    • output_dir - where the adapter goes. final/ is the finished LoRA; checkpoints/ holds per-epoch saves. Must not be the tensor folder.
    • checkpoint_dir and variant - must be the same tree the tensors were encoded against. See the trap below.
    • preset - recommended is the sane default; quick_test, high_quality and four vram_* tiers are the others. Loaded from upstream's training_v2/presets/.
    • rank / alpha - 32/64 is a good default under ten tracks. Rank is capacity, VRAM and file size, not minutes; step time is set by the base model.
    • epochs, gradient_accumulation, warmup_steps - the trio people get wrong. More below.
    • optimizer - adamw8bit needs bitsandbytes, prodigy needs prodigyopt. Both are checked before the run starts.
    • dry_run - run once with this on. It performs every pre-flight check and prints the exact command without launching anything. Cheap insurance.
    • resume_from - a checkpoint folder, to continue a run.
    • acestep_repo_path - the ACE-Step clone, passed to the child process through PYTHONPATH.

    Outputs: lora_dir (the finished adapter - empty if the run didn't finish), output_dir, exit_code (0 is success, 130 means you cancelled), and console.

    0 does not mean zero

    On rank, alpha, learning rate, epochs, batch size, gradient accumulation, save_every and warmup, 0 means "take it from the preset." It is not a literal zero. The run banner prints an Overrides line naming everything you actually changed, which is how you find out you set something you didn't mean to.

    Epochs are not steps

    batches per epoch = tracks รท batch_size
    steps per epoch   = batches per epoch รท gradient_accumulation
    total steps       = steps per epoch ร— epochs
    

    With 6 tracks, batch size 1 and gradient accumulation 2, that's 3 optimizer steps per epoch - so 200 epochs is 600 steps, not 200. This matters because warmup_steps counts optimizer steps, and every shipped preset sets it to 100. On a small dataset that's longer than the entire run: the learning rate ramps from zero the whole way and never decays, and you've trained inside your own warmup.

    The node computes the schedule and prints it:

    Steps      : 3/epoch x 200 epochs = 600 optimizer steps, warmup 60
    

    Rule of thumb: warmup โ‰ˆ 10% of total steps. No Note: lines under that banner means the schedule is sane. The measured reference run - 6 FLAC masters, 22.7 minutes of audio, xl_sft, bf16, gradient checkpointing on, AMD RX 9070 XT - came in at 53 minutes, peak 11.3 GiB, 80.1 MiB adapter. Budget roughly 12GB of VRAM and take the vram_* presets as starting points, not answers; they all still ship epochs: 100 and warmup_steps: 100, so override both.

    The trap

    The .pt tensors describe one specific set of weights. Point the trainer at a different variant or checkpoint and nothing errors: the run completes, the loss falls, the adapter is quietly worthless. Keep variant identical across Setup Check, Preprocess and Trainer, and delete the tensor folder if you change your mind.

    Install

    ComfyUI Manager โ†’ Nova Audio Player. Or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/NovaFemme/ComfyUI-NovaAudioPlayer.git
    

    Then, for this node only, the training dependencies - vector_quantize_pytorch, einx, frozendict, torch-einops-utils, and optionally tensorboard. Manager's install path runs the pack's install.py, which does that for you against your existing torch. Clone-by-hand users run training/nova_ace_setup.py, or install by hand with --no-deps. And clone ACE-Step 1.5 separately - this pack installs and downloads nothing at runtime.

    Finally: don't judge the result from the loss. Run tier 3, listen to the output, and put the epoch numbers in the folder names down as what they are - single noisy averages, not a ranking.

    Categoryโ–ถ๏ธ Nova Audio/๐ŸŽ“ LoRA Training

    Inputs (20)

    NameTypeDefaultDescription
    tensor_dirSTRINGDirectory of .pt tensors to train on.
    output_dirSTRINGWhere the adapter goes. final/ is the finished LoRA; checkpoints/ holds the per-epoch saves.
    checkpoint_dirSTRINGMust be the SAME checkpoint the tensors were encoded against. Different weights means the tensors describe a model you are not training.
    variantCOMBOxl_sftMatch the variant used for preprocessing.
    presetCOMBOrecommendedUpstream's preset, loaded from training_v2/presets/. Everything below set to 'from preset' or 0 comes from here.
    rankINT00โ€“512LoRA rank. 0 = take it from the preset. Higher means more capacity and more VRAM.
    alphaINT00โ€“1024LoRA alpha. 0 = from the preset. Convention is 2x rank.
    learning_rateFLOAT0.00000โ€“0.010 = from the preset (1e-4).
    epochsINT00โ€“1000000 = from the preset. quick_test is 10, recommended 100, high_quality 1000.
    batch_sizeINT00โ€“640 = from the preset.
    gradient_accumulationINT00โ€“2560 = from the preset. Effective batch is batch_size x this.
    save_everyINT00โ€“10000Checkpoint every N epochs. 0 = from the preset.
    optimizerCOMBOfrom presetadamw8bit needs bitsandbytes, prodigy needs prodigyopt. Both are checked before the run starts.
    gradient_checkpointingCOMBOfrom presetRecomputes activations: 40-60% less VRAM, 10-30% slower.
    deviceCOMBOautoOn ROCm, cuda is correct โ€” that is what torch calls it.
    precisionCOMBObf16bf16 matches the bf16 checkpoints.
    dry_runBOOLEANfalseRun every pre-flight check and print the exact command, without starting it.
    warmup_stepsINT00โ€“100000LR warmup, counted in OPTIMIZER STEPS, not epochs. 0 = from the preset (100), which on a small dataset is longer than the entire run. The banner reports the real step count before anything launches.
    acestep_repo_pathoptSTRINGPath to an ACE-Step clone. Passed to the child through PYTHONPATH.
    resume_fromoptSTRINGResume from a saved checkpoint directory.

    Outputs (4)

    NameTypeDescription
    lora_dirSTRINGThe finished adapter โ€” output_dir/final. Empty if the run did not finish.
    output_dirSTRINGThe run's output directory, holding final/, checkpoints/ and runs/.
    exit_codeINTThe trainer's exit code. 0 is success, 130 means cancelled.
    consoleSTRINGRun log โ€” wire into Nova Console.