Files
cmshoppe/docs/tasks/T-678.md
T
chengmaandClaude Fable 5 cd2dfe97ef docs(tasks): add custom gateway OpenAI lock and suite integration
拆成两个任务,T-678 是可独立发布的破坏性变更,T-679 依赖它。

T-678 自定义网关锁定 OpenAI 图片接口规范并支持多图输入:
- 记录当前 chat 接口类型并非 OpenAI 规范的证据(_find_image_ref 的
  跨结构搜刮器只为非标准中转网关而存在),收敛 API_TYPES 并删除
  chat/auto 请求构造。
- _image_edit_body 与 _multipart_body 支持有序多图,为 T-679 铺路;
  ②生图行为与计费口径不变。
- 记录迁移窗口:T-529 起自定义模型 UI 被硬藏,T-677 才放出,当前
  装机量几乎没有 chat 配置,现在收敛成本接近零,晚做则成为真正的
  破坏性变更。
- 存量 chat/auto 模型标记不可用而非静默改写,避免把请求打到不支持
  的端点。

T-679 商品套图接入自定义网关(主图 + 参考图):
- 指明来源耦合只有 _runtime() 与 _submit_or_resume_job() 两处接缝,
  direct 为同步路径,是跳过 submit/poll 而非补齐异步状态机。
- 记录回收守卫按 task_id 判断,direct job 天然不被拦,无需修改即可
  继续保护已扣点的 cmhub 任务;create_generation_jobs 需改写真实来源。
- 明确主体保留在 OpenAI 侧只能靠提示词,与 cmhub 服务端强制契约不
  等价,UI 须如实说明而非宣称同等效果。
- 记录三个实际问题:同步请求导致停止迟钝、超时常量需改用模型配置、
  aspect_ratio 到尺寸需换算。
- AI 帮写仍为默认网关独占(CATEGORIES 无 vision 类别)。
- 关联中写明本任务有意放宽 T-677 的边界及理由。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 17:07:08 +08:00

7.7 KiB
Raw Blame History

id, title, phase, deps, status, created
id title phase deps status created
T-678 自定义网关锁定 OpenAI 图片接口规范并支持多图输入 7
T-677
TODO 2026-07-20

T-678 自定义网关锁定 OpenAI 图片接口规范并支持多图输入

问题 / 背景

T-677 把⑤的自定义网关(ai.backend=direct)重新放出来后,暴露了 direct 生图路径的两个结构问题。

当前的 chat 接口类型并不是 OpenAI 规范。 标准 OpenAI 的 chat/completions 不返回生成的图片。本项目的 chat 生图之所以能工作,是因为 _find_image_ref()(app/ai.py:2667)是一个非常宽容的递归搜刮器,会在 choices、message、content、data、images、files 等结构里到处寻找 b64_json / image_base64 / url。这套逻辑是为把生成图塞进 chat 响应的非标准中转聚合网关准备的。api_type=auto 同样不做接口探测,chat 与 auto 实际走同一条对话请求,T-677 只能在 UI 上写一段"自动不会探测接口"的说明来遮盖这个事实。

direct 只能提交单张输入图。 _image_chat_payload()(app/ai.py:2557)的 content 数组只放一个 image_url;_image_edit_body()(app/ai.py:2569)的 files 是字典且只有一个 "image" 键,_multipart_body() 按字典遍历,结构上无法发送重复字段名。因此 T-679 要让商品套图在自定义网关下使用「主图 + 参考图」时,无法复用现有请求构造。

本任务存在时间窗口,晚做代价显著上升。 T-529 之后⑤的自定义模型 UI 被 _on_backend_changed() 无条件 setVisible(False) 硬藏,普通用户没有入口配置 chat 类型模型;该入口在 T-677(2026-07-20)才重新放出。因此当前装机量中几乎不存在可用的 chat/auto 直连配置,收敛接口规范的迁移成本接近于零。等 T-677 上线一段时间、用户配出一批 chat 模型后再收敛,就会变成真正的破坏性变更。

方案

1. 接口规范收敛

  • 自定义网关只支持 OpenAI 图片编辑接口(/v1/images/edits 形式的 multipart 请求)。appconfig.API_TYPES(app/appconfig.py:41)由 {"chat", "images_edits", "auto"} 收敛为单一取值。
  • 实现前必须按当前 OpenAI 官方文档核实多图输入字段名与模型支持范围(预期为 image[] 配合 gpt-image-1),并把核实结果与文档版本写入执行记录。文档与实现不一致时不得猜字段,按 T-596 既有约定停下并记录缺口。
  • 删除 _image_chat_payload()(app/ai.py:2557)及其在 gen_cover 中的分支(app/ai.py:348-386)。
  • _find_image_ref()(app/ai.py:2667)收敛为按标准响应结构取图(data[].b64_json / data[].url),不再跨 choices/message/content 递归搜刮。保留 data URL 与 base64 的解码分支和 _download_image() 回退。

2. 多图输入能力

  • _image_edit_body() 接受有序图片路径列表而不是单个路径:第一张为主体图,其余为参考图,按核实后的字段名发送。
  • _multipart_body()(app/ai.py:2586)的 files 由字典改为有序序列,支持同名重复字段。
  • 保留单图调用形式:②生成封面继续只发一张图,请求形式收敛但行为不变,不得因本任务改变②的生图结果口径或计费口径。
  • 本任务只提供多图能力,不改商品套图;套图接入由 T-679 完成。

3. 存量配置迁移

  • ai_models.json 中 api_type 为 chat 或 auto 的存量模型不得静默改写为新取值——请求形式不同,静默迁移会让用户在不知情的情况下把请求打到不支持的端点。
  • 载入时把这类模型标记为不可用,在⑤模型列表中以中文说明其原因(如「接口类型已不再支持,请改为 OpenAI 图片编辑接口并确认服务商支持」),并在②的自定义网关预检中作为"去⑤补齐"的一种原因。
  • 沿用 v3.1 约定:允许先保存不完整或不可用配置,不在切换来源或保存时弹阻断式校验。

4. ⑤ UI 与文案

  • 移除或降级 T-677 新增的「接口类型」下拉:只剩一种取值时不应继续以可选控件呈现。同步删除 T-677 为 auto 写的"不会探测接口"帮助文案。
  • ⑤自定义面板补充说明:自定义网关只支持 OpenAI 图片编辑接口,只做 chat 生图的中转聚合服务不可用。文案不得暴露内部实现细节或密钥。
  • 保留既有 objectName、配置键、日志字段和 app/ai.py 中文错误消息中的 cmhub 字样(沿用 T-677 第 5 节边界)。

验收要点

  • API_TYPES 只剩 OpenAI 图片编辑接口一种取值;chat 与 auto 的请求构造代码已删除,不留死分支。
  • _find_image_ref() 只按标准响应结构取图,不再跨 choices/message 搜刮;非标准响应给出可读中文错误而不是静默取错字段。
  • _image_edit_body() 与 _multipart_body() 支持有序多图,第一张为主体图;单图调用路径行为不变。
  • ②自定义网关生成封面的结果、重试、并发、日志和"不计点数"文案不回归。
  • 存量 chat/auto 模型不被静默改写,在⑤显示不可用原因,在②预检中作为补齐提示出现。
  • ⑤不再显示多取值的接口类型控件与 auto 帮助文案;新增的规范限制说明为中文且不暴露实现细节。
  • 默认网关(cmhub)的生文、生图、图片理解、异步 submit/poll、幂等键、计费与③更新蝦皮全部不受影响。

测试与文档

  • tests/test_ai.py:现有 4 处 api_type 断言(:63、:75、:307、:348)改为新规范;新增多图请求体断言(字段名、顺序、主体图在首位)与非标准响应的错误路径。
  • tests/test_appconfig.py:现有 10 处 api_type 断言(:542 起)改为新取值;补存量 chat/auto 模型载入后标记不可用且不被改写的用例。
  • tests/test_gui.py:⑤接口类型控件移除、不可用模型的中文提示、②预检把不可用模型作为补齐原因。
  • 更新 docs/cmhub-integration-design.md 修订说明(T-677 有限放开 direct,本任务进一步把 direct 收敛到 OpenAI 规范)、docs/routes.md、docs/api.md。

验证

py -3.10 -m unittest tests.test_ai tests.test_appconfig tests.test_gui
py -3.10 -m unittest discover -s tests
py -3.10 -m ruff check app tests main.py
py -3.10 -m compileall app main.py
git diff --check

边界(不改什么)

  • 不改商品套图(app/image_studio_generation.py)与图片理解(analyze_product_images()),套图接入见 T-679。
  • 不新增 vision 类别,appconfig.CATEGORIES 保持 {"text", "image"};⑥「AI 帮写」在自定义网关下继续不可用。
  • 不改 cmhub 的请求协议、重试与超时策略、异步 submit/poll 状态机、幂等键、预扣退点账本。
  • 不新增 provider 适配、接口自动探测或任意上游 URL 放行。
  • 不改 SQLite schema、Chrome/CDP、Excel 回写、蝦皮更新流程。
  • 不解除 T-596 的 BYOK 门禁;本任务仍属 direct 过渡形态范围内。

关联

  • T-677:⑤生成网关来源切换(本任务收敛其放出的 direct 接口形态)。
  • T-679:商品套图接入自定义网关(依赖本任务的多图能力)。
  • T-529:默认 cmhub 网关并隐藏 AI 后端选择(其隐藏期造就了本任务的低成本迁移窗口)。
  • T-596:BYOK 总设计与启动门禁(status: BLOCKED;正式形态仍要求经 cmhub 代理,本任务不解除该门禁)。

执行记录

(做完在这里写:改了什么文件、跑了什么验证命令及结果、遇到的阻塞、关键决策;务必记录 OpenAI 多图字段名的核实来源与文档日期。)