49 lines
4.9 KiB
Markdown
49 lines
4.9 KiB
Markdown
# 验收报告 · T-301 ~ T-303(含 T-302p + 采集关页修复)· Phase 3 AI 生成
|
||||
|
|
|
|||
|
|
- 日期:2026-06-27
|
|||
|
|
- 范围:Codex 完成的 Phase 3——T-301 `app/ai.py` 生成接口、T-302 Tab② 左右布局、T-302p `app/prompts.py` 提示词管理、T-303 开始生成(两段并发)+停止+进度;附带修复 e6d7de3(采集后关闭自动新建商品页)
|
|||
|
|
- 评审方式:编译检查 + 单元测试(本机实跑 ai/prompts)+ 逐模块源码阅读 + 对照 `docs/06-tasks.md` 验收要点
|
|||
|
|
- 结论:**通过,质量偏上。AI 接口健壮(脱敏/重试/多 API 形态/两段并发/失败隔离),提示词管理有完整防穿越校验。**
|
|||
|
|
|
|||
|
|
## 一、验证方法与结果
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
python3 -m unittest discover -s tests -p "test_ai.py" # Ran 6 tests, OK(本机实跑)
|
|||
|
|
python3 -m unittest discover -s tests -p "test_prompts.py" # Ran 3 tests, OK(本机实跑)
|
|||
|
|
python3 -m unittest discover -s tests # Ran 53 tests, OK (skipped=2)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- 本评审在 WSL 沙箱进行:临时安装 openpyxl + Pillow 后,**ai/prompts 测试本机实跑通过**(含重试、脱敏、jpeg 分辨率/质量、两段并发持久化、失败隔离、停止保持 collected)。
|
|||
|
|
- 仅 PySide6 的 `test_gui`/`test_workers` 在本机 skip;其“绿”以 Codex 在 Windows(`python` = PySide6 6.5.3)的运行为准。
|
|||
|
|
|
|||
|
|
## 二、逐任务核对
|
|||
|
|
|
|||
|
|
| 任务 | 结论 | 关键核对 |
|
|||
|
|
| --- | --- | --- |
|
|||
|
|
| T-301 `ai.py` | ✅ | `gen_title`/`gen_cover` 经 `get_model` 读 `config/ai_models.json` 明文 Key;角色模型校验类别/启用/必填字段;`gen_cover` 支持 `resolution`(512/1k/2k/4k)+`jpg_quality`+Pillow 存盘;`_call_with_retry` 退避重试;错误中文化;`_redact` 把 api_key 从异常/HTTP body 抹成 `***`;兼容两种图像 API(`images_edits` multipart / chat `image_url`),图片提取覆盖 b64/data-url/远程 url 下载 |
|
|||
|
|
| T-302 Tab② 布局 | ✅ | 左提示词(标题/封面多行)、右 批次/店铺/状态 三筛选 + 任务列表(店铺/商品id/旧/新标题/状态);筛选变更即刷新 |
|
|||
|
|
| T-302p `prompts.py`+管理 | ✅ | 标题 `title_prompt.txt` 存/启动回显;封面多模板下拉 + 新建/保存/另存为/重命名/删除(存 `prompts/cover/`,模板名做非法字符 + `.`/`..` + 路径穿越校验、重名保护);「插入标题」插 `{新标题}`;「预览」走 `render_prompt`;`render_prompt` 已接入 `generate_batch` 封面渲染 |
|
|||
|
|
| T-303 开始生成 | ✅ | 单「开始生成」+「停止」+进度 `标题/封面/失败`;`generate_batch` 先 `title_concurrency` 并发标题、再 `image_concurrency` 并发封面;每条封面成功即 `set_generated` 立即写库;停止取消未开始项(ThreadPoolExecutor 语义,符合“可取消未开始项”);双击弹窗左右对照旧/新封面 |
|
|||
|
|
| 修复 e6d7de3 | ✅ | 区分“断开 CDP”与“关闭 target”,采集只关本轮自动新建的商品页,保留用户原有 tab。良好卫生修复 |
|
|||
|
|
|
|||
|
|
## 三、设计上做得好
|
|||
|
|
|
|||
|
|
1. **失败隔离**:某条标题失败→该条不进封面阶段、`mark_failed("generate")` 后其余继续;`summary.ok=False` 但不阻塞(test 实测覆盖)。
|
|||
|
|
2. **脱敏贯穿**:错误信息、HTTP 错误体、URLError 全走 `_redact`,不泄 Key。
|
|||
|
|
3. **两段式并发**严格按文档:标题全部完成→只对成功标题的任务并发生成封面。
|
|||
|
|
|
|||
|
|
## 四、小问题(不影响验收)
|
|||
|
|
|
|||
|
|
1. **标题提示词不做变量替换**:`generate_batch` 把 `title_prompt` 原样喂给 `gen_title`,只有封面提示词走 `render_prompt`。与设计自洽(新标题此时尚不存在,旧标题由 user 消息单独传入),但若用户在标题提示词里写 `{旧标题}` 不会被替换。建议在 Tab② 标题框旁注明“标题提示词不支持变量”,或也接入 `render_prompt`(仅旧标题/商品id/店铺)。
|
|||
|
|
2. `_call_once` 用单一 `timeout=max(connect, read)`(urllib 不分连接/读超时),取最大值合理,但 `connect_timeout_seconds` 语义偏弱。可接受。
|
|||
|
|
3. `_looks_base64` 是启发式判断,已先用 `data:`/`http` 前缀挡掉,误判风险低。
|
|||
|
|
|
|||
|
|
## 五、待办 / 边界
|
|||
|
|
|
|||
|
|
- ⚠️ `gen_title`/`gen_cover` 对真实 AI 服务商仍是 mock(urllib 全程打桩),未真连过一次;`config/ai_models.json` 里的真实 Key 仅本地、gitignore。
|
|||
|
|
- **建议**:进 Phase 4(③ 更新 shopee)前,做一次端到端真机冒烟——账号④登录 → ① 真机采集 1~2 条出图 → ② 用真实模型各生成 1 条标题 + 1 张封面 → 看 `images/<slug>/<id>_new.jpg` 落盘且分辨率/质量正确。这同时验掉之前累计的 CDP + AI 两条未冒烟链路。
|
|||
|
|
|
|||
|
|
## 六、总评
|
|||
|
|
|
|||
|
|
合格偏上的工程交付:ai.py 健壮(脱敏/重试/多 API 形态/两段并发/失败隔离)且本机实测通过,prompts 文件操作有完整防穿越校验,Tab② 提示词管理与生成闭环按文档落地。可推进 Phase 4(T-401 Tab③ 列表 + 筛选 + 开始更新确认弹窗)。
|