别让重试吃掉你的预算:AI API 成本拆解实录
月底看到账单翻倍,第一反应通常是「是不是模型涨价了」。但拆开账目后发现,真正吃掉预算的往往不是单价,而是那些你以为「反正会成功」的重试。
按三个维度拆账单
按模型、按调用方(哪条业务线)、按时间(哪天的哪个时段)。切完之后通常会发现:大头不是最贵的模型,而是某个循环里没退出的重试。
有效的拆解方式是按三个维度切:按模型、按调用方(哪个业务线)、按时间(哪一天、哪个时段)。
哪些请求不该重试
已经产生了上游用量的请求不能重放——那部分 token 已经计费了,重试等于买两次。参数错误、额度不足、模型不存在这类错误重试多少次都不会成功。
所以成本优化的第一步不是换便宜模型,而是把无效重试去掉:不可重试的错误类型不要重试,已经失败且没有上游用量的请求不要重放。
因为高并发会触发上游的限流,限流之后就是失败,失败之后就是重试,重试就是更多 token。
并发上限在帮你省钱
听起来反直觉:高并发会触发上游限流,限流导致失败,失败触发重试,重试产生更多 token。一个把并发控制在合理区间的服务,通常比放开跑更便宜。
一个把并发控制在合理区间、没有失败重试的服务,通常比一个放开跑、天天触发限流的服务更便宜。
缓存命中率是最大的杠杆
如果应用每次都把一大段固定上下文完整送上去,prompt cache 命中与否会造成巨大的 token 差异。这也是会话亲和必须存在的原因。
所以渠道选择上要尽量保证同一会话落到同一渠道,否则缓存根本命中不了。
实操:带指数退避的重试封装,只对真正可重试的错误重试。
把可重试的状态码列成一个集合,不要用 except Exception 一把梭。
import random, time
from openai import OpenAI, APIStatusError
client = OpenAI(api_key=API_KEY, base_url="https://aiminis.info/v1")
RETRYABLE = {429, 500, 502, 503, 504}
def call_with_retry(fn, attempts=3):
for i in range(attempts):
try:
return fn()
except APIStatusError as e:
if e.status_code not in RETRYABLE or i == attempts - 1:
raise
time.sleep((2 ** i) + random.random())
# 4xx(参数错、额度不足、模型不存在)不该重试,换渠道也一样失败。
几个容易踩的坑
- 把最贵的模型当成「质量最好」,却没算重试带来的放大效应。
- 每个业务方各自维护一份价格表,半年后对不上账。
- 会话被路由到不同渠道,prompt cache 一直不命中。
- 包月套餐到期后又重新买了一把新 Key,所有客户端配置都要改一遍。
小结
把可观测性做在前面,后面所有的优化才有依据。
上面提到的能力基本都来自 https://aiminis.info/ 这个自建的 API 网关,支持 OpenAI 与 Anthropic 双协议接入,还有公开的模型健康看板 https://aiminis.info/model-health 可以先看看状态。
- 点赞
- 收藏
- 关注作者
评论(0)