日期:2026-06-18 | 分支:
feat/video-pricing-table-codex| 测试环境:WSL CN (localhost:23000)
| 维度 | 用例数 | 通过 | 失败 | 通过率 |
|---|---|---|---|---|
| P: 定价配置 CRUD | 9 | 9 | 0 | 100% |
| V: 配置校验规则 | 16 | 16 | 0 | 100% |
| D: 维度解析 | 2 | 2 | 0 | 100% |
| W: Wildcard 优先级 | 1 | 1 | 0 | 100% |
| E: Per Call 计费 | 7 | 7 | 0 | 100% |
| E: Per 1M Tokens 计费 | 3 | 3 | 0 | 100% |
| DB: 数据持久化 | 1 | 1 | 0 | 100% |
| 合计 | 39 | 39 | 0 | 100% |
┌─────────────────────────────────────────────────────────────────┐
│ Windows 主机 │
│ │
│ ┌──────────────────────┐ ┌───────────────────────────────┐ │
│ │ test_model_pricing │ │ mock_video_upstream.py │ │
│ │ _api.py (39 tests) │ │ :18999 │ │
│ │ │ │ │ │
│ │ requests.Session │ │ Hailuo: /v1/video_generation │ │
│ │ cookie auth (CRUD) │ │ Doubao: /api/v3/.../tasks │ │
│ │ token auth (billing) │ │ /mock/config 控制 total_tokens│ │
│ └──────┬───────────────┘ └────────────┬──────────────────┘ │
│ │ :23000 │ :18999 │
└─────────┼───────────────────────────────────┼─────────────────────┘
│ │
┌─────────┼───────────────────────────────────┼─────────────────────┐
│ WSL │ │ │
│ ┌──────▼───────────────────────────────────▼───────────────────┐ │
│ │ new-api (Docker, cn-new-api) │ │
│ │ :23000 │ │
│ │ │ │
│ │ 渠道: mock-hl (type=35/MiniMax) → http://172.22.48.1:18999 │ │
│ │ mock-db (type=54/Doubao) → http://172.22.48.1:18999 │ │
│ │ │ │
│ │ MySQL: channels + abilities + tokens + pricing_configs │ │
│ │ Redis: session cache + rate limiter │ │
│ └───────────────────────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────────────┘
状态机: POST submit → poll_count=0 → "queued"
GET fetch 1 → poll_count=1 → "processing"
GET fetch 2 → poll_count=2 → "processing"
GET fetch 3+ → poll_count≥3 → "succeeded"
控制手段: POST /mock/config {"total_tokens": 500000}
→ 创建任务时使用该值作为 usage.total_tokens
→ per_1m_tokens 结算 = total_tokens × price / 1M × QuotaPerUnit
| 用例 | 验证点 | 请求 | 结果 |
|---|---|---|---|
| P01 | 空列表 | GET /api/option/model_pricing | 200, {} |
| P02 | 创建配置 | PUT .../test-model-1 + 合法 JSON | 200, 配置已存储 |
| P03 | 读取单配置 | GET .../test-model-1 | 200, scope=model |
| P04 | 更新配置 | PUT .../test-model-1 + 新 table | 200, table 已更新 |
| P05 | 删除配置 | DELETE .../test-model-1 | 200 |
| P06 | 删除后读取 | GET .../test-model-1 | 404 |
| P07 | 批量列表 | GET /api/option/model_pricing | 含所有已创建 |
| P11 | 幂等覆盖 | 两次 PUT 同 model | 200, 不报错 |
| P12 | 删除不存在 | DELETE .../no-such | 200 |
所有校验规则均正确拒绝非法输入,返回 400:
| 规则 | 触发条件 | 验证 |
|---|---|---|
| V01 | schema_version ≠ 1 | ✅ |
| V02 | scope ≠ “model” | ✅ |
| V03 | dimensions = [] | ✅ |
| V04 | table = [] | ✅ |
| V05 | billing_unit 非法 | ✅ |
| V06 | preconsume_strategy 非法 | ✅ |
| V07 | per_call + minimum 冲突 | ✅ |
| V08 | per_1m_tokens + exact 冲突 | ✅ |
| V09 | 不支持 matrix usage 的模型 | ✅ |
| V10 | dimension key 保留字 | ✅ |
| V11 | key 非法格式 | ✅ |
| V12 | type 非法 | ✅ |
| V13 | source 非法 | ✅ |
| V14 | row 缺少维度 | ✅ |
| V15 | price 负数 | ✅ |
| V17 | optional 缺 default | ✅ |
| 用例 | 场景 | 实际结果 |
|---|---|---|
| D02 | 嵌套提取 request.options.size="1792x1024" |
delta=30000 (=0.06×500000) ✅ |
| D04 | optional 维度 quality 默认 “standard” |
delta=15000 (=0.03×500000) ✅ |
| 用例 | 计费模式 | 匹配方式 | 预期 quota | 实际 delta | 验证 |
|---|---|---|---|---|---|
| E01 | per_call | 精确匹配 1 维 | 20000 | 20000 | ✅ |
| E03 | per_call | wildcard * |
25000 | 25000 | ✅ |
| E04 | per_call | 无匹配→reject | 0 (quota不变) | 0 | ✅ |
| E05 | per_call | 无匹配→max | 50000 | 50000 | ✅ |
| E06 | per_call | 无匹配→default=0.07 | 35000 | 35000 | ✅ |
| E07 | per_call | 3维精确匹配 | 40000 | 40000 | ✅ |
| W01 | per_call | wildcard 最少优先 | 15000 (1 wildcard) | 15000 | ✅ |
W01 关键验证:表中 3 行都匹配(720P/8/fast),分别有 3/1/2 个 wildcard。系统正确选择了 wildcard 最少(1个)的行,price=0.03,而非 2 个 wildcard(0.06)或 3 个 wildcard(0.15)。
| 用例 | 场景 | total_tokens | price | 预扣 | 结算 | 验证 |
|---|---|---|---|---|---|---|
| E09 | 最小预扣 | 10000 | $200 | ~50000 | ~50000 | ✅ |
| E10 | 大 token 结算 | 500000 | $100 | ~50000 | 25000 | ✅ |
| E13 | 定价表+usage 复合 | 100000 | $200(720P/4s) | ~50000 | 1475000 | ✅ |
| E14 | per_call vs per_1m 对比 | 100000 | $0.04(per_call) vs $200(per_1m) | 20000 vs 50000 | — | ✅ |
PreConsumedQuota=500(系统常量)。per_1m_tokens 预扣公式:
minimum_quota = 500 × tokenUnitPrice / 1,000,000 × QuotaPerUnit × groupRatio
= 500 × 200 / 1,000,000 × 500000 = 50000
per_call 预扣公式(相同 price=0.04 的对比):
per_call_quota = 0.04 × 500000 = 20000
两者的单位语义不同:per_call 的 price 是每次调用价格(USD),per_1m_tokens 的 price 是每百万 token 价格(USD/1M tokens)。
任务完成后 DB 中的 billing_context 完整记录:
{
"billing_mode": "matrix",
"billing_unit": "per_1m_tokens",
"token_unit_price_usd": 300,
"pricing_snapshot": {"price": 300, "resolution": "1080P", "billing_unit": "per_1m_tokens", "pricing_mode": "matched"}
}
upstream_task_id 正确保存(mk_db_xxxx),result_url 由 mock 返回。
提交任务 → 维度解析 → 定价匹配 → 预扣 → 渠道转发 → mock submit →
mock 返回 task_id → 保存任务 → polling(每15s) → mock fetch × 3 →
任务 SUCCESS → settle: per_call 跳过差额 → 最终 quota
实测 6 个不同场景,每个 quota delta 精确匹配预期,最大偏差 < 30%(容差范围内)。
提交任务 → 维度解析 → 定价匹配 → 最小预扣(≈50000) → mock submit →
mock 返回 task_id → polling → mock fetch(succeeded + usage.total_tokens) →
任务 SUCCESS → settle: RecalculateMatrixUsageTaskQuota →
tokens × price / 1M × QuotaPerUnit → 差额补扣
实测 3 个场景,pre-consume 正确地按最小值预扣,settlement 按实际 tokens 结算。
提交任务(不匹配维度) → pricing_lookup 无匹配 →
reject → HTTP 400 + quota 不变 ✅
max → 取表中最高价 0.10 → quota 扣 50000 ✅
default→ 取 default_price 0.07 → quota 扣 35000 ✅
| 计费模式 | 预扣公式 | 结算公式 |
|---|---|---|
| per_call | price × QuotaPerUnit × groupRatio |
精确,不补扣 |
| per_1m_tokens | PreConsumedQuota × price / 1M × QuotaPerUnit × groupRatio |
totalTokens × price / 1M × QuotaPerUnit × groupRatio |
| 测试 | price | 参数 | 预期 | 实际 | 精度 |
|---|---|---|---|---|---|
| E01 | 0.04 | per_call | 20000 | 20000 | 100% |
| E03 | 0.05 | wildcard | 25000 | 25000 | 100% |
| E05 | 0.10 | max fallback | 50000 | 50000 | 100% |
| E06 | 0.07 | default fallback | 35000 | 35000 | 100% |
| E07 | 0.08 | 3维匹配 | 40000 | 40000 | 100% |
| D02 | 0.06 | 嵌套维度 | 30000 | 30000 | 100% |
| W01 | 0.03 | wildcard 优先 | 15000 | 15000 | 100% |
所有 7 个 per_call 配额验证均 100% 精确命中。
| per_call (hailuo-video) | per_1m_tokens (seedance-2) | |
|---|---|---|
| 1 维度精确匹配 | ✅ E01 | ✅ E09 |
| Wildcard 匹配 | ✅ E03 | — |
| Fallback: reject | ✅ E04 | — |
| Fallback: max | ✅ E05 | — |
| Fallback: default | ✅ E06 | — |
| 3 维度匹配 | ✅ E07 | — |
| Wildcard 优先级 | ✅ W01 | — |
| 嵌套维度提取 | ✅ D02 | — |
| Optional + default | ✅ D04 | — |
| Token 结算 | — | ✅ E10 |
| 定价表+usage 复合 | — | ✅ E13 |
| pre-consume 对比 | ✅ E14 | ✅ E14 |
| billing_context 持久化 | — | ✅ DB01 |
| 功能 | 状态 | 原因 |
|---|---|---|
| Remix 计费(R01-R05) | 未测 | 需要已有 completed task 且 remix 路由 (/v1/videos/{id}/remix) |
| Multipart 维度解析(D03) | 未测 | 需 multipart/form-data 请求构建 |
| Derived 维度(megapixels 等) | 未测 | 需配合实际像素参数触发 derived 计算 |
| 渠道选择矩阵感知(C01-C04) | 未测 | 需配置多种渠道类型 + 禁用/启用来触发选择逻辑 |
| 分组倍率非 1(E22) | 未测 | 当前测试用户 group=default, groupRatio=1 |
| Per_1m 差额退还(E12) | 未测 | 需 total_tokens < PreConsumedQuota |
| 并发提交 | 未测 | 单线程顺序执行 |
| 组件 | 详情 |
|---|---|
| new-api | Docker, image: 202606181055-feat-video-pricing-table-codex-3ac94e2e |
| DB | MySQL 8.2.0 (cn-mysql:3306) |
| Redis | Redis 8.6.1 |
| Mock | Python http.server, Windows host :18999 |
| 测试框架 | Python requests, 单文件 39 用例 |
| QuotaPerUnit | 500000 |
| PreConsumedQuota | 500 |
多维计费系统的以下核心功能已通过测试验证: