docs: define outfit factory config seeding

This commit is contained in:
2026-06-23 17:45:52 +08:00
parent a9360f9421
commit cad8b61bcf
4 changed files with 50 additions and 5 deletions
+1
View File
@@ -114,6 +114,7 @@ CMBot/
- UI 样式文件。
- 默认模板文件。
- 默认配置文件。
- AI 穿搭出厂配置:`ai_models.json`(不含真实 key)、`outfit_prompt.txt`、`title_prompt.txt`。这些文件应进入发布包的 `app\config\`,用于首次播种和运行时兜底补种;用户目录已有同名文件时不得覆盖。
规则:
+4 -1
View File
@@ -75,6 +75,8 @@
app_config.json # 用户偏好(输出格式、最近文件夹、最近模板、更新源等)
templates.json # 用户自定义模板
ai_models.json # AI 穿搭模型配置(管理员填写 key,首次可由出厂模板播种)
outfit_prompt.txt # AI 穿搭默认话术(用户可编辑,缺失时由出厂模板补种)
title_prompt.txt # 标题生成默认提示词(用户可编辑,缺失时由出厂模板补种)
logs\
output\ # 默认导出目录的回退位置(安装根不可写时,AI 穿搭回退到 output\穿搭图片)
```
@@ -110,8 +112,9 @@
1. 环境变量 `CMBOT_DATA_DIR` 非空时使用它(覆盖口,供测试或特殊部署)。
2. 打包态(`sys.frozen`)→ `~/.cmbot`(即 `%USERPROFILE%\.cmbot`)。**不依赖启动器注入环境变量**:即使用户绕过 `Launcher.exe` 直接双击 `app\CMBot.exe`,数据也落在 `~/.cmbot`。
3. 开发态 → 项目根(不污染开发者主目录,保持现状)。
- **首次运行播种**:`~/.cmbot/config/app_config.json`、`templates.json`、`ai_models.json` 不存在时,从程序包内 `app\config\` 拷贝对应出厂默认;缺省再退回内置默认(呼应 `docs/09` 第 6 节)。`ai_models.json` 出厂模板不得包含真实 API key,管理员在用户数据目录中填写。
- **首次运行播种**:`~/.cmbot/config/app_config.json`、`templates.json`、`ai_models.json`、`outfit_prompt.txt`、`title_prompt.txt` 不存在时,从程序包内 `app\config\` 拷贝对应出厂默认;缺省再退回内置默认(呼应 `docs/09` 第 6 节)。`ai_models.json` 出厂模板不得包含真实 API key,管理员在用户数据目录中填写。
- **新增配置的更新兼容**:启动器当前先执行播种,再应用 `staging\app.new`。因此用户通过自更新换到新版时,播种阶段读取的仍可能是旧版 `app\config\`,新增的出厂配置文件(例如 `ai_models.json`)不会在这次启动被复制。且 `Launcher.exe` 本身不参与自更新,旧 Launcher 也可能不知道新增文件名。新增配置文件必须由**主程序运行时兜底补种**:新版 app 启动或加载配置时,如果 `~/.cmbot/config/<name>` 不存在,应从当前新版 `app\config\<name>` 复制一次,仍不得覆盖用户已有文件。
- **已有配置的非覆盖式补全**:对于 `ai_models.json` 这类列表配置,用户文件已存在时不得整文件覆盖。若新版新增了默认标题模型(`app_config.title_model` 指定的 `name`,默认 `GPT-5.5 文本`),主程序应从当前 `app\config\ai_models.json` 查找同名条目并追加到用户 `ai_models.json`;用户已有同名条目时不改,出厂条目 `api_key` 仍为空,管理员后续在用户目录填写真实 key。
- 写入配置/模板/日志/输出前按需创建多级目录(`parents=True`)。
数据目录分离与 `~/.cmbot` 约定后续需同步 `docs/05-project-architecture.md` 与 `docs/09` 第 5、6 节的目录说明。
+18 -3
View File
@@ -117,6 +117,8 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只
- 首次安装:启动器可从 `app\config\ai_models.json` 播种到 `~/.cmbot/config/ai_models.json`。
- 自更新:不能只依赖启动器播种。启动器目前先播种旧 `app\config`,再应用新版 `app`;同时 `Launcher.exe` 本身不自更新,旧启动器也可能不知道 `ai_models.json`。因此新版 app 在启动或 `load_ai_models()` 时必须做运行时兜底:如果 `~/.cmbot/config/ai_models.json` 不存在,且当前 `app\config\ai_models.json` 存在,则复制一次。
- 任何播种/补种都**不得覆盖**用户已有 `~/.cmbot/config/ai_models.json`。
- **标题模型补全(升级兼容)**:如果用户目录的 `ai_models.json` 已存在,但缺少 `app_config.title_model` 指定的模型名(默认 `"GPT-5.5 文本"`),新版 app 在 `load_ai_models()` 时应从当前 `app\config\ai_models.json` 查找同名模型并**追加**到用户 `ai_models.json`。只追加缺失项,不覆盖、不合并、不改用户已有模型与 key;出厂条目的 `api_key` 仍为空,管理员需要在用户目录中填写真实 key。
- 如果用户已在 `app_config.title_model` 改成其它名字,则按该名字查找;出厂模板没有同名条目时只记录日志并保持现状,界面仍按 §17.3 给出「未找到标题模型」提示。
模板格式采用当前程序可直接加载的结构:
@@ -142,6 +144,16 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只
"timeout_seconds": 0,
"connect_timeout_seconds": 30,
"extra_body": {}
},
{
"name": "GPT-5.5 文本",
"url": "https://api.vectorengine.ai/v1/chat/completions",
"model": "gpt-5.5",
"api_key": "",
"api_type": "chat",
"timeout_seconds": 0,
"connect_timeout_seconds": 30,
"extra_body": {}
}
]
}
@@ -150,6 +162,7 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只
规则:
- `name` 是界面下拉框显示值,也是 `app_config.json` 中 `outfit_model` 的持久化值。
- `GPT-5.5 文本` 是标题生成默认模型名,对应 `app_config.json` 的 `title_model` 默认值;它必须是能返回文字的 `chat`/`gemini` 类模型,不应指向 `images`/`images_edits` 图片接口。
- `timeout_seconds=0` 表示按分辨率自动取超时(见 §8),`connect_timeout_seconds=30` 只控制连接阶段。
- 出厂模板**不得提交真实 `api_key`**;管理员在目标机器的 `~/.cmbot/config/ai_models.json`
中填写真实 key。
@@ -162,6 +175,7 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只
## 7. 提示词
- 提示词模板存 `~/.cmbot/config/outfit_prompt.txt`,界面可查看/编辑/保存;点「开始」前自动保存一次。
- 发布包应在 `app\config\outfit_prompt.txt` 带一份出厂穿搭话术;启动器首次播种或主程序运行时兜底会在用户目录缺失时复制到 `~/.cmbot/config/outfit_prompt.txt`。用户已有文件永不覆盖;出厂文件缺失时才退回代码内置 `DEFAULT_OUTFIT_PROMPT`。
- 占位符:仅 `{title}`(标题);界面提供「插入标题」按钮,把占位符插入光标处。**标题由用户经 `{title}` 自行放置(可前、可中、可省),程序不自动前置**——这样标题不会被焊死在固定位置,也不会与旧话术里的 `{title}` 重复。货号(`product_id`)不进提示词——只用于 Excel B 列读取与输出文件命名(`货号.jpg`)。(`render_prompt` 仍替换偶现的 `{product_id}` 以兼容,但界面不引导插入。)
- **「保存」按钮**(原「保存话术」改名、移到模板按钮行「重命名」之后):把当前编辑的模板原文(占位符原样保留,**不**存替换后的结果)经 `config_service` 写入当前模板。用途是"改完先存、暂不开跑";与"开始前自动保存"并存、互为兜底。
- **最终提示词预览改为按需弹窗(§7.3)**:左栏要同时容纳「标题生成」组与「穿搭话术」组,纵向空间紧张(常驻预览会撑到 ~690px > 视口 ~664px、逼出滚动),故预览不做常驻面板,改成话术编辑框下方一个「预览最终提示词」按钮 → 弹**非模态**小窗,内含数据行下拉 + 只读的替换后提示词(含 §7.1 输出要求)。要"边改边看"就开着弹窗,话术/分辨率/数据行变化时刷新。
@@ -374,8 +388,9 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只
遵循 cmbot「配置集中、放数据目录、凭据不入库」约定:
- **AI 模型与密钥** → `~/.cmbot/config/ai_models.json`(管理员预置或界面填写,**含明文 key、不提交 git**;与更新源凭据同等对待,见 `docs/10` §14)。
- 发布包可附带 `app\config\ai_models.json` 出厂模板(见 §6.1),用于首次播种;模板中的 `api_key` 必须为空或占位,真实 key 只写入用户数据目录。
- **提示词** → `~/.cmbot/config/outfit_prompt.txt`。
- 发布包可附带 `app\config\ai_models.json` 出厂模板(见 §6.1),用于首次播种/运行时补种;模板中的 `api_key` 必须为空或占位,真实 key 只写入用户数据目录。用户已有 `ai_models.json` 缺标题模型时,只追加同名出厂模型,不覆盖已有模型。
- **穿搭话术** → `~/.cmbot/config/outfit_prompt.txt`。发布包应带 `app\config\outfit_prompt.txt`;用户文件缺失时复制,已有不覆盖。
- **标题提示词** → `~/.cmbot/config/title_prompt.txt`。发布包应带 `app\config\title_prompt.txt`;用户文件缺失时复制,已有不覆盖。
- **批量设置 + 上次 Excel/输出路径** → 并入 `app_config.json`(`config_service` 集中读写,UI 不直接读写配置文件,遵守 `docs/04` 第 6 节 / `docs/05` 4.12)。
- **AI 穿搭默认输出目录** → 安装根旁的 `穿搭图片\`(不可写时回退 `~/.cmbot/output/穿搭图片\`);用户手动选择的目录存入 `app_config.json` 的 `outfit_output_dir`。
- 失败记录 / 日志沿用 `~/.cmbot/logs` 与现有日志服务。
@@ -459,7 +474,7 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只
- **命中的模型是纯图片接口(images/images_edits)时,开跑前就拦截(§19.21)**:`_find_title_model` 检出 `api_type ∈ {images, images_edits}` → 返回错误「『{名字}』是图片模型({api_type}),不能生成文字标题,请改选 chat/gemini 文本模型」→ `_resolve_title_model_config` 弹窗 + 中止,不逐行失败。
- 边界:`api_type=chat` 但实际返回图片的模型(如 Nano Banana)类型上无法预判,仍在运行时由 `AiTextClient`/「未找到文字标题」逐行暴露——这是固有限制。
- **`ai_models.json` 需有一条文本/视觉模型**(管理员维护,含真实 key,不入库):`api_type` 设 `chat`、`model` 填中转的真实 id(如 `gpt-5.5`)、`name` 与 `title_model` 一致(默认 `GPT-5.5 文本`)。`docs/ai_models.sample.json` 已含 chat 示例可参照。
- **标题提示词**:单份,存 `~/.cmbot/config/title_prompt.txt`(`load_title_prompt`/`save_title_prompt`,仿旧式单份,标题侧不做多套模板);默认文案为**批量风格 + 逗号分隔**——让模型生成**多条**电商女装标题、**标题之间用逗号分隔**、**不要表格/换行/序号/引号/表情**,数量由用户在提示词里写(默认示例可写「生成 10 条」)。与 §17.1 的逗号拆分配套。
- **标题提示词**:单份,存 `~/.cmbot/config/title_prompt.txt`(`load_title_prompt`/`save_title_prompt`,仿旧式单份,标题侧不做多套模板)。发布包应带 `app\config\title_prompt.txt`;用户目录缺失时首次播种/运行时兜底复制,已有不覆盖;出厂文件缺失时才退回代码内置 `DEFAULT_TITLE_PROMPT`。默认文案为**批量风格 + 逗号分隔**——让模型生成**多条**电商女装标题、**标题之间用逗号分隔**、**不要表格/换行/序号/引号/表情**,数量由用户在提示词里写(默认示例可写「生成 10 条」)。与 §17.1 的逗号拆分配套。
### 17.4 界面与运行
+26
View File
@@ -1495,3 +1495,29 @@
- [x] `ai_outfit_panel.py`:`_TitleWorker.run` 改调 `read_all_rows(self._excel_path, require_title=False)`;`_reload_after_titles` 仍可用默认(重载后 A 已填);图片生成/预览/`_show_no_pending_message` 不动(仍要求 A)
- [x] `tests/test_excel_service.py`:补用例——A 空、C 非空的行:`require_title=False` 收录、默认(True)跳过;既有用例保持绿
- [x] 验证:相关单测 + 全套 py37 通过;离屏冒烟:A 全空、C=印花目录的表,标题生成能加载 N 行(不再「无可处理行」),mock 文本模型 → 按序回填 A
### 19.28 AI 穿搭出厂模型/提示词运行时补全 — docs/11 §6.1 / §7 / §17.3,docs/10 §5
前置阅读:
- `docs/11-ai-outfit.md`(§6.1、§7、§11、§17.3)
- `docs/10-lan-update.md`(§4、§5)
- `docs/09-packaging-release.md`(§7)
- `src/services/config_service.py`(`load_ai_models` / `load_outfit_prompt` / `load_title_prompt`)
- `src/launcher.py`(`CONFIG_FILES` / `seed_defaults`)
- `packaging/default_config/`
背景:
现有运行时兜底只处理 `ai_models.json` 缺失;老用户已有 `ai_models.json` 时不会补新增标题模型。`title_prompt.txt` / `outfit_prompt.txt` 也可能只走代码内置默认,打包默认文件未被启动器/运行时补种。升级后会出现标题模型缺失、默认提示词文件缺失的问题。
任务:
- [x] 文档更新:`docs/11-ai-outfit.md`、`docs/10-lan-update.md`、`docs/09-packaging-release.md` 已明确出厂 title model 追加和两个 prompt txt 的非覆盖式补种
- [ ] `packaging/default_config/ai_models.json` 加入 title model 模板(`api_key` 留空,不提交真实 key),并保持图片模型顺序符合 `tests/test_config_service.py` 预期
- [ ] `packaging/default_config/outfit_prompt.txt` / `title_prompt.txt` 纳入发布包默认配置
- [ ] `src/launcher.py` `CONFIG_FILES` 加入 `outfit_prompt.txt` / `title_prompt.txt`,首次运行播种
- [ ] `config_service`:`load_outfit_prompt` / `load_title_prompt` 读取前调用运行时兜底复制;用户文件存在不覆盖
- [ ] `config_service`:`load_ai_models` 在用户文件存在但缺 `app_config.title_model` 时,从 factory `ai_models.json` 追加同名模型;不覆盖同名模型、不改 `api_key`;factory 无同名只记录日志
- [ ] 测试:缺 prompt 文件时从 factory 复制;已有 prompt 不覆盖;已有 `ai_models.json` 缺标题模型时追加;已有同名标题模型不重复;factory 无同名不报错
- [ ] 验证:相关单测、全套测试、离屏启动 AI 穿搭页