Replicate 怎么接入?它不是 OpenAI 兼容,是异步任务 API
接一家新的推理平台,多数时候是这么个流程:改 base_url、换 key、换模型 ID,跑通,收工。这套肌肉记忆在 Groq、DeepInfra、Novita、Cerebras 这些平台上都成立,因为它们都提供 OpenAI 兼容端点。
Replicate 不吃这一套。它有自己的 predictions API,请求体长得完全不一样,返回也不是”一次调用拿到结果”。如果你带着”改个 base_url 就行”的预期去接,大概率会在第一个小时里反复怀疑是不是 key 配错了——其实是范式不对。
这篇把范式差异讲清楚,再讲那张容易看错一个数量级的价格表。
先认清它的调用模型
Replicate 的核心对象叫 prediction,直译是”一次预测”,实际含义是”一个提交给平台去跑的任务”。你提交任务,拿到一个任务对象,然后去取结果——而不是像 chat completions 那样在同一个 HTTP 响应里把答案给你。
这个差别决定了后面所有事情:你的代码里会多出任务状态管理,你的超时逻辑要重写,你的错误处理要区分”提交失败”和”任务跑失败”这两件不同的事。
好消息是官方提供了同步模式的开关,短任务可以退化成熟悉的调用方式。坏消息是那只是个开关,底层还是任务式的,长任务上你必须面对异步。
三种 endpoint,分别什么时候用
官方文档给出三个提交入口:
| 场景 | Endpoint |
|---|---|
| 社区模型 | https://api.replicate.com/v1/predictions |
| 官方模型 | https://api.replicate.com/v1/models/{model}/predictions |
| Deployments | https://api.replicate.com/v1/deployments/{deployment}/predictions |
选哪个不是风格问题,是三种不同的东西:
第一个是通用入口,你在请求体里用 version 字段指定要跑哪个模型版本。社区上传的模型走这条路。
第二个把模型写在 URL 路径里,适合官方维护的模型——路径本身就锁定了模型,请求体里不用再带版本。
第三个是 deployments,可以理解成”你自己配置好的一套运行参数”。当你需要固定的扩缩容策略而不是每次现开,走这条。
接入初期我建议先用第一或第二个跑通,deployments 等你确定了长期用法再配——它多一层配置,调试期反而绕。
鉴权与请求体
鉴权是标准的 Bearer:
Authorization: Bearer $REPLICATE_API_TOKEN
环境变量名是 REPLICATE_API_TOKEN。注意它叫 TOKEN 不叫 API_KEY——如果你的配置管理里有一套 *_API_KEY 的命名约定,这里是个例外,容易在批量迁移配置时漏掉。
请求体的关键字段:
version:模型版本 IDinput:输入参数对象webhook:任务完成时回调的 URLwebhook_events_filter:触发 webhook 的事件类型数组
一个最简的提交长这样:
curl -X POST https://api.replicate.com/v1/predictions \
-H "Authorization: Bearer $REPLICATE_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"version": "<模型版本 ID>",
"input": { "prompt": "..." }
}'
input 里具体有哪些字段,取决于你调的是哪个模型——这和 chat completions 有固定的 messages 结构完全不同。每个模型自己定义输入 schema,所以换模型往往要改 input 的结构,不只是改个名字。
version 这个字段值得单独说
它钉的是模型版本 ID,不是”模型名”。这件事有两面。
好的一面:可复现性是天然的。你今天跑出来的结果,三个月后用同一个 version 再跑,用的是同一份权重和同一套推理代码。做内容生成、做需要留证据的业务,这个属性很值钱——你能说清楚”这张图是哪个版本生成的”。
负担的一面:版本管理被推到了你这边。平台不会替你悄悄升级到更好的版本,你得自己跟。这意味着你需要一个地方记录”当前生产用的是哪个 version”,需要有人定期去看有没有新版本、值不值得升。我的做法是把 version 收敛到配置文件的一个常量里,绝不散落在代码各处,并且在服务启动日志里把生效的 version 打出来——排查”为什么最近输出风格变了”的时候,这行日志能省掉半天。
最值钱的一节:同步还是异步
这是接 Replicate 真正要做的决策。
默认路径是异步
提交后你拿到的是任务对象,不是结果。拿结果有两条路:轮询,或者 webhook。
轮询的好处是简单,本地开发也能跑,坏处是你要自己控制轮询间隔和超时,任务多了以后轮询请求本身也是负担。
webhook 的好处是不用等,任务跑完平台来通知你。代价是几件很现实的事:
你需要一个公网可达的接收端。 内网服务、本地开发环境都收不到回调,这在开发阶段特别烦——通常得靠内网穿透工具,或者开发期先用轮询、上线才切 webhook。
你要处理重复投递和乱序。 回调这种东西,重试机制导致同一个事件可能到两次,多个任务的回调也不保证按提交顺序到达。接收端必须是幂等的:拿任务 ID 做去重键,先查状态再处理,别假设”收到就是第一次收到”。
你要过滤事件类型。 webhook_events_filter 就是干这个的——不指定的话你可能收到一堆中间状态的回调,处理逻辑要判断得很小心。想清楚你只关心”完成”还是也关心中间进度,按需订阅。
短任务可以切同步
请求头 Prefer: wait 会启用同步模式,还能指定等待秒数,比如 wait=5。
curl -X POST https://api.replicate.com/v1/predictions \
-H "Authorization: Bearer $REPLICATE_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Prefer: wait=5" \
-d '{ "version": "<模型版本 ID>", "input": { "prompt": "..." } }'
它适合什么:跑得快的模型、写一次性脚本、做原型验证、在 Notebook 里手动试参数。这些场景下多写一套轮询逻辑是浪费。
它不适合什么:耗时长的任务。同步模式意味着连接就挂在那儿等,中间任何网络抖动都会让你丢掉结果的取回路径(任务本身还在跑,但你的那次 HTTP 请求已经断了)。任务越长,这条路越脆。关于连接挂太久的通用问题,API 超时怎么设置里的思路同样适用。
Cancel-After 是烧钱的闸门
还有一个请求头 Cancel-After,设置任务的自动取消超时,格式像 1m30s、2h。
在按秒计费的平台上,这个头的重要性比它看起来高得多。一个卡住的任务不会自己停,而计费按秒往前走。参数给错、输入数据异常、模型陷进某种病态输入——这些情况下任务可能跑得远超预期,而你要到看账单的时候才发现。
我的建议是:默认就加上这个头,值设成你业务能容忍的最长时间的一点五倍左右。 它不改变正常任务的行为,只在异常时兜底。这是那种”平时完全没感觉、出事一次就回本”的配置。
计费口径:那张单位不统一的表
Replicate 是双计费的——GPU 按秒计,部分语言模型按 token 计。
GPU 按秒(官方定价页):
| GPU | 标识 | 价格 |
|---|---|---|
| Nvidia A100 (80GB) | gpu-a100-large | $0.001400/sec |
| 2x Nvidia A100 (80GB) | gpu-a100-large-2x | $0.002800/sec |
| Nvidia H100 | gpu-h100 | $0.001525/sec |
| Nvidia L40S | gpu-l40s | $0.000975/sec |
语言模型按 token:
| 模型 | 输入 | 输出 |
|---|---|---|
anthropic/claude-3.7-sonnet | $3.00 / million input tokens | $0.015 / thousand output tokens |
deepseek-ai/deepseek-r1 | $3.75 / million input tokens | $0.01 / thousand output tokens |
以上均以官方定价页为准,价格会变。
先说那个坑
看出来了吗——输入按”每百万”标价,输出按”每千”标价。
这不是笔误,官方页上就是这么列的。但如果你扫一眼表格,看到输入 3.00、输出 0.015,很容易得出”输出比输入便宜两百倍”的荒谬结论。实际上要换到同一单位才能比:
- $0.015 / 千 token = $15 / 百万 token
- $0.01 / 千 token = $10 / 百万 token
(这两行换算是本文按官方标价做的算术,不是官方原文表述。)
换算之后才看得清真实关系:claude-3.7-sonnet 是输入 $3 / 输出 $15,输出是输入的五倍;deepseek-r1 是输入 $3.75 / 输出 $10,输出不到输入的三倍。这两家的成本结构差别,在你的任务偏”长输入短输出”还是”短输入长输出”时会导致完全不同的账单。
抄价格表进 Excel 的时候,第一件事就是统一单位。我见过按原始数字直接做的成本模型,结论错了一个数量级,还挺自信。
按秒计费的直觉换算
秒价这种小数看不出感觉,换成小时就清楚了(算术演示,价格以官网为准):
- L40S:0.000975 × 3600 = $3.51 / 小时
- A100 80GB:0.0014 × 3600 = $5.04 / 小时
- H100:0.001525 × 3600 = $5.49 / 小时
- 2×A100:0.0028 × 3600 = $10.08 / 小时
有了小时价,就能和你熟悉的 GPU 云报价横着比了,也能反过来判断自建划不划算——这块的算法可以看自托管还是用 API。
按秒计费改变了”哪张卡便宜”的判断
这是我认为按秒计费最反直觉、也最值钱的一点。
假设同一个任务,在 L40S 上要跑 8 秒,在 H100 上要跑 3 秒(这两个秒数是为了说明问题假设的,不是实测值,你必须用自己的任务测):
- L40S:0.000975 × 8 = $0.0078 / 次,跑一万次是 $78
- H100:0.001525 × 3 = $0.004575 / 次,跑一万次是 $45.75
单价更高的卡,总账更便宜——因为你付的是秒数 × 秒价,而不是卡的挂牌价。在按小时租、按天租的模式下这个结论不成立(那时候空转也要付钱),但在按秒计费 + 任务式调用的模式下,它经常成立。
所以选卡的正确做法不是看谁便宜,是:拿你的真实任务,在候选卡上各跑一批,记录平均耗时,然后算每次任务的实际成本。这个测试花不了多少钱,但能省掉一个数量级的误判。
什么场景该选它
把上面几件事合起来看,Replicate 的产品形态是自洽的:按秒计费 + 任务式异步 + 版本 ID 显式管理。
这套组合天然适合:跑图跑视频这类耗时任务、离线批处理、需要留版本证据的生成业务、以及那些”跑一次几秒到几分钟、但不要求毫秒级响应”的活。任务跑多久付多久,不用为闲置买单,版本可追溯。
不适合:低延迟的聊天补全。不是它做不了,是这套范式在那个场景下的每一项设计都变成了成本——异步是多余的、版本管理是负担、按秒计费在高频短请求下也没有优势。那类需求去找 OpenAI 兼容端点的平台更省事,Serverless 推理怎么选里有对比思路。
顺带一提,这不是”哪家更好”的问题。同一个项目里同时接两家很常见:低延迟对话走兼容端点的平台,重活扔给 Replicate 异步跑。范式不同不是缺点,是分工。
接入自查清单
- 有没有搞清楚自己接的是任务式 API,而不是 chat completions 的兼容端点?调用代码的结构要按这个设计。
- 环境变量名是
REPLICATE_API_TOKEN(是 TOKEN 不是 API_KEY),配置管理里核一遍。 - 三种 endpoint 选对了吗?初期用通用或官方模型入口,deployments 等长期用法定了再配。
version是不是收敛到了配置里的单一常量,并且在启动日志里打印出来了?- 拿结果走轮询还是 webhook?选 webhook 的话,接收端幂等了吗、公网可达吗、
webhook_events_filter配了吗? Cancel-After加了吗?按秒计费的平台上,这是防止异常任务烧钱的唯一兜底。- 价格表统一单位了吗?输入按百万、输出按千,不换算就对比必然看错。
- 选卡之前,有没有拿真实任务在候选卡上各跑一批、记录平均耗时再算总成本?
接这家平台的技术难度不高,难的是先放下”改三处配置”的惯性。范式认清了,剩下的都是查文档就能解决的事;范式没认清,你会在一堆看起来毫不相干的报错里绕很久。