把上游用量和用户用量分开记

举报
Rolle 发表于 2026/11/15 18:05:50 2026/11/15
【摘要】 很多网关在设计上就把「上游实际消耗」和「用户应扣额度」混成一个数字。这会在两个地方同时出错:账单算不准,监控也说不清。

很多网关在设计上就把「上游实际消耗」和「用户应扣额度」混成一个数字。这会在两个地方同时出错:账单算不准,监控也说不清。

两个数字各有用途

上游消耗是平台的成本,用户扣减是产品的收入逻辑。两者之间可能有折扣、赠送、失败不计费等调节项。

并发上限和速率上限是两回事,两个都要有。

失败请求的计费口径要明确

请求级错误(参数错、上下文超长)通常不扣用户额度,但已经产生的上游 token 成本是实打实的。这两个判断要分开做。

用量统计的时间口径必须写清楚,是 UTC 还是某个业务时区,一周从哪天开始。

因为一个请求可能跑几十秒,几十个并发请求同时在跑,额度还没用完,服务就被并发上限卡住了。

成功率统计要标注口径

「近一小时请求统计」里的失败包含了输入被拒和额度拒绝——这些不是上游故障。所以这个指标不能直接当故障率用。

成功率、时间窗口、历史保留时长——这些数字如果口径不透明,看板就失去了参考价值。

例如「近一小时请求统计」和「历史明细保留 90 天」这类信息,必须在页面上明确标注。

幂等约束防止重复落库

沿用 (request_id, usage_id) 唯一约束,防止结算重试导致重复记账。这是整套统计可信度的地基。

用量按 UTC 存储、按 UTC+8 统计,这是最不容易出错的组合。

实操:把调用明细按天和模型聚合出来。

用量查询页展示的是「用户应扣」的口径,和内部成本口径不同。

import collections, json

# 用量查询接口返回最近 100 条调用明细
detail = fetch_usage_detail()          # 你的查询函数

by_model = collections.Counter()
by_day = collections.Counter()
by_status = collections.Counter()

for row in detail:
    by_model[row["model"]] += row.get("total_tokens", 0)
    by_day[row["created_at"][:10]] += row.get("total_tokens", 0)
    by_status[row["status"]] += 1

print("按模型:", by_model.most_common())
print("按天  :", sorted(by_day.items()))
print("状态  :", by_status)

# 明细只保留最近 100 条,所以这里看的是「近期趋势」,
# 要看整月账目应该以服务端返回的汇总口径为准。

几个容易踩的坑

  • 把「今日额度」「并发上限」「账户余额」当成同一个东西。
  • 日/周/月窗口用的时区没说清楚,用户看到的数字和自己的记录对不上。
  • 没有 Key 级限流,一个跑飞的脚本把共享额度吃完。
  • 结算重试没有幂等约束,同一笔用量被记了两次。

小结

把配置项和凭据都外置,是成本最低、收益最持久的一个工程习惯。

如果你也碰到上面这些问题,可以看看 https://aiminis.info/ —— 一个把协议适配、渠道调度、用量与额度都收敛在一起的 AI API 网关,OpenAI 与 Anthropic 两套协议都能直接接。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。