OpenAI API 速率限制
概述
什么是速率限制?
速率限制是 API 对用户或客户端在指定时间段内可以访问服务器的次数施加的限制。
为什么我们有速率限制?
速率限制是 API 的常见做法,它们的实施有几个不同的原因:
它们有助于防止滥用或误用 API。例如,恶意行为者可能会向 API 发送大量请求,以试图使其过载或导致服务中断。通过设置速率限制,OpenAI 可以防止此类活动。
速率限制有助于确保每个人都能公平地访问 API。如果一个人或组织发出过多的请求,可能会使其他人的 API 陷入困境。通过限制单个用户可以发出的请求数量,OpenAI 确保大多数人有机会使用 API 而不会遇到速度下降的情况。
速率限制可以帮助 OpenAI 管理其基础设施上的聚合负载。如果对 API 的请求急剧增加,可能会对服务器造成负担并导致性能问题。通过设置速率限制,OpenAI 可以帮助为所有用户保持流畅和一致的体验。
请完整阅读本文档,以更好地了解 OpenAI 的速率限制系统的工作原理。我们包括代码示例和可能的解决方案来处理常见问题。建议在填写速率限制增加请求表之前遵循此指南,并在最后一部分中详细说明如何填写。
我们的 API 有哪些速率限制?
我们根据使用的特定端点以及您拥有的帐户类型,在组织级别而非用户级别实施速率限制。速率限制以两种方式衡量:RPM(每分钟请求数)和 TPM(每分钟令牌数)。下表突出显示了我们 API 的默认速率限制,但在填写速率限制增加请求表后,可以根据您的用例增加这些限制。
TPM(每分钟令牌数)单位因型号而异:
类型 | 1 TPM 等于 |
---|---|
davinci | 每分钟 1 个令牌 |
curie | 每分钟 25 个令牌 |
babbage | 每分钟 100 个令牌 |
ada | 每分钟 200 个令牌 |
实际上,这意味着与 davinci 模型相比,您每分钟可以向 ada 模型发送大约 200 倍的令牌。
文本和嵌入 | 聊天 | 编码 | 编辑 | 图像 | 音频 | |
---|---|---|---|---|---|---|
免费试用用户 | •20 RPM
•150,000 TPM |
•20 RPM
•40,000 TPM |
•20 RPM
•40,000 TPM |
•20 RPM
•150,000 TPM |
50 images / min | 50 RPM |
按需付费用户(前 48 小时) | •60 RPM
•250,000 TPM* |
•60 RPM
•60,000 TPM* |
•20 RPM
•40,000 TPM |
•20 RPM
•150,000 TPM |
50 images / min | 50 RPM |
按量付费用户(48小时后) | •3,500 RPM
•350,000 TPM* |
•3,500 RPM
•90,000 TPM* |
•20 RPM
•40,000 TPM |
•20 RPM
•150,000 TPM |
50 images / min | 50 RPM |
重要的是要注意,根据首先发生的情况,任一选项都可能达到速率限制。例如,您可能会向 Codex 端点发送仅包含 100 个令牌的 20 个请求,这将达到您的限制,即使您没有在这 20 个请求中发送 40k 个令牌。
GPT-4 速率限制
在 GPT-4 推出期间,该模型将有更严格的速率限制以满足需求。 gpt-4/gpt-4-0314 的默认速率限制为 40k TPM 和 200 RPM。 gpt-4-32k/gpt-4-32k-0314 的默认速率限制为 80k PRM 和 400 RPM。联系我们请求提高速率限制或订购专用容量;请注意,我们可能无法方便地满足所有请求。
速率限制如何工作?
如果您的速率限制是每分钟 60 个请求和每分钟 150k davinci 令牌,您将受到限制,要么达到请求/分钟上限,要么用完令牌——以先发生者为准。例如,如果您的最大请求数/分钟为 60,则您应该能够每秒发送 1 个请求。如果您每 800 毫秒发送 1 个请求,一旦达到速率限制,您只需让程序休眠 200 毫秒即可再发送一个请求,否则后续请求将失败。默认值为 3,000 个请求/分钟,客户可以有效地每 20 毫秒或每 .02 秒发送 1 个请求。
如果我遇到速率限制错误会怎样?
速率限制错误如下所示:
Rate limit reached for default-text-davinci-002 in organization org-{id} on requests per min. Limit: 20.000000 / min. Current: 24.000000 / min.
如果您达到速率限制,这意味着您在短时间内发出了太多请求,并且 API 将拒绝满足进一步的请求,直到经过指定的时间量。
Rate limits vs max_tokens
我们提供的每个模型都有有限数量的令牌,可以在发出请求时作为输入传递。您不能增加模型接收的最大令牌数。例如,如果您使用的是 text-ada-001,则可以向该模型发送的最大令牌数是每个请求 2,048 个令牌。
错误缓解
我可以采取哪些措施来缓解这种情况?
OpenAI Cookbook 有一个 python notebook,详细解释了如何避免速率限制错误。
在提供编程访问、批量处理功能和自动社交媒体发布时,您还应该谨慎行事 - 考虑只为受信任的客户启用这些功能。
为防止自动和大量滥用,请在指定时间范围内(每天、每周或每月)为单个用户设置使用限制。考虑对超出限制的用户实施硬上限或人工审查流程。
使用指数退避重试
避免速率限制错误的一种简单方法是使用随机指数退避自动重试请求。使用指数退避重试意味着在遇到速率限制错误时执行短暂的休眠,然后重试不成功的请求。如果请求仍然不成功,则增加睡眠时间并重复该过程。这一直持续到请求成功或达到最大重试次数为止。这种方法有很多好处:
自动重试意味着您可以从速率限制错误中恢复而不会崩溃或丢失数据
指数退避意味着您可以快速尝试第一次重试,同时如果您的前几次重试失败,仍然可以从更长的延迟中获益
将随机抖动添加到延迟有助于重试所有同时命中。
请注意,不成功的请求会影响您的每分钟限制,因此不断重新发送请求将不起作用。
下面是一些使用指数退避算法的 Python 示例解决方案。
示例 #1:使用 Tenacity 库
Tenacity 是一个 Apache 2.0 许可的通用重试库,用 Python 编写,用于简化将重试行为添加到几乎所有内容的任务。要为您的请求添加指数退避,您可以使用 tenacity.retry 装饰器。下面的示例使用 tenacity.wait_random_exponential 函数向请求添加随机指数退避。
import openai
from tenacity import (
retry,
stop_after_attempt,
wait_random_exponential,
) # for exponential backoff
@retry(wait=wait_random_exponential(min=1, max=60), stop=stop_after_attempt(6))
def completion_with_backoff(**kwargs):
return openai.Completion.create(**kwargs)
completion_with_backoff(model="text-davinci-003", prompt="Once upon a time,")
请注意,Tenacity 库是第三方工具,OpenAI 不保证其可靠性或安全性。
示例 #2:使用退避库
另一个提供退步和重试的函数装饰器的python库是 backoff。
import backoff
import openai
@backoff.on_exception(backoff.expo, openai.error.RateLimitError)
def completions_with_backoff(**kwargs):
return openai.Completion.create(**kwargs)
completions_with_backoff(model="text-davinci-003", prompt="Once upon a time,")
与 Tenacity 一样,退避库是第三方工具,OpenAI 不保证其可靠性或安全性。
示例 3:手动退避实现
如果你不想使用第三方库,你可以按照这个例子实现你自己的退避逻辑:
# imports
import random
import time
import openai
# define a retry decorator
def retry_with_exponential_backoff(
func,
initial_delay: float = 1,
exponential_base: float = 2,
jitter: bool = True,
max_retries: int = 10,
errors: tuple = (openai.error.RateLimitError,),
):
"""Retry a function with exponential backoff."""
def wrapper(*args, **kwargs):
# Initialize variables
num_retries = 0
delay = initial_delay
# Loop until a successful response or max_retries is hit or an exception is raised
while True:
try:
return func(*args, **kwargs)
# Retry on specific errors
except errors as e:
# Increment retries
num_retries += 1
# Check if max retries has been reached
if num_retries > max_retries:
raise Exception(
f"Maximum number of retries ({max_retries}) exceeded."
)
# Increment the delay
delay *= exponential_base * (1 + jitter * random.random())
# Sleep for the delay
time.sleep(delay)
# Raise exceptions for any errors not specified
except Exception as e:
raise e
return wrapper
@retry_with_exponential_backoff
def completions_with_backoff(**kwargs):
return openai.Completion.create(**kwargs)
同样,OpenAI 不保证此解决方案的安全性或效率,但它可以作为您自己的解决方案的良好起点。
批处理请求
OpenAI API 对每分钟的请求数和每分钟的令牌数有单独的限制。
如果您达到每分钟请求的限制,但每分钟有可用的令牌容量,您可以通过将多个任务分批处理到每个请求中来提高吞吐量。这将使您每分钟可以处理更多的令牌,尤其是对于我们较小的模型。
发送一批提示与普通的 API 调用完全相同,只是您将字符串列表而不是单个字符串传递给提示参数。
没有批处理的例子
import openai
num_stories = 10
prompt = "Once upon a time,"
# serial example, with one story completion per request
for _ in range(num_stories):
response = openai.Completion.create(
model="curie",
prompt=prompt,
max_tokens=20,
)
# print story
print(prompt + response.choices[0].text)
使用批处理的例子
import openai # for making OpenAI API requests
num_stories = 10
prompts = ["Once upon a time,"] * num_stories
# batched example, with 10 story completions per request
response = openai.Completion.create(
model="curie",
prompt=prompts,
max_tokens=20,
)
# match completions to prompts by index
stories = [""] * len(prompts)
for choice in response.choices:
stories[choice.index] = prompts[choice.index] + choice.text
# print stories
for story in stories:
print(story)
警告:响应对象可能不会按照提示的顺序返回完成,因此请始终记住使用索引字段将响应匹配回提示。
请求增加
我什么时候应该考虑申请提高利率限制?
我们的默认速率限制帮助我们最大限度地提高稳定性并防止滥用我们的 API。我们增加限制以启用高流量应用程序,因此申请提高速率限制的最佳时间是当您认为您拥有必要的流量数据来支持提高速率限制的有力案例时。没有支持数据的大型速率限制增加请求不太可能获得批准。如果您正在为产品发布做准备,请通过10天以上的阶段性发布获取相关数据。
请记住,速率限制的增加有时可能需要 7-10 天,因此如果有数据支持您将达到您当前的增长数字,那么尝试提前计划并尽早提交是有意义的。
我的速率限制提高请求会被拒绝吗?
速率限制增加请求通常被拒绝,因为它缺乏证明增加的合理性所需的数据。我们在下面提供了数字示例,展示了如何最好地支持提高速率限制的请求,并尽力批准符合我们的安全政策并显示支持数据的所有请求。我们致力于使开发人员能够扩展我们的 API 并取得成功。
我已经为我的文本/代码 API 实现了指数退避,但我仍然遇到这个错误。如何提高速率限制?
目前,我们不支持增加我们的免费测试端点,例如编辑端点。我们也不会提高 ChatGPT 速率限制,但您可以加入 ChatGPT Professional 访问的候补名单。
我们理解有限的速率限制可能导致的挫败感,我们很乐意为每个人提高默认值。但是,由于共享容量限制,我们只能批准通过我们的速率限制增加请求表证明有需求的付费客户增加速率限制。为了帮助我们正确评估您的需求,我们要求您在表格的“分享需求证据”部分提供您当前使用情况的统计数据或基于历史用户活动的预测。如果此信息不可用,我们建议采用分阶段发布方法。首先按照您当前的速率限制向部分用户发布服务,收集 10 个工作日的使用数据,然后根据该数据提交正式的速率限制提高请求,以供我们审核和批准。
我们将审核您的请求,如果获得批准,我们将在 7-10 个工作日内通知您批准情况。
以下是您可以如何填写此表格的一些示例:
DALL-E API 示例
语言模型示例
代码模型示例
模型 | 估计代币/分钟 | 估计请求/分钟 | # 用户 | 需要的证据 | 1 小时最大吞吐量成本 |
---|---|---|---|---|---|
DALL-E API | N/A | 50 | 1000 | 我们的应用程序目前正在生产中,根据我们过去的流量,我们每分钟发出大约 10 个请求。 | $60 |
DALL-E API | N/A | 150 | 10,000 | 我们的应用程序在 App Store 中越来越受欢迎,我们开始达到速率限制。我们能否获得默认限制 50 img/min 的三倍?如果我们需要更多,我们将提交一份新表格。谢谢! | $180 |
模型 | 估计代币/分钟 | 估计请求/分钟 | # 用户 | 需要的证据 | 1 小时最大吞吐量成本 |
---|---|---|---|---|---|
text-davinci-003 | 325,000 | 4,0000 | 50 | 我们正在向最初的一组 alpha 测试人员发布,需要更高的限制来适应他们的初始使用。我们在这里有一个指向我们的谷歌驱动器的链接,它显示了分析和 api 使用情况。 | $390 |
text-davinci-002 | 750,000 | 10,000 | 10,000 | 我们的应用程序受到了很多关注;我们的候补名单上有 50,000 人。我们希望每天向 1,000 人的群组推出,直到我们达到 50,000 名用户。请查看过去 30 天我们当前令牌/分钟流量的链接。这是针对 500 个用户的,根据他们的使用情况,我们认为 750,000 个令牌/分钟和 10,000 个请求/分钟将是一个很好的起点。 | $900 |
模型 | 估计代币/分钟 | 估计请求/分钟 | # 用户 | 需要的证据 | 1 小时最大吞吐量成本 |
---|---|---|---|---|---|
code-davinci-002 | 150,000 | 1,000 | 15 | 我们是一群研究论文的研究人员。我们估计我们需要对 code-davinci-002 进行更高的速率限制,以便在月底前完成我们的研究。这些估计基于以下计算 [...] | Codex 模型目前处于免费测试阶段,因此我们可能无法为这些模型提供立即增加。 |
请注意,这些示例只是一般用例场景,实际使用率会因具体实施和使用情况而异。
更多建议: