dataset-doctor — LoRA 数据集 / caption 体检 + 修复
在训练前对 LoRA 数据集与标注做结构/卫生预检,给出 PASS / WARN / FAIL 结论和按优先级排序的修复建议;PASS 不代表图像与 caption 的语义已经人工验证。确认后用 fix_dataset.py 一行命令执行修复。体检只读;修复默认 dry-run,加 --apply 才动文件,且从不删除——被移除的文件全部进数据集内的 _quarantine/(体检与训练都会忽略它),随时可还原。任何 --apply 都必须先得到用户确认。
底层针对 lora-scripts-next(SD-Trainer)的数据集约定:train_data_dir 下放 <repeats>_<concept> 子文件夹(如 7_zkz = 重复 7 次、概念 zkz),caption 是与图同名的 sidecar .txt——单行、逗号分隔、可在末尾用「. 」接自然语言(已验证格式见 ../references/caption-guide.md)。Anima .json caption 仅是 UI 宣称的可选项,训练端 v2.7.0 未发现读取实现,不要依赖。
默认职责
接收一个数据集路径,运行体检脚本,解读 JSON/报告,向用户说明问题与修复顺序;用户确认后用 fix_dataset.py 执行修复并重检。trainer 本身只检查目录是否存在、有没有图,不检查质量——质量这块由本 skill 负责,二者互补。
适用范围(不限 SD-Trainer)
体检与修复是训练器无关的:检查对象是标准 kohya 数据集约定(<repeats>_<concept> 文件夹 + 同名 sidecar caption),sd-scripts / kohya_ss / OneTrainer 等训练器通用;脚本全程离线、不碰 GPU、不需要 trainer 在线。用户打算在任何训练器上练 LoRA,体检都照做。只有两处例外:
- WD14 打标:Anima 使用
../lora-pipeline/scripts/tag_dataset.py,与完整 pipeline 保持一致;SD1.5/SDXL/Flux 可走 SD-Trainer 的POST /api/interrogate。 - Anima
.jsoncaption 校验只对已经持有.json标注的数据集有意义,且.json是否真被训练端读取未经验证(v2.7.0 本地代码中无读取实现)——doctor 默认要求.txt;仅在明确使用会读取 JSON 的其他训练器时传--prefer-json。
触发与分支
有「训练前检查数据集 / caption / tag 质量」意图时触发:体检、检查数据集、看看标注、tag 有没有问题、能不能开训、trigger 一致吗、有没有重复图、步数够不够。
- 只是要自动打标(还没标注)→ Anima 走
tag_dataset.py;其他底模走/api/interrogate;打完再回来体检。 - 要开始训练 / 调参 → 交给
lora-trainer;它会在开训前调用本 skill 作为闸门。 - 要查 caption 怎么写 / trigger 怎么取 → 读
../references/caption-guide.md。
读取导航
| 需要处理的事 | 读取 / 执行 |
|---|---|
| 跑一次完整体检(默认) | scripts/doctor.py(见「运行体检」) |
修复体检发现的问题(dry-run → 确认 → --apply) |
scripts/fix_dataset.py(见「修复手册」) |
| 只看图像层面问题 | scripts/scan_dataset.py |
| 只看 caption / tag 问题 | scripts/check_captions.py |
| caption 格式、trigger、JSON 结构 | ../references/caption-guide.md |
| 打标 / 重打标 API | ../references/trainer-api.md |
| 训练参数与步数预算 | ../references/anima-params.md |
运行体检
脚本依赖 Pillow(纯 stdlib + Pillow,无需 numpy)。用一个装了 Pillow 的 Python 运行——trainer 自带的 embedded Python 最稳妥:
- 本机示例:
C:\SD-Trainer\python_embeded\python.exe - 通用:任何
python(缺 Pillow 时pip install pillow)
主入口 doctor.py(同时跑 scan + caption 并给总结论):
& "<PYTHON>" "<SKILL_DIR>/scripts/doctor.py" "<TRAIN_DATA_DIR>" `
--trigger <TRIGGER> --epochs <N> --batch-size <B> --target-reso 1024,1024 --json
<TRAIN_DATA_DIR>:<repeats>_<concept>的父目录(也可直接指向某个概念子文件夹)。--trigger:预期的触发词;不给则脚本会推断一个候选。--epochs/--batch-size:用于算总步数预算(可选但推荐)。- 输出:
--json(机器读,含verdict/summary/recommendations/scan/captions)、--report(人读 Markdown)、默认两者都打印。 - 退出码:PASS/WARN = 0,FAIL = 2。
需要分别看时用 scan_dataset.py / check_captions.py,参数同名。
解读结论
- FAIL(critical):有图无法解码(会让训练崩)、根本没有图。必须先修,禁止开训。
- WARN(high/medium):缺 caption、多行 caption(训练端只读第一行)、trigger 不一致、重复图、非 RGB、低于训练分辨率、过/欠标、artifact tag、JSON 结构错。可训,但先把建议过一遍并向用户确认。
- PASS(low/info 或无):可以训。
按 recommendations(已按严重度排序、去重)逐条处理。scan.issues / captions.issues 里每条都带 code、message、fix、items(示例文件,最多 12 个)。
修复手册(对应 issue code)
fix_dataset.py 与 doctor.py 用同一个 Python 运行。所有命令默认 dry-run(只打印计划),把计划摊给用户、确认后同一条命令加 --apply 执行。被移走的文件进 <dataset>/_quarantine/,不删除。
& "<PYTHON>" "<SKILL_DIR>/scripts/fix_dataset.py" <command> "<TRAIN_DATA_DIR>" [选项] [--apply]
| code | 修复命令 |
|---|---|
no_concept_folders |
fix_dataset.py organize <dir> --repeats <R> --concept <name> |
corrupt_images |
fix_dataset.py quarantine-corrupt <dir> |
exact_duplicates |
fix_dataset.py dedupe <dir>(保留分辨率最高的一张) |
near_duplicates |
fix_dataset.py dedupe <dir> --near |
non_rgb_mode |
fix_dataset.py to-rgb <dir>(原件备份进 _quarantine/) |
trigger_inconsistent |
fix_dataset.py add-trigger <dir> --trigger <T>(.txt 按 Anima 分段顺序插入;.json 写 character) |
artifact_tags / duplicate_tags |
fix_dataset.py strip-tags <dir>(移除 watermark/signature 等来源噪声;准确的逐图 quality 标签不是 artifact) |
multiline_caption |
训练端只读 .txt 第一行,后续行静默丢失。手动把每个 caption 合并成单行:tag 在前、. 接自然语言(格式见 ../references/caption-guide.md) |
ubiquitous_tags |
先核对哪个是有意的 trigger,其余用 strip-tags --tags "..." 删 |
missing_captions / empty_captions |
Anima:tag_dataset.py --dataset-dir <concept-dir> ...;其他底模:POST /api/interrogate + additional_tags=<TRIGGER> |
below_target_resolution / tiny_images |
换更高分辨率源;bucket_no_upscale 下小图细节受限(无自动修复) |
mixed_repeats |
核对各概念「有效图片数」比例是否符合预期(无需修复) |
打标 / 修复后,重新跑一次 doctor.py 确认问题已清。误修了想还原 → 把 _quarantine/ 里的文件移回原位即可。
自检
- 路径指向的是
train_data_dir(<repeats>_<concept>的父目录),不是散图目录;散图会触发no_concept_folders。 - 用了带 Pillow 的 Python;脚本能正常输出 JSON。
- 已知 trigger 时传了
--trigger,并核对trigger.presence_pct;Anima trigger 按分段顺序出现,不强制首位。 - 解读了
verdict并按recommendations顺序给建议。 - 任何
fix_dataset.py --apply/ 打标操作已先 dry-run 摊牌并取得用户确认;从不手写删除命令,从不直接删文件(一律走_quarantine/)。 - 修复后重跑体检确认。
可验证案例
用户:训练前帮我看看 D:/data/mychar(trigger 是 mych4r,打算 10 epoch)。
& "C:\SD-Trainer\python_embeded\python.exe" `
"<SKILL_DIR>/scripts/doctor.py" "D:/data/mychar" --trigger mych4r --epochs 10 --report
读 verdict:若 WARN 且 missing_captions+exact_duplicates,则:① Anima 用 tag_dataset.py 给缺标的图打标并生成语义审查;② fix_dataset.py dedupe "D:/data/mychar" dry-run 列出重复组 → 用户确认 → 加 --apply(被移除的进 _quarantine/);③ 修完重跑体检;④ PASS 或用户明确接受剩余 WARN 后,把数据集 + 建议的 repeats/epochs 交给 lora-trainer。
执行交接
- 体检与修复在本 skill;实际开训、组装 config、
POST /api/run、监看 SSE log 交给lora-trainer。 - 打标执行细节(端点、字段、轮询)见
../references/trainer-api.md;caption 写法见../references/caption-guide.md。 - 本 skill 不自行启动训练;修复一律 dry-run 先行、确认后
--apply、移除走_quarantine/不删除。