1
This commit is contained in:
@@ -1,15 +1,16 @@
|
||||
# 拼图 APIMart 图片模型路由接入 2026-05-01
|
||||
# 拼图图片模型路由接入 2026-05-01
|
||||
|
||||
> 2026-05-09 更新:GPT-image-2 图片生成已从 APIMart 迁移到 VectorEngine。本文保留前端模型选择和拼图扣费/持久化历史设计,图片上游接口、环境变量和请求体以 `VECTOR_ENGINE_GPT_IMAGE_2_GENERATION_2026-05-09.md` 为准。
|
||||
|
||||
## 背景
|
||||
|
||||
拼图创作已收口为填表式流程,首图生成和结果页关卡重新生成都由 `server-rs/crates/api-server/src/puzzle.rs` 执行外部图片 I/O,再把正式图写入 OSS 与 SpacetimeDB。新的模型选择只影响图片生成上游,不改变 SpacetimeDB 表结构、拼图草稿结构或前端运行时规则。
|
||||
|
||||
本轮参考 APIMart 文档:
|
||||
历史版本曾参考 APIMart 文档;当前 GPT-image-2 图片生成参考 VectorEngine Apifox 文档:
|
||||
|
||||
1. `https://docs.apimart.ai/cn/api-reference/images/gpt-image-2/generation`
|
||||
2. `https://docs.apimart.ai/cn/api-reference/images/gemini-3.1-flash/generation`
|
||||
1. `https://vectorengine.apifox.cn/api-448710071`
|
||||
|
||||
两条文档均指向 OpenAI 兼容风格的图片生成入口:`POST https://api.apimart.ai/v1/images/generations`,头部使用 `Authorization: Bearer {APIMART_API_KEY}`。请求体至少包含 `model`、`prompt`、`n`、`official_fallback = true`、`size`。返回体按 OpenAI images 兼容格式优先读取 `data[].url`,若供应商返回异步任务结构,则继续按 `task_id` / `tasks/{task_id}` 轮询并提取图片 URL。
|
||||
当前图片生成入口:`POST {VECTOR_ENGINE_BASE_URL}/v1/images/generations`,头部使用 `Authorization: Bearer {VECTOR_ENGINE_API_KEY}`。请求体至少包含 `model = gpt-image-2-all`、`prompt`、`n`、`size`,参考图使用 `image` 数组。返回体按同步 OpenAI images 结构读取 `data[].url` 或 `data[].b64_json`,不再轮询 APIMart `tasks/{task_id}`。
|
||||
|
||||
## 模型选项
|
||||
|
||||
@@ -17,8 +18,8 @@
|
||||
|
||||
| 前端显示 | 请求值 | 上游 |
|
||||
| --- | --- | --- |
|
||||
| `gpt-image-2` | `gpt-image-2` | APIMart `/v1/images/generations` |
|
||||
| `nanobanana2` | `gemini-3.1-flash-image-preview` | APIMart `/v1/images/generations` |
|
||||
| `gpt-image-2` | `gpt-image-2` | VectorEngine `/v1/images/generations`,上游模型 `gpt-image-2-all` |
|
||||
| `nanobanana2` | `gemini-3.1-flash-image-preview` | 历史兼容选项,后端回落到 VectorEngine `gpt-image-2-all` |
|
||||
|
||||
默认值为 `gpt-image-2`。前端只负责展示和传递所选模型,不能把模型路由逻辑、上游请求体拼装或 API Key 暴露到浏览器。历史草稿或旧请求中的空值、`original`、未知值统一按 `gpt-image-2` 处理,不再把拼图生图路由回 DashScope 原模型。
|
||||
|
||||
@@ -40,16 +41,15 @@
|
||||
2. `compile_puzzle_draft_with_initial_cover` 与 `generate_puzzle_image_candidates` 增加图片模型参数。
|
||||
3. `imageModel` 归一化规则:
|
||||
- 空值、`original` 或未知值统一回落为 `gpt-image-2`;
|
||||
- `gpt-image-2` 走 APIMart;
|
||||
- `gemini-3.1-flash-image-preview` 走 APIMart,前端显示名为 `nanobanana2`。
|
||||
4. APIMart 文生图和图生图共用 `POST /v1/images/generations`。有参考图时,后端将参考图 Data URL 作为 `image_urls` 数组传入;若上游不接受该字段,错误按上游失败返回,不在前端降级伪造结果。
|
||||
5. APIMart 尺寸使用文档要求的比例写法 `1:1`,所有 APIMart 图片请求体固定携带 `official_fallback = true`。`gemini-3.1-flash-image-preview` 额外带 `resolution = "1K"`,对齐约 1024px 的拼图正方形素材。
|
||||
6. APIMart 生成成功后仍下载远程图片,沿用现有 OSS 私有对象、`asset_object` 和 `asset_entity_binding` 写入流程。若图片已成功上传 OSS,但 Maincloud / SpacetimeDB 短暂返回 `503 Service Unavailable`,资产索引写入允许降级跳过,并返回本次生成图片;日志必须记录 `拼图图片资产索引写入因 SpacetimeDB 连接不可用而降级跳过`。
|
||||
7. `save_puzzle_generated_images` 写回草稿时若遇到 Maincloud 连接级 `503` 或断线,API 层基于本次生成结果合成 session 快照返回给前端,避免 APIMart 已成功出图却被后置持久化误报成服务不可用。余额不足、参数错误、上游生图失败仍按原错误返回,不做伪成功。
|
||||
8. 结果页 `generate_puzzle_images` 会携带当前作品信息和 `levelsJson`。当 Maincloud / SpacetimeDB 在读取 session 阶段就返回连接级 `503` 或断线时,后端必须先用这份结果页快照构造最小内存 session,再继续调用 APIMart;外部图片已经生成后仍按第 6、7 条处理持久化降级。余额不足、参数错误、缺少草稿快照、关卡不存在等业务错误不走此降级。
|
||||
9. APIMart 异步任务轮询按文档口径在提交后先等待 `10s`,再调用 `GET /v1/tasks/{task_id}`;图片地址提取同时支持 `url: "..."` 与 `url: ["..."]` 两种结构。
|
||||
10. APIMart 错误统一映射为 `502 UPSTREAM_ERROR`,`details.provider = "apimart"`,保留上游状态码、业务 message 和截断后的 raw excerpt。
|
||||
11. 拼图首图生成 `compile_puzzle_draft` 与关卡图片生成 `generate_puzzle_images` 每次预扣 `2` 光点;余额不足仍返回 `409 CONFLICT`,Maincloud 连接级 503 仍按既有降级策略处理。
|
||||
- `gpt-image-2` 走 VectorEngine;
|
||||
- `gemini-3.1-flash-image-preview` 不再走 APIMart,前端显示名仍为 `nanobanana2`,后端统一回落到 VectorEngine `gpt-image-2-all`。
|
||||
4. VectorEngine 文生图和图生图共用 `POST /v1/images/generations`。有参考图时,后端将参考图 Data URL 作为 `image` 数组传入;若上游不接受该字段,错误按上游失败返回,不在前端降级伪造结果。
|
||||
5. VectorEngine 拼图尺寸使用 `1024x1024`,请求体不携带 `official_fallback`。
|
||||
6. VectorEngine 生成成功后仍下载远程图片,沿用现有 OSS 私有对象、`asset_object` 和 `asset_entity_binding` 写入流程。若图片已成功上传 OSS,但 SpacetimeDB 短暂返回 `503 Service Unavailable`,资产索引写入允许降级跳过,并返回本次生成图片;日志必须记录 `拼图图片资产索引写入因 SpacetimeDB 连接不可用而降级跳过`。
|
||||
7. `save_puzzle_generated_images` 写回草稿时若遇到 SpacetimeDB 连接级 `503` 或断线,API 层基于本次生成结果合成 session 快照返回给前端,避免 VectorEngine 已成功出图却被后置持久化误报成服务不可用。余额不足、参数错误、上游生图失败仍按原错误返回,不做伪成功。
|
||||
8. 结果页 `generate_puzzle_images` 会携带当前作品信息和 `levelsJson`。当 SpacetimeDB 在读取 session 阶段就返回连接级 `503` 或断线时,后端必须先用这份结果页快照构造最小内存 session,再继续调用 VectorEngine;外部图片已经生成后仍按第 6、7 条处理持久化降级。余额不足、参数错误、缺少草稿快照、关卡不存在等业务错误不走此降级。
|
||||
9. VectorEngine 错误统一映射为 `502 UPSTREAM_ERROR`,`details.provider = "vector-engine"`,保留上游状态码、业务 message 和截断后的 raw excerpt。
|
||||
10. 拼图首图生成 `compile_puzzle_draft` 与关卡图片生成 `generate_puzzle_images` 每次预扣 `2` 光点;余额不足仍返回 `409 CONFLICT`,SpacetimeDB 连接级 503 仍按既有降级策略处理。
|
||||
|
||||
## 关卡名多模态生成
|
||||
|
||||
@@ -64,21 +64,21 @@
|
||||
新增服务端环境变量:
|
||||
|
||||
```text
|
||||
APIMART_BASE_URL="https://api.apimart.ai/v1"
|
||||
APIMART_API_KEY="YOUR_APIMART_API_KEY"
|
||||
APIMART_IMAGE_REQUEST_TIMEOUT_MS=180000
|
||||
VECTOR_ENGINE_BASE_URL="https://api.vectorengine.ai"
|
||||
VECTOR_ENGINE_API_KEY="YOUR_VECTOR_ENGINE_API_KEY"
|
||||
VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS=180000
|
||||
```
|
||||
|
||||
`APIMART_API_KEY` 只能存在于本地或部署环境,不写入 Git 跟踪文件。若选择 APIMart 模型但缺少 key,后端返回服务不可用错误,前端展示现有错误面板。
|
||||
`VECTOR_ENGINE_API_KEY` 只能存在于本地或部署环境,不写入 Git 跟踪文件。若缺少 key,后端返回服务不可用错误,前端展示现有错误面板。
|
||||
|
||||
## 验收
|
||||
|
||||
1. 创作表单和关卡详情的画面描述框左下角能切换 `gpt-image-2`、`nanobanana2`,默认显示 `gpt-image-2`。
|
||||
2. 点击“生成草稿”时,后端首图生成使用当前表单选择的模型。
|
||||
3. 点击“生成画面 / 重新生成画面”时,后端当前关卡图片生成使用关卡详情选择的模型。
|
||||
4. 历史 `original` 或空模型值不会再触发 DashScope,统一按 `gpt-image-2` 请求 APIMart。
|
||||
5. 选择 APIMart 模型时,请求 `POST {APIMART_BASE_URL}/images/generations`,使用 `Authorization: Bearer {APIMART_API_KEY}`,`model` 等于请求值,`official_fallback = true`,`size = 1:1`。
|
||||
6. 首图和结果页关卡重新生图成功后,Network 中应先完成图片生成,再调用 APIMart `POST {APIMART_BASE_URL}/chat/completions`,请求模型为 `gpt-4o-mini`,消息同时包含画面描述文本和正式图 `image_url` Data URL。
|
||||
4. 历史 `original` 或空模型值不会再触发 DashScope,统一按 `gpt-image-2` 请求 VectorEngine。
|
||||
5. 选择图片模型时,请求 `POST {VECTOR_ENGINE_BASE_URL}/v1/images/generations`,使用 `Authorization: Bearer {VECTOR_ENGINE_API_KEY}`,上游 `model = gpt-image-2-all`,不携带 `official_fallback`,`size = 1024x1024`。
|
||||
6. 首图和结果页关卡重新生图成功后,Network 中应先完成 VectorEngine 图片生成,再调用 APIMart `POST {APIMART_BASE_URL}/chat/completions`,请求模型为 `gpt-4o-mini`,消息同时包含画面描述文本和正式图 `image_url` Data URL。
|
||||
7. “生成草稿”和关卡详情生图按钮展示 `消耗2光点`;关卡详情确认后展示 30 秒预计剩余进度条。
|
||||
8. 不改 SpacetimeDB 表结构,因此无需更新 `migration.rs` 或重新生成 bindings。
|
||||
9. 后端改动后运行对应 Rust 测试,并按项目约束用 `npm run api-server` 重启验证。
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
- 每个玩法一个参考图,首版用于视觉识别,不承载规则说明。
|
||||
- 当前创作 Tab 顶部玩法卡带必须直接渲染这些图片,避免参考图只出现在隐藏弹层里。
|
||||
5. `.codex/skills/gpt-image-2-apimart/`
|
||||
- 封装仓库内 `gpt-image-2` 的 APIMart OpenAI 兼容调用流程。
|
||||
- 历史目录名保留,实际封装仓库内 `gpt-image-2` 的 VectorEngine 调用流程。
|
||||
- Skill 默认读取本地环境变量,不把密钥写入代码、文档或前端。
|
||||
|
||||
## UI 规则
|
||||
@@ -74,19 +74,17 @@
|
||||
Skill 封装仓库现有后端口径:
|
||||
|
||||
```text
|
||||
POST {APIMART_BASE_URL}/images/generations
|
||||
Authorization: Bearer {APIMART_API_KEY}
|
||||
model = gpt-image-2
|
||||
POST {VECTOR_ENGINE_BASE_URL}/v1/images/generations
|
||||
Authorization: Bearer {VECTOR_ENGINE_API_KEY}
|
||||
model = gpt-image-2-all
|
||||
n = 1
|
||||
official_fallback = true
|
||||
size = 1:1
|
||||
size = 1024x1024
|
||||
```
|
||||
|
||||
响应兼容:
|
||||
|
||||
1. `data[].url`
|
||||
2. `data[].b64_json`
|
||||
3. `task_id` 后续 `GET /tasks/{task_id}`
|
||||
|
||||
本次 Skill 只封装生成样例图和研发复用流程,不改变正式后端接口、扣费、OSS、SpacetimeDB 写入和发布链路。
|
||||
|
||||
@@ -99,12 +97,12 @@ size = 1:1
|
||||
- 未上传图片时,输入框标题为 `画面描述`。
|
||||
- 已上传图片时,输入框标题为 `画面AI重绘要求(提示词)`。
|
||||
- 展示图片模型切换。
|
||||
- `compile_puzzle_draft` 携带 `aiRedraw: true`,继续走 APIMart 生图与 `PUZZLE_IMAGE_GENERATION_POINTS_COST = 2` 扣费链路。
|
||||
- `compile_puzzle_draft` 携带 `aiRedraw: true`,继续走 VectorEngine 生图与 `PUZZLE_IMAGE_GENERATION_POINTS_COST = 2` 扣费链路。
|
||||
- 生成按钮展示 `消耗2光点`。
|
||||
2. `AI重绘=false`
|
||||
- 隐藏画面描述输入框和模型切换。
|
||||
- 必须上传拼图图片,按钮不展示 `消耗2光点`。
|
||||
- `compile_puzzle_draft` 携带 `aiRedraw: false`,后端只编译草稿和生成首关名,不调用 APIMart,不进入光点扣费 wrapper。
|
||||
- `compile_puzzle_draft` 携带 `aiRedraw: false`,后端只编译草稿和生成首关名,不调用 VectorEngine,不进入光点扣费 wrapper。
|
||||
- 后端把上传图片 Data URL 按拼图资产路径持久化,构造 `sourceType=uploaded` 的候选图并直接选为第一关正式图。
|
||||
3. 上传裁剪
|
||||
- 前端读取上传图原始宽高。
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
- [RUST_WORKSPACE_DEPENDENCY_CONSOLIDATION_2026-05-07.md](./RUST_WORKSPACE_DEPENDENCY_CONSOLIDATION_2026-05-07.md):记录 `server-rs` Cargo 依赖集中配置口径,第三方版本和 workspace 内部 crate path 统一维护在根 `server-rs/Cargo.toml`,成员 crate 只保留 feature/optional 差异。
|
||||
- [VECTOR_ENGINE_GPT_IMAGE_2_GENERATION_2026-05-09.md](./VECTOR_ENGINE_GPT_IMAGE_2_GENERATION_2026-05-09.md):记录 GPT-image-2 图片生成从 APIMart 迁移到 VectorEngine `gpt-image-2-all` 的接口、环境变量、尺寸映射、错误口径和验收命令。
|
||||
- [SPACETIMEDB_PUBLISH_SCCACHE_FALLBACK_2026-05-09.md](./SPACETIMEDB_PUBLISH_SCCACHE_FALLBACK_2026-05-09.md):记录本地 `spacetime publish` 被 sccache wrapper 通信异常阻断时的根因、`dev-rust-stack` 自动降级策略和手动排障命令。
|
||||
- [RECOMMEND_RUNTIME_AUTH_FAILURE_ISOLATION_FIX_2026-05-09.md](./RECOMMEND_RUNTIME_AUTH_FAILURE_ISOLATION_FIX_2026-05-09.md):记录平台推荐页自动加载作品、公开拼图作品完整运行态和展示层图片换签的局部请求 `401` 不应扩散成全局登出的修复,覆盖请求层局部鉴权失败隔离、推荐页 embedded 运行态启动、拼图开局/排行榜/下一关和回归测试。
|
||||
- [RECOMMEND_RUNTIME_AUTH_FAILURE_ISOLATION_FIX_2026-05-09.md](./RECOMMEND_RUNTIME_AUTH_FAILURE_ISOLATION_FIX_2026-05-09.md):记录平台推荐页自动加载作品、公开拼图作品完整运行态、平台 bootstrap 私有投影刷新和展示层图片换签的局部请求 `401` 不应扩散成全局登出的修复,覆盖 `authImpact: local` 请求策略、推荐页 embedded 运行态启动、拼图开局/排行榜/下一关和回归测试。
|
||||
- [AUTH_GATE_LOGIN_RACE_GUARD_FIX_2026-05-09.md](./AUTH_GATE_LOGIN_RACE_GUARD_FIX_2026-05-09.md):记录 `AuthGate` 登录成功后又被旧 hydrate 覆盖回未登录态的竞态根因、版本号保护修复与回归测试。
|
||||
- [HYPER3D_RODIN_GEN2_MODEL_GENERATION_2026-05-08.md](./HYPER3D_RODIN_GEN2_MODEL_GENERATION_2026-05-08.md):记录 Hyper3D Rodin Gen-2 文生 3D 模型、图生 3D 模型、状态查询和下载列表的后端代理、环境变量、请求约束与验收边界。
|
||||
- [VOLCENGINE_SPEECH_STREAMING_INTEGRATION_2026-05-08.md](./VOLCENGINE_SPEECH_STREAMING_INTEGRATION_2026-05-08.md):记录火山引擎大模型 ASR 双向流式、TTS WebSocket 双向流式和 TTS HTTP SSE 单向流式的后端代理、环境变量、协议帧和验收边界。
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
|
||||
这些请求一旦遇到本地代理错配、后端短暂不可用或 token 刷新失败,原请求层会按普通受保护请求处理 `401`,清空 access token 并广播全局鉴权变更。`AuthGate` 收到事件后重新 hydrate,于是当前用户界面被切回未登录态。
|
||||
|
||||
再次复测确认还有更深一层根因:即使单个业务请求显式传了 `clearAuthOnUnauthorized: false`,`refreshAccessToken()` 自身在 refresh 失败时也会先静默清空本地 access token。这样局部请求可能没有广播事件,却已经把本地凭证掏空;后续任意一次默认鉴权探测或 `AuthGate` hydrate 都会变成未登录。
|
||||
|
||||
推荐页进入公开拼图作品后还会伴随平台侧私有投影刷新,例如存档列表、浏览历史、个人看板和作品架列表。这些请求用于页面展示与局部缓存同步,不是账号会话权威;其中任意一个 401 都不应把整站登录态改写为未登录。
|
||||
|
||||
推荐页里还有一类更隐蔽的触发点:`ResolvedAssetImage` / `useResolvedAssetReadUrl` 在挂载时会请求 `/api/assets/read-url` 给 generated 私有图片换签。它本质上也是展示层后台请求,若按普通受保护请求处理 `401`,同样会把一次图片换签失败放大成全局掉线。
|
||||
|
||||
公开拼图作品的完整运行态还会在用户进入作品后自动发起 `startPuzzleRun`,通关后自动 `submitPuzzleLeaderboard`,点击下一关时 `advancePuzzleNextLevel`。这些请求属于当前玩法的运行态同步,失败时应该落到当前拼图错误态;它们不能清空全局 access token,也不能触发 `AuthGate` 重新 hydrate。
|
||||
@@ -26,12 +30,14 @@
|
||||
|
||||
本次把推荐页自动运行态请求定义为“卡片级后台请求”:
|
||||
|
||||
1. `apiClient` 增加 `clearAuthOnUnauthorized` 选项,允许局部请求在 `401` 时不清空全局 token。
|
||||
2. 推荐页嵌入式运行态请求统一传入 `skipRefresh: true`、`notifyAuthStateChange: false`、`clearAuthOnUnauthorized: false`。
|
||||
1. `apiClient` 增加 `authImpact: 'global' | 'local'` 策略,并导出 `BACKGROUND_AUTH_REQUEST_OPTIONS`。`local` 请求统一跳过 refresh,不清空 token,不广播 `AUTH_STATE_EVENT`。
|
||||
2. `refreshAccessToken()` 不再自行清空 token;只有 `refreshStoredAccessToken()` 这类全局会话恢复入口和默认全局请求策略能决定清 token。
|
||||
3. 推荐页嵌入式运行态请求统一使用 `BACKGROUND_AUTH_REQUEST_OPTIONS`。
|
||||
3. 推荐页自动启动作品前必须满足 `canReadProtectedData`,避免 `AuthGate` 仍在恢复阶段就提前发起受保护写请求。
|
||||
4. generated 图片换签请求同样使用局部后台鉴权选项并跳过 refresh,失败只让当前图片为空,不触发全局登录态清理。
|
||||
5. 公开拼图作品进入完整运行态后,把本次 run 标记为 `isolated` 鉴权模式;开局、重开、排行榜提交和下一关推进都沿用局部鉴权选项。
|
||||
6. Remix、发布、点赞、账号设置、退出登录等真正账号动作继续保留默认全局鉴权处理。
|
||||
6. 平台 bootstrap 的私有投影读写,包括个人看板、私有作品架、创作作品列表、浏览历史写入和存档列表刷新,也统一作为局部后台请求处理。
|
||||
7. Remix、发布、点赞、账号设置、退出登录等真正账号动作继续保留默认全局鉴权处理。
|
||||
|
||||
## 验证
|
||||
|
||||
@@ -45,6 +51,9 @@
|
||||
## 关联文件
|
||||
|
||||
1. `src/services/apiClient.ts`
|
||||
2. `src/components/platform-entry/PlatformEntryFlowShellImpl.tsx`
|
||||
3. `src/services/*-runtime/*RuntimeClient.ts`
|
||||
4. `src/services/visual-novel-works/visualNovelWorksClient.ts`
|
||||
2. `src/services/rpg-runtime/rpgRuntimeRequest.ts`
|
||||
3. `src/services/rpg-creation/rpgCreationRuntimeClient.ts`
|
||||
4. `src/components/rpg-entry/useRpgEntryBootstrap.ts`
|
||||
5. `src/components/platform-entry/PlatformEntryFlowShellImpl.tsx`
|
||||
6. `src/services/*-runtime/*RuntimeClient.ts`
|
||||
7. `src/services/visual-novel-works/visualNovelWorksClient.ts`
|
||||
|
||||
@@ -100,7 +100,7 @@ type GenerateCustomWorldOpeningCgResponse = {
|
||||
|
||||
### 5.1 故事板
|
||||
|
||||
图片模型固定使用 `gpt-image-2`,尺寸语义为 `2k`、`16:9`,当前 APIMart/OpenAI 兼容入口用 `2048x1152` 作为下游 size。
|
||||
图片模型固定使用 `gpt-image-2`,尺寸语义为 `2k`、`16:9`;2026-05-09 起实际请求 VectorEngine `gpt-image-2-all`,下游 size 按迁移文档归一为 `1536x1024`。
|
||||
|
||||
模板:
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
status=503 method=POST uri=/api/creation/square-hole/sessions/{sessionId}/actions
|
||||
```
|
||||
|
||||
该请求落在方洞 `/actions`,草稿编译成功后前端会自动追加执行 `square_hole_generate_visual_assets`。视觉资产生成依赖 APIMart OpenAI 兼容图片入口;当本地或部署环境缺少 `APIMART_API_KEY` 时,后端会在 `require_openai_image_settings()` 阶段快速返回 `503 SERVICE_UNAVAILABLE`,因此日志 latency 只有个位毫秒。
|
||||
该请求落在方洞 `/actions`,草稿编译成功后前端会自动追加执行 `square_hole_generate_visual_assets`。视觉资产生成依赖 VectorEngine GPT-image-2 图片入口;当本地或部署环境缺少 `VECTOR_ENGINE_API_KEY` 时,后端会在 `require_openai_image_settings()` 阶段快速返回 `503 SERVICE_UNAVAILABLE`,因此日志 latency 只有个位毫秒。
|
||||
|
||||
这类错误只表示“图片自动生成服务不可用”,不代表方洞草稿编译失败。前端处理规则:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user