docs: add multi-image image generation task

This commit is contained in:
QiuSW
2026-07-17 15:22:51 +08:00
parent 707941adb3
commit bd274e26e3
7 changed files with 71 additions and 9 deletions
+2
View File
@@ -99,6 +99,7 @@
| T-617 | 桌面端版本检查接口增加文件大小字段 | T-607, T-609 | 在 `GET /api/v1/client/releases/latest?platform=windows` 的当前版本响应中,为 `release` 对象新增 `size_bytes` 字段,用于桌面端下载后比对文件大小。**接口兼容**:只新增字段,不删除既有 `version` / `download_url` / `sha256` / `release_notes` / `force_update` / `published_at`;无当前版本或无下载地址时仍返回 `release:null`,不返回顶层 `size_bytes`。**数据来源**:`DownloadRelease` 新增 `size_bytes` 可空正整数字段,单位字节,django-admin 可填写并在列表展示;老数据为空时接口返回 `null`,客户端只在值为正整数时做大小校验。**安全**:接口仍公开匿名只读,不读取用户、不扣点、不暴露后台 ID、本地文件路径或内部状态。**文档**:同步 `api.md`、`routes.md`、`04-architecture.md`、`02-requirements.md`、`current-state.md`。**测试**:覆盖有值返回整数、未配置返回 `null`、未发布响应不返回顶层字段、响应字段白名单更新、admin 字段可见;`makemigrations --check` / `check` / 目标测试通过并在 `../progress.md` 留证据 | DONE |
| T-618 | 客户端发布版本后台必填文件校验元数据 | T-617 | 把 django-admin 里 `DownloadRelease` 的 `sha256` 和 `size_bytes` 改为必填,避免运营发布客户端安装包时漏填校验元数据,导致桌面端无法完整校验下载文件。**范围**:本任务只要求 admin 后台保存时必填;为兼容历史数据和现有 API 合约,第一步不直接把数据库字段改成 `NOT NULL`,`size_bytes` 仍允许旧记录为空,API 暂保持可返回 `null`;若后续要数据库级强约束,需先单独回填全量历史发布记录再做迁移。**实现**:`DownloadReleaseAdmin` 已挂专用 `ModelForm`,将 `sha256`、`size_bytes` 设为 required,并保留 `sha256` 64 位十六进制校验、`size_bytes >= 1` 校验;admin 新增 / 编辑保存时未填会显示字段级错误,不写库。**生产数据**:上线后必须补齐当前 `windows` 发布版本的 `size_bytes`,再验证 `/api/v1/client/releases/latest?platform=windows` 返回正整数 `release.size_bytes`;已有 `sha256` 继续保留并核对。**兼容性**:不删除既有 API 字段,不改变无当前版本时的 `release:null`;非 admin 的历史数据、迁移和只读接口不应因空值直接 500。**文档**:同步 `api.md`、`04-architecture.md`、`routes.md`、`current-state.md` 和 `progress.md` 的发布校验口径。**测试**:已覆盖 admin 表单缺 `sha256` / 缺 `size_bytes` 拒绝保存、合法 `sha256 + size_bytes` 可保存、API 仍能读取历史空值记录、当前版本补齐后接口返回正整数;`check` / `makemigrations --check` / 目标测试通过并在 `../progress.md` 留证据 | DONE |
| T-619 | 多张图片理解并返回文字 | T-613, T-601, T-306 | 新增独立的多模态图片理解能力,不复用“生成标题”语义。**操作与别名**:在 `ModelAlias.OperationType`、`CallRecord.OperationType` 和别名解析中新增 `vision`;建议首个数据库别名为 `vision-standard`,但不得在接口中暴露具体供应商模型名。`vision` 别名指向的 `AiModel` 及 Provider 必须同时具备 `vision` 与文字输出能力,图片生成 / 编辑专用 Provider 不得误接。**新增接口**:`POST /api/v1/analyze/images`,继承 `ExternalApiView`、使用 API Key 鉴权和生成限流,同步返回 `{text, alias, model_used, points_cost, points_balance, call_id}`;不改变 `/api/v1/generate/title`、`/api/v1/generate/image` 及异步生图接口。**请求结构**:`prompt` 必填,`model` 可选,`images` 为有序列表且至少 1 张;每项必须且只能提供一个 `image_url` 或 `image_base64`,允许 URL/base64 混合。新增 `VISION_MAX_IMAGES=8`、`VISION_MAX_IMAGE_BYTES=10485760`、`VISION_MAX_TOTAL_BYTES=33554432` 三个可配置上限,分别控制单次图片数量、单图解码后字节数和总字节数;超限、空列表、格式错误或同项双来源返回 `400 bad_request`,不扣点、不调上游。**安全时序**:serializer 后先按 T-604 审核 prompt,再下载 URL / 解码 base64;每个 URL 必须复用 T-306 的协议、公网地址、重定向逐跳校验、超时和响应大小保护,不另写弱化下载器。第一版只审核文字 prompt,不声称已做图片内容审核。**Provider**:复用 `apps/ai/providers` 现有 HTTP 适配层,增加向 Chat Completions / Gemini 发送多张图片并保序的兼容能力;不得复制第二套上游调用实现。现有单图标题 / 生图调用签名与行为保持兼容。**计费与留痕**:复用 T-613 共享生成 core 与 billing 的预扣 / 成功确认 / 幂等退点;第一版按 `operation_type=vision + alias` 的默认 `PricingRule` 对一次请求固定扣点,不按图片张数重复扣费,图片数量上限用于控制成本;上游失败必须退点。`CallRecord` 记录 `vision`、别名、实际模型、点数、耗时和结果摘要,不保存输入图片、base64、provider raw 或完整上游响应。**目录与运营配置**:`GET /api/v1/models` 和 portal 可用模型页按 T-601 既有语义列出 active、能力匹配的 `vision` 别名并显示 `requires_image=true`;有定价时返回 `priced`,缺定价时仍返回 `unpriced`,不得改变现有目录兼容行为。代码部署 / migrate 后由运营在 admin 配置支持视觉理解的 `AiModel`、`vision-standard` 默认别名和计费规则,不通过数据迁移写入真实上游配置或密钥。**范围边界**:本任务只做同步文字结果,不做流式输出、异步 vision task、OCR 专用接口、结构化 JSON schema、图片内容审核,也不为 OCR / 商品识别 / 图片对比各建别名;这些用途先由 prompt 表达,只有底层模型或价格确实不同时再增加别名。**文档**:实现时同步 `02-requirements.md`、`04-architecture.md`、`api.md`、`routes.md`、`env.md`、`current-state.md` 和 `progress.md`。**测试**:覆盖单图 / 多图 / 混合来源及顺序、默认 / 指定别名、模型与 Provider 能力拒绝、图片数量与大小限制、SSRF、敏感词先拦截、成功仅扣一次、上游失败仅退一次、调用记录不保存图片 / raw、模型目录安全字段、旧标题 / 生图接口回归;`makemigrations` / `migrate` / `check` / 目标测试 / `init` 通过并在 `../progress.md` 留证据 | DONE |
| T-620 | 图生图支持单图 / 多图主图与参考图 | T-613, T-614, T-616, T-619 | 扩展现有同步与异步图生图接口,使调用方可以提交单张或多张输入图片,并把全部图片按原顺序与提示词一起发送给中转站。**接口兼容**:`POST /api/v1/generate/image` 与 `POST /api/v1/generate/image/tasks` 新增有序 `images` 列表;每项必须且只能提供 `image_url` 或 `image_base64`。旧的单个 `image_url` / `image_base64` 字段继续可用,单图旧请求的响应、状态码、计费和错误语义不变;新旧字段同时出现、空列表、空图片项或超过限制时返回 `400 bad_request`,不得静默选择其中一套输入。**图片角色**:服务端固定注入图生图规则:`images[0]` 是主商品图,必须优先保留其主体与关键细节;`images[1:]` 仅作为风格、构图、场景或排版参考,不得替换主图商品。客户端提示词不能关闭或覆盖该规则;用户原始 prompt 仍先做 T-604 敏感词审核,固定规则只作为发送给上游的有效 prompt 组成部分。**输入与安全**:按顺序加载所有图片,新增 `IMAGE_MAX_INPUT_IMAGES=8`、`IMAGE_MAX_INPUT_IMAGE_BYTES=10485760`、`IMAGE_MAX_INPUT_TOTAL_BYTES=33554432`(或明确复用等价的统一多图上限);每个 `image_url` 继续复用 T-306 的公网校验、逐跳重定向校验、超时和流式大小保护;输入校验、敏感词、SSRF、大小或别名/定价错误发生在预扣前,不扣点、不调上游。一次请求无论单图还是多图只按当前 `image` 别名 / 分辨率规则扣一次,上游失败沿用既有幂等退点。**Provider 传递**:`apps/ai/providers` 的生成接口增加有序图片集合能力并保留旧单图调用兼容;Chat Completions 按顺序发送多段图片内容;JSON 图片接口按中转站契约发送有序 `image_urls` / `images` 数组;`images_edits` multipart 按顺序重复发送 `image` 字段。不得只发送第一张,也不得把第二张及之后的图拼接成一张图片。实现必须使用服务端固定规则明确主图 / 参考图语义;真实中转站验收使用两张明显不同的图片,确认多图请求返回图片。**异步任务**:`ImageGenerationTask` 需支持多个有序输入文件;建议新增任务输入子表(任务、序号、文件、MIME / 文件名),保留旧单 `input_image` 记录的读取兼容,不把 base64 原文或 provider raw 存入数据库;幂等提交、worker 重试、租约回收、成功确认和失败退款逻辑不复制第二套。**响应与留痕**:成功响应仍返回一个 `image_url`、`alias`、`model_used`、`points_cost`、`points_balance`、`call_id`;`CallRecord` 只记录输入数量等非敏感摘要,不保存 base64、完整 prompt、输入图片内容或 provider raw。**文档**:实现时同步 `02-requirements.md`、`04-architecture.md`、`api.md`、`routes.md`、`env.md`、`deployment.md`、`current-state.md` 和 `progress.md`,明确 `images[0]` 主图、`images[1:]` 参考图及中转站字段映射。**测试**:覆盖旧单图字段、`images` 单图、多图和混合 URL/base64;断言图片顺序传入 Chat / JSON / multipart Provider,固定主图规则出现在上游 prompt;断言新旧字段混用、空列表、超限、SSRF、敏感词和无定价均不扣点;同步与异步成功各只扣一次,失败/重试/僵任务退款不重复;幂等提交与跨用户轮询不回归;输入文件不泄露原始 base64;使用真实中转站两张不同图片完成一次成功验收;`makemigrations` / `migrate` / `check` / 目标测试 / `init` 通过并在 `../progress.md` 留证据 | TODO |
## 里程碑
@@ -117,6 +118,7 @@
- M13:桌面端版本文件大小校验元数据(T-617)。
- M14:客户端发布版本后台必填校验元数据(T-618)。
- M15:多张图片理解并返回文字(T-619)。
- M16:图生图支持单图 / 多图主图与参考图(T-620)。
## 待办池(Backlog)