File size: 8,573 Bytes
b497448 36fde01 7763ce9 b497448 36fde01 7763ce9 36fde01 7763ce9 36fde01 7763ce9 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | ---
license: other
base_model: black-forest-labs/FLUX.1-dev
tags: [flux, lora, style, character-design, concept-art, comfyui]
---
# art-lora-flux1-dev
Style LoRA for **FLUX.1-dev**. Trained on 19 curated painterly character-design references.
**Trigger:** `sk3tchref`
Hand-painted character concept art β broad flat brush shapes, hard-edged colour blocking,
minimal blending, muted olive / charcoal / cream / tan palette, flat off-white background
with a thin shadow smear, stylized elongated proportions.

---
## Repo contents
| Path | What it is |
|---|---|
| `sk3tchref.safetensors` | **Final weights (step 2000) β use this one** |
| `sk3tchref-step000005/1000/1500/2000.safetensors` | Intermediate checkpoints |
| `workflow.json` | ComfyUI workflow β drag onto the canvas |
| `workflow_api.json` | Same graph in API format, for `POST /prompt` |
| `dataset/` | All 19 training images **and** their caption files |
| `samples/` | Outputs per checkpoint + comparison grids |
Style LoRAs overfit, so the best checkpoint is not always the last. All of them are here
so you can compare β see `samples/_grids/`.
---
## 1. Download the models
Everything below goes into your ComfyUI `models/` tree. Total ~34 GB.
```bash
cd /workspace/ComfyUI # adjust to your ComfyUI root
mkdir -p models/diffusion_models models/text_encoders models/vae models/loras
```
### Transformer β FLUX.1-dev, 23.8 GB
The official repo **`black-forest-labs/FLUX.1-dev` is gated**: you must accept the licence
on the model page and use a read token. Same for `FLUX.1-schnell`.
```bash
# Option A β official, gated. Accept the licence first at
# https://huggingface.co/black-forest-labs/FLUX.1-dev
# then create a READ token at https://huggingface.co/settings/tokens
export HF_TOKEN=hf_xxxxxxxxxxxxxxxxxxxx
wget --header="Authorization: Bearer $HF_TOKEN" \
-O models/diffusion_models/flux1-dev.safetensors \
"https://huggingface.co/black-forest-labs/FLUX.1-dev/resolve/main/flux1-dev.safetensors"
```
```bash
# Option B β Comfy-Org mirror. Identical weights, no token needed at time of writing.
wget -O models/diffusion_models/flux1-dev.safetensors \
"https://huggingface.co/Comfy-Org/flux1-dev/resolve/main/flux1-dev.safetensors"
```
Option B is what this LoRA was trained against. Mirrors can be gated or removed without
notice β if Option B starts returning `401`, fall back to Option A.
### Text encoders β 10 GB
```bash
wget -O models/text_encoders/t5xxl_fp16.safetensors \
"https://huggingface.co/comfyanonymous/flux_text_encoders/resolve/main/t5xxl_fp16.safetensors"
wget -O models/text_encoders/clip_l.safetensors \
"https://huggingface.co/comfyanonymous/flux_text_encoders/resolve/main/clip_l.safetensors"
```
### VAE β 335 MB
```bash
# ungated mirror (black-forest-labs/FLUX.1-schnell is gated and returns 401)
wget -O models/vae/ae.safetensors \
"https://huggingface.co/ffxvs/vae-flux/resolve/main/ae.safetensors"
```
### This LoRA
```bash
wget -O models/loras/sk3tchref.safetensors \
"https://huggingface.co/kirusanth08/art-lora-flux1-dev/resolve/main/sk3tchref.safetensors"
# intermediate checkpoints, if you want to compare
for S in 00000500 00001000 00001500 00002000; do
wget -O "models/loras/sk3tchref-step$S.safetensors" \
"https://huggingface.co/kirusanth08/art-lora-flux1-dev/resolve/main/sk3tchref-step$S.safetensors"
done
```
If the repo is private, add `--header="Authorization: Bearer $HF_TOKEN"` to those too.
### Verify
A truncated download does not error β it fails later at load time with
`'NoneType' object has no attribute 'Params'`. Check the sizes:
```bash
ls -l models/diffusion_models/flux1-dev.safetensors # 23802932552
ls -l models/text_encoders/t5xxl_fp16.safetensors # 9787841024
ls -l models/text_encoders/clip_l.safetensors # 246144152
ls -l models/vae/ae.safetensors # 335304388
```
---
## 2. Run it
```bash
wget -O workflow.json \
"https://huggingface.co/kirusanth08/art-lora-flux1-dev/resolve/main/workflow.json"
```
Drag `workflow.json` onto the ComfyUI canvas. It wires up:
```
UNETLoader (flux1-dev, fp8_e4m3fn)
ββ LoraLoaderModelOnly (sk3tchref.safetensors, strength 1.0)
ββ KSampler ββ VAEDecode ββ SaveImage
DualCLIPLoader (clip_l + t5xxl_fp16, type "flux")
ββ CLIPTextEncode ββ¬β FluxGuidance 3.0 βββ positive
ββ ConditioningZeroOut ββ negative
```
`workflow_api.json` is the same graph for `POST /prompt`.
### Settings that matter
**`cfg` must stay at `1.0`.** Flux dev is CFG-distilled β raising it destroys the image,
and negative prompts do nothing, which is why the negative branch is just a zeroed-out
copy of the positive. `FluxGuidance` (~3.0) is the real prompt-adherence knob.
Sampler `euler`, scheduler `beta`, 28 steps, 832Γ1216.
### Prompt template
```
sk3tchref, a full body character illustration of <SUBJECT>, hand-painted character
concept art, broad flat brush shapes, hard-edged colour blocking, muted desaturated
palette, flat off-white background, thin grey shadow smear under the feet
```
The trigger must come first.
### Strength guide
| Strength | Result |
|---|---|
| 0.6 | Too weak β the base model's smooth prior shows through |
| 0.8 | Works |
| **1.0** | **Recommended β strongest read, no subject bleed** |
| 1.1+ | Training subjects and poses start reappearing |
See `samples/final/sweep.jpg`.
---
## 3. How it was trained
kohya `sd-scripts` (`sd3` branch), `flux_train_network.py`, on an RTX 5090 32 GB.
~1.75 s/it, ~1 hour for 2000 steps.
```bash
accelerate launch --num_processes 1 --mixed_precision bf16 \
--num_cpu_threads_per_process 8 flux_train_network.py \
--pretrained_model_name_or_path $M/diffusion_models/flux1-dev.safetensors \
--clip_l $M/text_encoders/clip_l.safetensors \
--t5xxl $M/text_encoders/t5xxl_fp16.safetensors \
--ae $M/vae/ae.safetensors \
--dataset_config dataset.toml \
--output_dir ./out --output_name sk3tchref \
--save_model_as safetensors --save_precision bf16 \
--network_module networks.lora_flux --network_dim 24 --network_alpha 24 \
--network_train_unet_only \
--optimizer_type adamw8bit --learning_rate 1e-4 \
--lr_scheduler constant_with_warmup --lr_warmup_steps 40 \
--max_train_steps 2000 --save_every_n_steps 500 \
--gradient_checkpointing --mixed_precision bf16 --fp8_base --sdpa --highvram \
--cache_latents_to_disk --cache_text_encoder_outputs --cache_text_encoder_outputs_to_disk \
--max_data_loader_n_workers 2 --persistent_data_loader_workers --seed 42 \
--timestep_sampling shift --discrete_flow_shift 3.1582 \
--model_prediction_type raw --guidance_scale 1.0 --loss_type l2
```
Dataset config: aspect-ratio bucketing at 1024 base, `min_bucket_reso 512`,
`max_bucket_reso 1536`, `keep_tokens = 1`, `shuffle_caption = false`.
---
## 4. The captioning method
This is the part that decides whether a style LoRA works.
Captions describe **content only** β who the character is, what they wear, what they do:
```
sk3tchref, two views, front and back, of a heavy-set older man with a grey beard in an
olive green jacket, cream shirt and dark green trousers, holding a bottle
```
Note what is *absent*: no "painterly", no "flat colour blocking", no "muted palette", no
"white background". Everything constant across the set and missing from the captions
collapses onto the single token they all share β `sk3tchref`.
Write style words into the captions and the style scatters across those common words
instead, producing a LoRA that is weak, hard to trigger, and unresponsive to strength.
`keep_tokens = 1` pins the trigger at the front so shuffling never displaces it.
Every caption in `dataset/` was written by looking at the image.
---
## Why a LoRA and not `--sref`
Reference-image conditioning was tested first and does not work for style transfer:
| Approach | Result |
|---|---|
| Redux / IPAdapter | Encodes the reference into **content** tokens. Below ~0.2 strength nothing transfers; above it the reference's *subject* appears β its hat, its props, its character. No setting yields brushwork without subject bleed. |
| Flux.2 Klein / Kontext edit-refs | Trained to **preserve** reference content; "style only" fights the objective. |
| Prompt engineering alone | Yields Flux's own house style. Sweeping guidance moves composition, not paint. |
Conditioning transfers content. Prompting transfers the base model's prior. Only weight
updates transfer style.
|