feat(ai-outfit): 左栏新增「标题生成」(看图→提示词→AI 文字标题→写回A列) (§19.18)
AI 穿搭页左栏新增独立的「生成标题」流程:用户写标题提示词,AI 看该行 衣服图(目录行取首图)生成电商标题,逐行立即写回 Excel A 列并刷新明细表; 完成后重载 Excel,紧接「开始生成」跑图即用新标题。移除原「最终生成要求预览」 腾出版面(docs/11 §17)。 - ai_text_service.py:AiTextClient 复用图像服务 HTTP 管道做文本输出; chat/gemini 带图视觉,images/images_edits 明确报错;extract_text 取首条标题 - ai_title.py + TitleResult:单行编排,never raises - excel_service.write_title_result:只写 A 列、不动 D/E/F - config_service:title_model 默认 + load/save_title_prompt + 默认标题话术 - 面板:标题生成组(提示词+标题模型下拉+保存+生成标题)置于话术组上方; _TitleWorker 顺序逐行+立即回填+刷新;与「开始生成」互斥;删预览相关组件 - 测试:文本解析/payload、generate_title(单文件/目录首图/失败)、 write_title_result、面板标题组存在且无预览;全套 py37 通过 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+49
-2
@@ -164,7 +164,7 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只
|
||||
- 提示词模板存 `~/.cmbot/config/outfit_prompt.txt`,界面可查看/编辑/保存;点「开始」前自动保存一次。
|
||||
- 占位符:仅 `{title}`(标题);界面只提供「插入标题」按钮,把占位符插入光标处。货号(`product_id`)不进提示词——它只用于 Excel B 列读取与输出文件命名(`货号.jpg`),不影响 AI 生成内容。(`render_prompt` 仍会替换偶然出现的 `{product_id}`,保持兼容,但界面不再引导插入。)
|
||||
- **「保存话术」按钮**:把当前编辑的模板原文(占位符原样保留,**不**存替换后的结果)经 `config_service` 写入 `outfit_prompt.txt`。用途是"改完先存、暂不开跑"并给用户明确反馈;与"开始前自动保存"并存、互为兜底(保留按钮是有意为之,对非技术用户更安心)。
|
||||
- **最终提示词预览(内嵌、不弹窗)**:左栏话术编辑下方常驻一块只读预览区,编辑话术时实时把占位符替换成样本行真值,显示最终要发送给 AI 的完整文字。**样本行下拉来自 Excel 的全部有效数据行(标题/货号/衣服图齐全,不看 E 列完成/失败状态)**,因此整表生成完成后仍能预览(见 §10.3);默认选第一行。未选 Excel / 无有效行时显示带高亮占位符的模板原文 + 提示;缺 `{title}` 占位符时在预览区提示。预览只读,不改话术本身。(早期设计为弹窗 `QDialog`,因调话术需"边改边看"改为内嵌。)
|
||||
- ~~**最终提示词预览(内嵌、不弹窗)**~~ **(§17 已移除)**:原左栏话术编辑下方的只读预览区 + 样本行下拉,为给左栏让出「标题生成」组(§17)已整体移除。相关历史问题(§10.1 下拉撑宽、§10.3 样本行为空、§10.4 不清空样本)随之作废。
|
||||
- 缺标题占位符时开始前弹窗询问是否继续。
|
||||
- 默认话术方向(穿搭/上身,区别于旧项目的主图场景,需另调):人物上身实穿、保留衣服款式/版型/颜色/印花、合适身材与场景、电商可用、默认纯净不加促销牛皮癣。
|
||||
|
||||
@@ -250,7 +250,7 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只
|
||||
|
||||
三栏布局:
|
||||
|
||||
- **左栏(数据源 + 话术创作,~360px)**:`Excel` / `输出` 各为**行内一行**(标签 + 路径 + 浏览,省纵向空间);数据源概览(共 N 行 / 完成 / 待处理 / 失败);**加大的**穿搭生成话术编辑 +「保存话术」+「插入标题」;下方常驻**加大的最终生成要求预览**(内嵌、实时,标题行右侧放样本行下拉,含 §7.1 自动附加的输出要求)。AI 模型下拉不在此(见右栏)。
|
||||
- **左栏(数据源 + 标题/话术创作,~360px)**:`Excel` / `输出` 各为**行内一行**(标签 + 路径 + 浏览,省纵向空间);数据源概览(共 N 行 / 完成 / 待处理 / 失败);**「标题生成」组(§17)在上**:标题生成提示词编辑 +「标题模型」下拉 +「保存」+「生成标题」;**「穿搭生成话术」组在下**:话术编辑 +「保存话术」+「插入标题」+ 多套模板下拉(§7.2)。**最终提示词预览已移除(§17)**。图片 AI 模型下拉不在此(见右栏);标题模型下拉在本栏标题组内。
|
||||
- **中栏(结果 + 明细)**:顶部「最近结果」缩略图条——**只展示已完成的人物效果图**,新图自动加到最左、首图标「最新」,单击看大图、右键开所在文件夹;下方「处理明细」表(行 / 标题 / 货号 / 衣服图 / 状态 / 结果或原因),按 Excel 行顺序,状态用 完成 / 失败 / 生成中 / 待处理 / 跳过 徽章。
|
||||
- **右栏(设置 + 运行,~400px)**:生成设置标题与「重试上次失败的行」同排;图片并发数 / 新请求间隔 / 单任务冷却 / 失败重试 / 分辨率 / JPG 质量保持 **3 列 × 2 行**;`AI 模型` 标签与下拉框同排;本次进度 + 统计(完成 / 失败 / 待处理);开始生成 / 停止生成同排;导出失败清单 / 打开输出目录同排;节省的纵向空间给实时日志(含 §8 心跳行)。
|
||||
|
||||
@@ -262,6 +262,8 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只
|
||||
|
||||
### 10.1 已知问题:左栏内容被中间面板裁掉(下拉框撑宽)
|
||||
|
||||
> **§17 更新:已作废。** 撑宽元凶「样本行下拉」随预览一并移除(§17);保留本节仅作历史记录。新「标题模型」下拉仍套用下方「修复方向」的 elide 策略,防止再撑宽。
|
||||
|
||||
**现象**:「2 AI 穿搭」左栏组件右侧显示不完整,像被中间面板遮挡了一部分。
|
||||
|
||||
**定位(离屏实测 1280×720)**:
|
||||
@@ -294,6 +296,8 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只
|
||||
|
||||
### 10.3 已知问题:全表生成完成后,预览样本行下拉为空
|
||||
|
||||
> **§17 更新:已作废。** 预览与样本行下拉已移除(§17),本问题不复存在。`read_all_rows` 仍保留——它现在是「标题生成」的行来源(§17)。保留本节作历史记录。
|
||||
|
||||
**现象**:选中的 Excel 整表生成成功后,再次选中该文件,「最终生成要求预览」的样本行下拉只显示「(选 Excel 后显示替换效果)」,无可选行。
|
||||
|
||||
**原因**:预览样本行用 `_reload_sample_rows()` 填,调的是给**生成**用的 `load_outfit_tasks()`——它按设计**跳过 E=「完成」的行**(失败行也只在勾「重试失败行」时返回)。整表都「完成」→ 返回空 → 下拉空 → 占位文案。预览本只是"拿一行真实数据看话术替换效果",与"这行要不要重新生成"无关,不该受状态过滤。
|
||||
@@ -306,6 +310,8 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只
|
||||
|
||||
### 10.4 改进:整表无待处理行时的提示 + 生成不清空预览样本
|
||||
|
||||
> **§17 更新:改进 2 作废**(预览样本已移除,§17);**改进 1(无待处理行提示)继续有效**。
|
||||
|
||||
承接 §10.3。整表都「完成」后点「开始生成」时当前体验不清晰,两项改进:
|
||||
|
||||
**改进 1 — 无待处理行时给明确提示。**
|
||||
@@ -389,3 +395,44 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只
|
||||
- Excel 行顺序处理、图片并发/限速/重试/温和停止生效;实时日志 + 进度 + 结束摘要 + 失败清单导出。
|
||||
- 日志写入 `~/.cmbot/logs`;AI 密钥不入库。
|
||||
- 核心逻辑单测通过、不依赖 GUI、Python 3.7 可运行。
|
||||
|
||||
## 17. 标题生成(左栏独立功能)
|
||||
|
||||
「添加印花」批量导出生成的 Excel(`docs/02` §6.12),A 列「标题」只是占位的**印花名**,不是真正的电商标题。本功能在 AI 穿搭页**左栏**新增一个**独立的「生成标题」**流程:用户写标题提示词,AI **看该行衣服图**(视觉)生成电商标题,**写回 Excel A 列**,再点「开始生成」跑图时图片提示词的 `{title}` 即用上新标题。与「开始生成」(图片)**互不绑定**、各自一个按钮。
|
||||
|
||||
### 17.1 数据流与回填语义
|
||||
|
||||
- **行来源**:复用 `excel_service.read_all_rows(excel)`(状态无关)——对全部有效行生成、**覆盖式**写 A,不看 E 列状态、不引入新列(保持与 `标题生成产品图.xlsx` 七列一致)。
|
||||
- **逐行看图、各生成 1 条、顺序回填**:按行顺序处理,第 i 行看第 i 行衣服图 → 生成 1 条标题 → **立即**写回第 i 行 A(`write_title_result(excel, row_index, title)`)→ 刷新中栏「处理明细」表该行「标题」列。即「第 n 条标题 → 第 n 行 A,顺序回填 + GUI 实时刷新」。
|
||||
- **目录行取首图**:C 列为图片目录时(印花 Excel 即如此),标题写回**一个 A 单元格**(整行一个标题),故只取 `ai_outfit.list_directory_images(dir)` 的**第一张**作视觉参考;标题提示词宜写成概括款式/印花的通用句式。
|
||||
- **条数对齐**:因逐行各生成 1 条,标题数永远 = 行数,不存在「AI 返回条数和行数对不上」的兜底问题。提示词即使写「生成 N 条」,每行也**只取第一条**(解析时取首个非空行、去行首序号/符号与首尾引号、单行化)。
|
||||
- **"覆盖图片组件的标题" = 写回 A + 重载**:图片生成在「开始生成」时当场 `load_outfit_tasks(excel)` 读 A 列,故标题写回 A 后无需另改图片组件;标题全部生成完**重新加载一次 Excel**,刷新界面与内存任务,紧接着「开始生成」即用新标题。
|
||||
|
||||
### 17.2 文本服务(复用图像服务的 HTTP 管道)
|
||||
|
||||
- 新增 `services/ai_text_service.py` 的 `AiTextClient(config, session=None)`:复用 `ai_image_service` 的 `AiModelConfig` / `image_to_data_url` / `detect_api_type` / `normalize_api_url` / Bearer 鉴权 / 超时 / session,不重写 HTTP。
|
||||
- `generate_text(prompt, image_path=None) -> str`:
|
||||
- `chat`:`messages=[{role:user, content:[{type:text,text:prompt}, {type:image_url,...}]}]`(带图=视觉)。
|
||||
- `gemini`:`contents[].parts=[{text},{inlineData}]`,`generationConfig.responseModalities=["TEXT"]`。
|
||||
- `images`/`images_edits`:纯图片接口,不能返回文字 → 抛 `AiTextServiceError`,提示「该模型不能生成文字,请改选文本/视觉模型」。
|
||||
- `extract_text_from_response(data)`:取 `choices[0].message.content`(str 或 content 列表的 text)/ gemini `candidates[0].content.parts[].text`;都取不到则抛错;返回**第一条标题**(见 §17.1 解析规则)。
|
||||
|
||||
### 17.3 模型与提示词
|
||||
|
||||
- **标题模型独立下拉**:图片/文本模型类型不同(图片模型返回图、不返回文字),左栏标题组内单独放「标题模型」下拉,与图片模型同源(`load_ai_models()`)但**独立记忆**所选(`app_config` 新键 `title_model`)。
|
||||
- **标题提示词**:单份,存 `~/.cmbot/config/title_prompt.txt`(`load_title_prompt`/`save_title_prompt`,仿旧式单份,标题侧不做多套模板);默认文案面向电商女装(结合款式/版型/颜色/印花,输出一行中文标题,不加引号/表情/促销词)。
|
||||
|
||||
### 17.4 界面与运行
|
||||
|
||||
- **左栏布局**(§10 已同步):「标题生成」组在上、「穿搭生成话术」组在下;预览块移除。标题组含:标题提示词编辑、`标题模型`下拉、「保存」、「生成标题」。
|
||||
- **运行**:`_TitleWorker(QObject)` 跑在 `QThread`(仿 `_OutfitWorker`),按行顺序逐行生成、立即回填、刷新该行 GUI;失败记日志、跳过该行、继续;用右栏「新请求间隔」做行间节流;温和停止。
|
||||
- **互斥**:「生成标题」与「开始生成」运行时互斥(避免同表并发写)。
|
||||
- 进度/结果走中栏「处理明细」表与右栏日志(不写 Excel 状态列)。
|
||||
|
||||
### 17.5 验收要点(标题生成)
|
||||
|
||||
- 左栏有「标题生成」组(提示词 + 标题模型下拉 + 生成标题按钮),无预览块。
|
||||
- 选印花生成的 Excel(A=印花名、C=目录),点「生成标题」→ 每行 A 被改写为 AI 标题、明细表标题列实时刷新、D/E/F 未动。
|
||||
- 标题模型选到纯图片接口(images/images_edits)时明确报错提示换模型。
|
||||
- 生成完重载 Excel,紧接「开始生成」跑图用的是新标题。
|
||||
- 文本解析、`generate_title`(单文件/目录取首图/无图失败/客户端异常)、`write_title_result`(只改 A)单测通过,Python 3.7。
|
||||
|
||||
Reference in New Issue
Block a user