ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

大模型 API 报 429 和超时:限流、重试与降级该怎么写

大模型 API 报 429 和超时:限流、重试与降级该怎么写 我手上有个批量任务每天要把几百条文案交给大模型 API 打分。跑了一周都挺顺结果上周三下午开始突然报错一看日志全是 429还夹着几个超时。我当时第一反应就是往上加重试结果越加越糟报错更多了。这篇把这次踩坑的过程和最后定下来的写法写清楚。先说下我那次批量任务的现场我用的是 OpenAI 兼容接口Python 里用 requests 直接调。平时每分钟能过三四十个请求那天下午开始连续十几条返回 429意思是限流了我这一分钟内打得太密服务端不接了。接着又有几个请求直接超时连状态码都没有就是连不上。我当时没多想给请求包了个循环报 429 就立刻重试想着多试几次总能过。结果试了十分钟429 越报越勤后来干脆连别的接口也跟着超时。这时候我才反应过来重试不是万能的乱重试等于给服务端火上浇油。哪些报错能重试哪些重试只会更糟这次我吃了个教训先按状态码把错误分了个类再决定要不要重试。429 和 5 开头的错500、502、503、504可以重试但必须等一会儿再试超时这种没状态码的可以重试次数别多两次封顶400、401、403 这种别重试重试一万次结果一样是我的请求本身有问题408 这种也要小心有些网关它内部已经处理了一半你重发可能造成重复判断是不是该重试我总结成一个土办法先看是不是我这边的错是就不重试再看是不是服务端临时抽风是就退避重试。指数退避加抖动代码就这么写网上讲的指数退避就是每次等待时间翻倍第一次等 1 秒、第二次等 2 秒、第三次等 4 秒这样。但光翻倍有个毛病多个请求同时失败时会一起重试又撞在一起。加个随机抖动就能错开这个思路我是从网上一个开源项目里学的。我最后定下来的写法是这样直接用def call_with_retry(fn, times5):wait 1for i in range(times):try:return fn()except RateLimitError as e:if i times - 1:raisewait min(wait * 2, 60)time.sleep(wait random.uniform(0, wait))重点就是最后一行wait 每次翻倍最多到 60 秒再叠加一个随机数这样同一时间失败的请求不会整整齐齐地一起重试。换上这个以后我那个批量任务的 429 基本降到了零。超时和重试次数我是这么定的超时时间我最初设的是 5 秒发现经常超时后来改成 30 秒一个请求最久等半分钟。重试次数设成 5 次重试间隔最长 60 秒也就是说最坏情况一个请求要拖几分钟。这对我来说能接受因为跑的是后台任务不赶时间。如果你是给用户直接调用的接口重试次数要再少一点两三次就够不然用户等得太久。这个数值没有标准答案得看你任务的容忍度我建议先按我这个参数跑一天再根据日志里实际的重试占比调整。真扛不住就降级别硬顶重试只能解决临时抖动如果服务端是真的忙不过来了或者你当天的额度用完了重试再多次也没用。这时候要降级。我的降级方案是按重要程度排的最要紧的请求排队慢速处理不着急的丢到明天的队列实在处理不了的就记下来人工过一遍。再往前一步就是提前看限流。很多大模型 API 会在响应头里给你返回余量比如 x-ratelimit-remaining 这种字段你可以在代码里读出来快用完了就先放慢速度别等到 429 打脸才被动重试。这个我还在试后面专门写一篇讲怎么读限流头、怎么做动态限速。这篇是大模型 API 调用系列的一篇。前面写过批量过文档怎么省成本后面打算写限流头怎么读、多账号轮询怎么分配都是自己踩过的。想看后续的可以关注账号。
返回列表