20 KiB
20 KiB
换发型项目部署操作手册
本手册详细描述在全新的 Ubuntu 22.04 + NVIDIA 3090 机器上,从零开始部署并运行换发型、换发色、训练模型三大功能的完整步骤。
目录
1. 环境前提
| 项目 | 要求 |
|---|---|
| 操作系统 | Ubuntu 22.04 LTS |
| GPU | NVIDIA RTX 3090(或其他 10GB+ 显存的 NVIDIA GPU) |
| NVIDIA 驱动 | ≥ 525.x(支持 CUDA 11.8) |
| 磁盘空间 | ≥ 90GB(代码 + 模型 + 环境) |
| 网络 | 需要访问 PyPI(创建 py310 环境时下载 pip 包) |
| Python | 不需要预装(通过 conda 管理) |
验证 GPU 和驱动:
nvidia-smi
# 应显示 GPU 信息和 CUDA 版本(≥ 11.8)
2. 安装系统依赖
2.1 安装基础工具
sudo apt update
sudo apt install -y git curl wget lsof
2.2 安装 Miniconda(如未安装)
# 下载并安装 Miniconda
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh -b -p $HOME/miniconda3
# 初始化 conda
$HOME/miniconda3/bin/conda init bash
source ~/.bashrc
# 验证
conda --version
2.3 配置 conda 镜像(国内可选,加速 py310 创建)
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
conda config --set show_channel_urls yes
3. Clone 代码
cd ~
git clone <仓库地址> change_hair_3090
cd change_hair_3090
Clone 后的目录结构(仅代码,不含模型/环境):
change_hair_3090/
├── hair_service_sd/ # 换发算法服务代码
├── photo_service/ # 训练调度服务代码
├── stable-diffusion-webui/ # SD WebUI 代码(不含 models/)
├── kohya_ss_home/ # kohya_ss 训练代码(不含 .local/)
├── conda_envs/
│ └── py310.yml # py310 环境定义文件
├── setup.sh # 部署脚本
├── start_all_services.sh # 启动脚本
├── stop_all_services.sh # 停止脚本
└── README.md
4. 下载网盘文件
将网盘上的 cloud_packages/ 目录下载到项目根目录。网盘文件已分类打包为 14 个文件,便于上传和下载。
4.1 网盘文件清单(已分类打包)
| 文件 | 大小 | 说明 |
|---|---|---|
my_hair.tar.gz |
4.2G | conda 环境(换发算法服务用) |
sdwebui.tar.gz |
3.6G | conda 环境(SD WebUI 用) |
kohya.tar.gz |
84M | conda 环境(LoRA 训练用,仅含 Python+numpy) |
sd_base_models.tar.gz |
3.6G | SD 底模(v1-5-pruned-emaonly.safetensors) |
lora_0-9.tar.gz |
29G | LoRA 模型(数字开头,约 228 个) |
lora_h.tar.gz |
132M | LoRA 模型(h 开头) |
lora_n.tar.gz |
132M | LoRA 模型(n 开头) |
lora_t.tar.gz |
791M | LoRA 模型(t 开头) |
weights.tar.gz |
9.2G | 换发算法模型(matting、分割等) |
kohya_local.tar.gz |
3.4G | 训练 pip 包(torch、accelerate、diffusers 等) |
kohya_code.tar.gz |
365M | kohya_ss 训练代码 + CLIP 缓存 |
data.tar.gz |
3.4G | 业务数据(参考发型图等) |
webui_controlnet.tar.gz |
4.1G | ControlNet 扩展 |
webui_repositories.tar.gz |
221M | SD 依赖仓库(k-diffusion 等) |
合计约 62G
4.2 下载后解压
cd ~/change_hair_3090
# 创建 cloud_packages 目录并下载网盘文件到这里
mkdir -p cloud_packages
# ... 将网盘上的 cloud_packages/ 目录下载到这里 ...
# 解压所有包(按顺序执行)
echo "=== 1. 解压 conda 环境 ==="
tar -xzf cloud_packages/my_hair.tar.gz -C conda_envs/
tar -xzf cloud_packages/sdwebui.tar.gz -C conda_envs/
tar -xzf cloud_packages/kohya.tar.gz -C conda_envs/
echo "=== 2. 解压 SD 模型 ==="
tar -xzf cloud_packages/sd_base_models.tar.gz -C stable-diffusion-webui/models/Stable-diffusion/
echo "=== 3. 解压 LoRA 模型 ==="
tar -xzf cloud_packages/lora_0-9.tar.gz -C stable-diffusion-webui/models/Lora/
tar -xzf cloud_packages/lora_h.tar.gz -C stable-diffusion-webui/models/Lora/
tar -xzf cloud_packages/lora_n.tar.gz -C stable-diffusion-webui/models/Lora/
tar -xzf cloud_packages/lora_t.tar.gz -C stable-diffusion-webui/models/Lora/
echo "=== 4. 解压换发算法权重 ==="
tar -xzf cloud_packages/weights.tar.gz -C hair_service_sd/
echo "=== 5. 解压 kohya 训练环境 ==="
tar -xzf cloud_packages/kohya_local.tar.gz -C kohya_ss_home/
tar -xzf cloud_packages/kohya_code.tar.gz -C kohya_ss_home/
echo "=== 6. 解压业务数据 ==="
tar -xzf cloud_packages/data.tar.gz -C .
echo "=== 7. 解压 WebUI 扩展 ==="
tar -xzf cloud_packages/webui_controlnet.tar.gz -C stable-diffusion-webui/extensions/
tar -xzf cloud_packages/webui_repositories.tar.gz -C stable-diffusion-webui/
4.3 解压后验证
cd ~/change_hair_3090
# 检查关键文件是否存在
ls -lh conda_envs/*.tar.gz
ls -d hair_service_sd/weights/
ls -d kohya_ss_home/.local/
ls -lh stable-diffusion-webui/models/Stable-diffusion/v1-5-pruned-emaonly.safetensors
期望输出:
-rw------- ... 84M ... conda_envs/kohya.tar.gz
-rw------- ... 4.2G ... conda_envs/my_hair.tar.gz
-rw------- ... 3.6G ... conda_envs/sdwebui.tar.gz
hair_service_sd/weights/
kohya_ss_home/.local/
-rw-rw-r-- ... 4.0G ... v1-5-pruned-emaonly.safetensors
4.3 关于 kohya 训练环境的架构说明
LoRA 训练环境由两部分组成,缺一不可:
conda_envs/kohya.tar.gz (84M) kohya_ss_home/.local/ (7.6G)
┌─────────────────────────┐ ┌──────────────────────────────────┐
│ Python 3.10 解释器 │ │ torch 2.0.1+cu118 │
│ numpy 1.24.4 │ +PYTHONPATH→ │ accelerate 0.23.0 │
│ tqdm │ │ bitsandbytes 0.41.1 │
│ setuptools 69.5.1 │ │ diffusers 0.21.4 │
│ (conda-pack 打包) │ │ transformers 4.30.2 │
│ │ │ xformers 0.0.21 │
│ │ │ safetensors, pytorch_lightning │
│ │ │ (从 Docker 容器复制的 pip 包) │
└─────────────────────────┘ └──────────────────────────────────┘
kohya.tar.gz 仅包含 Python 解释器和 numpy(解决版本兼容性),通过 PYTHONPATH 环境变量指向 .local/ 目录来加载 torch 等大包。这样避免重新下载 7.6G 的训练依赖。
5. 运行部署脚本
cd ~/change_hair_3090
chmod +x setup.sh start_all_services.sh stop_all_services.sh
./setup.sh
5.1 setup.sh 执行的 8 个步骤
| 步骤 | 说明 |
|---|---|
| 1/8 | 检查前提条件(git、conda、NVIDIA 驱动) |
| 2/8 | 生成 configure.ini(自动替换 __BASE_DIR__ 为实际路径) |
| 3/8 | 从 conda-pack 恢复 my_hair、sdwebui、kohya 三个 conda 环境 |
| 4/8 | 从 py310.yml 创建 py310 环境(需联网下载 pip 包) |
| 5/8 | 检查模型和数据目录完整性 |
| 6/8 | 检查训练底模 v1-5-pruned-emaonly.safetensors |
| 7/8 | 创建运行时目录(logs、data/tmp 等) |
| 8/8 | 验证 kohya 训练环境(测试 torch/accelerate 能否加载) |
5.2 成功输出
=== 换发型项目部署脚本 ===
BASE_DIR: /home/xxx/change_hair_3090
CONDA_BASE: /home/xxx/miniconda3
[1/8] 检查前提条件...
✓ 前提条件满足
[2/8] 生成 configure.ini...
✓ configure.ini 已生成
[3/8] 恢复 conda 环境(my_hair, sdwebui, kohya)...
✓ my_hair 已恢复
✓ sdwebui 已恢复
✓ kohya 已恢复
[4/8] 创建 py310 环境(从 yml)...
✓ py310 已创建
[5/8] 检查模型和数据目录...
✓ hair_service_sd/weights
✓ stable-diffusion-webui/models/Lora
...(全部 ✓)
[6/8] 检查训练底模 v1-5-pruned-emaonly...
✓ v1-5-pruned-emaonly.safetensors 已存在
[7/8] 创建运行时目录...
✓ 运行时目录已创建
[8/8] 验证 kohya 训练环境...
测试 torch/accelerate 加载...
torch=2.0.1+cu118 cuda=True
accelerate=0.23.0
✓ 训练环境验证通过
=== 部署结果 ===
✓ 所有检查通过,部署完成!
5.3 如果 CONDA_BASE 不在默认路径
# 方法1:设置环境变量
export CONDA_BASE=/your/conda/path
./setup.sh
# 方法2:脚本会自动通过 `conda info --base` 检测
# 只要 conda 在 PATH 中即可自动找到
6. 启动服务
./start_all_services.sh
6.1 启动的三个服务
| 服务 | 端口 | conda 环境 | 功能 |
|---|---|---|---|
| hair_service_sd | 8801 | my_hair | 换发型/换发色核心算法 |
| stable-diffusion-webui | 57860 | sdwebui | SD 图生图推理 |
| photo_service | 32678 | py310 | LoRA 训练调度(训练子进程使用 kohya 环境) |
6.2 成功输出
=== 启动换发型服务 ===
[1/3] 启动 hair_service_sd (端口 8801)...
hair_service_sd 已启动 (PID: xxxx, 端口 8801)
[2/3] 启动 stable-diffusion-webui (端口 57860)...
stable-diffusion-webui 已启动 (PID: xxxx, 端口 57860)
ℹ WebUI 首次启动需加载模型(约 30-60 秒),请耐心等待
[3/3] 启动 photo_service (端口 32678)...
photo_service 已启动 (PID: xxxx, 端口 32678)
=== 所有服务已启动 ===
等待 WebUI 就绪(检查端口 57860)...
✓ WebUI 已就绪
6.3 查看日志
# 换发型/换发色服务日志
tail -f logs/hair_service.log
# SD WebUI 日志
tail -f logs/webui.log
# 训练服务日志
tail -f logs/photo_service.log
7. 验证功能
7.1 验证服务状态
# 检查三个端口是否在监听
curl -s http://127.0.0.1:8801/ | head -5
curl -s http://127.0.0.1:57860/sdapi/v1/options | head -5
curl -s http://127.0.0.1:32678/ | head -5
7.2 验证换发色功能
# 准备一张人像照片(base64 编码)
IMG_B64=$(base64 -w0 test_photo.jpg)
curl -X POST http://127.0.0.1:8801/hairColor/v2 \
-H "Content-Type: application/json" \
-d "{
\"img\": \"data:image/jpeg;base64,${IMG_B64}\",
\"userId\": \"test_user\",
\"rgb\": \"120,60,30\"
}"
参数说明:
img:用户照片,支持 base64(data:image/jpeg;base64,...)或 URLuserId:用户标识rgb:目标发色 RGB 值(如120,60,30表示棕色)
7.3 验证换发型功能
curl -X POST http://127.0.0.1:8801/api/swapHair/v1 \
-H "Content-Type: application/json" \
-d "{
\"hair_id\": \"<发型ID>\",
\"task_id\": \"test_001\",
\"is_hr\": \"false\",
\"user_img_path\": \"data:image/jpeg;base64,${IMG_B64}\"
}"
参数说明:
hair_id:发型 ID(对应data/ref_hairstyle/目录下的发型)task_id:任务唯一标识is_hr:是否高清模式("true"或"false")user_img_path:用户照片,支持 base64 或 URL
7.4 验证训练功能
训练需要准备训练素材(10+ 张同一发型的照片),组织成指定目录结构:
hair_material_dir/
├── images/
│ └── 1_hairstyle/ # 数字开头的文件夹
│ ├── 001.png # 训练图片(≥10张)
│ ├── 001.txt # 标签文件(自动生成)
│ ├── 002.png
│ ├── 002.txt
│ └── ...
└── model/ # 训练输出目录(需提前创建)
发起训练请求:
curl -X POST http://127.0.0.1:32678/api/hair/train \
-H "Content-Type: application/json" \
-d "{
\"task_id\": \"train_001\",
\"hair_id\": \"test_hair\",
\"hair_material_dir\": \"/home/xxx/change_hair_3090/data/tmp/test_material\"
}"
训练日志查看:
tail -f logs/photo_service.log
# 训练开始后会看到 cmd_train 输出
# 训练完成后会在 hair_material_dir/model/ 下生成 hairstyle_hd_lora.safetensors
训练参数(已在代码中固定):
- 底模:
v1-5-pruned-emaonly.safetensors - 训练步数:1500 步
- 分辨率:2000x2000
- LoRA dim:128,alpha:64
- 优化器:AdamW8bit
- 精度:fp16
8. API 接口参考
8.1 换发色 API
| 项目 | 值 |
|---|---|
| URL | POST http://<IP>:8801/hairColor/v2 |
| 参数 | img(base64或URL), userId, rgb(如"120,60,30") |
| 返回 | JSON,含换色后的图片 URL 或 base64 |
8.2 换发型 API
| 项目 | 值 |
|---|---|
| URL | POST http://<IP>:8801/api/swapHair/v1 |
| 参数 | hair_id, task_id, is_hr, user_img_path(base64或URL), output_format(可选) |
| 返回 | JSON,含换发后的图片 URL 或 base64 |
8.3 训练 API
| 项目 | 值 |
|---|---|
| URL | POST http://<IP>:32678/api/hair/train |
| 参数 | task_id, hair_id, hair_material_dir(训练素材目录绝对路径) |
| 返回 | {"state": 0, "msg": "头发lora训练开始", "task_id": "..."} |
| 训练回调 | 训练完成/失败后 POST 到 http://127.0.0.1:8801/api/hair/trainCallBack |
8.4 推理 API
| 项目 | 值 |
|---|---|
| URL | POST http://<IP>:32678/api/hair/inference |
| 参数 | hair_id, inference_port, hair_material_dir, request_json(SD WebUI img2img 请求体) |
9. 停止与重启服务
9.1 停止所有服务
./stop_all_services.sh
输出:
=== 停止换发型服务 ===
✓ 已停止 hair_service_sd (端口 8801, PID xxxx)
✓ 已停止 webui (端口 57860, PID xxxx)
✓ 已停止 photo_service (端口 32678, PID xxxx)
9.2 重启服务
./stop_all_services.sh
./start_all_services.sh
9.3 手动停止单个服务
kill $(lsof -t -i:8801) # 停止换发服务
kill $(lsof -t -i:57860) # 停止 WebUI
kill $(lsof -t -i:32678) # 停止训练服务
10. 常见问题排查
10.1 setup.sh 报错 "conda 未安装"
# 确认 conda 已安装
which conda
# 如果没有,参考第2.2节安装 Miniconda
10.2 setup.sh 报错 "CONDA_BASE 不正确"
# 查找 conda 安装路径
which conda
# 或
conda info --base
# 设置后重新运行
export CONDA_BASE=$(conda info --base)
./setup.sh
10.3 py310 环境创建失败(网络问题)
py310 环境需要从 PyPI 下载 pip 包(flask、gevent、opencv-python 等)。如果网络不通:
# 使用国内 PyPI 镜像
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
# 手动创建
conda create -n py310 python=3.10 -y
conda activate py310
pip install flask==3.0.3 gevent==24.2.1 opencv-python==4.10.0.84 numpy==2.0.0 scipy==1.14.0 scikit-image==0.24.0 pillow==10.4.0 requests==2.32.3
10.4 start_all_services.sh 报 "端口已被占用"
# 先停止已有服务
./stop_all_services.sh
# 确认端口已释放
lsof -i :8801
lsof -i :57860
lsof -i :32678
# 重新启动
./start_all_services.sh
10.5 WebUI 启动失败
# 查看详细日志
tail -100 logs/webui.log
# 常见原因:
# 1. 模型文件缺失 → 检查 stable-diffusion-webui/models/Stable-diffusion/
# 2. 显存不足 → 检查 nvidia-smi
# 3. xformers 兼容性 → 尝试去掉 --xformers 参数
10.6 训练失败
# 查看训练日志
tail -100 logs/photo_service.log
# 常见原因:
# 1. 训练素材目录结构不对 → 参考 7.4 节
# 2. 底模缺失 → 检查 v1-5-pruned-emaonly.safetensors
# 3. .local 包损坏 → 重新从网盘下载 kohya_ss_home/.local/
# 4. kohya 环境问题 → 重新运行 setup.sh
10.7 GPU 不可用(CUDA error)
# 检查驱动
nvidia-smi
# 检查 CUDA
nvcc --version
# 测试 torch CUDA
CONDA_BASE=$(conda info --base)
PYTHONPATH=$PWD/kohya_ss_home/.local/lib/python3.10/site-packages \
$CONDA_BASE/envs/kohya/bin/python -c "import torch; print(torch.cuda.is_available())"
# 应输出 True
10.8 内存不足(OOM)
3090 有 24GB 显存。如果同时运行三个服务出现 OOM:
# 先停止不需要的服务
./stop_all_services.sh
# 只启动需要的服务(如只换发型)
$CONDA_BASE/envs/my_hair/bin/python hair_service_sd/run_copy_cost_colorb64.py &
$CONDA_BASE/envs/sdwebui/bin/python stable-diffusion-webui/webui.py --api --listen --xformers --port 57860 &
11. 架构说明
11.1 系统架构
用户请求
│
┌─────────────┼─────────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────────┐
│hair_service│ │photo_service│ │stable-diffusion│
│ _sd │ │ │ │ -webui │
│ (8801) │ │ (32678) │ │ (57860) │
└────┬─────┘ └─────┬─────┘ └───────┬────────┘
│ │ │
│ 训练子进程 │
│ │ │
│ ┌────────┴────────┐ │
│ │ kohya conda env │ │
│ │ + .local/ 包 │ │
│ │ accelerate │ │
│ │ train_network │ │
│ └─────────────────┘ │
│ │
▼ ▼
weights/ models/Stable-diffusion/
(换发模型) v1-5-pruned-emaonly.safetensors
models/Lora/ (228个LoRA)
11.2 数据流
换发型/换发色:
用户图片 → hair_service_sd(8801) → 调用 WebUI(57860) img2img → 返回结果
训练 LoRA:
训练素材 → photo_service(32678) → kohya环境+accelerate → train_network.py → 生成 LoRA
训练后推理:
用户图片 + LoRA → photo_service(32678) → 复制LoRA到webui/models/Lora/ → WebUI img2img → 返回
11.3 conda 环境说明
| 环境 | 用途 | 包含内容 | 大小 |
|---|---|---|---|
| my_hair | 换发算法服务 | torch, cv2, flask, 换发依赖 | 4.2G |
| sdwebui | SD WebUI | torch, xformers, webui 依赖 | 3.6G |
| py310 | 训练调度服务 | flask, gevent, cv2, numpy 2.0 | ~500M |
| kohya | LoRA 训练 | Python 3.10, numpy 1.24 | 84M |
| .local/ | 训练大包(非conda) | torch 2.0.1, accelerate, diffusers | 7.6G |
kohya 环境通过 PYTHONPATH 指向 .local/ 目录来复用训练大包,避免重复下载。
附录:完整部署速查
# 1. 安装 conda(如未安装)
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh -b -p $HOME/miniconda3
source ~/.bashrc
# 2. Clone 代码
cd ~
git clone <仓库地址> change_hair_3090
cd change_hair_3090
# 3. 下载网盘文件(合并到项目根目录)
# ... 手动下载 ...
# 4. 部署
chmod +x setup.sh start_all_services.sh stop_all_services.sh
./setup.sh
# 5. 启动
./start_all_services.sh
# 6. 验证
curl http://127.0.0.1:8801/
curl http://127.0.0.1:57860/sdapi/v1/options
curl http://127.0.0.1:32678/
# 7. 停止
./stop_all_services.sh