feat(ai-title): 标题生成读取超时改用 4K 档 600 秒 (§19.30)

标题是「一次请求·纯提示词·生成多条」,需经中转站转发 + 大模型排队 +
整段返回,比一张图更耗时。原借 1K 档 240 秒读取超时,慢/排队型模型常在
返回前 ReadTimeout。改为借 4K 档 600 秒(resolution_timeout 512/1K/2K/4K →
180/240/360/600s),仅改标题链路,不动 generate_texts 默认 1K;模型条目
timeout_seconds>0 仍优先覆盖。

- ai_title.py:加常量 _TITLE_TIMEOUT_RESOLUTION="4K",generate_titles
  显式传 resolution 借 600s
- docs/11 §17.2 补读取超时说明、新增 §17.8 决策
- tests/test_ai_title:断言以 resolution="4K" 调 generate_texts
- tasks.md:新增 §19.30;同时含 match_stamp §19.30–§19.34 任务段的移除
  (用户回退 match_stamp 功能,本提交仅移除其 tasks.md 段落)

验证:test_ai_title / test_ai_text_service + 全套 py37(232 测试)通过,
唯一失败为无关的 test_config_service packaging 模板;离屏冒烟确认读取超时
=600s、timeout_seconds>0 优先覆盖。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-04 15:09:46 +08:00
co-authored by Claude Opus 4.8
parent f6ee4b452a
commit bc40905b38
4 changed files with 42 additions and 76 deletions
+12 -75
View File
@@ -1542,87 +1542,24 @@
- [x] 测试:标题模型不出现在图片 AI 模型下拉;图片模型仍显示;标题生成仍能按 `title_model` 找到同名模型;只有标题模型时下拉为空/占位
- [x] 验证:`py_compile`、`test_ai_outfit_panel.py`、全套 `python -m unittest discover -s tests`、离屏启动 AI 穿搭页通过
### 19.30 独立脚本:合并图匹配印花清单 — `match_stamp.py`
背景:
需要一个独立脚本(不引用现有项目代码)按“方案2”生成匹配清单:例如合并图 `output\20260623_094529\TY037\1_TY037.png`,从文件名后缀提取 `TY037`,在印花文件夹 `D:\chengma\印花和底图\已处理印花\卡通71(66大码200斤 KEKE已上)\横1` 中匹配 `TY037.png`,输出 CSV 清单。
任务:
- [x] 新增 `match_stamp.py`,只使用 Python 标准库,不导入 `src/` 或项目服务代码
- [x] 脚本顶部提供 `OUTPUT_DIR` / `STAMP_DIR` / `REPORT_PATH`,默认生成 `match_stamp_report.csv`
- [x] 递归扫描合并图和印花图,按合并图文件名最后一个 `_` 后的编码匹配印花文件 stem
- [x] CSV 字段:`status` / `code` / `merged_image` / `stamp_image` / `merged_folder` / `message`,支持 `matched` / `missing` / `duplicate` / `bad_name`
- [x] 验证:`python -m py_compile match_stamp.py`;用示例目录生成系统临时 CSV,匹配 96 张、缺失 0、重复 0、坏名 0
### 19.31 合并图按图片内容匹配印花 — 需求与方案文档
背景:
§19.30 的 `match_stamp.py` 是按文件名后缀匹配,例如 `1_TY037.png -> TY037.png`。用户澄清真实需求是:给定一张衣服图片(可理解为合并后的图片)和一个印花目录,通过类似 OpenCV template matching 的图像内容匹配,找出衣服图中印花与目录内哪张印花最相似;先不保存 CSV,直接 `print` 结果。
任务:
- [x] 新增 `docs/12-stamp-template-matching.md`,单独记录需求、输入输出、方案比较、推荐方案和依赖
- [x] 明确推荐第一版:多尺度 `matchTemplate` + alpha mask + 边缘辅助分数,直接打印 Top N
- [x] 明确第三方库:最小 `opencv-python` + `numpy`,建议用 `Pillow` 处理 Windows 中文路径
- [x] 明确约束:独立脚本、不引用项目代码、不修改图片、第一版不写 CSV/Excel、不接入 GUI
- [x] 验证:文档格式检查通过
### 19.32 独立脚本:按图片内容匹配合并图印花 — `match_stamp.py`
### 19.30 标题生成读取超时改用 4K 档(240s→600s) — docs/11 §17.2 / §17.8
前置阅读:
- `docs/12-stamp-template-matching.md`
- `match_stamp.py`
- `docs/11-ai-outfit.md`(§17.2 文本服务、§17.8 决策)
- `src/core/ai_title.py`(`generate_titles` 调 `generate_texts`)
- `src/services/ai_text_service.py`(`generate_texts`/`generate_text` 的 `resolution` 形参、`_post` 的 `read_timeout` 取值)
- `src/services/ai_image_service.py`(`RESOLUTION_TIMEOUTS` / `resolution_timeout`)
- `tests/test_ai_title.py`、`tests/test_ai_text_service.py`
背景:
§19.31 已明确真实需求不是按 `1_TY037.png -> TY037.png` 的文件名规则匹配,而是给定一张衣服 / 合并图和一个印花目录,通过图像内容匹配找出最相似的印花。第一版继续保持为独立脚本,不接入 GUI,不写 CSV,直接打印结果。
标题是「一次请求、纯提示词、生成多条」(§17.7)。这次请求要经中转站转发 + 大模型排队 + 生成多条再整段返回,比一张图更耗时。原借 1K 档 240 秒读取超时,慢/排队型模型常在返回前 `ReadTimeout`。改为借 4K 档 600 秒(`resolution_timeout`:512/1K/2K/4K → 180/240/360/600 秒),只改标题链路,不动 `generate_texts` 默认 `1K`。
任务:
- [x] 将 `match_stamp.py` 从“递归扫描 output 并按文件名写 CSV”改为“单张合并图 + 印花目录内容匹配”
- [x] 使用 `Pillow` 读取图片以兼容 Windows 中文路径,再转为 `numpy` / OpenCV 数组
- [x] 遍历印花目录内 PNG/JPG/JPEG/WEBP 图片,对透明 PNG 使用 alpha mask 并裁剪透明边界
- [x] 使用多尺度模板匹配,主分数使用 RGB 彩色 `matchTemplate`,边缘图分数作为辅助
- [x] 输出最佳匹配和 Top N,包含综合分、模板分、边缘分、坐标、缩放比例和匹配尺寸
- [x] 找不到高可信结果时打印低分提示;不保存 CSV,不修改任何图片
- [x] 支持命令行覆盖 `--image`、`--stamp-dir`、`--top`
- [x] 验证:`python -m py_compile match_stamp.py` 通过;临时构造一张合并图和两个候选印花,Top 1 命中正确印花
### 19.33 合并图印花匹配:宽高不等比例变形方案文档
背景:
实际合成衣服和印花时,印花可能不按原始宽高比缩放。例如原始印花 `1000x1000`,合成到衣服上时被设置为 `1000x800`。这种非等比例变形不是单一 `scale` 能覆盖的,当前脚本只做等比例多尺度搜索时匹配稳定性会下降。
任务:
- [x] 更新 `docs/12-stamp-template-matching.md`,明确 `matchTemplate` 对宽高不等比例变形敏感
- [x] 将推荐方案扩展为“多尺度模板匹配 + 有限宽高比变形 + alpha mask + 边缘辅助分数”
- [x] 明确不做完整 `scale_x × scale_y` 暴力搜索,优先用基础 `scale` 加少量 `aspect_y` 候选控制耗时
- [x] 明确 `1000x1000 -> 1000x800` 可由 `scale_x=1.00`、`scale_y=0.80`、`aspect_y=0.80` 覆盖
- [x] 更新输出字段建议:从单一 `scale` 改为 `scale_x`、`scale_y`、`aspect_y`
- [x] 验证:文档路径、标题、示例和验收点检查通过
### 19.34 独立脚本:支持宽高不等比例印花匹配 — `match_stamp.py`
前置阅读:
- `docs/12-stamp-template-matching.md`
- `match_stamp.py`
背景:
§19.33 已明确实际合成时印花可能被非等比例缩放,例如原始 `1000x1000` 合成后变成 `1000x800`。`match_stamp.py` 需要按文档把单一 `scale` 搜索扩展为基础 `scale` 加有限 `aspect_y` 候选,提升这类场景的匹配稳定性。
任务:
- [x] 新增 `ASPECT_Y_FACTORS = 0.60 / 0.70 / 0.80 / 0.90 / 1.00 / 1.10 / 1.20`
- [x] 将缩放搜索从单一 `scale` 改为 `scale_x=scale`、`scale_y=scale*aspect_y`
- [x] RGB 模板、边缘模板和 alpha mask 使用同一组 `scale_x / scale_y` 缩放
- [x] 最佳结果保存并打印 `scale_x`、`scale_y`、`aspect_y`,不再只打印单一 `scale`
- [x] 保持独立脚本约束:不引用项目代码、不写 CSV、不修改图片
- [x] 验证:`python -m py_compile match_stamp.py` 通过;临时构造 `100x100 -> 100x80` 非等比例样本,Top 1 命中正确印花且输出 `aspect_y=0.8000`
- [x] 文档更新:`docs/11-ai-outfit.md` §17.2 补读取超时说明、新增 §17.8 决策
- [x] `ai_title.py`:加常量 `_TITLE_TIMEOUT_RESOLUTION = "4K"`(带注释说明借 4K 档的 600s);`generate_titles` 改调 `client.generate_texts(prompt, resolution=_TITLE_TIMEOUT_RESOLUTION)`
- [x] 不动 `generate_texts`/`generate_text` 默认 `resolution="1K"`;模型条目 `timeout_seconds>0` 仍优先覆盖(`_post` 逻辑不变)
- [x] 测试:`tests/test_ai_title.py` 断言 `generate_titles` 以 `resolution="4K"` 调 `generate_texts`(mock 客户端捕获 kwargs);既有用例保持绿
- [x] 验证:`test_ai_title.py`、`test_ai_text_service.py`、全套 py37 通过(`test_config_service` 的 packaging 模板失败属并行历史遗留,无关)