Files
cmshoppe/docs/tasks/T-645.md
T

127 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.
---
id: T-645
title: 商品套图AI帮写接入cmhub图片理解
phase: 7
deps: [T-637]
status: DONE
created: 2026-07-17
---
## 问题 / 背景
⑥「商品套图」的「AI 帮写」当前虽然要求用户先添加至少一张商品原图,但实际只把商品 ID、平台、站点、语言和已有卖点文本传给 `ai.gen_title()`。它调用的是 cmhub 生文别名和标题接口,**不会读取商品图片内容**,因此生成结果无法根据款式、颜色、图中文字和可见细节补全卖点。
cmhub 已提供独立的图片理解能力:
- 能力别名:`vision-standard`;
- 路由:`POST /api/v1/analyze/images`;
- 输入:一张或多张有序本地图片的 base64 数据;
- 输出:完整文字;
- 当前网关实测:单张商品主图可在约44秒内成功返回商品品类、颜色、款式、可见卖点和图中文字,单次扣1点。
用户决定将⑥「AI 帮写」改为以 `vision-standard` 理解当前商品原图,再生成可直接编辑的「商品卖点与要求」。②「AI生成」的标题生成仍使用 `title-standard`,商品套图正式生图仍使用 `image-hd` 或⑤设置中的生图别名,三类能力不得混用。
## 方案
### 1. 新增独立的图片理解客户端
修改 `app/ai.py`,新增供⑥使用的公开 helper,例如 `analyze_product_images()`:
- 仅在 `backend=cmhub` 时调用 cmhub 图片理解接口;不把 `vision-standard` 塞进现有 `gen_title()` 或 `/generate/title` 路径;
- 使用 `POST /api/v1/analyze/images`,请求体固定包含:
- `prompt`:要求模型用当前任务的输出语言,基于图片提炼可用于商品套图生图的商品名称/品类、颜色、款式、可见细节、卖点、目标人群、使用场景和禁用/避免虚构要求;
- `model`:⑤设置保存的 `ai.cmhub.vision_alias`;
- `images`:按用户原图 `source_order` 排序的本地 `image_base64` 数据;
- 可选低随机度参数,确保卖点输出稳定。
- 成功只返回文本及经过白名单筛选的元数据(别名、扣点、余额、调用 ID);不得返回 API Key、完整请求体、base64 图片、上游 URL 或 Provider 原始响应。
- 复用既有 cmhub Base URL 规整、Bearer Key、禁用系统代理、连接超时、结构化中文错误和脱敏日志机制;新增 `vision` 操作时,`_cmhub_runtime()` 必须明确映射 `vision_alias`,不能把未知操作静默落到 `image_alias`。
- 图片理解读取等待单独定义有界超时,默认不少于实测44秒并建议120秒;连接超时继续复用⑤设置的 `connect_timeout`。一次 HTTP 读超时后不自动盲重试,避免用户不确定是否已扣点;由用户再次点击重新发起。
- 客户端在请求前校验:至少一张本地可用图片、最多8张、单张不超过10MiB、总计不超过32MiB。超过上限时在本地用中文提示,不能先发请求再依赖服务端拒绝。
### 2. ⑥「AI 帮写」改为真实读取商品原图
修改 `app/gui/tabs/product_suite.py` 和 `app/gui/workers.py`:
- `start_ai_write()` 从当前任务可用原图中按 `source_order` 取前8张,传给 `ProductSuiteAiWriteWorker`;原图超过8张时状态提示明确「已使用前8张商品原图进行理解」,不静默假装全部使用。
- 已有「商品卖点与要求」作为补充约束传给视觉提示词,不能被当作图片事实;模型返回内容必须以图片可见信息为主,避免在没有依据时虚构材质、尺寸、功能、认证、价格或物流承诺。
- `ProductSuiteAiWriteWorker` 调用新的图片理解 helper,成功后沿用现有“用户输入期间有修改则确认是否覆盖”的结果回填逻辑;用户始终可以继续手工编辑。
- 原图缺失、远程图尚未下载、超过本地大小上限、未配置视觉别名、点数不足、模型不支持视觉、接口超时或上游失败时,保持当前任务和用户已输入卖点不变,显示脱敏中文错误。
- 运行中保留既有「取消」入口和多任务不阻塞语义。取消只在请求前或请求返回后安全生效;不得强杀网络线程或误报“已取消且未扣点”。
- 成功状态展示中文摘要,例如「AI帮写完成:已理解3张商品原图,图片理解扣点1,当前余额231」,不展示接口路径、完整提示词、图片路径、API Key 或 Provider 信息。
### 3. ⑤设置新增“图片理解别名”
修改 `app/appconfig.py`、`app/gui/tabs/settings.py` 和 cmhub 模型发现逻辑:
- `ai.cmhub` 新增 `vision_alias`,新配置默认 `vision-standard`;旧配置缺失该字段时迁移为该默认值,已保存的用户值必须保留。
- ⑤设置在 cmhub 模型区域新增中文组件「图片理解别名」,与「生文别名」「生图别名」职责并列。
- 刷新模型时只列出 `operation_type=vision`、`requires_image=true` 且已定价的别名;保留当前保存但暂时不可用的值并显示明确中文状态,避免保存时无声丢失。
- 保存/生成前校验 `vision_alias`。缺失时提示「请到⑤设置配置图片理解别名」,不能退回 title 或 image 别名。
- ②标题生成继续只读 `title_alias`,封面和套图生成继续只读 `image_alias`;不要扩大⑤设置的 direct 兼容入口。
### 4. 计费、日志与异常语义
- 图片理解是一次独立 cmhub 调用,按 cmhub 返回的 `points_cost` / `points_balance` 显示;不把它计入②生文/生图进度,也不写入商品套图正式生成 job。
- 对网络读超时或客户端连接中断,状态文案必须表达“结果未确认,请先查看点数余额或稍后重试”,不得断言未扣点。
- 对 cmhub 已返回明确 `upstream_error`、`insufficient_points`、`model_not_allowed`、`no_pricing_rule` 等结构化错误,沿既有中文映射提示,不裸露英文技术信息。
- 诊断日志可记录耗时、图片张数、别名、扣点、余额和调用 ID;不得记录 base64、完整本地路径、图片 URL、API Key、完整提示词或上游原始响应。
### 5. 文档与手工验证
同步更新:
- `docs/04-architecture.md`:⑥AI帮写的视觉理解调用、最多8张本地原图、取消/超时语义和三别名职责;
- `docs/api.md`:客户端对 cmhub `/api/v1/analyze/images` 的请求/响应最小契约和脱敏边界;
- `docs/routes.md`:⑥AI帮写的用户路径、图片数量上限、余额/超时可见状态;
- `docs/cmhub-integration-design.md`:在现有标题/生图/模型发现契约外补充图片理解接口与 `vision_alias`。
手工使用当前测试主图验证:请求 `vision-standard` 应返回可读商品理解文本;确认结果不会覆盖用户在请求期间修改的卖点,且在无图、未配置、余额不足、超时和模型不可用时不丢原文本。
## 验收要点
- [ ] ⑥「AI 帮写」不再调用标题生成接口,而是用 `vision_alias` 调用图片理解接口。
- [ ] 默认/迁移后的 `vision_alias` 为 `vision-standard`;⑤可刷新和选择视觉能力别名。
- [ ] `vision_alias` 缺失、不可用或未定价时有明确中文提示,不回退到生文/生图别名。
- [ ] 1至8张可用本地原图按 `source_order` 发送,超过8张明确提示只使用前8张。
- [ ] 无本地可用原图、远程图未下载、单图/总大小超限时不发 cmhub 请求且保留用户原卖点。
- [ ] 返回文本能根据图片提炼商品事实,并保留用户已有要求作为补充约束;用户请求期间编辑文本时仍走确认覆盖。
- [ ] 成功显示图片张数、扣点和余额;日志、弹窗和状态栏不泄露图片 base64、路径、接口 URL、Key、完整提示词或 Provider 原始响应。
- [ ] 取消、超时和连接中断不强杀线程、不篡改原卖点、不谎称未扣点。
- [ ] ②AI生成标题、②生图、⑥正式生成套图、Shopee CDP/更新流程行为不回归。
## 测试
- `tests/test_ai.py`:
- 图片理解请求使用 `/api/v1/analyze/images`、`vision_alias`、有序 data URL 图片和受限超时;
- 成功响应文本/计费元数据映射;
- 缺少视觉别名、结构化错误、读超时不盲重试、图片数量/大小超限和日志脱敏。
- `tests/test_appconfig.py` / `tests/test_gui.py`:
- `vision_alias` 默认值、旧配置迁移、保存和模型发现只筛选已定价视觉别名。
- `tests/test_product_suite_gui.py` / `tests/test_workers.py`:
- AI帮写按原图顺序传入1至8张、超过8张提示、无图不启动 worker;
- 成功回填、用户编辑冲突确认、取消、错误和状态文案;
- 不调用 `ai.gen_title()`,不影响其他套图任务。
- 运行:
```bash
py -3.10 -m unittest tests.test_ai tests.test_appconfig tests.test_gui tests.test_product_suite_gui tests.test_workers
py -3.10 -m unittest discover -s tests
py -3.10 -m ruff check app tests main.py
py -3.10 -m compileall app main.py
git diff --check
```
## 边界(不改什么)
- 不将 `vision-standard` 伪装成标题或生图别名,不改 cmhub 服务端 API、计费规则、上游模型配置或点数余额。
- 不修改②AI生成的标题/封面调用链、批量进度、重试、SQLite 任务状态或 Excel 回写。
- 不修改⑥正式套图生图的 job、轮次、历史、终选或导出逻辑。
- 不修改Shopee页面采集、CDP、标题/封面更新或账号登录流程。
- 不保存API Key、base64图片、完整图片路径、Cookie、完整提示词或Provider原始响应到版本库、SQLite业务字段或用户可见日志。
## 执行记录
- 2026-07-17:根据真实 cmhub 网关验证创建任务。`vision-standard` 已出现在模型发现接口中,声明为已定价的独立 `vision` 能力;单张商品主图理解请求成功返回中文商品事实,耗时约44秒、扣1点。待按本任务接入桌面端代码。
- 2026-07-17:已实现 `ai.analyze_product_images()`,通过 `POST /api/v1/analyze/images` 使用独立 `vision_alias`,请求前校验 1 至 8 张本地原图、单图 10MiB、总计 32MiB,并以 120 秒读取等待和不自动重试处理结果未确认的超时。图片理解的文本与白名单计费元数据由商品套图 AI 帮写 worker 回填,保留已有的用户编辑冲突确认和协作取消语义。
- 2026-07-17:⑤设置已增加「图片理解别名」并按已定价、需要图片的 `vision` 模型筛选;旧配置自动补 `vision-standard`。已同步更新架构、API、路由及 cmhub 集成设计文档。验证通过:`py -3.10 -m unittest tests.test_ai tests.test_appconfig tests.test_gui tests.test_product_suite_gui tests.test_workers`(318 项)、`py -3.10 -m unittest discover -s tests`(564 项)、`py -3.10 -m ruff check app tests main.py`、`py -3.10 -m compileall app main.py`、`git diff --check`。