feat(ai): enforce direct image edit contract
This commit is contained in:
+4
-2
@@ -73,6 +73,8 @@ update_ai_model(name, **fields) -> None
|
||||
delete_ai_model(name) -> None # 至少各留一个 text+image;删到剩一禁用
|
||||
model_request_url(model) -> str # url 为 /v1 或 /api/v1 base 时按 api_type 补 /chat/completions 或 /images/edits
|
||||
test_ai_model(name) -> dict # 「测试连接」:用 key/url/model 发最小请求 -> {ok, status?, error?}
|
||||
check_image_model_config(name) -> dict # 图片模型本地校验,不发网络/计费请求 -> {ok, check_only, error?}
|
||||
is_image_edit_model(model) -> bool # category=image 且 api_type=images_edits
|
||||
get_model(name) -> dict # 返回模型定义,含 api_key(调用方不得写日志)
|
||||
```
|
||||
|
||||
@@ -330,7 +332,7 @@ fetch_cmhub_models(base_url, api_key, connect_timeout=10, read_timeout=30) -> li
|
||||
|
||||
要点:
|
||||
|
||||
- `backend=direct`:设置页「自定义网关」的客户端直连兼容路径;标题用 `default_text_model`、封面用 `default_image_model`(`appconfig.get_model` 取定义,含 url/key/api_type)。②在创建 worker 前按本轮生成内容校验所需模型;运行中使用冻结的内存模型快照,不重读 `ai_models.json`。它不支持图片理解或商品套图新建任务。
|
||||
- `backend=direct`:设置页「自定义网关」的客户端直连兼容路径;标题用 `default_text_model`,保留 `chat` / `auto`;封面用 `default_image_model`,只接受 `category=image` 且 `api_type=images_edits`(`appconfig.get_model` 取定义,含 url/key/api_type)。封面固定 `POST /v1/images/edits`,multipart 中按顺序重复 `image[]`,首项是主体图,固定 `n=1`,只读取 `data[].b64_json` 或 `data[].url`,仅允许 data URL/base64/HTTP(S) 下载结果。②在创建 worker 前按本轮生成内容校验所需模型;运行中使用冻结的内存模型快照,不重读 `ai_models.json`。历史 `chat` / `auto` 图片模型仍可保存和查看,但不可提交图片生成。它不支持图片理解或商品套图新建任务。
|
||||
- `backend=cmhub`:设置页「默认网关」及普通产品默认路径;标题调用 `POST /api/v1/generate/title`;②批量封面生成调用 `POST /api/v1/generate/image/tasks` + `GET /api/v1/generate/image/tasks/{task_id}`,模型字段使用 `ai.cmhub.title_alias/image_alias`,Key 来自 `data/config/cmhub.json`。商品套图中的「AI帮写」单独调用 `POST /api/v1/analyze/images`,只使用 `ai.cmhub.vision_alias`,不得回退或混用生文/生图别名;同一商品项目的原图在一条请求内联合理解,用户勾选状态不参与选图。`gen_cover()` 单独调用没有任务/DB 上下文,第一版保留旧同步 `POST /api/v1/generate/image` 兼容路径。
|
||||
- 标题提示词组装:`gen_title()` 的 direct 与 cmhub 路径共用标题 prompt 规则。若标题提示词包含 `{旧标题}`,生成前替换为该任务旧标题,不再自动追加旧标题块;若不包含 `{旧标题}`,保持旧行为自动追加“旧标题:...”块。两种情况都会追加“请只返回新标题,不要解释。”输出约束;其它 `{...}` 原样保留。
|
||||
- `fetch_cmhub_models()` 调 `GET /api/v1/models` 返回别名清单,供设置页动态下拉、商品套图 AI帮写和商品套图正式生成的付费前确认共用;Base URL 会先规整为网关根,HTTP 404 映射为 `not_found` 并提示检查 Base URL 或实例是否部署 `/api/v1/models`。GUI 只在进程内按规整网关地址和别名短期缓存公开模型元数据,不缓存 API Key,也不写入配置、SQLite、日志或导出。AI帮写仅在当前 `vision_alias` 命中 `operation_type=vision`、`requires_image=true`、`pricing_status=priced` 且有唯一无条件 `points_cost` 时显示预计扣点;正式套图同样只在当前 `image_alias` 命中唯一无条件的图片生图价格时显示单张和按最终 `specs` 计算的总价。其它情况只提示实际以网关返回为准,预估值不参与扣减或成功判定。
|
||||
@@ -505,7 +507,7 @@ T-523 后 GUI 已从旧 `app/gui.py` 拆为 `app/gui/` 包:`__init__.py` 负
|
||||
设置当前要点(T-501):
|
||||
|
||||
- `SettingsTab` 使用居中内容区 + 适度左右留白布局,当前留白已从 T-506 初始实现缩短到约 40%;实现上使用最大内容宽度和自适应 margin,避免固定像素导致小屏挤压。各设置组默认响应式 3 列表单:短字段占 1 格,长字段(URL/API Key/路径)跨 2 格或 3 格,窄窗口降为 2 列/1 列。点击「保存设置」成功后,调用 `QMessageBox.information` 弹出“设置已保存”轻量提示框,同时保留状态栏提示。T-531 已完成:`save_app_settings()` 返回 bool,成功写 `data/config.json` + `data/config/cmhub.json` 后清 dirty,失败保留 dirty 并让调用方阻止离开。
|
||||
- `SettingsTab` 的生成网关配置:用 `gatewayDefaultButton` / `gatewayCustomButton` 分段选择器表达 `cmhub` / `direct` 来源,选择仅标记待保存,保存后才写 `ai.backend`。默认网关 Base URL 保存/刷新前规整为网关根,API Key 单独读写 `data/config/cmhub.json`,别名下拉来自 `fetch_cmhub_models()`;自定义网关复用 `data/config/ai_models.json` 的模型 CRUD 与文本/图片角色选择。两套配置并存,模型 CRUD 立即保存;`refresh_cmhub_models()` / `test_cmhub_connection()` 使用输入框实时值但不得自动保存。`settingsSaved` 通知主窗口刷新⑥能力状态;`is_dirty()` / `discard_unsaved_changes()` / `_suspend_dirty`(或等价机制)用于保存和放弃来源选择。
|
||||
- `SettingsTab` 的生成网关配置:用 `gatewayDefaultButton` / `gatewayCustomButton` 分段选择器表达 `cmhub` / `direct` 来源,选择仅标记待保存,保存后才写 `ai.backend`。默认网关 Base URL 保存/刷新前规整为网关根,API Key 单独读写 `data/config/cmhub.json`,别名下拉来自 `fetch_cmhub_models()`;自定义网关复用 `data/config/ai_models.json` 的模型 CRUD 与文本/图片角色选择。图片模型只展示「OpenAI 图片编辑接口」;历史不兼容配置保留并标示。图片模型的「检查图片配置」只做本地校验,不发送网络图片请求。两套配置并存,模型 CRUD 立即保存;`refresh_cmhub_models()` / `test_cmhub_connection()` 使用输入框实时值但不得自动保存。`settingsSaved` 通知主窗口刷新⑥能力状态;`is_dirty()` / `discard_unsaved_changes()` / `_suspend_dirty`(或等价机制)用于保存和放弃来源选择。
|
||||
- T-532 要求 `SettingsTab._on_cmhub_finished()` 从 worker payload 的 `balance` / user/account 字段提取 cmhub 账号身份,成功文案优先显示 `cmhub 账号「<账号名>」连接成功:...`;当前 `/balance` 结构兼容 `{ "user": "cmhub_user", "points_balance": 88, "account": { "username": "cmhub_user", "display_name": "主账号" } }`,显示名优先 `account.display_name`,再兜底 `account.username` / `user` / 顶层常见字段;账号字段缺失时保持 `cmhub 连接成功:...`。显示名必须脱敏处理邮箱,且不得把 API Key、token 或完整敏感响应写入 GUI、run log 或诊断日志。
|
||||
- `MainWindow` 已负责设置页离开守卫:切 Tab 与 `closeEvent` 发现 `SettingsTab.is_dirty()` 时弹保存/放弃/取消;保存成功后继续,保存失败或取消时回到设置。由于 `QTabWidget.currentChanged` 是切换后信号,需维护上一个 index,并用 `_reverting_tab_change` 或等价 guard 防止 `setCurrentIndex()` 递归。
|
||||
- 模型详情字段按 3 个组件一组排列:启用、类别、api_type、连接超时等短字段一格;服务商名、模型 ID 视宽度占一格或两格;网址、密钥跨整行或跨 2/3 列。
|
||||
|
||||
Reference in New Issue
Block a user