Home › Guides › How I train character LoRAs for Krea 2
How I train character LoRAs for Krea 2
Every setting, every measurement, and the reasoning behind both. This is the exact pipeline behind the characters in the shop — no settings withheld.
Most LoRA guides give you a config and a shrug. This one gives you the config and the alternative it was measured against, because almost every number below started as a different number that changed after timing it or looking at the output side by side.
Every figure here is measured on one machine. Training speeds come
out of a real train.log. Image generation times come
from the file timestamps of actual batches. Nothing is a
manufacturer claim.
The hardware
GPU NVIDIA GeForce RTX 5090 - 32,607 MiB VRAM, driver 591.86
CPU Intel Core i9-14900KF
OS Windows 11, training inside WSL2 (Ubuntu 24.04.4 LTS)
RAM WSL capped at 24 GB in .wslconfig
Stack PyTorch 2.11.0+cu128, CUDA 12.8
Trainer ai-toolkit
Previews ComfyUI, on the Windows side
Everything runs on one card. There is no second GPU to offload previews onto. Training, captioning and image generation all queue for the same 32 GB, and that constraint shaped more decisions than any quality consideration did.
Train on Raw, generate on Turbo
Krea 2 ships in more than one variant, and picking the wrong one costs you either quality or the ability to train at all. Krea 2 Raw (26 GB) is the variant intended for fine-tuning, so that is what trains. krea2_turbo_mxfp8 renders the previews at roughly half the VRAM of bf16.
LoRAs trained on Raw transfer to Turbo. That is the whole trick, and it is what allows training against the full model while rendering previews at 8 steps.
- Turbo needs cfg 1. Its workflow feeds the sampler
a
ConditioningZeroOutof the positive prompt as its negative. Fine at cfg 1, where the negative is never evaluated. Push the same workflow to cfg 3.5 and you get strong artefacts. - You cannot make a Turbo version of a merged checkpoint. Turbo is distilled from Raw, not quantised from it. Merge a LoRA into Raw for a standalone checkpoint and that checkpoint will always need ~30 steps.
The dataset
Across every character dataset on disk: median 48 images, mean 49, range 8–101.
40–80 images is the working range. Below forty, the model starts binding incidental details to the character — a background, a jacket, a particular crop. Past a hundred, the extra images mostly repeat what the earlier ones already said.
Around 200 candidates are generated per character, and the dataset is selected from them — for variety of pose, distance, angle, expression, lighting and setting, not for which images look best.
A dataset that is uniformly beautiful in one lighting setup teaches the model that this person arrives with that lighting.
That generalises: anything constant across the dataset and absent from the captions is what the trigger word ends up meaning. If every image is lit the same way and no caption mentions lighting, the trigger learns the lighting.
Captions
Captioning runs on Qwen3-VL-8B-Instruct locally, in batches of 4, falling back to one-at-a-time if a batch fails. Three rules shape every caption.
Trigger first, always
Captions are written trigger, description. Writing
description, trigger does not fire the LoRA reliably.
Position genuinely matters.
The traits phrase goes in every caption, in full
Every caption for a character carries the same anatomical description. That is what holds the physique together — reference conditioning is heavily face-biased in every model tested here, so the face transfers on its own while the body drifts back to the base model's prior unless the text insists otherwise.
No magnitude words
"Extremely muscular", "very large", and category nouns produced a
physique noticeably bigger than the reference. Describe anatomy
precisely instead: well-developed deltoids works,
huge shoulders overshoots.
Describe what should vary; stay silent about what should be learned.
For a character LoRA, describe the person precisely and let the environment vary. For a style LoRA it is the exact inverse: describe the content thoroughly and say nothing about the look, because the look is what is being trained.
The ai-toolkit config, in full
A real generated config, copied verbatim:
job: extension
config:
name: <character>
process:
- type: sd_trainer
device: cuda:0
trigger_word: <character>
network:
type: lora
linear: 32
linear_alpha: 32
save:
dtype: float16
save_every: 250
max_step_saves_to_keep: 6
datasets:
- folder_path: <dataset>
caption_ext: txt
caption_dropout_rate: 0.05
shuffle_tokens: false
cache_latents_to_disk: true
resolution:
- 512
- 1024
train:
batch_size: 1
steps: 2000
gradient_accumulation_steps: 1
train_unet: true
train_text_encoder: false
content_or_style: content
gradient_checkpointing: true
noise_scheduler: flowmatch
optimizer: adamw8bit
lr: 0.0002
dtype: bf16
ema_config:
use_ema: true
ema_decay: 0.99
model:
name_or_path: <krea2-raw>
arch: krea2
quantize: true
qtype: qfloat8
sample:
sampler: flowmatch
sample_every: 2001
width: 1024
height: 1024
prompts: []
guidance_scale: 3.5
sample_steps: 30
Why each setting is what it is
resolution: [512, 1024] — and specifically not 768
Krea 2 was pretrained at 256, 512 and 1024. Never at 768.
The [512, 768, 1024] in ai-toolkit's example configs is
inherited from Flex configurations. It is copied boilerplate, not a
Krea 2 recommendation. Training at a resolution the base model never
saw spends your step budget on a bucket it has no prior for.
linear: 32, linear_alpha: 32
Rank 16 at 1000 steps gave a likeness worth calling "a good 60%". Rank 32 at 1500 steps was noticeably better on the same dataset and seed. For a photographic character, 32 is where it stops improving enough to justify the cost. Alpha equals rank; no scaling games.
steps: 2000
The same two characters were trained at 2000 and at 2500 steps and compared across five framings with identical seeds. The identity was already resolved at 2000. The extra 500 steps bought nothing, and cost about 24 minutes each.
quantize: true, qtype: qfloat8
This is what makes Krea 2 fit. Blackwell has native
FP8 tensor cores, so quantising to qfloat8 costs very
little and brings a 26 GB model comfortably inside 32 GB with room
for the optimizer, the gradients and the cached latents.
train_text_encoder: false
UNet only. Training the text encoder on a 40–80 image dataset overfits the trigger word to the dataset's phrasing rather than to the person.
shuffle_tokens: false
Deliberate. The captions are ordered — trigger first, then the traits phrase, then the variable content. Shuffling tokens would destroy the position rule above.
sample_every: 2001 — previews disabled during training
The step count is 2000, so an interval of 2001 means the sampler
never fires, and the prompt list is empty too. This is worth
30–40 minutes on every run: four preview images at
sample_steps: 30 cost about five minutes on a 5090, and
sampling at every checkpoint means paying that eight times. Previews
are rendered afterwards in ComfyUI at 8 steps instead.
Training times, measured
A real run, caught in progress:
1,948 steps in 1 hour 24 minutes. From the checkpoint timestamps of that same run, 250 steps apart:
| Step | Written at | Elapsed |
|---|---|---|
| 500 | 07:05 | — |
| 750 | 07:17 | 12 min |
| 1000 | 07:27 | 10 min |
| 1250 | 07:36 | 9 min |
| 1500 | 07:47 | 11 min |
| 1750 | 07:59 | 12 min |
1,250 steps in 54 minutes, or 2.59 s/step. The long-run average across many characters is 2.45 s/step, about 82 minutes for a full 2000-step character LoRA. The run above is slightly slower because the machine was in use.
Measured and rejected
This is the section worth reading twice.
Training at 0.25 MP
43 minutes instead of 82 — almost exactly half. Rejected: the likeness degrades visibly. Half the time for a worse product is not a trade worth taking when the product is the likeness.
Fizgig, a Krea 2 specific trainer
A trainer built specifically for Krea 2, advertising dramatically
faster training. It would not start under WSL2 at all —
CUDA driver error: unknown error down four different
install routes, with CUDA working fine in isolated tests. On native
Windows it does run, and gives 2.97 s/step at 1024,
which is slower than ai-toolkit's 2.45. Its advertised "20
minutes" came from training at 0.25 MP, and its standard Krea 2
preset is rank 32/32 — the same as here.
The lesson generalises to every speed claim you will ever read: check what resolution the number was measured at. A trainer that is "3x faster" at 0.25 MP against your 1 MP is not faster. It is smaller.
Generating images in ComfyUI
Model krea2_turbo_mxfp8.safetensors
Sampler euler
Scheduler simple
Steps 8
CFG 1.0
Size 2 MP (9:16 for characters)
LoRA character LoRA at weight 1.0
Measured throughput, from the file timestamps of two real batches: 11.7 s median over 120 images, and 13.2 s over 70. That is end-to-end per image, including saving; the sampling itself is about 8 seconds.
Startup costs 21 seconds to launch plus 8 to load the models, which is why ComfyUI stays open during a batch. The flip side: closing it frees 18 GB of VRAM — measured, from 11.2 GB free to 29.5. On a single-GPU machine that is the difference between being able to start a training run and not.
Things that cost me time
A LoRA that needs weight 1.5 to apply is a symptom, not a setting. Something upstream is wrong — usually the trigger word, the caption position, or an undertrained rank.
Copy-of-a-copy degrades. Bootstrap a character from a small LoRA, generate a synthetic dataset from it, and the bootstrap's likeness becomes the synthetic set's likeness, which becomes V1's. Make the bootstrap better than it needs to be.
Training on a model's own output cannot expand its priors. Synthetic generation works for characters, because the bootstrap supplies an identity the base model does not have. It does not work for shifting a distribution.
Style LoRAs are limited by subject variety, not image count. A style trained on 49 frames that were all night-time urban scenes failed on cars, animals, landscapes and daytime exteriors. Rank 32 and 86 frames changed nothing.
Checking a filename is not checking identity. A copy step here once compared file size to decide whether to reinstall a LoRA, so a retrained LoRA at the same rank was never copied and every test ran against the old weights. Compare hashes.
Where these characters live
This is the pipeline behind the original synthetic character LoRAs for Krea 2 — each one a specific person: the same face, the same build, the same presence, in any scene you can describe.
Also here: the AI reels bundle, 900+ vertical clips with no voiceover and no watermarks. And custom LoRA commissions — you bring the source material and pick the base model: Krea 2, Flux, SDXL, Illustrious, Pony, Qwen-Image or WAN.