229805a070
Add WeChat service account routing with sync acks, connectivity tests, and context isolation; document deploy runbooks; and bundle related MindSpace, voice, Plaza, and server gateway changes for production rollout. Co-authored-by: Cursor <cursoragent@cursor.com>
52 lines
3.6 KiB
Markdown
52 lines
3.6 KiB
Markdown
# H5 计量计费网关设计
|
||
|
||
## 背景:当前计费的问题
|
||
|
||
当前计费内联在 `tkmind-proxy.mjs` 里,靠嗅探上游 SSE 的 `Finish` 帧扣费。100 服务实测发现三类问题:
|
||
|
||
1. **定价与成本脱钩,约 20× 超收**:默认 flat `2分/1k input` 对 DeepSeek 中继(goose `custom_tkmind_relay_deepseek`)严重偏贵。对账每条会话 H5 实扣 / goose 自报 `accumulated_cost × 7.2` 稳定落在 ~20×。换 provider 又会反向亏——单一硬编码 token 单价无法跟随模型。
|
||
2. **计量点分散**:只覆盖走 `tkmind-proxy` 的 H5 会话;`mindspace-agent-runner` 等其他 LLM 出口可能未计费。
|
||
3. **可靠性弱**:`onFinish` 为 fire-and-forget(`sse-billing.mjs` 的 `.catch(()=>{})`),扣费失败即漏计;`requestId` 全程传 `null`,无幂等键、无流水对账;读 `previous` 在事务外存在并发双扣竞态(`user-auth.mjs:943`)。
|
||
|
||
## 已落地的止血改动(本次)
|
||
|
||
`billing.mjs` 扩展 `H5_USE_BACKEND_COST` 成本路径,新增 `H5_MARGIN_MULTIPLIER`:
|
||
|
||
```
|
||
最终扣费 = 上游 accumulated_cost(USD) 增量 × H5_USD_CNY_RATE × H5_MARGIN_MULTIPLIER
|
||
```
|
||
|
||
- 自动跟随 provider/模型,换模型不需重调 token 单价。
|
||
- 仅当上游回传 `accumulatedCost` 时生效;缺失则**回退**原 flat token 路径,不破坏现有计费。
|
||
- 生产启用:`.env` 设 `H5_USE_BACKEND_COST=1` + `H5_MARGIN_MULTIPLIER=<目标毛利>`。
|
||
|
||
> ⚠️ 上线前需确认:一帧真实 SSE 的 `token_state` 是否带 `accumulated_cost`(goose `sessions.db` 有该列,但要确认 SSE Finish 事件也序列化了它)。确认前 multiplier 改动是安全的(无 cost 即回退)。
|
||
|
||
## 目标架构:独立计量网关
|
||
|
||
把"计量 + 定价 + 扣费 + 对账"从 H5 代理里抽出,成为所有 LLM 出口的统一收口点。
|
||
|
||
```
|
||
H5 session ─┐
|
||
agent-runner ┤→ [计量网关] → upstream(goose/...) → usage+cost
|
||
cover-ai 等 ─┘ │
|
||
├─ 定价引擎(按 provider/模型,cost × margin)
|
||
├─ 幂等扣费(requestId 去重 + 事务内读写钱包)
|
||
└─ ledger 流水(每次调用一条,可对账/审计/退款)
|
||
```
|
||
|
||
### 关键设计点
|
||
|
||
1. **统一收口**:所有发往 LLM 的调用都经网关,拿 provider 回传的真实 `usage` + `cost`,而非各出口各自实现。
|
||
2. **定价引擎按 provider 配置**:`{ provider, model } → { 计价基准, marginMultiplier }`。DeepSeek 与未来的 Claude 成本差几十倍,必须差异化,不能一个 flat 单价打天下。优先用成本基准(cost × margin),无 cost 的 provider 才退回 token 单价表。
|
||
3. **幂等扣费**:每次调用带 `requestId`;ledger 以 `requestId` 唯一约束,重放/重连不重复扣。当前 SSE 重连靠"accumulated 单调 → delta 0"兜底,脆弱,应换显式幂等键。
|
||
4. **事务内读写**:钱包扣减与计费状态读取在同一事务 + `FOR UPDATE`,消除并发双扣。
|
||
5. **ledger 流水表**:`(request_id, user_id, session_id, provider, model, input_tokens, output_tokens, upstream_cost_usd, charged_cents, margin, created_at)`。支撑对账(H5 扣费 vs 上游成本)、用户账单明细、纠纷退款。
|
||
6. **失败可恢复**:扣费写库失败要可重试/补偿,不能像现在 fire-and-forget 直接吞掉。
|
||
|
||
### 落地阶段
|
||
|
||
- **P0(已做)**:成本模式 + margin,env 切换止血 20× 超收。
|
||
- **P1**:补 `requestId` 幂等 + 修事务竞态 + ledger 流水表(仍在 proxy 内,先把可靠性和对账补齐)。
|
||
- **P2**:抽出独立计量模块/服务,纳入 agent-runner 等其他出口,定价引擎按 provider 配置化。
|