diff --git a/docs/11-ai-outfit.md b/docs/11-ai-outfit.md index 7ecd139..055c60c 100644 --- a/docs/11-ai-outfit.md +++ b/docs/11-ai-outfit.md @@ -81,6 +81,7 @@ C 列除了单张图片文件,**也可以是一个目录**(如 `d:/images/a/ 共用本行的标题/货号与话术。 - 输出落到 `AI 穿搭输出目录/<目录叶子名>/`(默认是程序旁的 `穿搭图片\`,见 §9.1);Excel 回写仍是**整行一个状态**: D=子目录绝对路径、E=全部成功才 `完成` 否则 `失败`、F=失败张数/原因。 +- Excel 行本身按顺序处理;并发只发生在当前目录行内部(见 §8 / §9.1)。 - 目录不存在或目录内没有图片 → 该行 `失败` 并记录原因,不中断其它行。 ## 5. 内部数据模型 @@ -212,10 +213,12 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只 ## 8. 并发、限速、重试、停止 -复用旧项目策略(`docs/旧ai穿搭项目.md` §5.3): +复用旧项目的限速、重试、心跳与温和停止策略(`docs/旧ai穿搭项目.md` §5.3),但并发语义改为更适合「一行一个目录」的模型: -- **并发由 Python 线程负责,PySide6 不参与**:`requests` 在等网络响应时释放 GIL,所以 `ThreadPoolExecutor` 起多线程跑行任务时多个 HTTP 请求是真并发。Qt 只负责把进度/结果通过 **signal 跨线程排队回主线程**刷新 UI——**子线程绝不直接操作控件**(违反会崩溃/随机出错)。默认并发 1 是迁就中转 API 限流(429),非框架限制,可在界面调高。 -- `ThreadPoolExecutor(max_workers=并发数)` 调度行任务;`RateLimiter(新请求间隔)` 限制请求开始间隔;任务间 `单任务冷却`。 +- **Excel 行并发固定为 1**:批次按 Excel 行顺序处理。这样一行一个目录时,D/E/F 仍按行聚合写回,避免多行同时写表或同时刷状态导致排查困难。 +- 界面参数命名为**图片并发数**,只控制**当前目录行内部**同时生成多少张图片。默认 1;调到 2/3 时,同一目录内最多同时发起对应数量的图片请求。单文件行不参与图片并发,仍一行一张顺序处理。 +- **并发由 Python 线程负责,PySide6 不参与**:`requests` 在等网络响应时释放 GIL,所以目录内 `ThreadPoolExecutor(max_workers=图片并发数)` 的多个 HTTP 请求是真并发。Qt 只负责把进度/结果通过 **signal 跨线程排队回主线程**刷新 UI——**子线程绝不直接操作控件**(违反会崩溃/随机出错)。 +- `RateLimiter(新请求间隔)` 限制同一目录内每个新图片请求的启动间隔;任务间 `单任务冷却` 作用于 Excel 行之间。因为行并发固定为 1,批次的最大 HTTP 并发约等于图片并发数。 - 每行最多「首次 + 重试次数」尝试;限流/429 用短阶梯等待,普通错误短等待。 - 单次请求放子线程 + 主线程秒级检查,**等待 >30 秒持续打心跳日志**;超时按分辨率动态决定(512/1K/2K/4K → 180/240/360/600 秒,可被 `timeout_seconds` 覆盖)。 - **温和停止**:置位停止后不再提交新任务,已发请求收尾后正常写回。 @@ -238,9 +241,8 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只 - **不加 `_1`/`_2` 去重后缀**:目标文件已存在视为「已生成」并**跳过**,使整行可 幂等重试——重试只补做缺失/失败的那几张,已成功的不重复调 API。 - 整行回写 Excel 时,D 列写**子目录**绝对路径(而非单个文件)。 -- 目录内逐张**顺序**生成(同一 worker 内);为避免压垮中转 API,逐张之间按 - 「新请求间隔」本地 sleep 节流。并发=1(默认)时即等于全局节流;并发>1 时为近似。 - 进度条按 Excel 行前进(一个目录=1 格),逐张进度通过实时日志反馈。 +- 目录内按**图片并发数**生成;默认 1 时等同旧的逐张顺序生成。为避免压垮中转 API,每个新图片请求启动前仍按「新请求间隔」节流。图片并发数 >1 时,完成日志和缩略图出现顺序不保证与文件名排序完全一致。 +- 进度条按 Excel 行前进(一个目录=1 格),逐张进度通过实时日志与最近结果缩略图反馈。整行全部图片收尾后才写回 Excel D/E/F。 ## 10. 界面(「2 AI 穿搭」页签) @@ -250,7 +252,7 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只 - **左栏(数据源 + 话术创作,~360px)**:`Excel` / `输出` 各为**行内一行**(标签 + 路径 + 浏览,省纵向空间);数据源概览(共 N 行 / 完成 / 待处理 / 失败);**加大的**穿搭生成话术编辑 +「保存话术」+「插入标题」;下方常驻**加大的最终生成要求预览**(内嵌、实时,标题行右侧放样本行下拉,含 §7.1 自动附加的输出要求)。AI 模型下拉不在此(见右栏)。 - **中栏(结果 + 明细)**:顶部「最近结果」缩略图条——**只展示已完成的人物效果图**,新图自动加到最左、首图标「最新」,单击看大图、右键开所在文件夹;下方「处理明细」表(行 / 标题 / 货号 / 衣服图 / 状态 / 结果或原因),按 Excel 行顺序,状态用 完成 / 失败 / 生成中 / 待处理 / 跳过 徽章。 -- **右栏(设置 + 运行,~400px)**:生成设置标题与「重试上次失败的行」同排;并发数 / 新请求间隔 / 单任务冷却 / 失败重试 / 分辨率 / JPG 质量保持 **3 列 × 2 行**;`AI 模型` 标签与下拉框同排;本次进度 + 统计(完成 / 失败 / 待处理);开始生成 / 停止生成同排;导出失败清单 / 打开输出目录同排;节省的纵向空间给实时日志(含 §8 心跳行)。 +- **右栏(设置 + 运行,~400px)**:生成设置标题与「重试上次失败的行」同排;图片并发数 / 新请求间隔 / 单任务冷却 / 失败重试 / 分辨率 / JPG 质量保持 **3 列 × 2 行**;`AI 模型` 标签与下拉框同排;本次进度 + 统计(完成 / 失败 / 待处理);开始生成 / 停止生成同排;导出失败清单 / 打开输出目录同排;节省的纵向空间给实时日志(含 §8 心跳行)。 > **设计取舍:不做"实时单图大预览"。** 这是"开了走人、回头抽查"的批量工具;单图实时预览在并发时会产生"该显示哪一行"的歧义。改为「最近结果缩略图条」——只展示已落地成品,既保留"早发现话术/模型不对、及时停掉改话术"的价值,又因只显示成品而消除并发歧义。 @@ -357,7 +359,7 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只 ## 13. 安全考量 - AI 中转 API key 为明文,仅放 `~/.cmbot`,**不入库、不随包分发到公网**;内部使用可接受(与更新凭据一致)。 -- 中转 API 会 429 限流:并发默认 1,阶梯重试。 +- 中转 API 会 429 限流:图片并发数默认 1,阶梯重试。 - 衣服图为本机路径;不存在/打不开/非图片 → 该行失败并记录,继续下一行。 ## 14. 实现阶段建议 @@ -384,6 +386,6 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只 - 按行处理:跳过「完成」、按设置重试「失败」、空字段行安全跳过。 - 衣服图 + 提示词 → 生成人物上身 JPG(1:1、≤2MB、命名去重)。 - 每行实时写回 D/E/F 并保存 Excel;Excel 被占用时明确提示。 -- 并发/限速/重试/温和停止生效;实时日志 + 进度 + 结束摘要 + 失败清单导出。 +- Excel 行顺序处理、图片并发/限速/重试/温和停止生效;实时日志 + 进度 + 结束摘要 + 失败清单导出。 - 日志写入 `~/.cmbot/logs`;AI 密钥不入库。 - 核心逻辑单测通过、不依赖 GUI、Python 3.7 可运行。 diff --git a/docs/ui-ai-outfit.html b/docs/ui-ai-outfit.html index f5d7d30..8f950b3 100644 --- a/docs/ui-ai-outfit.html +++ b/docs/ui-ai-outfit.html @@ -340,7 +340,7 @@