134 lines
6.7 KiB
Markdown
134 lines
6.7 KiB
Markdown
# 脸部 LoRA 训练项目 · 项目管理总览
|
||
|
||
> 最后更新:2026-08-09
|
||
> 状态:**v3 训练进行中**(4090,约 2.5h 完成)
|
||
> 唯一入口:本文件 + `docs/云端训练完整操作文档.md`
|
||
|
||
---
|
||
|
||
## 项目目标
|
||
|
||
用老婆的照片训练脸部 LoRA,叠加 `Qwen-Rapid-AIO-NSFW-v23` checkpoint 出图。
|
||
训练底模:Qwen-Image-Edit-2511 bf16 官方底模。
|
||
|
||
---
|
||
|
||
## 当前训练状态(实时)
|
||
|
||
| 项 | 值 |
|
||
|---|---|
|
||
| GPU | RTX 4090($0.74/h,v2 验证过的最优解) |
|
||
| pod | `k1nzrqh8lfj7jg`(IP 103.196.86.68:50155) |
|
||
| 训练 | dim32/lr1e-4/120ep/32张=3840步,~2.5s/步,ETA ~2.5h |
|
||
| 监控 | 计划任务 `FaceLoRA-Monitor-v3` 每 5 分钟 |
|
||
| 进度 | **查 `temp/train_env.json` + `C:\Users\hmo\AppData\Local\Temp\opencode\face_lora\`** |
|
||
| 预算 | 4h 封顶($0.74×4=$2.96),余额 $10 |
|
||
|
||
**如何查当前进度(给 AI / 用户的快速指令)**:
|
||
```powershell
|
||
# 1. 训练实时进度(SSH pod)
|
||
ssh -i ~/.ssh/id_rsa -p 50155 root@103.196.86.68 "tail -c 500 /workspace/train.log | tr '\r' '\n' | tail -2"
|
||
# 2. 监控状态(下载了多少 checkpoint)
|
||
Get-Content C:\Users\hmo\AppData\Local\Temp\opencode\face_lora\train_events.log
|
||
Get-ChildItem C:\Users\hmo\AppData\Local\Temp\opencode\face_lora\checkpoints_v3\
|
||
# 3. pod 是否还在 / 计费
|
||
```
|
||
|
||
---
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
脸部LoRA训练-Qwen-Image/
|
||
├── docs/
|
||
│ └── 云端训练完整操作文档.md ← 训练全流程唯一权威参考(含全部踩坑)
|
||
├── tools/
|
||
│ ├── caption_gui.py ← 打标 GUI(http://127.0.0.1:7860)
|
||
│ ├── face_checker.py ← 素材审核/选图/auto流水线
|
||
│ ├── monitor_train_v3.ps1 ← 训练监控(计划任务,全自动)★正式版
|
||
│ ├── merge_fixed.py ← ComfyUI 融合工具
|
||
│ └── validate_lora.py ← 训练后验证
|
||
├── cloud/
|
||
│ ├── dataset.zip ← 训练集打包(32 img+32 txt)
|
||
│ ├── bootstrap.sh ← 云端引导(装musubi+下模型+预缓存)
|
||
│ ├── train.sh ← 云端训练(含崩溃重启)
|
||
│ ├── correct_key.pub ← 正确 SSH key(指纹 7Eep5Qz)
|
||
│ └── sample_prompts.txt
|
||
├── config/
|
||
│ ├── train_config.json ← GUI 训练配置(train_dataset/output_dir)
|
||
│ ├── dataset.toml / *_active ← 数据集配置
|
||
│ └── 训练脚本.py ← 本地训练脚本(已废弃,走云端)
|
||
├── temp/ ← 运行数据(非正式,可清理)
|
||
│ ├── train_env.json ← 监控配置(pod_id/dl_url/ssh/预算)★关键
|
||
│ └── ...
|
||
├── photos/ 素材/ 打标/ output/ ← 本地素材与输出
|
||
└── README.md ← 旧版项目说明
|
||
```
|
||
|
||
---
|
||
|
||
## 关键文件索引
|
||
|
||
| 文件 | 用途 | 谁改 |
|
||
|---|---|---|
|
||
| `docs/云端训练完整操作文档.md` | 训练全流程+踩坑记录 | 训练相关改动必须同步 |
|
||
| `tools/monitor_train_v3.ps1` | 训练监控(正式版) | 监控逻辑改动 |
|
||
| `temp/train_env.json` | 当前训练 pod 配置 | 每次新 pod 更新 |
|
||
| `cloud/train.sh` | 云端训练参数 | 换 GPU/参数时 |
|
||
| `cloud/bootstrap.sh` | 云端环境搭建 | 环境变化时 |
|
||
|
||
---
|
||
|
||
## 流程速览
|
||
|
||
1. **素材准备**:`photos_原始/` → `face_checker.py auto` → GUI ②候选换图筛选
|
||
2. **整理训练集**:GUI「📦 整理训练集」→ `train_dataset/`(自动跟随素材目录)
|
||
3. **打包**:`cloud/dataset.zip`(含 img+txt)
|
||
4. **云端训练**:创建 pod → 修 SSH key → 上传 → bootstrap → train(详见 docs)
|
||
5. **监控下载**:计划任务自动增量下载 checkpoint 到 `checkpoints_v3/`
|
||
6. **验证**:checkpoint → WebUI Rapid-AIO 出图
|
||
|
||
---
|
||
|
||
## ⚠️ 血泪教训(必须遵守,详见 docs 第八章)
|
||
|
||
1. **只用 Secure Cloud**,禁 Community
|
||
2. **换 GPU 前查架构兼容**:5090(sm_120) 与镜像 PyTorch 不兼容,禁用;4090/A40 可用
|
||
3. **预缓存验证看 `_qie.safetensors`**(数量=素材数),不是 .npz
|
||
4. **PS 5.1 变量名不区分大小写**:路径变量别叫 `$STATE`(会被 `$state` 覆盖),用 `$STATEFILE`
|
||
5. **PS 5.1 脚本存 GBK 编码**,输出目录用纯 ASCII,状态用纯文本(.json 写入不可靠)
|
||
6. **train_env.json 读取失败必须退出**,绝不用空值删 pod
|
||
7. **监控全自动**:计划任务每 5 分钟,增量下载 checkpoint,超时/崩溃自动止损,完成自动删 pod
|
||
8. **文档保持更新**:改了就要同步 docs/(不用问用户)
|
||
|
||
---
|
||
|
||
## ⚠️ ComfyUI workflow 编写要点(2026-08-09 查证,别手写 link id!)
|
||
|
||
**血泪教训**:直接改 workflow JSON 加连接(手写 link id 44-47)→ 加载显示正确但实际不稳定(操作其他连线时连接被替换)。用户前端重连(link id 47-50)后稳定。
|
||
|
||
**根因(2026-08-09 源码级验证,LiteGraph + ComfyUI 前端 TS 版)**:
|
||
- workflow UI format 的 link 是 6 元组 `[id, src_node, src_slot, dst_node, dst_slot, type]`
|
||
- **连接 = 三方引用必须一致**:① links 数组 ② 目标 node 的 `inputs[].link` ③ 源 node 的 `outputs[].links`(数组,一个输出可扇出多条)
|
||
- 只改 links 数组不动 node 引用 → 线"幽灵"或消失
|
||
- **核心机制**:连接新线时 `linkId = lastLinkId + 1`;前端加载 workflow 时 `state.lastLinkId = Math.max(当前, JSON值)`,**不扫描 links 数组**。脚本手写 link id 但没同步 lastLinkId → 下次连接新线生成重复 id → `_links.set(id, 新线)` 覆盖手写的连接
|
||
- **铁律:脚本加 link 后必须把 `state.lastLinkId`(新schema)或 `last_link_id`(旧schema)设为 ≥ 最大 link id**
|
||
- **正确做法**:连接让前端生成,或脚本严格 lastLinkId 同步 + 三方一致
|
||
|
||
**关键规则**:
|
||
1. API format(执行):`{"id": {"class_type":..., "inputs":{...}}}`,连接 `["源ID字符串", 输出槽]`,**节点 ID 必须字符串**
|
||
2. UI format(画布):顶层 nodes+links+groups,**保存画布用 UI format**(API→UI 有损丢布局)
|
||
3. 写节点前查 `/object_info/<NodeType>` 拿真实 schema,别猜 widgets 顺序
|
||
4. 类型不匹配插转换节点(IMAGE↔LATENT 用 VAEEncode/VAEDecode)
|
||
5. 验证阶梯:静态检查 → /object_info → 小图 /prompt 冒烟 → 全量
|
||
6. 参考 skill:`SlavaSexton/ComfyUI-Agent-Kit`(最全)+ `artokun/comfyui-mcp`(精简权威)
|
||
|
||
---
|
||
|
||
## 权限与密钥(不提交 Git)
|
||
|
||
- RunPod API key:`temp/../.runpod_api_key`(rpa_ 开头,50位)
|
||
- SSH key:`~/.ssh/id_rsa`(指纹 7Eep5Qz,对应 cloud/correct_key.pub)
|
||
- Gitea:xiaoxiao 凭证(curl 拉 correct_key.pub 用)
|
||
- GUI 状态:`tools/gui_state.json`
|