Replicate API 限流与重试实现

说明如何按 Replicate 的预测创建与其他调用分别限流,识别 HTTP 429、设置有上限退避,并处理轮询、webhook 幂等、超时和重复投递问题。

Replicate API 的直接答案是:把创建 prediction 的请求单独限流,在收到 HTTP 429 时采用有上限的退避重试;Replicate 的限流说明写明,创建 prediction 默认每分钟 600 次,其他 endpoint 每分钟 3000 次,允许短暂突发请求,临近 credit 耗尽会适用更严格限制,命中限制则返回带重置时间提示的 HTTP 429,获授 credit 且未登记 payment method 的账户还受每秒 1 次、每分钟最多 6 次的限制。做 AI部署时,还要处理不可盲目重复创建、预测轮询和 webhook 重复投递。

AI部署中的限流与调用准备

先准备 API token、请求分类器和本地重试预算。Replicate 的 API token 文档要求通过 Authorization header 传入 Bearer token,并建议使用 environment variable,而不是把 token 硬编码进源码。

本地限流器至少要分别处理 prediction 创建、其他 endpoint 和账户状态,可先用下面的关系确定有效额度:

effective_limit = min(endpoint_limit, account_limit)

如果账户同时存在每秒和每分钟约束,所有窗口都通过后才发送请求。收到 429 时,响应体可能是:

{"detail":"Request was throttled. Your rate limit resets in ~30s."}

这里的重置时间带有近似标记,不应直接转换成固定等待时间。等待基数、退避倍数、最大等待时间和最大尝试次数都属于你的客户端策略。

创建请求和轮询不是同一个重试动作

Replicate 列出了三种 prediction 创建入口:

  • 社区模型:predictions.create
  • 官方模型:models.predictions.create
  • Deployments:deployments.predictions.create

创建 prediction 的官方文档说明,API 默认异步返回 prediction ID 和尚未完成的 prediction 对象。同步模式使用 Prefer: wait,默认保持请求 60 秒;Prefer: wait=5 表示等待 5 秒。如果期限内没有完成,返回对象的 status 会是 starting 或 processing,此时应继续 GET 初始响应 urls.get 或 Location header 提供的 prediction URL,文档示例每 1–2 秒检查一次。

需要设置自动取消期限时,可在创建请求中加入 Cancel-After header;其有效范围为 5 seconds 至 24 hours。同步等待结束只表示本次连接没有继续等待,并不等同于 prediction 已经失败。

对 HTTP 429 执行有上限退避

所引限流页没有给出统一的客户端等待秒数、最大尝试次数或 SDK retry flag。下面是应用侧策略骨架,不是 Replicate 官方 SDK 命令;所有 YOUR_ 值都需要按自己的流量和恢复目标填写。

import asyncio
import logging
from itertools import count


async def create_with_retry(client, endpoint, payload):
    headers = {
        "Authorization": "Bearer YOUR_API_TOKEN",
    }

    for attempt in count():
        response = await client.post(
            endpoint,
            headers=headers,
            json=payload,
        )

        if response.status_code != 429:
            return response

        logging.warning(
            "throttled: %s",
            response.json().get("detail"),
        )

        if attempt == YOUR_FINAL_ATTEMPT_INDEX:
            return response

        delay = min(
            YOUR_RETRY_BASE_SECONDS * (YOUR_BACKOFF_FACTOR ** attempt),
            YOUR_RETRY_MAX_SECONDS,
        )
        await asyncio.sleep(delay)

这段代码只对明确收到的 429 退避。连接中断、请求写出后超时等异常会直接向上抛出,避免自动重放创建请求。所引创建文档没有承诺 prediction 创建支持去重或幂等重放;如果客户端没有拿到 prediction ID,应先核对当前文档和业务记录,不能把同一任务盲目创建多次。

Webhook 重试方向相反

Webhook 是 Replicate 向你的 endpoint 投递事件,不是客户端重试 prediction API。Replicate 的 webhook 接收文档要求 endpoint 在几秒内返回 2xx,否则 webhook 可能被重试;终态 webhook 使用指数退避,最后一次约在 prediction 完成后 1 分钟发出,中间状态不重试,而且完全相同的 webhook 可能重复投递。

因此 webhook handler 必须幂等。先按 Replicate 的 webhook 验证文档检查 webhook-id、webhook-timestamp 和 webhook-signature,再以经过验证的 webhook-id 建立去重记录,确保重复到达时不会重复执行扣款、写入或任务派发。

验证与异常分支

Prediction 错误码采用 E#### 格式。对表示启动 prediction 超时的 E6716,Replicate 错误码文档建议稍等后重试、检查是否存在系统问题;如果持续出现,可尝试在非高峰时段运行。不要把 E6716 与 429 混成同一种重试原因。

上线前可在单元测试中验证:

  • 分类器是否分别约束创建、其他 endpoint 和账户窗口。
  • 收到 429 时是否记录 detail、执行有上限退避,并在最后停止。
  • 非 429 响应是否原样交给上层处理,连接异常是否避免自动重放创建请求。
  • 异步 prediction 是否保留 ID 并继续查询,重复 webhook 是否只产生一次业务结果。

本文步骤按正文链接的官方文档整理,未运行或测量;使用前应先对照当前版本核验。

资料来源