Files
cmbot/docs/旧ai穿搭项目.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

152 lines
11 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 生图」参考项目分析
> 来源:`D:\chengma\标题生成产品图工具源码`(同事编写)。本文用于为 cmbot 的「AI 穿搭」模块开发提供参考——分析它的功能与实现,提炼可复用点与注意事项。
>
> ⚠️ 说明:该项目实际名为**「标题生成产品图工具」**,不是字面上的「AI 穿搭」,但它是同事做过的**最接近的 AI 图像生成实现**(本地图 + 提示词 → 调中转 AI 图像 API → 生成电商主图),其 API 调用、传图、批量、并发重试等机制对「AI 穿搭」高度可复用。
---
## 1. 项目定位
一个 **PySide6 桌面批量生图工具**:读取 Excel 中的商品标题、货号、本地商品图路径,套用通用提示词,调用 **Nano Banana(Gemini 图像)/ GPT Image** 中转 API,为「台湾虾皮女装电商」生成 1:1 的 JPG 主图,并把结果实时写回 Excel。
面向非技术员工:一键启动、一键打包、离线运行、配置可迁移。
## 2. 技术栈与依赖
- **GUI**:PySide6(`requirements.txt`:`PySide6>=6.6,<7`)。
- **Excel**:`openpyxl`(读写 `.xlsx`,实时写回)。
- **图像**:`Pillow`(校验、压缩到 ≤2MB、转 JPG)。
- **HTTP**:`requests` + `urllib3<2`。
- **并发**:标准库 `concurrent.futures.ThreadPoolExecutor` + `threading`。
- **运行/打包**:`bootstrap.py` 自举 + `offline_runtime/windows-x64`(内置 `python.exe` + 预下载 wheels),`.bat` 一键启动/打包。
代码组织:**几乎全部逻辑集中在单文件 `app/main.py`(约 1643 行)**,GUI 与业务逻辑混在一起(与 cmbot 的 app/core/services 分层不同)。
## 3. 目录结构
```
标题生成产品图工具源码/
app/main.py # 全部逻辑:配置/Excel/API/并发/GUI
bootstrap.py # 启动自举:建 venv 或用离线 runtime,装依赖,起 main
api_config.json # 多模型 API 配置(含明文 api_key)
settings.json # 上次界面设置(Excel/输出/并发/间隔/分辨率/质量…)
prompt.txt # 通用话术(提示词模板,含 {title} {product_id} 占位符)
requirements.txt
offline_runtime/windows-x64/ # 内置 python + wheels(员工免装 Python)
runtime/ # 运行期 venv、日志、失败记录、requirements_state
logs/ # 带时间戳的运行日志(保留最近 20 个)
图片/ 输出图片/ # 示例输入/输出
标题生成产品图.xlsx # 示例 Excel
*.bat # win 一键启动/打包
需求规格说明.md 需求梳理草稿.md README_使用说明.md
```
## 4. 功能概览(按需求规格)
- Excel 批量驱动:A 标题 / B 货号 / C 本地图路径 / D 结果图路径(写回) / E 状态(完成/失败,写回) / F 失败原因(写回)。
- 每处理一行**实时保存 Excel**,降低中途崩溃丢结果的风险;自动跳过 E=「完成」的行;是否重试 E=「失败」的行由界面复选框控制。
- 通用话术 `prompt.txt` 可在界面查看/编辑/保存,支持插入 `{title}` `{product_id}` 占位符,提供「最终提示词预览」。
- 图片作为**图像输入**随请求发送(不是文本占位符)。
- 输出 JPG,1:1,≤2MB,三档质量(小文件 75 / 均衡 85 / 高清 92);默认名 `货号.jpg`,重名自动 `_1`/`_2`,非法字符替换为 `_`。
- 并发 / 新请求间隔 / 单任务冷却 / 失败重试次数 / 分辨率(512/1K/2K/4K)/ JPG 质量,均可在界面设置并存 `settings.json`。
- 温和停止(不启新任务、已发请求收尾)、实时日志、进度统计(完成/失败/跳过)、结束摘要弹窗、导出失败清单。
## 5. 核心实现要点
### 5.1 多模型 API 抽象(最值得借鉴)
`api_config.json` 支持**多个模型**,每个含 `url / model / api_key / api_type / timeout_seconds / connect_timeout_seconds / extra_body`,界面记住 `last_selected_model`。当前预置两个:
- `gpt_image_2` → `.../v1/images/edits`,`api_type=images_edits`
- `nano_banana_2` → `.../v1/chat/completions`,`model=gemini-3.1-flash-image-preview`,`api_type=auto`
`ImageApiClient.generate()` 根据 `api_type`(`detect_api_type` 可从 URL 自动判断:`auto/chat/gemini/images/images_edits`)构造**四种请求格式**:
- **chat(OpenAI 兼容 `/v1/chat/completions`)**:
```json
{"model": "...", "messages": [{"role":"user","content":[
{"type":"text","text": prompt},
{"type":"image_url","image_url":{"url":"data:image/jpeg;base64,..."}}]}], "stream": false}
```
- **gemini(`generateContent`)**:`contents[].parts` = `{text}` + `{inlineData:{mimeType,data(base64)}}`,`generationConfig.responseModalities=["TEXT","IMAGE"]`。
- **images**:`{model, prompt, image_urls:[data_url], aspect_ratio:"1:1", resolution, n:1}`。
- **images_edits(multipart)**:`data={model,prompt,n,size}` + `files={"image": (name, handle, mime)}`,`Authorization: Bearer <key>`。
`normalize_api_url()` 把 URL 补全到正确端点(`/v1/chat/completions`、`/v1/images/edits` 等)。`extra_body` 可合并进 payload,便于适配不同接口。
### 5.2 传图与响应解析
- **传图**:`image_to_data_url()` 把本地图读成 `data:<mime>;base64,<...>` 的 data-url(chat/gemini/images 用),或 multipart 直接传文件(images_edits 用)。
- **取图**:`extract_image_from_response()` 递归遍历 JSON(`walk_json_values`),从多种字段里找图——`image_base64/base64/b64_json/inlineData.data`、或 `data:image/...;base64,` 内联、或图片 URL(再用 session 下载)。对中转 API 返回结构差异做了较强兼容。
- **保存**:`save_jpg_under_limit()` 用 Pillow 转 JPG、`ImageOps` 处理方向,循环降质量/尺寸直到 ≤2MB。
### 5.3 并发、限速、重试、超时
- `BatchWorker.run()` 用 `ThreadPoolExecutor(max_workers=concurrency)` 调度行任务。
- `RateLimiter(interval)`:保证任意两次请求开始间隔 ≥ 新请求间隔。
- `process_one()`:每行最多「首次 + retry_count 次」尝试;`retry_delay_seconds(error, attempt)` 对限流/429 用**短阶梯等待**,普通错误短等待,避免看起来卡死;任务间 `task_cooldown` 冷却。
- `call_generate_with_heartbeat()`:把单次请求放进子线程,主线程每秒检查,**等待超过 30 秒持续打「已等待 N 秒」心跳日志**;超时按分辨率动态决定(512=180s/1K=240s/2K=360s/4K=600s,可被 `timeout_seconds` 覆盖)。
- **温和停止**:`stop_event`(`threading.Event`)置位后不再提交新任务,已发请求等其完成再收尾。
### 5.4 Excel 写回与失败清单
- `check_excel_writable()` 开始前检测 Excel 是否被占用。
- 每行成功 → 写 D(结果路径)/E=完成;失败 → E=失败/F=原因;**每行处理完即保存**。
- `runtime/failure_records.json` 记录失败行;「导出失败清单」只导失败行 + 失败时间 + 重试次数。
### 5.5 配置、日志、设置
- `settings.json` 持久化界面设置(Excel/输出路径、并发、间隔、冷却、重试、分辨率、质量、是否重试失败行)。
- `logs/` 带时间戳日志,`cleanup_logs()` 只保留最近 20 个;界面实时日志用 Qt 信号 `log = Signal(str)`。
- `api_config_errors()` 校验缺失字段:启动时轻提示、点开始时严格阻止。
### 5.6 GUI 与线程模型
- `MainWindow(QMainWindow)` 构建界面;后台用 `QThread` + `BatchWorker(QObject)`,信号 `log / progress(done,total,success,failed,skipped) / finished(summary)` 回主线程更新。
- 这套「QThread + Worker(QObject) + 信号回主线程」与 cmbot 现有更新检查/导出的后台线程思路一致。
### 5.7 启动与离线打包
- `bootstrap.py`:优先用 `offline_runtime/windows-x64/python/python.exe` + 预置 wheels 建 venv 装依赖(员工电脑免装 Python),再启动 `app/main.py`;记录 `runtime/requirements_state.json` 避免重复装。
- `.bat`(`win一键启动.bat` / `启动软件.bat` / `start_windows.bat`)调 bootstrap。
## 6. 对 cmbot「AI 穿搭」模块的借鉴点
「AI 穿搭」预期是:输入衣服图 → 调 AI 图像 API → 生成模特上身/穿搭效果图。与本项目「本地图 + 提示词 → 生成主图」**核心相同**,可直接借鉴:
- ✅ **API 客户端抽象**(多模型、`api_type` 多格式、URL 归一化、`extra_body`)——几乎可整体移植成 cmbot 的 `services/ai_image_service.py`。
- ✅ **传图方式**(base64 data-url / multipart)与**响应取图**(递归找 base64/URL、下载)的兼容写法。
- ✅ **提示词模板 + 占位符 + 预览**(cmbot 可换成衣服相关占位符,如 `{garment}` 或风格参数)。
- ✅ **批量 + 并发 + 限速 + 阶梯重试 + 心跳超时**这套稳态调度(中转 API 易 429)。
- ✅ **温和停止、实时日志、进度统计、失败清单**的交互范式。
- ✅ **JPG 压缩到限值**的输出处理。
与 cmbot 的差异(落地时要调整):
- **数据源仍用 Excel(已确认不变)**:cmbot 的 AI 穿搭把 Excel 当作 I/O 适配边界——读行转成内部模型 `OutfitTask`、生成后把新图路径写回 Excel(D/E/F 列),核心对内部模型工作、与数据源解耦(将来再加文件夹/队列输入也不必改核心)。设计见 `docs/11-ai-outfit.md`。
- cmbot 走 **app/core/services 分层 + 单测**;本项目是单文件混排,移植时应拆进 `services`(API/网络/Excel)与 `core`(无 GUI 逻辑),便于测试。
- cmbot 已有数据目录(`~/.cmbot`)、配置(`config_service`)、日志、打包/更新体系,**不需要**照搬本项目的 bootstrap/offline_runtime/.bat 那一套。
- 注意 **Python 3.7 兼容**:旧项目用了 `dict[str, Any]` 等 PEP 585 写法,移植到 cmbot(Python 3.7.9)需 `from __future__ import annotations` 或改 `typing.Dict`。
## 7. 注意事项与风险
- 🔒 **`api_config.json` 含明文 API key**(vectorengine.ai 中转)。本文已脱敏,**切勿把真实 key 提交到仓库或外泄**;cmbot 接入时应像更新源凭据那样,放用户数据目录、不入库。
- 中转 API 稳定性未知,**会出现 429 上游繁忙**——并发默认 1,阶梯重试,必要时排队。
- 接口返回结构不统一,取图逻辑做了较强兼容,移植时保留这套「递归找图」的鲁棒性。
- 2K/4K 更慢更贵,界面有二次确认;cmbot 接入时也应提示成本/耗时。
- 该项目仅在「标题→主图」场景验证过,「穿搭」提示词与上身效果需另行调试。
## 8. 关键文件清单(移植时重点看)
| 文件 / 函数 | 作用 |
|---|---|
| `app/main.py` `ImageApiClient.generate/build_payload/build_multipart_fields` | API 请求构造(四种格式)⭐ |
| `app/main.py` `extract_image_from_response/walk_json_values/decode_image_data_url` | 响应取图(鲁棒)⭐ |
| `app/main.py` `image_to_data_url/save_jpg_under_limit` | 传图 / JPG 压缩 |
| `app/main.py` `BatchWorker.run/process_one/call_generate_with_heartbeat/RateLimiter` | 并发/限速/重试/心跳 ⭐ |
| `app/main.py` `detect_api_type/normalize_api_url/api_config_errors` | 多接口适配与校验 |
| `api_config.json` / `settings.json` / `prompt.txt` | 配置与提示词模板 |
| `bootstrap.py` + `offline_runtime/` | 离线运行/打包(cmbot 不需要照搬) |
| `需求规格说明.md` | 完整功能需求(最权威) |