Files
cmbot/docs/11-ai-outfit.md
T
adminandClaude Opus 4.8 c82f870910 docs: add AI outfit module design (docs/11-ai-outfit.md)
Design for the "2 AI 穿搭" tab: Excel as the (fixed) data source → convert rows
to OutfitTask → garment image + prompt → AI image API → person-wearing-clothes
JPG → write result path back to Excel. Ports the old project's API client /
batch / retry into cmbot's app/core/services layering, reusing config/log/
~/.cmbot/output. Also fixes the 旧ai穿搭项目.md §6 recommendation (keep Excel).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 16:30:26 +08:00

183 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AI 穿搭模块设计
## 1. 文档定位
本文档定义 cmbot「2 AI 穿搭」页签的设计。它是一项独立能力,按 `docs/09` 第 262 行「新能力单独成文」要求成文,不混入印花合成相关文档。
参考来源:同事旧项目「标题生成产品图工具」的分析见 `docs/旧ai穿搭项目.md`。本模块把该项目验证过的「本地图 + 提示词 → 调 AI 图像 API → 写回 Excel」机制,移植进 cmbot 的分层架构(`app` / `core` / `services`)。
一句话目标:**以 Excel 为数据源,按行读取「衣服图 + 标题/货号」,套提示词调 AI 图像 API 生成「人物穿着该衣服」的效果图,保存 JPG 并把结果路径写回 Excel。**
## 2. 目标与非目标
### 2.1 目标
- Excel 批量驱动:逐行读取标题、货号、衣服图路径,生成后把结果写回 Excel(与旧项目列约定一致)。
- AI 生成:衣服图作为图像输入 + 提示词(可插标题/货号占位符)→ 生成人物上身/穿搭效果图,保留款式、版型、颜色、印花。
- 复用 cmbot 现有设施:配置(`config_service` / `~/.cmbot`)、日志、输出目录、后台线程模式、打包/更新,不重造。
- 稳态批量:并发、限速、阶梯重试、温和停止、实时日志、进度与失败清单。
- 分层可测:AI 调用与 Excel 适配放 `services`,无 GUI 逻辑放 `core`,关键逻辑有单测。
### 2.2 非目标
- 不改变数据源形态:**输入固定为 Excel**(不在本期改为文件夹/队列;但核心对内部模型工作,将来加别的输入源不必改核心)。
- 不做模特/姿态/背景的精细可视化编辑(由提示词控制,不做画布微调)。
- 不内置 AI 模型,依赖外部中转 API。
- 不照搬旧项目的 bootstrap / offline_runtime / .bat(cmbot 已有自己的打包与更新体系)。
## 3. 总体架构
把 Excel 当作 **I/O 适配边界**,中间用 cmbot 内部数据模型,核心 AI 逻辑与数据源解耦:
```
Excel(数据源,固定)
│ services/excel_service:读行 → List[OutfitTask](转成内部模型)
▼
core/ai_outfit + services/ai_image_service:
衣服图 + 提示词 → 调 AI 图像 API → 人物上身图(JPG)
│ 复用:并发/日志/配置/进度/~/.cmbot
▼
services/excel_service:把结果写回 Excel(D 新图路径 / E 状态 / F 原因)
```
分层落点:
- `core/models.py`:新增 `OutfitTask` / `OutfitResult`(纯数据,无 PySide6)。
- `services/excel_service.py`:Excel 读取、写回、占用检测、跳过/重试判断。
- `services/ai_image_service.py`:移植旧项目 `ImageApiClient`(多模型、多请求格式、传图、取图、重试、超时)。
- `core/ai_outfit.py`(或 service 内):单行生成的纯逻辑编排(提示词渲染、调用、保存、产出结果),可单测。
- `app/widgets/ai_outfit_panel.py` + 主窗口「2 AI 穿搭」页签:界面与后台线程(`QThread` + `Worker(QObject)` + 信号)。
## 4. Excel 适配(数据源)
沿用旧项目列约定(固定,先不做可配置):
| 列 | 含义 | 读/写 |
|---|---|---|
| A | 标题 | 读 |
| B | 货号(商品 ID) | 读 |
| C | 衣服图路径(本机绝对路径) | 读 |
| D | 生成结果图片路径 | 写回 |
| E | 完成状态:`完成` / `失败`(空=未处理) | 写回 |
| F | 失败原因(仅人工查看) | 写回 |
规则:
- 默认读第一个工作表,第 1 行表头,从第 2 行开始。
- **跳过 E=`完成` 的行**;是否处理 E=`失败` 的行由界面「重试失败行」决定(勾选则处理「空白 + 失败」,否则只处理「空白」)。
- 标题/货号/衣服图任一为空 → 跳过该行,不写状态、不中断。
- 字段按原样读取,不清理空格、不回写清理值。
- **开始前检测 Excel 是否被占用**(Office 打开会锁文件,openpyxl 无法写回)→ 提示「请关闭 Excel 后再开始」。
- **每处理完一行即保存 Excel**(降低崩溃丢结果风险)。
- 成功 → D=新图绝对路径、E=`完成`;失败 → E=`失败`、F=原因(同步写日志)。
## 5. 内部数据模型
`core/models.py` 新增(纯 dataclass,Python 3.7 兼容,不依赖 PySide6):
- `OutfitTask`:`row_index:int`、`title:str`、`product_id:str`、`garment_path:str`、`status:str`(待处理/完成/失败)。
- `OutfitResult`:`task`、`success:bool`、`output_path:str`、`error:str`、`attempts:int`。
Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只认 `OutfitTask`,因此将来换数据源只需另写适配器。
## 6. AI 图像服务(移植旧项目)
`services/ai_image_service.py` 移植旧项目 `ImageApiClient`,要点(详见 `docs/旧ai穿搭项目.md` §5.1/5.2):
- **多模型配置**:`url / model / api_key / api_type / timeout_seconds / connect_timeout_seconds / extra_body`,记住上次所选模型。
- **多请求格式**(按 `api_type`:`auto/chat/gemini/images/images_edits`):
- chat(OpenAI 兼容 `/v1/chat/completions`):`messages[].content` = `{type:text}` + `{type:image_url, image_url:{url:data_url}}`。
- gemini(`generateContent`):`contents[].parts` = `{text}` + `{inlineData:{mimeType,data}}`。
- images:`{model,prompt,image_urls:[data_url],aspect_ratio,resolution,n}`。
- images_edits:multipart `data` + `files={"image":...}`。
- **传图**:本地衣服图 → `data:<mime>;base64,...`(data-url)或 multipart 文件。
- **取图**:递归遍历响应 JSON 找 base64 / data-url / 图片 URL(再下载),对中转 API 结构差异强兼容。
- **URL 归一化**、`extra_body` 合并、字段校验(缺 `url/model/api_key` 时阻止开始)。
> Python 3.7 注意:旧项目用了 `dict[str, Any]` 等 PEP 585 写法,移植时需 `from __future__ import annotations` 或改用 `typing.Dict`,以兼容 cmbot 的 Python 3.7.9。
## 7. 提示词
- 提示词模板存 `~/.cmbot/config/outfit_prompt.txt`,界面可查看/编辑/保存;点「开始」前自动保存一次。
- 占位符:`{title}`(标题)、`{product_id}`(货号);界面提供「插入占位符」按钮与「最终提示词预览」。
- 缺标题占位符时开始前弹窗询问是否继续。
- 默认话术方向(穿搭/上身,区别于旧项目的主图场景,需另调):人物上身实穿、保留衣服款式/版型/颜色/印花、合适身材与场景、电商可用、默认纯净不加促销牛皮癣。
## 8. 并发、限速、重试、停止
复用旧项目策略(`docs/旧ai穿搭项目.md` §5.3):
- `ThreadPoolExecutor(max_workers=并发数)` 调度行任务;`RateLimiter(新请求间隔)` 限制请求开始间隔;任务间 `单任务冷却`。
- 每行最多「首次 + 重试次数」尝试;限流/429 用短阶梯等待,普通错误短等待。
- 单次请求放子线程 + 主线程秒级检查,**等待 >30 秒持续打心跳日志**;超时按分辨率动态决定(512/1K/2K/4K → 180/240/360/600 秒,可被 `timeout_seconds` 覆盖)。
- **温和停止**:置位停止后不再提交新任务,已发请求收尾后正常写回。
## 9. 输出
- 格式 JPG,1:1,压缩到 ≤2MB;质量三档(小文件 75 / 均衡 85 / 高清 92)。
- 默认输出目录沿用 cmbot `get_output_dir()`(程序旁的「合并后的图片」,见 `docs/10` §5),界面可改。
- 命名:`货号.jpg`,重名自动 `_1`/`_2`,非法字符替换为 `_`(不改 Excel 原始货号)。
- 成功后把**实际新图绝对路径**写回 Excel D 列。
## 10. 界面(「2 AI 穿搭」页签)
把主窗口当前禁用的「2 AI 穿搭」页签启用,做成独立工作页(与「1 添加印花」并列、互不干扰)。控件:
- 选择 Excel 文件、选择输出目录(记住上次,存 `app_config.json`)。
- 模型下拉(来自 AI 模型配置)。
- 通用话术编辑 + 保存 + 插入占位符 + 最终提示词预览。
- 设置:重试失败行、并发数、新请求间隔、单任务冷却、重试次数、分辨率、JPG 质量。
- 开始生成 / 停止生成;实时日志;进度与统计(完成/失败/跳过);结束摘要弹窗;导出失败清单。
- 后台用 `QThread` + `Worker(QObject)` + 信号回主线程(与 cmbot 更新检查/导出一致)。
> 页签内容切换:当前页签栏不切换内容面板(见 `docs/07` §4.2)。启用 AI 穿搭需要为页签接一个 `QStackedWidget`(「1 添加印花」=现有工作区,「2 AI 穿搭」=本面板);这部分在实现阶段一并补。
## 11. 配置与数据位置
遵循 cmbot「配置集中、放数据目录、凭据不入库」约定:
- **AI 模型与密钥** → `~/.cmbot/config/ai_models.json`(管理员预置或界面填写,**含明文 key、不提交 git**;与更新源凭据同等对待,见 `docs/10` §14)。
- **提示词** → `~/.cmbot/config/outfit_prompt.txt`。
- **批量设置 + 上次 Excel/输出路径** → 并入 `app_config.json`(`config_service` 集中读写,UI 不直接读写配置文件,遵守 `docs/04` 第 6 节 / `docs/05` 4.12)。
- 失败记录 / 日志沿用 `~/.cmbot/logs` 与现有日志服务。
## 12. 依赖与兼容
- 新增依赖:`requests`(HTTP)、`openpyxl`(Excel);`Pillow`、`PySide6` 已有。写入 `requirements.txt` 并锁版本(兼容 Python 3.7:`requests>=2.31,<3`、`openpyxl>=3.1,<4`、`urllib3<2`)。
- 所有新代码保持 **Python 3.7.9** 兼容(注意类型注解写法)。
- `docs/03-technical-stack.md` 增列上述依赖;`docs/02-prd.md`、`docs/07-ui-design.md` §4.2 加指针指向本文档。
## 13. 安全考量
- AI 中转 API key 为明文,仅放 `~/.cmbot`,**不入库、不随包分发到公网**;内部使用可接受(与更新凭据一致)。
- 中转 API 会 429 限流:并发默认 1,阶梯重试。
- 衣服图为本机路径;不存在/打不开/非图片 → 该行失败并记录,继续下一行。
## 14. 实现阶段建议
分步落地,每步可独立验证:
1. **核心与服务(无 GUI,可测)**:`core.models.OutfitTask/OutfitResult`、`services/excel_service.py`(读/写回/占用检测)、`services/ai_image_service.py`(移植 ImageApiClient)、`core/ai_outfit.py`(单行编排)+ 单测(Excel 读写、提示词渲染、取图、命名去重;API 用 mock)。
2. **批量编排**:并发/限速/重试/停止的 `Worker`,纯逻辑部分尽量可测。
3. **UI 页签**:页签 `QStackedWidget` + `ai_outfit_panel`,接线后台线程、日志、进度、失败清单。
4. **配置与提示词**:`ai_models.json` / `outfit_prompt.txt` / `app_config.json` 接入,集中读写。
5. **真机联调**:用真实中转 API + 小批量 Excel 跑通端到端,调穿搭提示词。
## 15. 暂不做
- 文件夹/队列作为输入源(保留扩展位,本期不做)。
- 模特/姿态/背景的可视化精细编辑。
- 多 Excel / 多工作表批处理、列映射可配置化。
- 生成结果的应用内预览画廊(先以写回 Excel + 输出目录为准)。
## 16. 验收要点
- 选 Excel + 输出目录并记住上次;能读/存提示词。
- 能校验 AI 配置缺失;缺 `url/model/api_key` 时阻止开始并提示。
- 按行处理:跳过「完成」、按设置重试「失败」、空字段行安全跳过。
- 衣服图 + 提示词 → 生成人物上身 JPG(1:1、≤2MB、命名去重)。
- 每行实时写回 D/E/F 并保存 Excel;Excel 被占用时明确提示。
- 并发/限速/重试/温和停止生效;实时日志 + 进度 + 结束摘要 + 失败清单导出。
- 日志写入 `~/.cmbot/logs`;AI 密钥不入库。
- 核心逻辑单测通过、不依赖 GUI、Python 3.7 可运行。