feat: add ai model alias configuration

This commit is contained in:
QiuSW
2026-07-02 11:07:44 +08:00
parent c9fbabb04f
commit 18ac054dc5
23 changed files with 955 additions and 48 deletions
+27 -20
View File
@@ -67,8 +67,8 @@
| 数据 | 来源 | 说明 |
| --- | --- | --- |
| AiModel | 迁移自 `cmbot/config/ai_models.json` | name、url、model、**api_key(加密存储)**、api_type、timeout、**capabilities**(text/image/vision、支持的分辨率) |
| ModelAlias | 运营配置 | 对外**能力别名** → 映射到一个具体 AiModel;调用方只见别名,不见 SKU |
| AiModel | 迁移自 `cmbot/config/ai_models.json` | name、url、model、`api_type`、`capabilities`、`timeout_seconds`、`connect_timeout_seconds`、`extra_body`、`is_active`、**api_key_encrypted(Fernet 加密存储)** |
| ModelAlias | 运营配置 | `operation_type + alias` → 映射到一个具体 AiModel;支持每个操作一个默认别名;调用方只见别名,不见 SKU |
| PricingRule | 运营配置 | 操作类型 × **能力别名**(+ 可选分辨率)→ 点数单价 |
| ExchangeRate | 运营配置 | 金额 → 点数 的汇率(如 1 元 = N 点),可带生效时间 |
@@ -82,7 +82,7 @@
- ⚠️ 两个图片模型**都不是**标准 `images/generations`,不可套用通用图片生成 SDK 写法;每个模型**独立 url + key**,不共享 base_url。
- ⚠️ 图片返回结构(URL / base64、在返回中的位置)**首次对接须抓一次真实响应,再定适配器解析代码**。
- `capabilities` 显式声明每个模型能做什么;标题接口只允许声明 `text` 的模型,图片接口只允许声明 `image` 的模型。
- `api_key` **加密存储**,admin 列表脱敏、不回显明文;模型/密钥/别名映射的变更需审计留痕。
- `api_key` **使用 Fernet 加密存储到 `api_key_encrypted`**,admin 只提供写入型 `api_key` 字段、脱敏显示、不回显明文;模型/密钥/别名映射的变更需审计留痕。
- 汇率在**充值下单创建订单时**锁定并记录到订单,同时计算预计到账点数;后续改汇率不影响已创建订单。支付回调入账时使用订单上的 `exchange_rate` / `points_granted`,不重新读取当前汇率。
#### 配置表目标 schema
@@ -90,27 +90,32 @@
```sql
-- 上游模型(具体 SKU,后台维护,密钥加密)
CREATE TABLE ai_model (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL, -- 后台展示名
url TEXT NOT NULL,
model TEXT NOT NULL, -- 供应商模型标识
api_key_enc TEXT NOT NULL, -- 加密后的密钥,不存明文
api_type TEXT NOT NULL, -- chat/gemini/images/images_edits/auto
capabilities TEXT NOT NULL, -- JSON: {text,image,vision, resolutions:[...]}
timeout_seconds INTEGER,
connect_timeout_seconds INTEGER,
status TEXT NOT NULL DEFAULT 'active',
updated_at TEXT NOT NULL
id BIGINT PRIMARY KEY,
name VARCHAR(128) NOT NULL UNIQUE, -- 后台展示名
url VARCHAR(500) NOT NULL,
model VARCHAR(128) NOT NULL, -- 供应商模型标识
api_key_encrypted LONGTEXT NOT NULL, -- Fernet 密文,不存明文
api_type VARCHAR(32) NOT NULL, -- chat/gemini/images/images_edits/auto
capabilities JSON NOT NULL, -- ["text","image","vision"] 或等价对象
timeout_seconds INTEGER NOT NULL DEFAULT 0,
connect_timeout_seconds INTEGER NOT NULL DEFAULT 30,
extra_body JSON NOT NULL,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
created_at DATETIME(6) NOT NULL,
updated_at DATETIME(6) NOT NULL
);
-- 能力别名(对外稳定标识 → 当前映射的具体模型)
CREATE TABLE model_alias (
id INTEGER PRIMARY KEY,
alias TEXT UNIQUE NOT NULL, -- 如 title-standard / image-hd,对外用
operation_type TEXT NOT NULL, -- title / image
ai_model_id INTEGER NOT NULL REFERENCES ai_model(id), -- 可随时改指向
status TEXT NOT NULL DEFAULT 'active',
updated_at TEXT NOT NULL
id BIGINT PRIMARY KEY,
alias VARCHAR(64) NOT NULL, -- 如 title-standard / image-hd,对外用
operation_type VARCHAR(32) NOT NULL, -- title / image
ai_model_id BIGINT NOT NULL REFERENCES ai_model(id), -- 可随时改指向
is_default BOOLEAN NOT NULL DEFAULT FALSE,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
created_at DATETIME(6) NOT NULL,
updated_at DATETIME(6) NOT NULL,
UNIQUE(operation_type, alias)
);
-- 计费规则(按别名定价,换底层模型不影响计费)
@@ -124,6 +129,8 @@ CREATE TABLE pricing_rule (
);
```
T-102 已实现 `AiModel` / `ModelAlias` 的 Django models、admin、迁移与别名解析。默认别名唯一性由 model validation、admin 与导入器保证;MySQL 不支持通用 partial unique index,后续若要强制数据库层约束可在 T-103/T-401 评估触发器或约束表。
> 可选增强(接口预留、MVP 不实现):`account_alias_permission`(按账号授权可用别名,防止调用方点用未授权/昂贵模型);别名按比例分流到多个模型(灰度/AB/故障转移)。适配器接口需为此留口子。
### 3.2 业务动态数据