ai_call 写一行 —— 成功、失败、取消都写 —— 包括 Token 数(provider 返回则记录)、延迟、错误信息。这一张表撑起了 /admin/usage 后台,也是你定位失控模型或挂掉 provider 唯一需要看的地方。
前置条件
- 数据库已迁移(
pnpm db:push),ai_call表存在。 - 实际跑过几次 AI 调用 —— 不然表是空的。
- 看一遍
src/ai/manager.ts的recordCall(),每行数据都是从这里诞生的。
关键字段
userId、(provider, model)、status、createdAt 上的索引覆盖了后台要跑的所有查询。
为什么没有成本字段
我们故意不计算或存储美元成本。Provider 定价是个移动靶 —— 缓存折扣、微调加价、协议价档位 —— 任何本地副本几周就会和实际账单对不上。Vibestrap 的职责是记录”发生了什么”(调用、Token、延迟、错误);Provider 后台是”花了多少钱”的唯一权威来源。 如果你的产品确实需要在 vibestrap 里看 $(比如你按 provider 调用次数对终端用户收费),自己加一列cost_micro_cents + 自己写算法。schema 故意保留扩展空间。
为什么 Token 可以为 NULL
返回 Token 的 API(OpenAI / Anthropic / OpenRouter chat)会填inputTokens 和 outputTokens。图像 / 视频 / 音频类 API(Replicate / fal.ai)通常不返回,那些行就保持 NULL。别把 NULL 当 0 加,要把它当成”不适用”。
步骤:写一份用量报告
三条直接打ai_call 的查询。
近 30 天日调用量
各模型错误率
各模型 p95 延迟
PostgreSQL 自带percentile_cont:
调用与积分的对应关系
每次成功的 chat 调用都走 manager 的 token 预扣 + 结算。同一行ai_call 记录的 inputTokens / outputTokens 就是 tokensToCredits()(在 src/credits/index.ts)的输入。改了 siteConfig.credits.perKToken,历史行不会重新换算 —— 只对新调用生效。
图像调用走 siteConfig.credits.perImage flat rate(不区分 provider)。如果你想按计算时长收费,自己在业务代码里覆盖。