角色IP LoRA 训练集构建 Skill(通用版)
适用:krea2 模型 + ComfyUI + 任意LoRA训练平台(ModelScope / kohya / 本地) 前置:设计稿已就绪、ComfyUI可访问(默认 http://127.0.0.1:8188) 目标:6-9轮迭代产出150-200张合格训练集,可直接上传训练 本Skill自包含:迭代规则、固化脚本创建、测试流程全部内置,无需外部文档
一、触发条件
用户提出以下任一需求时启动本Skill:
- "训练角色LoRA"、"构建训练集"、"抽卡凑样本"
- "按照设计稿出图用于训练"、"迭代出图入训练集"
- 已有设计稿,需要批量生成符合角色设定的图片
二、目录结构约定(首次执行时创建)
在AI agent的当前工作目录下创建 lora-dataset/ 目录。通用资源共享,项目文件按设计稿/项目名分开,避免不同角色的训练集、报告、出图混在一起。
lora-dataset/
├── core/ # 【通用共享】固化脚本(所有项目共用,创建后勿改)
│ └── comfy_krea.py # ComfyUI API 封装
├── knowledge/ # 【通用共享】跨项目知识沉淀(越积累越厚)
│ ├── params.md # 关键参数沉淀(种子/工作流/LoRA权重)
│ ├── pitfalls.md # 踩坑记录(触发条件/对策/状态)
│ └── prompts.md # 优秀提示词库(金牌片段/负面词库)
└── projects/ # 【按项目分开】每个角色/设计稿一个子目录
└── <项目名>/ # 如:shenjingque / curve_body / 自定义名
├── iter/ # 该项目的迭代出图脚本(按版本存放)
│ └── configs/ # 每轮config JSON(含每张prompt/seed/权重)
├── dataset/ # 该项目的最终训练集(图片+同名.txt成对)
│ ├── head/ # 大头照
│ ├── half/ # 半身照
│ └── full/ # 全身照
├── reports/ # 该项目的迭代报告
│ ├── summaries/ # 每轮迭代总结(汇总级)
│ └── analyses/ # 每轮图片逐张分析(逐张级,与总结分开)
└── output/ # 该项目的每轮原始出图(round1_00001_.png等)
创建命令(agent执行一次即可,<项目名>替换为实际名称):
mkdir -p lora-dataset/{core,knowledge}
mkdir -p lora-dataset/projects/<项目名>/{iter/configs,dataset/{head,half,full},reports/{summaries,analyses},output}
目录划分原则:
| 类型 | 位置 | 说明 |
|---|---|---|
| 固化脚本 | core/ | 通用,所有项目共用,只创建一次 |
| 知识沉淀 | knowledge/ | 通用,跨项目积累,每个项目迭代后都往这里补充 |
| 迭代脚本 | projects/<项目名>/iter/ | 项目专属,不同角色的提示词模板不同 |
| 训练集 | projects/<项目名>/dataset/ | 项目专属,严格按角色分开,禁止混放 |
| 迭代报告 | projects/<项目名>/reports/ | 项目专属,按角色归档 |
| 原始出图 | projects/<项目名>/output/ | 项目专属,按角色分开便于回溯 |
2.1 core/ 与 iter/ 的核心区别(严禁混淆)
| 维度 | core/(固化脚本) | iter/(迭代脚本) |
|---|---|---|
| 本质 | 通用工具库,稳定不变 | 每轮临时执行脚本,频繁变化 |
| 内容 | ComfyUI API封装、工作流构建、批量生成函数 | 具体提示词、种子、LoRA权重、本轮任务列表 |
| 修改频率 | 创建后几乎不改,改了就是bug修复或功能升级 | 每轮都改,每轮一个新版本 |
| 复用范围 | 所有项目、所有角色共用 | 仅当前项目、当前轮次使用 |
| 是否含角色设定 | ❌ 不含任何角色/设计稿相关内容 | ✅ 含具体角色的提示词、服装、姿势等 |
| 是否含具体参数 | ❌ 只提供函数接口,参数由调用方传入 | ✅ 硬编码本轮的种子、权重、尺寸、任务列表 |
| 举例 | comfy_krea.py(generate_one / generate_batch) | round1_headshots.py、v2_round3_fullbody.py |
| 存放位置 | lora-dataset/core/ | lora-dataset/projects/<项目名>/iter/ |
判断口诀:
- 换一个角色还能用的 → 放
core/ - 换一个角色就不能用的 → 放
iter/ - 写死了"沈惊鹊"、"绯红礼服"、"瑞凤眼"等具体角色内容的 → 必须放
iter/ - 只是
generate_batch(wf, tasks, negative)这种通用函数的 → 放core/
常见错误:把包含具体提示词和任务列表的迭代脚本放进 core/。这会导致core目录越来越乱,不同角色的脚本混在一起,下次新项目无法直接复用core。正确做法是:迭代脚本 import core.comfy_krea,然后在iter脚本里写具体的提示词和任务。
iter脚本标准写法示例:
# 文件:lora-dataset/projects/shenjingque/iter/v1_round1.py
import sys, os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "..", "core"))
from comfy_krea import generate_batch
# 这里写具体的提示词、种子、任务列表(每轮不同)
tasks = [
{"name": "head_01", "prompt": "沈惊鹊,鹅蛋偏瓜子脸,瑞凤眼...", "seed": 77777777, "size": (1024,1024)},
# ...
]
generate_batch("turbo", tasks, negative="...", out_prefix="projects/shenjingque/round1")
三、前置检查(开工前必须确认)
□ 设计稿文件已完整读取(用户提供路径或已上传)
□ ComfyUI 正在运行,API 可访问(默认 http://127.0.0.1:8188)
□ krea2 模型已加载(turbo / raw 工作流可用)
□ lora-dataset/ 目录结构已创建
□ 固化脚本 comfy_krea.py 已创建并通过测试(见第四节)
任一不满足→先解决再开工,禁止跳过。
四、固化脚本创建与测试(首次必做)
4.1 创建 comfy_krea.py
在 lora-dataset/core/comfy_krea.py 创建以下脚本(ComfyUI API封装,支持turbo/raw/hybrid三种工作流):
"""
comfy_krea.py - krea2 ComfyUI 固化生图工具
支持:turbo / raw / hybrid(混合流) 三种工作流
功能:单张生成、批量生成、多LoRA链式挂载、自动记录prompt/seed/权重
"""
import json, time, urllib.request, urllib.parse, os, random
COMFY_URL = "http://127.0.0.1:8188"
# 输出根目录:默认为当前工作目录下的 lora-dataset/,可通过环境变量 LORA_DATASET_ROOT 覆盖
OUTPUT_ROOT = os.environ.get("LORA_DATASET_ROOT", os.path.join(os.getcwd(), "lora-dataset"))
# ========== 工作流默认参数 ==========
WF_DEFAULTS = {
"turbo": {"steps": 8, "cfg": 1.0, "sampler": "euler", "scheduler": "simple", "shift": 3.0},
"raw": {"steps": 25, "cfg": 2.0, "sampler": "er_sde", "scheduler": "simple", "shift": 3.0},
"hybrid": {"raw_steps": 6, "total_steps": 12, "cfg": 1.0, "sampler": "euler", "scheduler": "simple", "shift": 3.0},
}
def _queue_prompt(prompt_workflow, client_id):
"""提交工作流到ComfyUI队列"""
data = json.dumps({"prompt": prompt_workflow, "client_id": client_id}).encode()
req = urllib.request.Request(f"{COMFY_URL}/prompt", data=data, headers={"Content-Type": "application/json"})
return json.loads(urllib.request.urlopen(req).read())
def _get_history(prompt_id):
"""轮询等待生成完成"""
while True:
with urllib.request.urlopen(f"{COMFY_URL}/history/{prompt_id}") as r:
history = json.loads(r.read())
if prompt_id in history:
return history[prompt_id]
time.sleep(2)
def _build_workflow(wf, prompt, negative, seed, size, loras, **kwargs):
"""构建krea2工作流JSON(根据实际ComfyUI节点ID调整)"""
w, h = size
params = WF_DEFAULTS[wf].copy()
params.update(kwargs)
client_id = f"agent_{random.randint(10000,99999)}"
# 基础工作流结构(需根据实际ComfyUI的krea2工作流节点ID适配)
# 以下为模板,agent首次使用时需对照实际工作流JSON修正节点编号
workflow = {
"1": {"class_type": "KSampler", "inputs": {
"seed": seed, "steps": params["steps"], "cfg": params["cfg"],
"sampler_name": params["sampler"], "scheduler": params["scheduler"],
"denoise": 1.0, "model": ["2", 0], "positive": ["3", 0], "negative": ["4", 0],
"latent_image": ["5", 0]}},
"2": {"class_type": "UNETLoader", "inputs": {
"unet_name": "krea2_turbo_fp8_scaled.safetensors" if wf != "raw" else "krea2_raw_fp8_scaled.safetensors",
"weight_dtype": "fp8_e4m3fn"}},
"3": {"class_type": "CLIPTextEncode", "inputs": {"text": prompt, "clip": ["6", 0]}},
"4": {"class_type": "CLIPTextEncode", "inputs": {"text": negative or "", "clip": ["6", 0]}},
"5": {"class_type": "EmptyLatentImage", "inputs": {"width": w, "height": h, "batch_size": 1}},
"6": {"class_type": "CLIPLoader", "inputs": {"clip_name": "qwen3vl_4b_fp8_scaled.safetensors", "type": "stable_cascade"}},
"7": {"class_type": "VAELoader", "inputs": {"vae_name": "qwen_image_vae.safetensors"}},
"8": {"class_type": "VAEDecode", "inputs": {"samples": ["1", 0], "vae": ["7", 0]}},
"9": {"class_type": "SaveImage", "inputs": {"images": ["8", 0], "filename_prefix": "lora_dataset"}},
}
# LoRA链式挂载(插入LoraLoader节点)
if loras:
lora_node_id = "10"
prev_model = ["2", 0]
for i, (lora_name, weight) in enumerate(loras):
if weight == 0:
continue
nid = str(10 + i)
workflow[nid] = {"class_type": "LoraLoader", "inputs": {
"lora_name": lora_name, "strength_model": weight, "strength_clip": weight,
"model": prev_model, "clip": ["6", 0]}}
prev_model = [nid, 0]
workflow["1"]["inputs"]["model"] = prev_model
# hybrid混合流:raw前N步 + turbo后M步(需用ModelSamplingSD3或自定义节点实现)
# 简化版:hybrid用raw_steps参数控制,实际需根据工作流调整
if wf == "hybrid":
workflow["1"]["inputs"]["steps"] = params["total_steps"]
# 注:完整hybrid实现需要raw+turbo双UNet切换,agent可根据实际工作流扩展
return workflow, client_id
def generate_one(wf="turbo", prompt="", negative="", seed=None,
size=(1024,1024), loras=None, out_prefix="gen", timeout=300, **kwargs):
"""
单张生成
wf: turbo / raw / hybrid
prompt: 正面提示词
negative: 负面提示词(turbo/hybrid下cfg=1负面无效,可留空)
seed: 随机种子,None=随机
size: (宽,高)
loras: [(lora文件名, 权重), ...],权重0跳过
out_prefix: 输出文件名前缀
返回: {ok, path, seed, prompt, negative, loras, size, wf}
"""
if seed is None:
seed = random.randint(1, 2**31 - 1)
loras = loras or []
workflow, client_id = _build_workflow(wf, prompt, negative, seed, size, loras, **kwargs)
workflow["9"]["inputs"]["filename_prefix"] = out_prefix.replace("\\", "/")
try:
resp = _queue_prompt(workflow, client_id)
prompt_id = resp["prompt_id"]
history = _get_history(prompt_id)
outputs = history.get("outputs", {})
# 提取保存的图片路径
img_path = None
for node_id, out in outputs.items():
if "images" in out:
for img in out["images"]:
img_path = os.path.join(COMFY_URL.replace(":8188", ""), "view", f"?filename={img['filename']}&subfolder={img.get('subfolder','')}&type={img.get('type','output')}")
return {"ok": True, "path": img_path, "seed": seed, "prompt": prompt,
"negative": negative, "loras": loras, "size": size, "wf": wf}
except Exception as e:
return {"ok": False, "error": str(e), "seed": seed, "prompt": prompt}
def generate_batch(wf="turbo", tasks=None, negative="", size=(1024,1024),
out_prefix="batch", timeout=300, **kwargs):
"""
批量生成(迭代抽卡主力)
tasks: [{"name":"01","prompt":"...","seed":123,"loras":[...],"size":(1024,1344)}, ...]
每条task可单独覆盖公共参数
跑完自动写 record JSON 到 output/ 目录
"""
tasks = tasks or []
results = []
for i, task in enumerate(tasks):
name = task.get("name", f"{i:04d}")
print(f"[{i+1}/{len(tasks)}] {name}")
rec = generate_one(
wf=task.get("wf", wf),
prompt=task["prompt"],
negative=task.get("negative", negative),
seed=task.get("seed"),
size=task.get("size", size),
loras=task.get("loras", []),
out_prefix=f"{out_prefix}/{name}",
timeout=timeout,
**{k:v for k,v in task.items() if k not in ["name","prompt","negative","seed","size","loras","wf"]}
)
rec["name"] = name
results.append(rec)
# 保存record到out_prefix所在目录(项目级output目录)
record_dir = os.path.join(OUTPUT_ROOT, os.path.dirname(out_prefix)) if os.path.dirname(out_prefix) else OUTPUT_ROOT
os.makedirs(record_dir, exist_ok=True)
record_path = os.path.join(record_dir, f"{os.path.basename(out_prefix).replace('/','_')}_record.json")
with open(record_path, "w", encoding="utf-8") as f:
json.dump({"wf": wf, "total": len(tasks), "results": results}, f, ensure_ascii=False, indent=2)
print(f"记录已保存: {record_path}")
return results
def clear_queue():
"""清空ComfyUI队列(卡死时用)"""
try:
urllib.request.urlopen(f"{COMFY_URL}/queue", data=b"").read()
except: pass
def interrupt():
"""中断当前生成"""
try:
urllib.request.urlopen(f"{COMFY_URL}/interrupt", data=b"").read()
except: pass
重要:上述脚本中的工作流节点ID("1","2","3"...)和模型文件名是模板。agent首次创建后,必须对照本机ComfyUI中实际的krea2_turbo / krea2_raw工作流JSON,修正节点编号和模型文件名,否则无法运行。修正方法:在ComfyUI中打开工作流→右键→Export(API Format)→用实际JSON替换
_build_workflow函数中的结构。
4.2 测试流程(创建后必须执行)
创建脚本后,依次测试三种基础工作流,每种生成1张测试图:
import sys, os
sys.path.insert(0, os.path.join("lora-dataset", "core"))
from comfy_krea import generate_one
TEST_PROMPT = "一位20岁东方女性,正面半身肖像,黑色长发,自然微笑,纯色背景,真实人像摄影"
TEST_NEG = "低画质,模糊,变形,多人"
# 测试1: turbo(应~30秒出图)
r1 = generate_one("turbo", TEST_PROMPT, TEST_NEG, seed=77777777, size=(1024,1024), out_prefix="test/turbo")
print(f"turbo: ok={r1['ok']}, seed={r1['seed']}")
# 测试2: hybrid混合流(应~40秒出图)
r2 = generate_one("hybrid", TEST_PROMPT, TEST_NEG, seed=77777777, size=(1024,1024), out_prefix="test/hybrid", raw_steps=6, total_steps=12)
print(f"hybrid: ok={r2['ok']}, seed={r2['seed']}")
# 测试3: raw(应~100秒出图,负面词生效)
r3 = generate_one("raw", TEST_PROMPT, TEST_NEG, seed=77777777, size=(1024,1024), out_prefix="test/raw")
print(f"raw: ok={r3['ok']}, seed={r3['seed']}")
测试通过标准:
- 三种工作流均返回
ok=True - 输出目录
lora-dataset/output/test/下有对应图片 - 图片无明显崩坏(人脸正常、无黑图/灰图)
测试不通过:检查ComfyUI是否运行、模型文件名是否正确、节点ID是否匹配实际工作流。修正后重测,直到三种全部通过。
4.3 BBOX工作流(可选,需用户安装节点)
BBOX结构化构图工作流需要安装自定义节点:
- 节点仓库:https://github.com/ukr8b3g-cmyk/Krea2-BBOX-Prompter
- 安装方法:在ComfyUI的
custom_nodes/目录下git clone该仓库,重启ComfyUI - 适用场景:补角度短板(纯侧/背身)、稳定全身防裁切、精确控景别
- 注意:BBOX对泪痣/银铃等小细节控制弱,面部锚点抽卡不推荐使用
提示用户:如果需要BBOX功能,请先告知用户安装上述自定义节点;未安装时只用turbo/hybrid/raw三种基础流。
五、迭代规则(内置,每轮必须遵守)
5.1 迭代总原则(不可妥协)
- 每轮必须评估、总结、调优后再进下一轮,禁止盲跑多轮。
- 每轮结束即出报告,不积压、不事后补写。
- 以设计稿为唯一验收标准,每轮对照检查不变量是否达标。
- 优秀提示词和参数必须沉淀,下一轮优先复用,避免重复踩坑。
- 失败原因必须记录,同类错误不允许出现第三次。
5.2 每轮闭环流程
设定本轮目标 → 批量出图 → 逐张评估 → 总结沉淀 → 调优下一轮
↑ │
└──────────────────────────────────────────────┘
设定目标:明确本轮核心问题(如泪痣位置、脸型、服装形制),确定样本量/景别配比/工作流配比。
批量出图:使用固化脚本,种子/LoRA权重/尺寸/工作流必须记录到config JSON。
逐张评估:对照设计稿不变量逐项检查,统计合格数/淘汰数/淘汰原因分类。逐张分析记录存入 projects/<项目名>/reports/analyses/,与总结报告分开。
总结沉淀:归纳有效提示词片段、参数组合、失败根因,更新 knowledge/ 下三个文档。
调优下一轮:基于本轮结论调整提示词/LoRA权重/种子/工作流配比,保留有效参数,替换无效参数。
5.3 入库评判铁律
图片入库只看设计稿,不看提示词。 两个维度严格分离:
| 维度 | 评判标准 | 用途 | |---|---|---| | 图片入库 | 只看图片本身是否符合设计稿(脸型/眼型/发型/身材/服装/标记等) | 决定是否选入训练集 | | 提示词记录 | 只有"出图质量好且符合提示词"的才记录 | 用于优化提示词,与入库无关 |
具体执行:
- 提示词写全身但出成半身/大头→按实际景别评判,符合设计稿就入对应训练集
- 提示词写A服装但出成B服装→只要B服装符合设计稿就可入库
- "不符合提示词"永远不是废图理由
5.4 入库与打标规则
- 合格图复制到
projects/<项目名>/dataset/head|half|full/,按规范重命名:<模块>_v<版本>r<轮次>_t<序号>.png - 必须同步生成同名
.txt,内容两段(见第七节5.2) - 记录原始文件名→训练集新文件名对应关系
- 单套服装样本不超过总量10%,表情/姿势/光影/角度必须覆盖设计稿要求
5.5 迭代终止条件
满足任一可暂停:
- 连续2轮合格率≥70%,且不变量稳定
- 训练集数量达到目标(角色IP建议150-200张)
- 核心锚点(脸型/眼型/发型/身材)连续3轮达标率≥80%
- 用户明确喊停
暂停后输出全量汇总,包含所有轮次参数沉淀、提示词库、踩坑记录、训练集统计。
六、执行流程(7步)
Step 1:设计稿解析
通读设计稿,提取两张清单:
不变量(硬锚点,每张必须达标):
- 脸型、眼型、发型、身材、标记物(痣/疤/饰品)、肤色妆容基调
可变维度(多样性来源):
- 表情≥8种、姿势≥8种、角度≥6种、光影≥6种
- 服装≥5色系×3形制,单套不超过总量10%
- 背景≥5种
设计稿常见坑预判:
- 泪痣位置→模型对"右眼"理解=画面右侧,建议降级为偶发钩子(10-25%概率),不强制每张必出
- 花钿→古风情绪词(温婉/明艳)会触发,负面词需强化+去掉情绪形容词
- 银铃→半身照看不到脚踝,写了必跑手腕,半身不写银铃只在全身写
Step 2:提示词模板
三段式结构:
【角色锚点段】脸型+眼型+发型+肤色+妆容(固定,所有景别共用)
【身材/服装段】身材描述+具体服装形制+颜色+刺绣+袖型(半身/全身用)
【构图/光影段】景别+姿势+表情+光影+背景+镜头(按景别换)
各景别参数: | 景别 | 尺寸 | 脸占比 | LoRA权重(如有身材LoRA) | 关键描述 | |---|---|---|---|---| | 大头 | 1024×1024 | 60-75% | 0.5 | 头部角度+表情+光影 | | 半身 | 1024×1344 | 30-40% | 0.9 | 头顶到大腿中段,面部完整可见双眼 | | 全身 | 1024×1600 | 15-25% | 1.0 | "镜头拉远+人物占九成高+双脚在底部+严禁裁脚" |
通用负面词库(复制即用):
网红脸,AI平均脸,圆脸,宽脸,大脸,方脸,圆下巴,钝下颌,
杏眼圆润,圆眼睛,大眼,狐狸眼吊梢眼,
花钿,额饰,面靥,眼尾花纹,多颗痣,双痣,痣串,雀斑,斑点,
旗袍,立领,盘扣,短袖,无袖,吊带,现代服装,高开衩,
平胸,小胸,无腰,臀下垂,瘦弱,骨感,比例失衡,
断肢,坏手,多指,缺指,畸形,多人,裁切,头部裁切,脚部裁切,
银铃在手腕,银铃在手上,多个银铃,双脚都有银铃,
低画质,模糊,塑料磨皮,文字水印
长度铁律:单条提示词≤400字(Qwen3-VL-4B文本编码器上限,超长会OOM)。
Step 3:迭代抽卡
每轮配置:
- 20-24张:大头10 + 半身6 + 全身8
- 工作流配比:turbo 70% + hybrid 30%(角色脸禁用raw和bbox)
- 种子区间:77777777-77777816(花钿率低,已验证)
- 输出到
projects/<项目名>/output/round<N>_
工作流选择结论(已验证): | 工作流 | 速度 | 负面词 | 角色脸抽卡 | |---|---|---|---| | turbo | ~30s | ❌无效 | ⭐⭐⭐⭐⭐ 主力(发型/脸型锁定最稳) | | hybrid | ~38s | ❌无效 | ⭐⭐⭐⭐ 辅助(质量/速度平衡) | | raw | ~100s | ✅生效 | ⭐⭐ 禁用(发型5/6跑偏、脸型3/6偏圆) | | bbox | ~40s | ❌无效 | ⭐⭐ 禁用(小细节弱,泪痣变泪痕) |
Step 4:逐张评估
评估铁律:只看设计稿,不看提示词(见5.3)。
逐张检查清单:
- [ ] 脸型?眼型?发型?
- [ ] 身材(半身/全身)?标记物位置?
- [ ] 无花钿/多颗痣/短袖硬伤?
- [ ] 无结构错误(断肢/多指/裁切)?
- [ ] 画质清晰?
统计:合格数、淘汰数、淘汰原因TOP3分类。逐张分析存入 projects/<项目名>/reports/analyses/<模块>_图片分析_R<N>_<日期>.md。
Step 5:入库与同步打标
入库:合格图复制到 projects/<项目名>/dataset/head|half|full/,重命名,记录对应关系。
同步打标(必须,格式严格统一):每张 xxx.png 必须伴随同名 xxx.txt,UTF-8编码,内容固定为以下两段格式:
【源提示词】
正向:<生成该图时实际使用的完整prompt,从record JSON提取,一字不改,含加权语法>
负面:<完整negative prompt,无负面词则写"无">
LoRA:<lora文件名> @ <权重>;<第二个lora> @ <权重>(无LoRA则写"无")
工作流:<turbo|hybrid|raw> | 种子:<数字> | 尺寸:<宽>×<高>
原始文件:<output目录中的原始文件名>
【训练caption】
<触发词>, <脸型>, <眼型>, <发型>, <身材描述>, <服装形制>, <服装颜色>, <姿势>, <表情>, <光影>, <背景>
格式铁律:
- 两段标题固定为
【源提示词】和【训练caption】,不可改名 - 字段名固定为
正向:、负面:、LoRA:、工作流:、原始文件:,冒号为中文全角 - 多个LoRA用分号分隔,如
curve_body_v2.safetensors @ 0.9; sjq_face_v1.safetensors @ 0.7 - 无LoRA时写
LoRA:无,不可留空 - 源提示词必须从当轮record JSON提取,不得凭记忆补写或改写
- 训练caption以触发词开头(如
shenjingque,),后续用英文逗号+空格分隔 - 训练caption只保留角色特征+服装+姿势+表情+光影+背景,去掉镜头/画质/分辨率等套话
- 原始文件字段记录output目录中的文件名,便于回溯
完整示例:
【源提示词】
正向:沈惊鹊,鹅蛋偏瓜子脸,下颌尖窄,瑞凤眼,眼尾飞挑,半挽垂发,颊边碎发,暖象牙白瓷光肌,沙漏身材,C杯胸,极细腰,绯红织金礼服,广袖,交领,腰封,长裙,侧身回眸,微微笑,暖侧光,竹林背景,真实人像摄影
负面:网红脸,圆脸,宽脸,花钿,额饰,多颗痣,短袖,平胸,断肢,坏手,低画质,模糊
LoRA:curve_body_v2.safetensors @ 0.9
工作流:turbo | 种子:77777801 | 尺寸:1024×1344
原始文件:round1_half_03_00001_.png
【训练caption】
shenjingque, 鹅蛋偏瓜子脸, 瑞凤眼, 半挽垂发, 沙漏身材, 绯红织金礼服, 广袖, 交领, 腰封, 长裙, 侧身回眸, 微笑, 暖侧光, 竹林背景
Step 6:迭代调优
本轮淘汰原因TOP3 → 针对性修改提示词/负面词/参数 → 下一轮验证
↓
有效参数→knowledge/params.md
踩坑→knowledge/pitfalls.md
金牌提示词→knowledge/prompts.md
每轮总结存入 projects/<项目名>/reports/summaries/<模块>_迭代总结_R<N>_<日期>.md。
Step 7:训练配置(达标后)
通用训练参数(适用于ModelScope / kohya等): | 参数 | 推荐值 | 说明 | |---|---|---| | 网络大小(dim) | 32 | | | 网络Alpha | 32 | alpha=dim | | Unet学习率 | 0.0001 | 主力 | | 文本编码器学习率 | 0.00001 | 比Unet低10倍 | | 调度器 | cosine_with_restarts | 重启3次 | | 优化器 | AdamW | | | 混合精度 | fp16 | | | 图片分辨率 | 1024×1024 | 开启arb桶 | | 最大token | 225 | | | 打乱标注 | 开启 | | | 训练步数 | 先2000-3000步试效果 | 稳定后5000-6000步 | | 保存间隔 | 每500步 | 方便挑选最佳epoch |
训练集配比:大头40% + 半身35% + 全身25%,总量150-200张起步。
七、关键参数速查表
| 项目 | 值 | 置信度 | |---|---|---| | 主力工作流 | turbo(角色脸) | ✅已验证 | | 辅助工作流 | hybrid(多样性) | ✅已验证 | | 禁用工作流 | raw(发型锁不住)、bbox(小细节弱) | ✅已验证 | | 种子区间 | 77777777-77777816 | ✅已验证 | | 大头尺寸 | 1024×1024 | ✅ | | 半身尺寸 | 1024×1344 | ✅ | | 全身尺寸 | 1024×1600(非1536,1536易被裁) | ✅ | | 身材LoRA权重 | 大头0.5/半身0.9/全身1.0 | ✅ | | 单条提示词长度 | ≤400字 | ✅ | | batch_size | 1 | ✅ | | 每轮张数 | 20-24 | ✅ | | 目标训练集 | 150-200张 | ✅ | | 大头:半身:全身 | 4:3:3 | ✅ |
八、踩坑速查(Top 10)
| # | 坑 | 触发条件 | 对策 | 状态 | |---|---|---|---|---| | 1 | 泪痣位置反 | 写"右眼" | 降级为偶发钩子,不强制每张必出 | ✅闭环 | | 2 | 多颗痣 | 写"全脸仅此一颗" | 不写数量否定+负面"多颗痣" | ✅解决 | | 3 | 花钿 | 古风情绪形容词 | 去情绪词+负面"花钿,额饰" | ✅解决 | | 4 | 广袖变短袖 | turbo+广袖 | 半身/全身用宽袖款+负面"短袖" | ✅解决 | | 5 | 银铃跑手腕 | 半身照写银铃 | 半身不写银铃,只在全身写 | ✅解决 | | 6 | 银铃跑手上 | 全身+手部复杂 | 负面加"银铃在手上,挂手指,吊手上" | ⚠️偶发 | | 7 | raw锁不住发型 | raw+半挽垂发 | 角色脸用turbo,不用raw | ✅解决 | | 8 | bbox小细节弱 | bbox+泪痣/银铃 | 面部锚点不用bbox | ✅解决 | | 9 | ComfyUI OOM | 提示词>400字+batch=2 | ≤400字+batch=1+每轮重启 | ✅解决 | | 10 | 全身被裁脚 | 写"全身照"+1536高度 | 1600高度+"镜头拉远+脚在底部" | ✅解决 |
九、合格率进化参考
9轮迭代实测(沈惊鹊角色IP):
R1:18% → R2:41% → R3:69% → R4:82% → R5:91% → R6:100% → R7:83% → R8:92% → R9:92%
通常3-4轮后稳定在80%+,6-9轮凑齐150-200张。
十、交付物清单
一次完整的角色LoRA训练集构建,应交付:
- ✅ 训练集图片(150-200张,分head/half/full目录)
- ✅ 每张图片的同名
.txt打标文件(源提示词+训练caption) - ✅ 迭代报告(每轮总结+逐张分析记录)
- ✅ 知识沉淀(参数/踩坑/提示词库三个文档)
- ✅ 训练配置单
- ✅ 文件名对应关系登记表
Skill创建:2026-08-31 | 通用版,基于9轮迭代实践提炼 | 维护:每次新角色训练后更新
微信扫一扫