FLUX.2 klein 的微调是两件事:训练跑在你自己显卡上,对着开放权重的 Base 检查点;调用发生在 api.bfl.ai,端点在请求体里多加两个字段。两边参数名不同,混着用就是最常见的翻车方式。
微调到底改了哪一部分
训练目标是 Base 变体,不是那个快的。总览页把 Base 称为保留完整训练信号的未蒸馏基础模型,训练页补上关键一句:这种架构正是 LoRA 需要的,而且训出来的适配器之后仍能加载到蒸馏版上。许可证决定你能发布哪个尺寸:4B Base 是 Apache 2.0,9B Base 挂在 FLUX Non-Commercial 下,训练页推荐多数人用 4B,因为硬件门槛更低。适配器通常 10–200MB,在消费级显卡上跑一到三小时;全量微调则是大文件、数天到数周。两个尺寸都不在公共 API 上提供,所以回路从你自己的机器开始。
数据集规则与最低硬件
训练页对图片质量说得很细,对张数一个字没提:1024px 起、质量一致、没有伪影。另外两个官方页面给出的数字互相矛盾——分步示例说 20–40 张最优,Hugging Face 上的教程说 15–40 张。以你实际读到的那页为准。
caption 的规则和直觉相反:描述内容,不要描述你想教给模型的风格,每条都以同一个触发词开头,训练页把它记作 [trigger]。分辨率是两段式:迭代用 512px,最终训练用 1024px 或更高。
官方公布的最低配置
| 变体 | 最低显卡 | 内存 | 许可证 |
|---|---|---|---|
| FLUX.2 klein 4B Base | NVIDIA,12GB 显存 | 32GB | Apache 2.0 |
| FLUX.2 klein 9B Base | NVIDIA,22GB 显存 | 64GB | FLUX Non-Commercial |
厂商教程说 4B 的 LoRA 训练占用不到 24GB 显存,RTX 4090 上约一小时。官方没有描述 AMD 或 Apple Silicon 的路径;点名的两个训练器是 AI-Toolkit 和 Diffusers。
微调回路:一步步走一遍

把这个回路读成四个阶段,因为每个阶段的用词都不一样:装着图片和同名 caption 的文件夹;由 trigger_word、train.lr 这类键驱动的训练运行;训练留下的 .safetensors 适配器,在 Customization → Finetunes 上传;以及最后那个端点——finetune_id 和 finetune_strength 在这里出现,训练器的键全部消失。
最后这个切换点就是多数集成出错的地方:train.lr 属于一个已经跑完的配置文件,finetune_strength 属于一个正在进行的请求,谁都不接受对方的名字。
写训练配置
分步示例公布了一份完整的 AI-Toolkit 作业,真正有用的地方在于每次要改的很少。移动的只有三个键:config.name、trigger_word 和 datasets[0].folder_path,分别指定输出目录、对齐 caption、指向图片位置。network 里的 linear 和 conv 设定适配器的秩,linear_alpha 和 conv_alpha 是缩放系数,默认值是 32/32 配 16/16。
先准备数据,因为 caption 的文件名必须和图片一一对应。
# 一个目录:每张图都要有一个同名 caption 文件。
mkdir -p ~/klein-lora/dataset
cd ~/klein-lora/dataset
for i in 1 2 3; do
cp ~/raw/shirt-$i.png "SHIRT_$i.png"
printf '%s\n' \
"SHIRTTR1GGER. A cream knit sweater on a plain white background, front view." \
> "SHIRT_$i.txt"
done
ls
作业本身就是一个 YAML 文件加一条命令,键名逐字照抄官方文档。
mkdir -p ~/klein-lora/config
cat > ~/klein-lora/config/shirt_lora.yaml <<'YAML'
job: "extension"
config:
name: "shirt_lora_v1"
process:
- type: "diffusion_trainer"
training_folder: "/app/ai-toolkit/output"
device: "cuda"
trigger_word: "SHIRTTR1GGER"
network:
type: "lora"
linear: 32
linear_alpha: 32
conv: 16
conv_alpha: 16
save:
dtype: "bf16"
save_every: 250
datasets:
- folder_path: "/home/you/klein-lora/dataset"
caption_ext: "txt"
resolution:
- 512
- 768
- 1024
train:
batch_size: 1
steps: 3000
lr: 0.0001
optimizer: "adamw8bit"
timestep_type: "weighted"
content_or_style: "balanced"
model:
name_or_path: "black-forest-labs/FLUX.2-klein-base-4B"
quantize: true
meta:
name: "[name]"
version: "1.0"
YAML
cd /app/ai-toolkit && python run.py ~/klein-lora/config
quantize: true 是让 4B 训练塞进 12GB 显卡的那一行,示例把它列在显存优化第一条。文档默认配置指向的其实是 9B 检查点。
跑训练,读结果
学习率这一档的不对称性是官方写明的:训练页给 LoRA 的是 8e-5 到 1e-4,示例补了一条纠偏——loss 降得太慢就提到 2e-4,loss 来回跳就降到 5e-5。
步数在官方页面之间明确打架。训练页说风格 LoRA 用 1500–2500 步、角色 LoRA 用 1500–3000 步;示例按数据集规模缩放,从 800–1200 步到 50 张图的 2000–3000 步,而它自己的配置写 3000 步、save_every: 150,最后又报告 1500 步的 checkpoint 效果最好。所以盯的是 checkpoint 本身:没存下来的点你根本选不了。
要看样本输出,而不是只盯 loss 曲线。训练页把过拟合点名为需要盯防的失败模式:如果每步的样本不管提示词怎么写都长得像你的数据集,那就是信号。
上传适配器并调用微调端点
上传走 Dashboard,不是 API。在 Customization → Finetunes 下,+ Add Finetune 要你填名称、底模、精度、可选的触发短语和 .safetensors 文件。名称会成为你的 finetune_id,底模的选择决定哪个端点能提供它。
官方公布了六个端点。两个 Base 端点 /v1/flux-2-klein-base-4b-finetuned 和 /v1/flux-2-klein-base-9b-finetuned 服务于在 Base 检查点上训练的适配器,四个蒸馏端点同样接受它们。默认精度是 FP8。
提交加轮询的形状和其他所有 FLUX.2 端点一样,新增的只有两个字段。
# 端点必须和你在 Dashboard 里选的底模与精度一致。
MODEL="flux-2-klein-base-4b-finetuned"
RESPONSE=$(curl -s -X POST "https://api.bfl.ai/v1/${MODEL}" \
-H "x-key: ${BFL_API_KEY}" \
-H 'Content-Type: application/json' \
-d '{
"prompt": "A cream knit sweater on a plain white background, SHIRTTR1GGER product shot.",
"finetune_id": "shirt-lora-v1",
"finetune_strength": 1.0
}')
POLLING_URL=$(echo "$RESPONSE" | jq -r '.polling_url')
while true; do
RESULT=$(curl -s "$POLLING_URL" -H "x-key: ${BFL_API_KEY}")
STATUS=$(echo "$RESULT" | jq -r '.status')
[ "$STATUS" = "Ready" ] && echo "$RESULT" | jq -r '.result.sample' && break
[ "$STATUS" = "Error" ] || [ "$STATUS" = "Failed" ] && echo "$RESULT" && break
sleep 1
done
finetune_id 必填,别人共享的适配器写成 {owner_org_id}/{name}。finetune_strength 默认 1.0;适配器盖过提示词时,官方解法是固定 seed 后在 0.7 → 0.9 之间扫。
同一个适配器也能在本地跑,走训练页给出的 Diffusers 管线。
python - <<'PY'
import torch
from diffusers import Flux2KleinPipeline
pipe = Flux2KleinPipeline.from_pretrained(
"black-forest-labs/FLUX.2-klein-base-4B", torch_dtype=torch.bfloat16
)
pipe.load_lora_weights("klein-lora/output/shirt_lora_v1/shirt_lora_v1.safetensors")
pipe.to("cuda")
image = pipe(
"A cream knit sweater on a plain white background, SHIRTTR1GGER product shot.",
num_inference_steps=50,
guidance_scale=4.0,
).images[0]
image.save("shirt-lora-sample.png")
PY
两条限制框住设计空间:一次请求只接受一个 LoRA,不支持叠加;底模匹配严格,4B 端点会拒绝为 9B 上传的适配器。公开测试期间微调端点按底模同分辨率计费,训练本身的价格官方没有公布。官方没给的数字去看各端点怎么计费,别抄第三方报价。本地 ComfyUI 部署先讲采样器设置,提交与轮询范式在别处有完整记录,中文上手与提示词管的是模型而不是管线出问题的情况。
常见问题
能直接通过 API 训练吗? 不能。Base 变体是面向本地开发的开放权重,不在公共 API 上提供。
该训哪个 Base 尺寸? 4B,除非你需要 9B 的质量并且有 22GB 显存。它是 Apache 2.0,硬件门槛也更低。
9B 的适配器能挂在 4B 端点上吗? 不能。底模匹配严格,不匹配的适配器会失败。
finetune_strength 该给多少? 从默认的 1.0 起步,只有适配器盖过提示词时才固定 seed 去 0.7 → 0.9 之间扫。