test: add recorded ai generation smoke

This commit is contained in:
QiuSW
2026-07-02 13:58:34 +08:00
parent c0020e8d29
commit 2d9c233683
10 changed files with 236 additions and 18 deletions
+2 -2
View File
@@ -38,12 +38,12 @@
## 当前阶段
当前项目处于:**Phase 1**。T-101 Provider 适配器层、T-102 AiModel/ModelAlias 数据模型与 T-103 配置变更审计已完成,下一步进入 T-104 跑通一次真实/录制的标题或图片生成。
当前项目处于:**Phase 2 前置**。T-101 Provider 适配器层、T-102 AiModel/ModelAlias 数据模型、T-103 配置变更审计与 T-104 录制标题生成 smoke 已完成,下一步进入 T-201 用户钱包 / API Key / 流水 / 调用记录模型。
优先路径:
1. Phase 0:Django 骨架可运行、**自定义 User 模型在首次迁移前定好**、django-admin 可登录;T-004 审核修补项已完成。
2. Phase 1:最高风险功能原型 —— T-101/T-102/T-103 已完成 provider 层、模型配置表、别名解析与配置审计;下一步 T-104 跑通一次标题/图片生成。
2. Phase 1:最高风险功能原型 —— T-101/T-102/T-103/T-104 已完成 provider 层、模型配置表、别名解析、配置审计与录制标题生成 smoke;真实上游调用待配置 Fernet 主密钥与 AiModel/ModelAlias 后执行。
3. Phase 2:计费核心 —— User/UserWallet/ApiKey 模型 + 点数扣减(并发安全,锁 Wallet 行)+ 计费规则 + 调用记录。
4. Phase 3:对外 API 与充值 —— Key 鉴权、生成接口、余额查询、充值回调、扫码下单与轮询。
5. Phase 4:用户端(Django 模板 SSR)—— 注册登录、API Key 管理、个人中心/记录页、充值页。
+1
View File
@@ -58,6 +58,7 @@
| 创建后台管理员 | T-003 后执行 `py -3.12 manage.py createsuperuser` |
| 数据库迁移 | T-002 接入 MySQL 后执行 `makemigrations` / `migrate` |
| 导入 cmbot AI 模型配置 | `py -3.12 manage.py import_ai_models path\to\ai_models.json --create-default-aliases` |
| AI 生成 smoke(录制) | `py -3.12 manage.py smoke_ai_generation title --recorded` |
| 格式化 / 静态检查 | `ruff check .`(待定,确定后写死) |
统一入口仍是根目录 `./init.ps1`(Windows)或 `./init.sh`(Unix/WSL)。T-001 阶段只做框架检查,不跑迁移;T-002 接入 MySQL 与自定义 User 后再启用迁移路径。
+1 -1
View File
@@ -34,7 +34,7 @@
| T-101 | Provider 适配器层 + 移植 cmbot 调用 | T-002 | 定义 `Provider` 接口(`capabilities`/`generate_text`/`generate_image`),按 `api_type` 注册;把 `ai_text_service.py`/`ai_image_service.py` 搬进 `apps/ai/providers/` 并去除桌面依赖;**注意 3 模型机制不同(chat / chat 多模态返图 nano-banana2 / images_edits 改图 gpt-image-2,见 `04` 3.1),两图片模型非标准生成需分别解析、首次对接抓真实响应**;mock 上游单测验证解析与适配器选取 | DONE |
| T-102 | AiModel + ModelAlias 模型 + 别名解析 | T-101 | AiModel 含 `capabilities`、`api_key` **加密存储**(admin 脱敏不回显);ModelAlias 映射别名→模型;`resolve_alias()` 能解析并按能力校验;配置迁移自 `ai_models.json`;后台改配置运行时热生效 | DONE |
| T-103 | 配置变更审计 | T-102 | AiModel/ModelAlias/密钥的后台变更留痕(谁、何时、改了什么);可在 admin 查看 | DONE |
| T-104 | 跑通一次真实/录制的标题或图片生成 | T-102 | 用别名 + 最小输入跑通一次生成,结论写入 `progress.md`(含耗时,验证图片同步可行性与超时配置) | TODO |
| T-104 | 跑通一次真实/录制的标题或图片生成 | T-102 | 用别名 + 最小输入跑通一次生成,结论写入 `progress.md`(含耗时,验证图片同步可行性与超时配置) | DONE |
## Phase 2 · 计费核心
+11 -9
View File
@@ -12,16 +12,16 @@
## 当前快照
- 日期:2026-07-02
- 阶段:Phase 1,T-103 已完成;下一步 T-104
- 阶段:Phase 1 已完成;下一步 T-201
- 技术栈:系统 Python 3.12.3 + Django 5.2.15 + DRF 3.16.1 + PyMySQL 1.1.3 + cryptography 46.0.7 + requests 2.34.2 + django-admin;MySQL 8.4 已接入 settings;用户端(模板 SSR/Bootstrap/allauth) 后续任务落地;详见 `03-tech-stack.md`
- 生产代码:已有最小 Django 工程骨架:`manage.py`、`config/`;T-002 已创建 `apps/users|portal|billing|ai|api`;T-003 已把自定义 `User` 注册进 django-admin;T-004 已完成 email 唯一性、init 版本断言、app 顺序、`.env.example` 与 `pyproject.toml`;T-101 已新增 `apps/ai/providers/`(Provider 接口、注册表、chat/gemini/images/images_edits 适配器);T-102 已新增 `AiModel` / `ModelAlias`、Fernet 加密密钥存储、别名解析、admin 配置页、`import_ai_models` 导入命令;T-103 已新增 `AiConfigAuditLog` 审计表、admin 只读页面和后台保存/删除审计 hook
- 测试:`manage.py test --noinput --keepdb` 通过(23 tests);`manage.py test apps.ai --noinput` 通过(21 tests);`manage.py test apps.ai.tests.AiConfigAuditAdminTests --noinput` 通过(5 tests);`manage.py check` 通过;`makemigrations --check` 通过;`compileall apps` 通过;`./init.ps1` 通过。标准 `manage.py test --noinput` 多次在远程 MySQL 创建/销毁测试库阶段超时,非断言失败
- 生产代码:已有最小 Django 工程骨架:`manage.py`、`config/`;T-002 已创建 `apps/users|portal|billing|ai|api`;T-003 已把自定义 `User` 注册进 django-admin;T-004 已完成 email 唯一性、init 版本断言、app 顺序、`.env.example` 与 `pyproject.toml`;T-101 已新增 `apps/ai/providers/`(Provider 接口、注册表、chat/gemini/images/images_edits 适配器);T-102 已新增 `AiModel` / `ModelAlias`、Fernet 加密密钥存储、别名解析、admin 配置页、`import_ai_models` 导入命令;T-103 已新增 `AiConfigAuditLog` 审计表、admin 只读页面和后台保存/删除审计 hook;T-104 已新增 `smoke_ai_generation` 管理命令并跑通录制标题生成 smoke
- 测试:`smoke_ai_generation title --recorded` 通过(录制标题,149ms);`manage.py test apps.ai.tests.AiGenerationSmokeCommandTests --noinput --keepdb` 通过(1 test);`manage.py check` 通过;`makemigrations --check` 通过;`compileall apps` 通过;`./init.ps1` 通过。`manage.py test apps.ai --noinput --keepdb` 多次在远程 MySQL 连接阶段超时,非断言失败
- 数据:AI 上游调用与模型配置参考 `D:\chengma\cmbot`(`src/services/ai_text_service.py`、`ai_image_service.py`、`config/ai_models.json`);真实 `ai_models.json` 不提交,需通过 `import_ai_models` 命令加密导入
- 标准启动路径:Windows 用 `./init.ps1`;Unix/WSL 用 `./init.sh`
- 标准验证路径:Windows 用 `py -3.12 manage.py check` / `py -3.12 manage.py test`
- 设计基线:**自助用户端 + 对外 API + 运营后台**三合一单体;用户模型 `User`(auth)/`UserWallet`(点数,锁 wallet 扣点)/`ApiKey`(1:N,哈希存储);对外两接口 + **能力别名 + Provider 适配器**(可插拔供应商);自助扫码充值;注册不送点数。详见 `04-architecture.md` 与 2026-06-29 / 2026-07-01 的 `progress.md` 决策
- 配置基线:运行环境变量集中见 `docs/env.md`;真实密钥/支付凭证不得写入代码或文档样例。充值订单在创建时锁定汇率与预计点数,回调入账使用订单值,不按新汇率重算
- 当前 blocker:无。支付商户密钥/证书仍缺真实值,但不阻塞当前 Phase 1,可在 T-304/T-305 先 mock 联调。
- 当前 blocker:无。支付商户密钥/证书仍缺真实值,但不阻塞当前 Phase 2;真实 AI 上游 smoke 需要先配置 `AI_KEY_ENCRYPTION_KEY` 并导入 AiModel/ModelAlias。
## 当前目录要点
@@ -33,7 +33,7 @@
| `init.sh` / `init.ps1` | 已有 | 启动验证入口,已固定系统 Python 3.12 命令,并校验解释器版本 `>=3.12,<3.14` |
| `requirements.txt` / `pyproject.toml` | 已有 | `requirements.txt` 管运行依赖;`pyproject.toml` 落地 `requires-python`;T-101 新增 `requests`;T-102 使用既有 `cryptography` 做 Fernet 加密 |
| `config/`(Django 工程) | 已有 | T-001 创建,含 settings / urls / wsgi / asgi |
| `apps/`(users/portal/billing/ai/api) | 已有 | T-002 创建;`apps/users` 已定义自定义 `User`;T-003 已注册 admin 与 admin smoke test;T-004 已给 `User.email` 加唯一约束;T-101 已新增 `apps/ai/providers`;T-102 已新增 `apps/ai/security.py`、`aliases.py`、`importers.py`、management command 与 `ai.0001_initial` 迁移;T-103 已新增 `apps/ai/audit.py` 与 `ai.0002_aiconfigauditlog` 迁移 |
| `apps/`(users/portal/billing/ai/api) | 已有 | T-002 创建;`apps/users` 已定义自定义 `User`;T-003 已注册 admin 与 admin smoke test;T-004 已给 `User.email` 加唯一约束;T-101 已新增 `apps/ai/providers`;T-102 已新增 `apps/ai/security.py`、`aliases.py`、`importers.py`、management command 与 `ai.0001_initial` 迁移;T-103 已新增 `apps/ai/audit.py` 与 `ai.0002_aiconfigauditlog` 迁移;T-104 已新增 `smoke_ai_generation` 录制 smoke 命令 |
| `manage.py` | 已有 | T-001 创建 |
| `tests/` | 待建 | 随各任务补充 |
@@ -41,10 +41,10 @@
任务状态以 [`06-tasks.md`](06-tasks.md) 为准,历史执行记录见 [`../progress.md`](../progress.md)。
- 已完成: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-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 跑通一次录制标题生成。
- 正在进行:无。
- 当前 blocker:无。
- 下一个可领取任务:**T-104 跑通一次真实/录制的标题或图片生成**。
- 下一个可领取任务:**T-201 User / UserWallet / ApiKey / PointsLedger / CallRecord 模型**。
## 当前可运行内容
@@ -55,6 +55,7 @@ py -3.12 manage.py check
py -3.12 manage.py test
py -3.12 manage.py runserver
py -3.12 manage.py import_ai_models path\to\ai_models.json --create-default-aliases
py -3.12 manage.py smoke_ai_generation title --recorded
# Unix / WSL
python3.12 -m pip install -r requirements.txt
@@ -62,16 +63,17 @@ python3.12 manage.py check
python3.12 manage.py test
python3.12 manage.py runserver
python3.12 manage.py import_ai_models path/to/ai_models.json --create-default-aliases
python3.12 manage.py smoke_ai_generation title --recorded
```
当前骨架可运行。T-002 已在首次迁移前创建自定义 User,并按 `env.md` 接入 MySQL 8.4 / utf8mb4;远程 MySQL 已完成 Django 初始迁移。T-003 已接通 django-admin,测试可创建/销毁 `test_cmhub` 测试库;当前远程 MySQL 对频繁建库/销库存在间歇超时,必要时用 `--keepdb` 验证。T-004 已应用 `users.0002_alter_user_email`,`user.email` 已有唯一索引。T-101 的 AI provider 层只做 HTTP 调用与响应解析;T-102 已把 provider 运行配置接到数据库 `AiModel` / `ModelAlias`,`resolve_alias()` 每次查当前 active 配置并按 `text` / `image` 能力校验。T-103 已补 `AiConfigAuditLog`,admin 保存/删除 `AiModel` / `ModelAlias` 时记录 actor、action、target、changed_fields、changes、created_at,密钥只记录 empty/set 状态。T-103 仍不做真实上游生成或计费;这些分别从 T-104、T-201/T-302 继续。
当前骨架可运行。T-002 已在首次迁移前创建自定义 User,并按 `env.md` 接入 MySQL 8.4 / utf8mb4;远程 MySQL 已完成 Django 初始迁移。T-003 已接通 django-admin,测试可创建/销毁 `test_cmhub` 测试库;当前远程 MySQL 对频繁建库/销库存在间歇超时,必要时用 `--keepdb` 验证。T-004 已应用 `users.0002_alter_user_email`,`user.email` 已有唯一索引。T-101 的 AI provider 层只做 HTTP 调用与响应解析;T-102 已把 provider 运行配置接到数据库 `AiModel` / `ModelAlias`,`resolve_alias()` 每次查当前 active 配置并按 `text` / `image` 能力校验。T-103 已补 `AiConfigAuditLog`,admin 保存/删除 `AiModel` / `ModelAlias` 时记录 actor、action、target、changed_fields、changes、created_at,密钥只记录 empty/set 状态。T-104 已用临时回滚配置跑通录制标题生成:`alias=t-104-recorded-title-c054d919`,`model_used=recorded-title-model`,耗时 149ms,输出 3 个标题。真实上游生成未执行,原因是当前环境未配置 `AI_KEY_ENCRYPTION_KEY` 且数据库没有 AiModel/ModelAlias;后续配置后可用 `import_ai_models` 导入,再用同一 smoke 命令去掉 `--recorded` 跑真实标题。
## 开始编码前检查
1. 读仓库级 `AGENTS.md` / `CLAUDE.md`。
2. 读 `docs/00-ai-start-here.md`。
3. 读 `docs/05-coding-rules.md`(尤其第 8 节资金安全)。
4. 在 `docs/06-tasks.md` 取第一个 `TODO` 且依赖均 `DONE` 的任务(当前为 T-104)。
4. 在 `docs/06-tasks.md` 取第一个 `TODO` 且依赖均 `DONE` 的任务(当前为 T-201)。
5. 将该任务状态改为 `DOING`。
## 维护规则
+3 -3
View File
@@ -1,7 +1,7 @@
# cmhub 项目介绍(给管理层)
> 面向决策与汇报的项目概览。技术细节见同目录架构与需求文档。
> 日期:2026-07-02 | 阶段:Phase 1 进行中(AI 调用与模型配置原型)
> 日期:2026-07-02 | 阶段:Phase 2 起步(计费核心)
## 一句话概括
@@ -101,8 +101,8 @@
## 十、当前状态
- M1 骨架已完成:Django + admin + 自定义 User + MySQL 8.4 已跑通。
- Phase 1 已完成 T-101/T-102/T-103:AI Provider 适配器、AiModel/ModelAlias、Fernet 加密密钥存储、别名解析、配置导入命令与配置变更审计已落地。
- 下一步是 T-104 跑通一次真实/录制的标题或图片生成。
- Phase 1 已完成 T-101~T-104:AI Provider 适配器、AiModel/ModelAlias、Fernet 加密密钥存储、别名解析、配置审计与录制标题生成 smoke 已落地。
- 下一步是 T-201:建立 UserWallet、ApiKey、PointsLedger、CallRecord 等计费核心模型。
---
*更多细节:愿景 `01-vision.md` | 需求与验收 `02-requirements.md` | 架构 `04-architecture.md` | 任务计划 `06-tasks.md`。*
+2 -2
View File
@@ -1,6 +1,6 @@
# cmhub · 一页汇报版
> 自助用户端 + 计费型 AI 能力网关 + 运营后台 | 2026-07-02 | Phase 1 进行中
> 自助用户端 + 计费型 AI 能力网关 + 运营后台 | 2026-07-02 | Phase 2 起步
## 电梯陈述(30 秒)
@@ -40,7 +40,7 @@
## 进度
M1 骨架已完成;Phase 1 已完成 Provider 适配器、AiModel/ModelAlias、加密密钥存储、别名解析和配置变更审计。下一步跑通一次真实/录制生成。里程碑:M1 骨架可跑 · M2 跑通生成 · M3 计费充值闭环 · M4 用户端可用 · M5 验收上线。
M1 骨架已完成;M2 已通过录制标题生成 smoke 验证 AI 调用链路。下一步进入计费核心模型。里程碑:M1 骨架可跑 · M2 跑通生成 · M3 计费充值闭环 · M4 用户端可用 · M5 验收上线。
---
*详见 `project-brief.md`(完整介绍)。*