diff --git a/docs/11-ai-outfit.md b/docs/11-ai-outfit.md index f8d5c29..f0913b0 100644 --- a/docs/11-ai-outfit.md +++ b/docs/11-ai-outfit.md @@ -287,7 +287,7 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只 三栏布局: -- **左栏(数据源 + 标题/话术创作,~360px)**:`Excel` / `输出` 各为**行内一行**(标签 + 路径 + 浏览,省纵向空间);数据源概览(共 N 行 / 完成 / 待处理 / 失败);**「标题生成」组(§17)在上**:标题生成提示词编辑 +「保存」+「生成标题」(**无标题模型下拉**,模型由 `title_model` 配置定名,§17.3);**「穿搭生成话术」组在下**:模板下拉 + 按钮行 `新建/另存为/重命名/保存/删除` + 话术编辑框 + 下方「插入标题」「预览最终提示词」(预览为弹窗,数据行下拉在弹窗内,§7.3)。图片 AI 模型下拉在右栏;标题模型不放界面。 +- **左栏(数据源 + 标题/话术创作,~360px)**:`Excel` / `输出` 各为**行内一行**(标签 + 路径 + 浏览,省纵向空间);数据源概览(共 N 行 / 完成 / 待处理 / 失败);**「标题生成」组(§17)在上**:标题生成提示词编辑 +「保存」+「生成标题」(**无标题模型下拉**,模型由 `title_model` 配置定名,§17.3);「标题生成提示词」label 右侧预留标题请求等待计时位(§17.10),点击「生成标题」后显示 `等待中 01:35 / 10:00`;**「穿搭生成话术」组在下**:模板下拉 + 按钮行 `新建/另存为/重命名/保存/删除` + 话术编辑框 + 下方「插入标题」「预览最终提示词」(预览为弹窗,数据行下拉在弹窗内,§7.3)。图片 AI 模型下拉在右栏;标题模型不放界面。 - **中栏(结果 + 明细)**:顶部「最近结果」缩略图条——**只展示已完成的人物效果图**,新图自动加到最左、首图标「最新」,单击看大图、右键开所在文件夹;下方「处理明细」表(行 / 标题 / 货号 / 衣服图 / 状态 / 结果或原因),按 Excel 行顺序,状态用 完成 / 失败 / 生成中 / 待处理 / 跳过 徽章。 - **列宽(§19.25 / §19.26)**:「行 / 货号 / 状态」是**窄固定列**(`QHeaderView.Fixed`,约 46 / 88 / 76px);「衣服图 / 结果·原因」也收窄为可手拖的小初值(`Interactive`,约 90 / 130px,§19.26 再缩);省下的横向空间全部让给**标题**——「标题」列设 `QHeaderView.Stretch` 吃满剩余宽度(其余列越窄,标题越宽)。由 `_configure_detail_table_columns()` 统一设置。 - **右栏(设置 + 运行,~400px)**:生成设置标题与「重试上次失败的行」同排;图片并发数 / 新请求间隔 / 单任务冷却 / 失败重试 / 分辨率 / JPG 质量保持 **3 列 × 2 行**;`AI 模型` 标签与下拉框同排;本次进度 + 统计(完成 / 失败 / 待处理);开始生成 / 停止生成同排;导出失败清单 / 打开输出目录同排;节省的纵向空间给实时日志(含 §8 心跳行)。 @@ -487,6 +487,7 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只 - **左栏布局**(§10 已同步):「标题生成」组在上、「穿搭生成话术」组在下;预览块移除。标题组含:标题提示词编辑、「保存」、「生成标题」(**无标题模型下拉**,模型由 `title_model` 配置定名,§17.3)。 - **运行**:`_TitleWorker(QObject)` 跑在 `QThread`(仿 `_OutfitWorker`),**一次请求**(纯提示词,无图)拿到标题列表 → **按序逐条回填** `write_title_result` + 刷新该行 GUI;条数对不上按 §17.1 兜底(多丢、少留空、记日志);请求失败记日志并以「成功 0」收尾;温和停止。模型用 `_resolve_title_model_config()`(按 `title_model` 名字查 `ai_models.json`)。**只有一次请求,不再用「新请求间隔」做行间节流**。 - **互斥**:「生成标题」与「开始生成」运行时互斥(避免同表并发写)。 +- **标题请求等待计时**:点击「生成标题」后,在「标题生成提示词」label 右侧显示 `等待中 mm:ss / 10:00`(§17.10),每秒刷新;请求返回后切到写回/完成状态,失败或超时后复位并提示。该计时只表达“已等待 / 最长等待”,不是模型真实生成百分比。 - 进度/结果走中栏「处理明细」表与右栏日志(不写 Excel 状态列)。 ### 17.5 验收要点(标题生成) @@ -538,3 +539,20 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只 - **为什么两层都要**:哨兵最干净但依赖模型照做(推理模型偶尔漏);句号兜底不依赖提示词、对现有精细模板(发布包 `【台灣現貨】` 模板,未含哨兵)当场生效。二者叠加:模型配合时确定性、不配合时仍能救。 - **为什么不选纯提示词约束 / JSON 数组**:纯靠"别输出思考"压不住推理模型(§本节前提)。JSON 数组(`["t1","t2",…]` + 抽第一个 `[...]` 解析)鲁棒性更高、还能容忍标题内嵌逗号,但要改输出格式、超长数组偶有截断/非法风险;当前保留用户熟悉的逗号格式 + 上述两层过滤,改动最小。若日后逗号内嵌成为真问题,再迁 JSON(把逗号切分降级为 fallback)。 - **边界**:② 假设标题不含 `。`;若某条标题真带句号会被误切——由提示词"禁标点"约束兜住,属可接受的固有边界(与 §17.3 一致)。中转站若能单独返回 `reasoning_content` 或支持关思考参数,则从源头无前导思考,比解析更干净(值得在中转文档确认;本次不依赖)。 + +### 17.10 决策:标题生成显示等待计时(已等待 / 最长等待) + +标题生成支持用户在提示词里一次要求生成上百条标题。该流程是“一次请求、纯提示词、多条返回”(§17.7),请求发出后程序无法获得模型内部生成百分比;若只显示按钮禁用和旧的行进度条,用户容易误判为卡死。 + +交互规则: + +- 点击「生成标题」后,在左栏「标题生成提示词」label 右侧显示 `等待中 mm:ss / 10:00`,例如 `等待中 01:35 / 10:00`。 +- `10:00` 来自标题生成当前默认读取超时 600 秒(§17.8);若模型配置 `timeout_seconds > 0` 覆盖超时,则右侧最大等待应显示覆盖后的秒数。 +- 计时每秒刷新,直到请求返回、失败、超时或用户停止。 +- 请求返回后进入 Excel 写回阶段时,文案可改为 `写入中 已完成/总数`;全部写回后显示 `完成 N 条` 并在短暂停留后复位。 +- 超时或失败时显示 `等待超时` / `生成失败`,同时保留弹窗和日志里的详细原因。 + +产品边界: + +- 这不是模型真实进度条,不能用百分比暗示“已生成多少”。它只表达“已等待多久 / 最长等多久”。 +- 现有右栏本次进度条继续按 Excel 行/写回进度推进;标题 label 右侧计时只覆盖“单次标题请求等待”这段长等待空窗。 diff --git a/tasks.md b/tasks.md index aea5896..c93e4ad 100644 --- a/tasks.md +++ b/tasks.md @@ -1585,4 +1585,33 @@ - [x] `config_service.py`:`DEFAULT_TITLE_PROMPT` 补哨兵约定(思考写最前、单独一行 `===TITLES===`、其后只放逗号标题) - [x] 不碰 `packaging/default_config/title_prompt.txt`(用户精细模板,并行未提交工作) - [x] 测试:真实前导思考样本(带 `。`+逗号列表)被剥离、取全部标题;哨兵优先于句号且忽略思考内逗号;无前导的纯逗号列表不变;末条带收尾 `。`、无前导时不误切清空 -- [x] 验证:`test_ai_text_service.py`、`test_ai_title.py`、全套 py37 通过;离屏冒烟用真实返回样本走 `extract_titles_from_response` \ No newline at end of file +- [x] 验证:`test_ai_text_service.py`、`test_ai_title.py`、全套 py37 通过;离屏冒烟用真实返回样本走 `extract_titles_from_response` + +### 19.32 标题生成等待计时显示 — docs/11 §17.10 + +前置阅读: + +- `docs/11-ai-outfit.md`(§17.4、§17.8、§17.10) +- `src/app/widgets/ai_outfit_panel.py`(标题生成组、`_start_title`、`_on_title_*`、线程清理) +- `src/core/ai_title.py`(标题生成使用 4K 档 600 秒) +- `src/services/ai_text_service.py`(模型 `timeout_seconds` 覆盖读取超时) + +背景: + +用户在标题提示词里要求一次生成上百条标题时,标题生成是一次长请求;请求期间程序无法知道模型真实进度,旧进度条只在返回并写回 Excel 后才推进,容易让用户误以为卡死。需要在「标题生成提示词」label 右侧显示等待计时,例如 `等待中 01:35 / 10:00`。 + +任务: + +- [ ] `ai_outfit_panel.py`:在「标题生成提示词」label 右侧新增等待计时 QLabel,默认隐藏或空白,不挤压编辑框 +- [ ] 点击「生成标题」后启动 1 秒计时器,显示 `等待中 mm:ss / MM:SS` +- [ ] 最大等待默认取标题生成 600 秒;若当前标题模型 `timeout_seconds > 0`,显示该覆盖值 +- [ ] 请求返回并进入写回阶段时,文案切换为 `写入中 已完成/总数` 或同等清晰状态;完成后短暂停留并复位 +- [ ] 失败、超时、停止、线程清理时停止计时并复位,避免残留旧状态 +- [ ] 不把该显示做成真实百分比进度,不影响右栏本次进度条和明细表刷新 +- [ ] 测试:离屏断言点击「生成标题」后计时 label 变为等待中;mock 超时值覆盖;完成/失败后复位 + +验收: + +- [ ] 长时间标题生成期间,用户能看到已等待时间和最长等待时间 +- [ ] 计时文案不暗示模型内部完成百分比 +- [ ] 标题生成和图片生成互斥、原有进度/明细行为不回退