docs: add multi-image image generation task
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
ai_models.json
|
ai_models.json
|
||||||
.secrets/
|
.secrets/
|
||||||
secrets/
|
secrets/
|
||||||
|
deploy/
|
||||||
|
|
||||||
# Python / Django local artifacts
|
# Python / Django local artifacts
|
||||||
__pycache__/
|
__pycache__/
|
||||||
@@ -15,6 +16,7 @@ htmlcov/
|
|||||||
db.sqlite3
|
db.sqlite3
|
||||||
media/
|
media/
|
||||||
staticfiles/
|
staticfiles/
|
||||||
|
xiaxiuxiu_outputs/
|
||||||
|
|
||||||
# Local virtual environments
|
# Local virtual environments
|
||||||
.venv/
|
.venv/
|
||||||
@@ -23,3 +25,5 @@ venv/
|
|||||||
# Editor / OS noise
|
# Editor / OS noise
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
api_key.txt
|
||||||
|
cmhub_api_key.txt
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ Python 3.12 / Django 5.2 LTS + DRF / django-admin / 用户端 Django 模板 SSR
|
|||||||
|
|
||||||
Phase 2 计费核心已完成,Phase 3 对外 API 与充值已完成到 T-306,Phase 4 用户端已完成 T-501~T-505,Phase 5 已完成 T-401 运营后台完善、T-402 MVP 完整验收与 T-403 部署 / 运行文档,Phase 6 已完成 T-601 可用别名发现、T-602/T-603 django-admin 中文化、T-604 中文敏感词本地过滤、T-605 免邮箱验证策略落地、T-606 公开首页 + 客户端下载入口、T-607 桌面端最新版本检查接口、T-608 新用户注册赠送 100 点试用点数、T-609 桌面端版本强制更新标记、T-610 首页导入模板下载入口、T-611 用户端品牌名统一为“虾皮圈”、T-612 生图同步接口止血、T-613 抽生成核心 service、T-614 生图异步任务化接口、T-615 旧同步生图接口遥测 / 弃用口径、T-616 生图失败自动重试 2 次、T-617 桌面端版本文件大小字段与 T-618 客户端发布版本后台必填校验元数据。用户可通过公开首页进入注册、登录、下载客户端和下载导入模板;新用户注册后经计费层自动获得 100 点并写注册赠点流水;登录后可扫码充值并轮询到账,生成 / 删除(吊销)API Key,查看余额、充值总额、分页充值记录、分页点数记录与可用模型;桌面端可匿名请求最新客户端版本 JSON,并读取 `release.force_update` 判断是否必须升级、读取 `release.size_bytes` 校验安装包大小;新版桌面端可用异步生图提交 / 轮询接口,旧同步生图接口继续兼容并写结构化用量日志;运营可在 django-admin 检索用户、钱包、API Key、计费规则、汇率、充值订单、点数流水、注册赠点记录、调用记录、图片生成任务、客户端发布版本和导入模板,客户端发布版本新增 / 编辑时必须填写 SHA256 与文件大小,并通过计费层带原因手工调点。生产侧仍需补真实支付回调到账闭环,并按日志观察旧同步生图接口迁移进度。详见 [`docs/current-state.md`](docs/current-state.md)。
|
Phase 2 计费核心已完成,Phase 3 对外 API 与充值已完成到 T-306,Phase 4 用户端已完成 T-501~T-505,Phase 5 已完成 T-401 运营后台完善、T-402 MVP 完整验收与 T-403 部署 / 运行文档,Phase 6 已完成 T-601 可用别名发现、T-602/T-603 django-admin 中文化、T-604 中文敏感词本地过滤、T-605 免邮箱验证策略落地、T-606 公开首页 + 客户端下载入口、T-607 桌面端最新版本检查接口、T-608 新用户注册赠送 100 点试用点数、T-609 桌面端版本强制更新标记、T-610 首页导入模板下载入口、T-611 用户端品牌名统一为“虾皮圈”、T-612 生图同步接口止血、T-613 抽生成核心 service、T-614 生图异步任务化接口、T-615 旧同步生图接口遥测 / 弃用口径、T-616 生图失败自动重试 2 次、T-617 桌面端版本文件大小字段与 T-618 客户端发布版本后台必填校验元数据。用户可通过公开首页进入注册、登录、下载客户端和下载导入模板;新用户注册后经计费层自动获得 100 点并写注册赠点流水;登录后可扫码充值并轮询到账,生成 / 删除(吊销)API Key,查看余额、充值总额、分页充值记录、分页点数记录与可用模型;桌面端可匿名请求最新客户端版本 JSON,并读取 `release.force_update` 判断是否必须升级、读取 `release.size_bytes` 校验安装包大小;新版桌面端可用异步生图提交 / 轮询接口,旧同步生图接口继续兼容并写结构化用量日志;运营可在 django-admin 检索用户、钱包、API Key、计费规则、汇率、充值订单、点数流水、注册赠点记录、调用记录、图片生成任务、客户端发布版本和导入模板,客户端发布版本新增 / 编辑时必须填写 SHA256 与文件大小,并通过计费层带原因手工调点。生产侧仍需补真实支付回调到账闭环,并按日志观察旧同步生图接口迁移进度。详见 [`docs/current-state.md`](docs/current-state.md)。
|
||||||
|
|
||||||
T-619 已完成:新增独立 `vision` 能力和同步 `POST /api/v1/analyze/images` 多图理解接口,按一次请求固定扣点;既有标题、生图和异步生图接口保持兼容。生产启用前需在 admin 配置同时具备 `text`、`vision` 能力的模型、`vision-standard` 默认别名及默认计费规则。
|
T-619 已完成:新增独立 `vision` 能力和同步 `POST /api/v1/analyze/images` 多图理解接口,按一次请求固定扣点;既有标题、生图和异步生图接口保持兼容。生产启用前需在 admin 配置同时具备 `text`、`vision` 能力的模型、`vision-standard` 默认别名及默认计费规则。T-620 已登记:图生图接口支持单图 / 多图,第一张为主图、后续为参考图。
|
||||||
|
|
||||||
> ⚠️ 涉及资金/点数。改动充值、扣费、退款、对账相关代码前,先读 [`docs/05-coding-rules.md`](docs/05-coding-rules.md) 第 8 节与 [`docs/04-architecture.md`](docs/04-architecture.md) 第四节计费时序。
|
> ⚠️ 涉及资金/点数。改动充值、扣费、退款、对账相关代码前,先读 [`docs/05-coding-rules.md`](docs/05-coding-rules.md) 第 8 节与 [`docs/04-architecture.md`](docs/04-architecture.md) 第四节计费时序。
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
当前项目处于:**Phase 6 增强任务推进期**。Phase 2 计费核心已完成到 T-204;Phase 3 已完成 T-301 API Key 鉴权、T-302 生成标题 / 图片接口、T-303 余额查询接口、T-304 充值回调、T-305 扫码充值下单 + 轮询与 T-306 对外 API 安全加固;Phase 4 已完成 T-501 注册 / 登录(allauth)、T-502 API Key 自助管理页、T-503 个人中心 / 记录页、T-504 充值页与 T-505 用户端审核优化;Phase 5 已完成 T-401 运营后台完善、T-402 MVP 完整验收与 T-403 部署 / 运行文档;Phase 6 已完成 T-601「可用别名发现」、T-602「django-admin 中文化第 1-3 层」、T-603「django-admin 字段级中文化」、T-604「中文敏感词本地过滤」、T-605「免邮箱验证策略落地」、T-606「公开首页 + 客户端下载入口」、T-607「桌面端最新版本检查接口」、T-608「新用户注册赠送 100 点试用点数」、T-609「桌面端版本检查接口增加强制更新标记」、T-610「首页导入模板下载入口」、T-611「用户端品牌名统一为虾皮圈」、T-612「生图同步接口止血」、T-613「抽生成核心 service」、T-614「生图异步任务化接口」与 T-615「旧同步生图接口遥测 / 弃用口径」。生图慢 / 504 / 客户端超时已拆为 T-612~T-615 并完成:T-612 已做同步接口上游硬截止止血,T-613 已抽共享生成 core,T-614 已新增异步提交 / 轮询接口与 DB worker,T-615 已给旧同步 / 新异步提交路径接入结构化日志并形成旧同步接口退出条件。生产侧仍需补真实支付回调到账闭环;邮件服务仅用于后续密码找回/通知等邮件能力,不阻塞注册登录。
|
当前项目处于:**Phase 6 增强任务推进期**。Phase 2 计费核心已完成到 T-204;Phase 3 已完成 T-301 API Key 鉴权、T-302 生成标题 / 图片接口、T-303 余额查询接口、T-304 充值回调、T-305 扫码充值下单 + 轮询与 T-306 对外 API 安全加固;Phase 4 已完成 T-501 注册 / 登录(allauth)、T-502 API Key 自助管理页、T-503 个人中心 / 记录页、T-504 充值页与 T-505 用户端审核优化;Phase 5 已完成 T-401 运营后台完善、T-402 MVP 完整验收与 T-403 部署 / 运行文档;Phase 6 已完成 T-601「可用别名发现」、T-602「django-admin 中文化第 1-3 层」、T-603「django-admin 字段级中文化」、T-604「中文敏感词本地过滤」、T-605「免邮箱验证策略落地」、T-606「公开首页 + 客户端下载入口」、T-607「桌面端最新版本检查接口」、T-608「新用户注册赠送 100 点试用点数」、T-609「桌面端版本检查接口增加强制更新标记」、T-610「首页导入模板下载入口」、T-611「用户端品牌名统一为虾皮圈」、T-612「生图同步接口止血」、T-613「抽生成核心 service」、T-614「生图异步任务化接口」与 T-615「旧同步生图接口遥测 / 弃用口径」。生图慢 / 504 / 客户端超时已拆为 T-612~T-615 并完成:T-612 已做同步接口上游硬截止止血,T-613 已抽共享生成 core,T-614 已新增异步提交 / 轮询接口与 DB worker,T-615 已给旧同步 / 新异步提交路径接入结构化日志并形成旧同步接口退出条件。生产侧仍需补真实支付回调到账闭环;邮件服务仅用于后续密码找回/通知等邮件能力,不阻塞注册登录。
|
||||||
|
|
||||||
T-616~T-619 也已完成:生图失败自动重试、客户端版本文件校验元数据、多图理解 `vision` 操作与同步接口均已落地。生产启用多图理解前仍需在 admin 配置视觉模型、默认别名和计费规则。
|
T-616~T-619 也已完成:生图失败自动重试、客户端版本文件校验元数据、多图理解 `vision` 操作与同步接口均已落地。生产启用多图理解前仍需在 admin 配置视觉模型、默认别名和计费规则。T-620 已登记为下一项:扩展同步 / 异步图生图接口接收单图或多图,并约定第一张为主图、后续为参考图。
|
||||||
|
|
||||||
优先路径:
|
优先路径:
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ T-616~T-619 也已完成:生图失败自动重试、客户端版本文件校
|
|||||||
4. Phase 3:对外 API 与充值 —— T-301 Key 鉴权、T-302 生成接口、T-303 余额查询、T-304 充值回调、T-305 扫码下单与轮询、T-306 安全加固已完成。
|
4. Phase 3:对外 API 与充值 —— T-301 Key 鉴权、T-302 生成接口、T-303 余额查询、T-304 充值回调、T-305 扫码下单与轮询、T-306 安全加固已完成。
|
||||||
5. Phase 4:用户端(Django 模板 SSR)—— T-501 注册登录、T-502 API Key 管理、T-503 个人中心 / 记录页、T-504 充值页与 T-505 用户端审核优化已完成。
|
5. Phase 4:用户端(Django 模板 SSR)—— T-501 注册登录、T-502 API Key 管理、T-503 个人中心 / 记录页、T-504 充值页与 T-505 用户端审核优化已完成。
|
||||||
6. Phase 5:后台与发布 —— T-401 运营后台完善、T-402 完整验收 MVP、T-403 部署 / 运行文档已完成;计划内 MVP 任务已收尾。
|
6. Phase 5:后台与发布 —— T-401 运营后台完善、T-402 完整验收 MVP、T-403 部署 / 运行文档已完成;计划内 MVP 任务已收尾。
|
||||||
7. Phase 6:增强(MVP 后)—— T-601~T-619 已完成,覆盖可用别名发现、后台中文化、敏感词过滤、免邮箱验证、公开首页与客户端发布、注册赠点、用户端品牌、生图异步化 / 遥测 / 自动重试、客户端发布校验元数据和同步多图理解;当前没有已登记的下一编号任务。
|
7. Phase 6:增强(MVP 后)—— T-601~T-619 已完成,覆盖可用别名发现、后台中文化、敏感词过滤、免邮箱验证、公开首页与客户端发布、注册赠点、用户端品牌、生图异步化 / 遥测 / 自动重试、客户端发布校验元数据和同步多图理解;T-620「图生图支持单图 / 多图主图与参考图」已登记为下一项 `TODO`。
|
||||||
|
|
||||||
## 领取任务规则
|
## 领取任务规则
|
||||||
|
|
||||||
|
|||||||
@@ -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-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-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-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)。
|
- M13:桌面端版本文件大小校验元数据(T-617)。
|
||||||
- M14:客户端发布版本后台必填校验元数据(T-618)。
|
- M14:客户端发布版本后台必填校验元数据(T-618)。
|
||||||
- M15:多张图片理解并返回文字(T-619)。
|
- M15:多张图片理解并返回文字(T-619)。
|
||||||
|
- M16:图生图支持单图 / 多图主图与参考图(T-620)。
|
||||||
|
|
||||||
## 待办池(Backlog)
|
## 待办池(Backlog)
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,8 @@
|
|||||||
- T-614/T-616 生产代码补充:已新增 `ImageGenerationTask` 与 `api.0001_initial`,新增 `POST /api/v1/generate/image/tasks`、`GET /api/v1/generate/image/tasks/{task_id}`、`apps.api.image_tasks` 任务服务、`run_image_tasks` management command 和只读 admin;异步提交支持 `Idempotency-Key` 去重 / 冲突检测,worker 使用 DB 任务表、租约、心跳与 reaper,成功返回 cmhub 托管 URL;T-616 已通过 `api.0002_imagegenerationtask_next_attempt_at_and_more` 增加 `next_attempt_at` 与 `(status, next_attempt_at)` 索引,临时性 `upstream_timeout` / `upstream_error` 默认最多重试 2 次,重试期间不退点,最终失败 / 僵任务才走计费层幂等退款。
|
- T-614/T-616 生产代码补充:已新增 `ImageGenerationTask` 与 `api.0001_initial`,新增 `POST /api/v1/generate/image/tasks`、`GET /api/v1/generate/image/tasks/{task_id}`、`apps.api.image_tasks` 任务服务、`run_image_tasks` management command 和只读 admin;异步提交支持 `Idempotency-Key` 去重 / 冲突检测,worker 使用 DB 任务表、租约、心跳与 reaper,成功返回 cmhub 托管 URL;T-616 已通过 `api.0002_imagegenerationtask_next_attempt_at_and_more` 增加 `next_attempt_at` 与 `(status, next_attempt_at)` 索引,临时性 `upstream_timeout` / `upstream_error` 默认最多重试 2 次,重试期间不退点,最终失败 / 僵任务才走计费层幂等退款。
|
||||||
- T-617 生产代码补充:`DownloadRelease` 已新增 `size_bytes` 可空正整数字段和迁移 `portal.0004_downloadrelease_size_bytes`,django-admin 可填写并在列表展示;`GET /api/v1/client/releases/latest` 的 `release` 对象新增 `size_bytes`,有值返回整数,未配置返回 `null`,未发布时仍只返回 `release:null`。
|
- T-617 生产代码补充:`DownloadRelease` 已新增 `size_bytes` 可空正整数字段和迁移 `portal.0004_downloadrelease_size_bytes`,django-admin 可填写并在列表展示;`GET /api/v1/client/releases/latest` 的 `release` 对象新增 `size_bytes`,有值返回整数,未配置返回 `null`,未发布时仍只返回 `release:null`。
|
||||||
- T-618 生产代码补充:`DownloadReleaseAdmin` 已挂专用 `ModelForm`,后台新增 / 编辑客户端发布版本时 `sha256` 与 `size_bytes` 必填;数据库字段仍兼容历史空值,API 仍可读取历史 `size_bytes=null` 记录。
|
- T-618 生产代码补充:`DownloadReleaseAdmin` 已挂专用 `ModelForm`,后台新增 / 编辑客户端发布版本时 `sha256` 与 `size_bytes` 必填;数据库字段仍兼容历史空值,API 仍可读取历史 `size_bytes=null` 记录。
|
||||||
- T-619 生产代码补充:`ModelAlias` / `CallRecord` 已新增 `vision` 操作并生成 `ai.0005` / `billing.0008` 迁移;`POST /api/v1/analyze/images` 已接入 API Key 鉴权、生成限流、prompt 前置审核、有序多图 URL/Base64 读取、SSRF 与大小保护、Chat/Gemini 多模态 Provider、固定单次预扣 / 成功确认 / 幂等退款及安全调用摘要。模型目录与 portal 可用模型页会展示能力匹配的 active `vision` 别名并标记 `requires_image=true`。生产仍需配置同时具备 `text`、`vision` 能力的 `AiModel`、`vision-standard` 默认别名和默认 `PricingRule`。
|
- T-619 生产代码补充:`ModelAlias` / `CallRecord` 已新增 `vision` 操作并生成 `ai.0005` / `billing.0008` 迁移;`POST /api/v1/analyze/images` 已接入 API Key 鉴权、生成限流、prompt 前置审核、有序多图 URL/Base64 读取、SSRF 与大小保护、Chat/Gemini 多模态 Provider、固定单次预扣 / 成功确认 / 幂等退款及安全调用摘要。模型目录与 portal 可用模型页会展示能力匹配的 active `vision` 别名并标记 `requires_image=true`。2026-07-16 已在 `185.216.248.75` 部署 `707941a` 并应用迁移,复用 active `GPT-5.5 文本`(`text + vision`)创建默认 active `vision-standard`,默认价格为 1 点/次;Nginx 已把该同步接口分流到 `cmhub-generate` 长请求池。
|
||||||
|
- T-619 生产验收:真实提交两张图片成功返回中文文字,HTTP 200,`model_used=gpt-5.5`,`call_id=6096`;余额 234→233,调用记录为 `vision/success`,对应 consume 1 条、refund 0 条。验收临时 API Key 已吊销;`cmhub-web`、`cmhub-generate`、Nginx、MySQL 8.4 均为 active,66 个异步生图 worker 未因本次部署重启。
|
||||||
- 最新验证:T-619 已完成 `ai.0005_alter_modelalias_operation_type` 与 `billing.0008_alter_callrecord_operation_type_and_more` 迁移并应用到当前开发库;`manage.py check` 0 issues,`makemigrations --check --dry-run` 无变化;Provider 专项 10 tests OK,T-619 API / 别名 / 目录专项 13 tests OK,包含旧标题 / 生图的扩展回归 84 tests OK,users / billing / moderation 分组 46 tests OK。完整单命令回归在 604 秒达到执行器超时,之后 API 全量重试在测试库初始化阶段遇到远程 MySQL `43.128.3.240` 连接超时,均未产生断言失败;测试期仍有 allauth 在 MySQL 条件唯一约束上的既有 `models.W036` 警告。
|
- 最新验证:T-619 已完成 `ai.0005_alter_modelalias_operation_type` 与 `billing.0008_alter_callrecord_operation_type_and_more` 迁移并应用到当前开发库;`manage.py check` 0 issues,`makemigrations --check --dry-run` 无变化;Provider 专项 10 tests OK,T-619 API / 别名 / 目录专项 13 tests OK,包含旧标题 / 生图的扩展回归 84 tests OK,users / billing / moderation 分组 46 tests OK。完整单命令回归在 604 秒达到执行器超时,之后 API 全量重试在测试库初始化阶段遇到远程 MySQL `43.128.3.240` 连接超时,均未产生断言失败;测试期仍有 allauth 在 MySQL 条件唯一约束上的既有 `models.W036` 警告。
|
||||||
- 验证补充:API 全量 88 条测试已重试两次,均在执行断言前因远程 MySQL 握手超时中断;`Test-NetConnection 43.128.3.240 -Port 3306` 同期显示 TCP 可达。收尾 `./init.ps1` 通过(Python 3.12.3,Django system check 0 issues)。
|
- 验证补充:API 全量 88 条测试已重试两次,均在执行断言前因远程 MySQL 握手超时中断;`Test-NetConnection 43.128.3.240 -Port 3306` 同期显示 TCP 可达。收尾 `./init.ps1` 通过(Python 3.12.3,Django system check 0 issues)。
|
||||||
- 验证恢复:远程 MySQL 恢复后,新增“单图 + 指定 vision 别名”成功测试 1 test OK;API 非生成类拆分为鉴权 / 余额 / 模型目录 / 客户端版本 28 tests OK、充值回调 / 下单状态 13 tests OK,结合此前 `GenerateApiTests` 整类回归与新增单测,当前 API 89 条均有通过证据;`apps.portal.tests` 全量 39 tests OK。因此完整回归已通过拆分执行完成,单命令超时仅作为环境现象保留。
|
- 验证恢复:远程 MySQL 恢复后,新增“单图 + 指定 vision 别名”成功测试 1 test OK;API 非生成类拆分为鉴权 / 余额 / 模型目录 / 客户端版本 28 tests OK、充值回调 / 下单状态 13 tests OK,结合此前 `GenerateApiTests` 整类回归与新增单测,当前 API 89 条均有通过证据;`apps.portal.tests` 全量 39 tests OK。因此完整回归已通过拆分执行完成,单命令超时仅作为环境现象保留。
|
||||||
@@ -75,9 +76,9 @@
|
|||||||
- 已完成:T-001 初始化 Django + DRF 项目骨架;T-002 建立 apps 目录、自定义 User 与配置;T-003 接通 django-admin 与最小测试;T-004 Phase 0 骨架审核修补;T-101 Provider 适配器层 + 移植 cmbot 调用;T-102 AiModel + ModelAlias 模型 + 别名解析;T-103 配置变更审计;T-104 跑通一次录制标题生成;T-105 Phase 1 AI 层审核修补;T-201 User / UserWallet / ApiKey / PointsLedger / CallRecord 模型;T-202 PricingRule / ExchangeRate 模型 + 计费计算;T-203 并发安全扣点 / 退点;T-204 Phase 2 计费核心审核加固;T-301 API Key 鉴权;T-302 生成标题 / 图片接口;T-303 余额查询接口;T-304 充值回调;T-305 扫码充值下单 + 轮询;T-306 Phase 3 对外 API 安全加固;T-501 注册 / 登录(allauth);T-502 API Key 自助管理页;T-503 个人中心 / 记录页;T-504 充值页(扫码 + 轮询到账);T-505 Phase 4 用户端审核优化;T-401 运营后台完善;T-402 完整验收 MVP;T-403 部署 / 运行文档;T-601 可用别名发现;T-602 django-admin 中文化(第 1-3 层);T-603 django-admin 中文化(第 4 层·字段级);T-604 中文敏感词本地过滤;T-605 免邮箱验证策略落地;T-606 公开首页 + 客户端下载入口;T-607 桌面端最新版本检查接口;T-608 新用户注册赠送 100 点试用点数;T-609 桌面端版本检查接口增加强制更新标记;T-610 首页导入模板下载入口;T-611 用户端品牌名统一为虾皮圈;T-612 生图同步接口止血(上游硬截止 + 长请求池校准);T-613 抽生成核心 service(计费+审核+上游共享 core);T-614 生图异步任务化接口(提交+轮询,新增不动旧接口);T-615 旧同步生图接口用量遥测 + 弃用口径;T-616 生图失败自动重试 2 次;T-617 桌面端版本检查接口增加文件大小字段;T-618 客户端发布版本后台必填文件校验元数据。
|
- 已完成:T-001 初始化 Django + DRF 项目骨架;T-002 建立 apps 目录、自定义 User 与配置;T-003 接通 django-admin 与最小测试;T-004 Phase 0 骨架审核修补;T-101 Provider 适配器层 + 移植 cmbot 调用;T-102 AiModel + ModelAlias 模型 + 别名解析;T-103 配置变更审计;T-104 跑通一次录制标题生成;T-105 Phase 1 AI 层审核修补;T-201 User / UserWallet / ApiKey / PointsLedger / CallRecord 模型;T-202 PricingRule / ExchangeRate 模型 + 计费计算;T-203 并发安全扣点 / 退点;T-204 Phase 2 计费核心审核加固;T-301 API Key 鉴权;T-302 生成标题 / 图片接口;T-303 余额查询接口;T-304 充值回调;T-305 扫码充值下单 + 轮询;T-306 Phase 3 对外 API 安全加固;T-501 注册 / 登录(allauth);T-502 API Key 自助管理页;T-503 个人中心 / 记录页;T-504 充值页(扫码 + 轮询到账);T-505 Phase 4 用户端审核优化;T-401 运营后台完善;T-402 完整验收 MVP;T-403 部署 / 运行文档;T-601 可用别名发现;T-602 django-admin 中文化(第 1-3 层);T-603 django-admin 中文化(第 4 层·字段级);T-604 中文敏感词本地过滤;T-605 免邮箱验证策略落地;T-606 公开首页 + 客户端下载入口;T-607 桌面端最新版本检查接口;T-608 新用户注册赠送 100 点试用点数;T-609 桌面端版本检查接口增加强制更新标记;T-610 首页导入模板下载入口;T-611 用户端品牌名统一为虾皮圈;T-612 生图同步接口止血(上游硬截止 + 长请求池校准);T-613 抽生成核心 service(计费+审核+上游共享 core);T-614 生图异步任务化接口(提交+轮询,新增不动旧接口);T-615 旧同步生图接口用量遥测 + 弃用口径;T-616 生图失败自动重试 2 次;T-617 桌面端版本检查接口增加文件大小字段;T-618 客户端发布版本后台必填文件校验元数据。
|
||||||
- 已完成补充:T-619 多张图片理解并返回文字。
|
- 已完成补充:T-619 多张图片理解并返回文字。
|
||||||
- 正在进行:无。
|
- 正在进行:无。
|
||||||
- 待开始:仍按真实支付回调到账闭环、客户端发布、生产多图理解模型配置和线上旧同步接口用量观察继续拆任务。
|
- 待开始:T-620 图生图支持单图 / 多图主图与参考图;仍按真实支付回调到账闭环、客户端发布、生产多图理解模型配置和线上旧同步接口用量观察继续拆任务。
|
||||||
- 当前 blocker:支付商户真实密钥/证书与生产 SDK 依赖仍待提供;微信回调到账闭环仍需真实支付验收;真实 AI 标题生成已在线上跑通,图片生成慢 / 504 / 客户端超时风险已拆为 T-612~T-616 并完成工程侧处理。
|
- 当前 blocker:支付商户真实密钥/证书与生产 SDK 依赖仍待提供;微信回调到账闭环仍需真实支付验收;真实 AI 标题生成已在线上跑通,图片生成慢 / 504 / 客户端超时风险已拆为 T-612~T-616 并完成工程侧处理。
|
||||||
- 下一个可领取任务:当前无明确编号任务;先根据生产优先级登记新任务,再按 [`06-tasks.md`](06-tasks.md) 领取。
|
- 下一个可领取任务:T-620 图生图支持单图 / 多图主图与参考图;具体范围与验收以 [`06-tasks.md`](06-tasks.md) 为准。
|
||||||
|
|
||||||
## 当前可运行内容
|
## 当前可运行内容
|
||||||
|
|
||||||
|
|||||||
+17
-3
@@ -13,6 +13,7 @@
|
|||||||
/media/ -> MEDIA_ROOT(MVP 本地媒体;后续可换对象存储)
|
/media/ -> MEDIA_ROOT(MVP 本地媒体;后续可换对象存储)
|
||||||
/api/v1/generate/image/tasks* -> Gunicorn 普通请求池(异步提交/轮询,短请求)
|
/api/v1/generate/image/tasks* -> Gunicorn 普通请求池(异步提交/轮询,短请求)
|
||||||
/api/v1/generate/* -> Gunicorn 长请求池(旧同步生成,超时更长)
|
/api/v1/generate/* -> Gunicorn 长请求池(旧同步生成,超时更长)
|
||||||
|
/api/v1/analyze/images -> Gunicorn 长请求池(同步多图理解)
|
||||||
其他路径 -> Gunicorn 普通请求池(用户端 / admin / 余额 / 充值)
|
其他路径 -> Gunicorn 普通请求池(用户端 / admin / 余额 / 充值)
|
||||||
-> cmhub Django 单体
|
-> cmhub Django 单体
|
||||||
-> cmhub image-task worker(management command,后台处理异步生图)
|
-> cmhub image-task worker(management command,后台处理异步生图)
|
||||||
@@ -24,6 +25,7 @@
|
|||||||
|
|
||||||
- 使用系统 Python 3.12,不使用虚拟环境。
|
- 使用系统 Python 3.12,不使用虚拟环境。
|
||||||
- 图片生成已提供旧同步接口和新异步提交 / 轮询接口;真实图片生成耗时仍需在生产链路记录,并用于校准旧同步超时和异步 worker 容量。
|
- 图片生成已提供旧同步接口和新异步提交 / 轮询接口;真实图片生成耗时仍需在生产链路记录,并用于校准旧同步超时和异步 worker 容量。
|
||||||
|
- T-619 多图理解为同步接口,必须分流到长请求池;请求体上限需覆盖 Base64 膨胀,默认 32 MiB 解码后总图片上限建议配置至少 50 MiB 的 Nginx `client_max_body_size`。
|
||||||
- 真实支付需微信 / 支付宝商户密钥、证书、生产 SDK 与公网回调地址;未配置前只能用 `PAYMENT_CALLBACK_MODE=mock`。
|
- 真实支付需微信 / 支付宝商户密钥、证书、生产 SDK 与公网回调地址;未配置前只能用 `PAYMENT_CALLBACK_MODE=mock`。
|
||||||
|
|
||||||
## 二、系统准备
|
## 二、系统准备
|
||||||
@@ -241,7 +243,7 @@ python3.12 manage.py smoke_ai_generation title
|
|||||||
|
|
||||||
## 七、Gunicorn 运行
|
## 七、Gunicorn 运行
|
||||||
|
|
||||||
建议把同步图片生成分流到独立 Gunicorn 池,避免长请求占满普通页面和 admin 的 worker。
|
建议把同步图片生成与同步多图理解分流到独立 Gunicorn 池,避免长请求占满普通页面和 admin 的 worker。
|
||||||
|
|
||||||
普通请求池示例:
|
普通请求池示例:
|
||||||
|
|
||||||
@@ -269,7 +271,7 @@ gunicorn config.wsgi:application \
|
|||||||
--error-logfile -
|
--error-logfile -
|
||||||
```
|
```
|
||||||
|
|
||||||
`--timeout` 必须按真实图片生成耗时校准:生图 Provider 实际读取超时为 `min(AiModel.timeout_seconds 或分辨率默认值, AI_IMAGE_UPSTREAM_DEADLINE_SECONDS)`;`Gunicorn timeout` 应大于这个内层上游硬截止,Nginx `proxy_read_timeout` 应大于 Gunicorn timeout,调用方 read timeout 应不小于 Nginx。
|
`--timeout` 必须按真实生成耗时校准:生图 Provider 实际读取超时为 `min(AiModel.timeout_seconds 或分辨率默认值, AI_IMAGE_UPSTREAM_DEADLINE_SECONDS)`;多图理解读取超时取视觉模型的文本请求超时。`Gunicorn timeout` 应大于内层上游超时,Nginx `proxy_read_timeout` 应大于 Gunicorn timeout,调用方 read timeout 应不小于 Nginx。
|
||||||
|
|
||||||
systemd 单元可分别命名为 `cmhub-web.service` 和 `cmhub-generate.service`。服务的 `WorkingDirectory` 指向 `/www/wwwroot/cmhub`,`ExecStart` 使用上面的两条 Gunicorn 命令,环境变量由项目根目录 `.env` 在 Django settings 中读取。
|
systemd 单元可分别命名为 `cmhub-web.service` 和 `cmhub-generate.service`。服务的 `WorkingDirectory` 指向 `/www/wwwroot/cmhub`,`ExecStart` 使用上面的两条 Gunicorn 命令,环境变量由项目根目录 `.env` 在 Django settings 中读取。
|
||||||
|
|
||||||
@@ -371,7 +373,7 @@ server {
|
|||||||
listen 443 ssl http2;
|
listen 443 ssl http2;
|
||||||
server_name cmhub.example.com;
|
server_name cmhub.example.com;
|
||||||
|
|
||||||
client_max_body_size 25m;
|
client_max_body_size 64m;
|
||||||
|
|
||||||
location /static/ {
|
location /static/ {
|
||||||
alias /www/wwwroot/cmhub/staticfiles/;
|
alias /www/wwwroot/cmhub/staticfiles/;
|
||||||
@@ -407,6 +409,17 @@ server {
|
|||||||
proxy_read_timeout 120s;
|
proxy_read_timeout 120s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location = /api/v1/analyze/images {
|
||||||
|
proxy_pass http://127.0.0.1:8002;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto https;
|
||||||
|
proxy_connect_timeout 30s;
|
||||||
|
proxy_send_timeout 360s;
|
||||||
|
proxy_read_timeout 360s;
|
||||||
|
}
|
||||||
|
|
||||||
location /api/v1/generate/ {
|
location /api/v1/generate/ {
|
||||||
proxy_pass http://127.0.0.1:8002;
|
proxy_pass http://127.0.0.1:8002;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
@@ -436,6 +449,7 @@ server {
|
|||||||
- `/static/` 必须指向 `STATIC_ROOT`,否则 Bootstrap/qrcode 本地资源在 `DEBUG=False` 下 404。
|
- `/static/` 必须指向 `STATIC_ROOT`,否则 Bootstrap/qrcode 本地资源在 `DEBUG=False` 下 404。
|
||||||
- `/media/` 是 MVP 本地图片结果访问路径;如果改对象存储,应同步更新 `MEDIA_URL` 和存储配置。
|
- `/media/` 是 MVP 本地图片结果访问路径;如果改对象存储,应同步更新 `MEDIA_URL` 和存储配置。
|
||||||
- `/api/v1/generate/image/tasks` 与 `/api/v1/generate/image/tasks/{task_id}` 必须写在 `/api/v1/generate/` 前面,确保异步提交 / 轮询走普通 web 池;旧同步生成接口继续走长请求池。
|
- `/api/v1/generate/image/tasks` 与 `/api/v1/generate/image/tasks/{task_id}` 必须写在 `/api/v1/generate/` 前面,确保异步提交 / 轮询走普通 web 池;旧同步生成接口继续走长请求池。
|
||||||
|
- `/api/v1/analyze/images` 不在 `/api/v1/generate/` 前缀下,必须单独写精确 location 并转发到长请求池;否则会落入普通 web 池并可能拖慢登录、余额和 admin。
|
||||||
- 宝塔若已在外层配置 HTTP 到 HTTPS 跳转,`DJANGO_SECURE_SSL_REDIRECT=false` 即可;如果由 Django 负责跳转,再设为 `true`。
|
- 宝塔若已在外层配置 HTTP 到 HTTPS 跳转,`DJANGO_SECURE_SSL_REDIRECT=false` 即可;如果由 Django 负责跳转,再设为 `true`。
|
||||||
|
|
||||||
## 九、上线前验证
|
## 九、上线前验证
|
||||||
|
|||||||
+41
@@ -1950,3 +1950,44 @@
|
|||||||
- API 充值回调 / 下单状态分组:13 tests OK。
|
- API 充值回调 / 下单状态分组:13 tests OK。
|
||||||
- `apps.portal.tests` 全量:39 tests OK。
|
- `apps.portal.tests` 全量:39 tests OK。
|
||||||
- 结合此前 `GenerateApiTests` 整类 47 tests OK 与新增单测,当前 API 89 条测试均有通过证据;所有应用已通过拆分方式完成完整回归。完整单命令超时仍作为远程 MySQL / 执行器稳定性现象保留,不再构成测试覆盖缺口。
|
- 结合此前 `GenerateApiTests` 整类 47 tests OK 与新增单测,当前 API 89 条测试均有通过证据;所有应用已通过拆分方式完成完整回归。完整单命令超时仍作为远程 MySQL / 执行器稳定性现象保留,不再构成测试覆盖缺口。
|
||||||
|
|
||||||
|
## 2026-07-16 生产启用:T-619 多张图片理解
|
||||||
|
|
||||||
|
- 目标:`185.216.248.75`,域名 `cm.833729.com`,发布版本 `707941a`。
|
||||||
|
- 备份:
|
||||||
|
- `/root/cmhub_deploy_backups/cmhub-before-t619-20260716174234.tar.gz`:排除 media/staticfiles 的代码与 `.env`,root-only。
|
||||||
|
- `/root/cmhub_deploy_backups/cmhub-config-before-t619-20260716174234.tar.gz`:Nginx、systemd、MySQL 8.4 配置,root-only。
|
||||||
|
- `/root/cmhub_deploy_backups/cmhub-db-before-t619-20260716174234.sql.gz`:MySQL 8.4 逻辑备份,已重新压缩并通过 `gzip -t`。
|
||||||
|
- 部署:
|
||||||
|
- 本地 `main` 推送到远程后,以 `git archive 707941a` 生成发布包;SHA256 为 `ccf111ae126cf3274dfdc060d5ad742a13f565fd19cd781736614840668a15b9`。
|
||||||
|
- 服务器无 Git 工作副本,使用 staging + `rsync --delete` 同步跟踪文件;明确排除 `.env*`、media、staticfiles、`.secrets`、`.well-known` 与部署标记。
|
||||||
|
- `manage.py check` 0 issues;生产已应用 `ai.0005`、`billing.0008`。仅保留 allauth 在 MySQL 条件唯一约束上的既有 `models.W036` 警告。
|
||||||
|
- `.env` 显式配置 `VISION_MAX_IMAGES=8`、`VISION_MAX_IMAGE_BYTES=10485760`、`VISION_MAX_TOTAL_BYTES=33554432`。
|
||||||
|
- Nginx HTTP / HTTPS server 均新增 `/api/v1/analyze/images` 精确路由,转发到 `127.0.0.1:8012`,连接超时 30 秒、发送/读取超时 900 秒;`client_max_body_size=168m` 保持不变。`nginx -t` 通过。
|
||||||
|
- 依次 reload Nginx、重启 `cmhub-generate`、验证 8012,再重启 `cmhub-web`;66 个 `cmhub-image-worker@*.service` 未重启,避免打断排队生图任务。
|
||||||
|
- 运营配置:
|
||||||
|
- 复用 `AiModel(id=7, GPT-5.5 文本, api_type=chat)`,其 active capabilities 为 `text + vision`。
|
||||||
|
- 新建 active 默认别名 `vision-standard`,并写 `AiConfigAuditLog`。
|
||||||
|
- 新建 active 默认计费规则 `operation_type=vision + alias=vision-standard + resolution=""`,价格为 1 点/次。
|
||||||
|
- 真实验收:
|
||||||
|
- 使用临时生产验收 API Key 提交两张相同截图,调用 `POST https://cm.833729.com/api/v1/analyze/images`。
|
||||||
|
- 返回 HTTP 200、`model_used=gpt-5.5`、`points_cost=1`、`call_id=6096` 和非空中文理解文字。
|
||||||
|
- 余额 234→233;`CallRecord` 为 `vision/success`;consume 1 条、refund 0 条;结果摘要长度 258,不保存输入图片。
|
||||||
|
- `cmhub-generate` access log 确认请求由长请求池处理;临时验收 Key 已吊销。
|
||||||
|
- 收尾状态:`cmhub-web`、`cmhub-generate`、Nginx、MySQL 8.4 均 active,无 failed systemd unit;公网首页返回 200。
|
||||||
|
|
||||||
|
## 2026-07-17 文档登记:T-620 图生图支持单图 / 多图主图与参考图
|
||||||
|
|
||||||
|
- 状态:TODO(仅任务登记,未改代码、数据库或线上配置)。
|
||||||
|
- 背景:当前 cmhub 图生图链路的请求模型、生成核心和 Provider 都只传递单张输入图;中转站 `/v1/images/edits` 已通过直连测试确认可以接收按顺序重复的 multipart `image` 字段并返回图片,但 cmhub 尚未把该能力暴露给调用方。业务需要约定第一张为主图,第二张及之后为参考图。
|
||||||
|
- 文档变更:
|
||||||
|
- `docs/06-tasks.md`:新增 T-620「图生图支持单图 / 多图主图与参考图」,状态为 TODO,并登记 M16。
|
||||||
|
- `docs/00-ai-start-here.md`、`README.md`、`docs/current-state.md`:将 T-620 登记为下一项任务。
|
||||||
|
- 方案口径:
|
||||||
|
- 同步 `/api/v1/generate/image` 与异步 `/api/v1/generate/image/tasks` 增加有序 `images` 列表,同时保留旧单个 `image_url` / `image_base64` 字段;新旧输入不能混用。
|
||||||
|
- cmhub 服务端固定注入主图 / 参考图规则,`images[0]` 为主图、`images[1:]` 为参考图;用户 prompt 仍先审核,固定规则随有效 prompt 发送给中转站。
|
||||||
|
- Provider 按协议传递完整有序图片集合:Chat 多段图片、JSON `image_urls` / `images` 数组、`images_edits` 重复 `image` multipart 字段;不得只发第一张或拼接图片。
|
||||||
|
- 异步任务新增有序输入文件存储,旧单输入任务保持读取兼容;一次请求只扣一次点,失败 / 重试 / 僵任务继续沿用现有幂等退点。
|
||||||
|
- 输入数量、单图和总大小、SSRF、敏感词、无定价等校验均在预扣前完成;不保存 base64、输入图片内容或 provider raw。
|
||||||
|
- 中转站直连验收证据:使用 `gpt-image-2`、两张本地图片调用 `/v1/images/edits`,HTTP 200,约 73 秒返回 `data[0].b64_json`,解码后图片约 2.04 MB;输出保存于工作区外的 `D:\chengma\cmhub-relay-tests\multi-images-edits-result.bin`。该结果确认重复 `image` 字段可被接受,但主图 / 参考图语义仍由 T-620 的服务端固定 prompt 和真实两张明显不同图片验收确认。
|
||||||
|
- 验证:任务登记完成后执行文档 diff 检查;未运行代码测试,因为本轮未改实现。
|
||||||
|
|||||||
Reference in New Issue
Block a user