Train Anima Slider LoRA (QPOLA)
Train an Anima slider LoRA from nothing but prompts — and swap in the QPOLA optimizer
- model
- clip
- vae
- lora
- report_json
- lora_path
- report_path
Normally, training a LoRA means collecting images, captioning them, and fighting a dataset loader. This node does none of that. It trains an Anima "slider" LoRA - a direction LoRA that pushes one attribute up or down - from nothing but a YAML file full of prompts, and this particular variant does it with QPOLA, a moment-free CUDA optimizer most people have never heard of. If that sounds like a science experiment, you've got the right read: it's marked experimental by the author on purpose.
This is the Train Anima Slider LoRA (QPOLA) node from Shiba-2-shiba's comfyui-anima-slider-node pack, sitting alongside its plain AdamW sibling. Anima has no ControlNet, so sliders are one of the few levers you get for steering attributes - breast size, skirt length, emotion intensity, chibi style - and the pack ships around forty bundled prompt YAMLs covering exactly those. The author ported the anima-slider-experiment flow-slider trainer into ComfyUI so you can train one without leaving the app.
Why there are two nodes
The QPOLA node exists so you can A/B it against the AdamW one. Same prompts, same teacher signal, same MSE loss, same LoRA targets - the only thing that changes is the optimizer. QPOLA is a "moment-free, spatially-cooperative" update rule, vendored at v1.0.4 with its CUDA kernel and PTX shipped inside the pack (Apache-2.0, attribution in third_party/qpola). It replaces loss.backward() + AdamW with a custom per-step update that runs as a CUDA kernel.
The author is refreshingly blunt about scope: QPOLA needs NVIDIA CUDA, needs the LoRA weights in fp32, needs a driver that can load the bundled PTX, and there is no fallback. If the loader, preflight, or kernel launch fails, the node errors out rather than silently training with AdamW. The report JSON and the safetensors metadata record which optimizer ran and what version. No pretending.
How it works
Under the hood it's the same flow as the base node:
- Load a prompt YAML - a list of entries with
target,positive,unconditional,neutral,guidance_scale, andaction(enhance or erase). - Encode those prompts once with your loaded
CLIP(the Qwen3 encoder Anima uses) - no text-encoder training, and the embeddings are cached up front, which is the big speed lever in modern LoRA training. - Build the teacher as
target ± eta × (positive − unconditional), optionally norm-matched to the neutral reference. - Take MSE between that teacher and the model's output with the LoRA injected, backprop, and let QPOLA (or AdamW on the sibling node) step.
The VAE input is there for workflow parity with Anima pipelines - the current text-only trainer doesn't encode any images, so you can feed it but it's ignored.
The inputs that actually matter
Most of the schema is AdamW-node plumbing you won't touch. Set these:
model,clip- the Anima model and its text encoder, loaded as usual.vaeis ignored.prompt_yaml- pick a bundled YAML (defaultprompts-anima-breast_size_slider.yaml), or pointcustom_prompt_yaml_pathat your own file.prompt_indices/eval_prompt_indices- bundled prompts are ordered 0–5 train, 6–7 eval. Keep that default.steps(600) andlr- QPOLA's default is1e-4; the README's first comparison ladder is3e-5,1e-4,3e-4.rank/alpha- 16/16, the sensible modern default for a DiT.network_preset(attn_mlp),model_residency(prefer_cuda),gradient_checkpointing(on) - the README's 16GB VRAM recipe for 1024×1024.qpola_eps(1e-8) andqpola_low_vram(on) - QPOLA-specific. Low-VRAM frees the CUDA allocator cache after every step, which saves cached memory but can slow training; turn it off if it's hurting.width/height-0uses the YAML's resolution. If you copied a workflow that saved512, reset these to0or you'll silently train full-body sliders at 512.
What comes out
Four outputs: lora (a LORA_MODEL you can wire straight into an Apply LoRA), report_json, and the file paths - lora_path and report_path. It saves to ComfyUI's output directory under loras/anima_slider_qpola by default. The report carries the optimizer type, QPOLA version, gradient-checkpointing flag, eval-skip settings, and CUDA memory diagnostics, which is exactly what you want for comparing runs.
Installing it
ComfyUI Manager: search comfyui-anima-slider-node and install. Or the manual route:
cd C:\path\to\ComfyUI\custom_nodes
git clone https://github.com/Shiba-2-shiba/Comfyui-anima-slider-node Comfyui-anima-slider-node
Restart ComfyUI and you'll find it under training/anima slider. There's no requirements.txt - it's a ComfyUI V3 backend node that rides on ComfyUI's own torch, so the only real dependency is the NVIDIA CUDA driver. And note the pack's third-party notice: QPOLA's CUDA source and PTX are bundled, so nothing to download, but it's another reason this one is NVIDIA-only.
Where people get burned
- No CUDA, or a stale driver → hard error from the preflight, and
lora_weight_dtypeis locked tofp32here. On a CPU-only box the README points you at the AdamW node instead. - OOM at 1024² on 16GB → work the README's ladder: 512 first, then 768, then 1024 with
skip_initial_eval/skip_final_evalon to isolate the OOM phase, then turn evals back on. Those toggles are diagnostics, not quality switches - don't ship a run with them off. - Full-body sliders looking wrong → resolution trap. Chibi/skirt sliders want 896×1152 or
width=0/height=0, not 512. - Age-slider YAMLs erroring → some bundled age prompts need
allow_unsafe_age_terms=True.
It's an experiment, and the honest expectation is a weekend of fiddling rather than a turnkey result. But for "how do I make this one attribute stronger without a dataset," it's the only tool doing it inside ComfyUI - and if QPOLA ever does beat AdamW for you, the metadata is right there in the JSON to prove it.
Inputs (40)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | Loaded diffusion model to train against. | |
| clip | CLIP | Loaded text encoder used to encode the prompt YAML. | |
| vae | VAE | Accepted for workflow parity with Anima pipelines; the current text-only trainer does not encode images. | |
| prompt_yaml | COMBO | prompts-anima-breast_size_slider.yaml | Prompt YAML bundled with this custom node. |
| custom_prompt_yaml_path | STRING | Optional absolute or ComfyUI-working-directory-relative YAML path. Overrides prompt_yaml when set. | |
| prompt_indices | STRING | 0,1,2,3,4,5 | Comma-separated prompt indices to cycle during training. |
| eval_prompt_indices | STRING | 6,7 | Comma-separated prompt indices for before/after eval. Empty uses prompt_indices. |
| steps | INT | 6001–100000 | Training optimizer steps. |
| lr | FLOAT | 00–1 | Fallback LoRA learning rate. |
| qpola_eps | FLOAT | 01e-12–0.01 | Epsilon used by QPOLA gradient-scale normalization. |
| qpola_low_vram | BOOLEAN | true | Release the CUDA allocator cache after every QPOLA step. This may reduce cached VRAM but can slow training. |
| rank | INT | 161–256 | Fallback LoRA rank. |
| alpha | FLOAT | 16.00–1024 | LoRA alpha. |
| network_preset | COMBO | attn_mlp | LoRA target preset. |
| network_reg_dims | STRING | Optional YAML mapping of regex fullmatch patterns to LoRA ranks. | |
| network_reg_lrs | STRING | Optional YAML mapping of regex fullmatch patterns to learning rates. | |
| model_residency | COMBO | prefer_cuda | Best-effort base model residency after ComfyUI loading. Falls back to DynamicVRAM behavior if CUDA promotion fails. |
| lora_weight_dtype | COMBO | fp32 | Trainable LoRA weight dtype. QPOLA phase 1 requires fp32. |
| gradient_checkpointing | BOOLEAN | true | Checkpoint trainable diffusion blocks during LoRA training to reduce activation VRAM. |
| skip_initial_eval | BOOLEAN | true | Skip the pre-training eval pass for OOM isolation. Not a quality substitute. |
| skip_final_eval | BOOLEAN | false | Skip the post-training eval pass for OOM isolation. Not a quality substitute. |
| width | INT | 00–4096 | Training latent width in pixels. 0 uses the selected prompt YAML resolution. |
| height | INT | 00–4096 | Training latent height in pixels. 0 uses the selected prompt YAML resolution. |
| num_inference_steps | INT | 203–200 | Number of simple scheduler sigmas. |
| timestep_sampling | COMBO | shift | 6 options: uniform, mid, early_late, sigmoid, shift, flux_shift |
| sigmoid_scale | FLOAT | 1.000.01–20 | — |
| discrete_flow_shift | FLOAT | 3.000.01–20 | — |
| loss_weighting_scheme | COMBO | none | 3 options: none, sigma_sqrt, cosmap |
| direction_loss | COMBO | enhance_only | 2 options: enhance_only, bidirectional |
| teacher_guidance_scale | FLOAT | 1.000–20 | Global multiplier applied after each prompt YAML guidance_scale. |
| teacher_norm_reference | COMBO | positive | Output norm reference for the teacher signal. neutral usually makes stronger sliders less prone to scale blow-up. |
| min_step_index | INT | -1-1–10000 | -1 uses the default lower bound. |
| max_step_index | INT | -1-1–10000 | -1 uses the default upper bound. |
| eval_step_indices | STRING | Comma-separated eval step indices. Empty uses midpoint. | |
| eta | FLOAT | 1.000–20 | — |
| seed | INT | 9612183145239960–18446744073709550000 | — |
| eval_seed | INT | 9612183145239960–18446744073709550000 | — |
| vary_seed | BOOLEAN | true | — |
| allow_unsafe_age_terms | BOOLEAN | false | — |
| output_lora_prefix | STRING | loras/anima_slider_qpola | Output prefix under the ComfyUI output directory. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| lora | LORA_MODEL | — |
| report_json | STRING | — |
| lora_path | STRING | — |
| report_path | STRING | — |