Train a Character LoRA (local, Flux.1-dev)

Train a character/identity LoRA locally on FLUX.1-dev via the comfyui-mcp train_* tools (GPU Docker + ostris ai-toolkit).

How to install

How to install

  1. Setup differs for this server — follow the Installation part of the README below.
  2. Claude Code: claude mcp add <name> -- <command>.
  3. Claude Desktop / Cursor: add it under mcpServers in the MCP config file.
Claude Code — installs the whole folder, not just SKILL.md
npx degit artokun/comfyui-mcp/plugin/skills/train-character-lora#main ~/.claude/skills/train-character-lora

For one project only, change the path to .claude/skills/train-character-lora. This skill also uses run.py — copying SKILL.md alone won't be enough. See the folder on GitHub.

This one runs on your machine and can reach your files. Read the README below before you connect it.

Not working?
  • Check which app you pasted it into — the steps above name the right one.
  • Some skills need the paid tier of Claude or ChatGPT.
Step-by-step guide with screenshots · Ask in the forum

Paste into Claude, ChatGPT or Cursor.

Show the full text95 lines
train-character-lora/SKILL.md95 lines5.1 KBpushed 27d agoRawView on GitHub

Train a Character LoRA (local, Flux.1-dev)

Overview

The trainer runs ostris ai-toolkit's run.py inside a headless GPU Docker container, driven through the three train_* MCP tools. You (the LLM) are the UI. Each takes an action: train_prepare_dataset owns the datasets, train_start owns the jobs, and train_doctor owns the trainer itself. You generate the dataset, launch the job, watch progress, and the finished LoRA lands in ComfyUI models/loras/ and the LoRA catalog without further steps.

  • Base model: FLUX.1-dev (the best proven character consistency; needs ~24GB VRAM with quantization, RTX 4090 class).
  • Phase-1 scope: character LoRAs only. Style/slider/edit and other bases come later.

The flow (tool sequence)

  1. train_doctor {action:"doctor"}. Preflight once per session. Checks docker daemon, --gpus all GPU passthrough, trainer image, HF_TOKEN. If image:false, run train_doctor {action:"build_image"} (one-time, several minutes, since it builds CUDA plus torch plus ai-toolkit). If hfTokenSet:false, warn the user: the first run downloads FLUX.1-dev (gated HF repo) and needs HF_TOKEN in the MCP server env.
  2. train_prepare_dataset {action:"prepare"}. Stage the images. See "Dataset" below.
  3. train_start {action:"start"}. Launch. Returns a job id at once; training runs detached.
  4. train_start {action:"status", id}. Poll progress (progress.step/totalSteps/loss, recent samples, log tail). Poll on a slow cadence (every few minutes). A 2000-step run is roughly an hour on a 4090. Don't block on it.
  5. Done. status:"completed" means the .safetensors was copied to models/loras/<name>.safetensors and upserted into the LoRA catalog (result has the paths and catalog id). Verify by loading it in a Flux workflow (LoraLoaderModelOnly, strength 1.0) with the trigger word in the prompt.

Dataset guidance

Call train_prepare_dataset {action:"prepare"} with name, items: [{path, caption?}, ...] and a defaultCaption.

  • 10 to 30 varied images of the subject: different angles, expressions, lighting, backgrounds, distances (close-up, half-body, full-body). Variety beats count.
  • Trigger word: pick something rare and stable (e.g. ohwx, zxc_person), NOT a real word. Use it as defaultCaption and pass it as trigger to train_start.
  • Captions: describe what changes between images (pose, setting, clothing, expression); the model learns the constant identity from the images themselves. Start each caption with the trigger word, e.g. ohwx person sitting in a cafe, laughing, natural light. Keep them short and factual. When in doubt, the trigger word alone (defaultCaption) is a workable baseline.
  • Images are copied and renamed img_00001.<ext> etc. Source files are never modified.

Params (sane defaults — override sparingly)

Param Default When to change
steps 2000 200 for a smoke test; 1500–3000 real runs. More ≠ better (overbake = plasticky).
lr 1e-4 5e-5 for a tighter/subtler identity.
rank 16 32 for very detailed characters.
resolution [512,768,1024] [512] if VRAM-constrained.
quantize true Keep true on 24GB.
saveEvery / sampleEvery 250 Lower (100) to watch early progress.

Monitoring & judgement

  • train_start {action:"status"}'s progress.samples are host paths. Look at them. (ai-toolkit prints no saved-sample lines, so they populate at finalize from the output dir; mid-run you can look directly in the job's output/<name>/samples/ folder.) Identity should be recognizable by ~1/3 of the run; if samples stay generic past halfway, the run will likely underfit. Cancel (train_start {action:"cancel", id}) and check captions and trigger.
  • Loss should trend down and stabilize (~0.1 to 0.3); wild spikes usually mean lr too high.
  • Checkpoints save every saveEvery steps under the job's output/ dir, so a cancelled run isn't a total loss.

Failure modes

  • no_docker / no_image from train_start {action:"start"}: run train_doctor {action:"doctor"}, follow its hints.
  • OOM / CUDA errors in the log tail: drop resolution to [512], keep quantize:true, batch stays 1.
  • handoff failed in job error: training itself finished; the LoRA is still under the job's output/<name>/ dir. Copy it into models/loras/ manually and upsert the catalog.
  • First run is slow before step 1. FLUX.1-dev download (~24GB) plus latent caching. As long as the log tail moves, it's fine. The HF cache persists across runs.

Sources

  • Official: none found.
  • Empirical: sampler values, wiring, and prompt notes from working graphs in packs/ and observed renders; not a vendor prompting guide.
1---
2name: train-character-lora
3description: Train a character/identity LoRA locally on FLUX.1-dev via the comfyui-mcp train_* tools (GPU Docker + ostris ai-toolkit). Use when the user wants to train a LoRA of a person/character from their photos on the local GPU. Covers dataset prep, launch, monitoring, and using the result in ComfyUI. For WAN/Z-Image training via the ai-toolkit UI see ai-toolkit-trainer.
4globs:
5 - "**/*.json"
6---
7 
8# Train a Character LoRA (local, Flux.1-dev)
9 
10## Overview
11 
12The trainer runs ostris ai-toolkit's `run.py` inside a headless GPU Docker container,
13driven through the three `train_*` MCP tools. You (the LLM) are the UI. Each takes
14an `action`: `train_prepare_dataset` owns the datasets, `train_start` owns the jobs, and
15`train_doctor` owns the trainer itself. You generate the dataset, launch the job, watch
16progress, and the finished LoRA lands in ComfyUI `models/loras/` and the LoRA catalog
17without further steps.
18 
19- Base model: FLUX.1-dev (the best proven character consistency; needs ~24GB VRAM with
20 quantization, RTX 4090 class).
21- Phase-1 scope: character LoRAs only. Style/slider/edit and other bases come later.
22 
23## The flow (tool sequence)
24 
251. `train_doctor {action:"doctor"}`. Preflight once per session. Checks docker daemon,
26 `--gpus all` GPU passthrough, trainer image, HF_TOKEN. If `image:false`, run
27 `train_doctor {action:"build_image"}` (one-time, several minutes, since it builds CUDA
28 plus torch plus ai-toolkit). If `hfTokenSet:false`, warn the user: the first run
29 downloads FLUX.1-dev (gated HF repo) and needs `HF_TOKEN` in the MCP server env.
302. `train_prepare_dataset {action:"prepare"}`. Stage the images. See "Dataset" below.
313. `train_start {action:"start"}`. Launch. Returns a job id at once; training runs
32 detached.
334. `train_start {action:"status", id}`. Poll progress (`progress.step/totalSteps/loss`,
34 recent `samples`, `log` tail). Poll on a slow cadence (every few minutes). A 2000-step
35 run is roughly an hour on a 4090. Don't block on it.
365. Done. `status:"completed"` means the `.safetensors` was copied to
37 `models/loras/<name>.safetensors` and upserted into the LoRA catalog (`result` has the
38 paths and catalog id). Verify by loading it in a Flux workflow (`LoraLoaderModelOnly`,
39 strength 1.0) with the trigger word in the prompt.
40 
41## Dataset guidance
42 
43Call `train_prepare_dataset {action:"prepare"}` with `name`, `items: [{path, caption?}, ...]`
44and a `defaultCaption`.
45 
46- 10 to 30 varied images of the subject: different angles, expressions, lighting,
47 backgrounds, distances (close-up, half-body, full-body). Variety beats count.
48- Trigger word: pick something rare and stable (e.g. `ohwx`, `zxc_person`), NOT a
49 real word. Use it as `defaultCaption` and pass it as `trigger` to `train_start`.
50- Captions: describe what changes between images (pose, setting, clothing,
51 expression); the model learns the constant identity from the images themselves. Start
52 each caption with the trigger word, e.g. `ohwx person sitting in a cafe, laughing, natural
53 light`. Keep them short and factual. When in doubt, the trigger word alone
54 (`defaultCaption`) is a workable baseline.
55- Images are copied and renamed `img_00001.<ext>` etc. Source files are never modified.
56 
57## Params (sane defaults — override sparingly)
58 
59| Param | Default | When to change |
60|-------|---------|----------------|
61| steps | 2000 | 200 for a smoke test; 1500–3000 real runs. More ≠ better (overbake = plasticky). |
62| lr | 1e-4 | 5e-5 for a tighter/subtler identity. |
63| rank | 16 | 32 for very detailed characters. |
64| resolution | [512,768,1024] | [512] if VRAM-constrained. |
65| quantize | true | Keep true on 24GB. |
66| saveEvery / sampleEvery | 250 | Lower (100) to watch early progress. |
67 
68## Monitoring & judgement
69 
70- `train_start {action:"status"}`'s `progress.samples` are host paths. Look at them.
71 (ai-toolkit prints no saved-sample lines, so they populate at finalize from the output
72 dir; mid-run you can look directly in the job's `output/<name>/samples/` folder.)
73 Identity should be recognizable by ~1/3 of the run; if samples stay generic past
74 halfway, the run will likely underfit. Cancel (`train_start {action:"cancel", id}`) and
75 check captions and trigger.
76- Loss should trend down and stabilize (~0.1 to 0.3); wild spikes usually mean lr too high.
77- Checkpoints save every `saveEvery` steps under the job's `output/` dir, so a cancelled
78 run isn't a total loss.
79 
80## Failure modes
81 
82- `no_docker` / `no_image` from `train_start {action:"start"}`: run
83 `train_doctor {action:"doctor"}`, follow its hints.
84- OOM / CUDA errors in the log tail: drop `resolution` to `[512]`, keep `quantize:true`,
85 batch stays 1.
86- `handoff failed` in job error: training itself finished; the LoRA is still under the
87 job's `output/<name>/` dir. Copy it into `models/loras/` manually and upsert the catalog.
88- First run is slow before step 1. FLUX.1-dev download (~24GB) plus latent caching. As
89 long as the log tail moves, it's fine. The HF cache persists across runs.
90 
91## Sources
92 
93- **Official:** none found.
94- **Empirical:** sampler values, wiring, and prompt notes from working graphs in `packs/` and observed renders; not a vendor prompting guide.
95 

Discussion

Alternatives

Also in Illustration & art