速率限制(Rate limits)
概览(Overview)
限速的定义( What are rate limits?)
速率限制是指API在特定时间段内为用户或客户端设置的访问服务器次数限制。
为什么要限速( Why do we have rate limits?)
速率限制是API的常见实践,它们出于几个不同的原因而被设置。
-
它们有助于保护API免受滥用或误用的侵害。 例如,恶意行为者可能会不断向API发出请求,试图超载或干扰其服务。通过设置速率限制,OpenAI可以防止此类活动的发生。
-
速率限制有助于确保所有人都可以公平地访问API。
如果有一个人或组织发送过多的请求,可能会使API变得拥塞,不利于其他人。
通过限制单个用户可以发出的请求数量,OpenAI确保尽可能多的人有机会使用API,而不会出现减速的情况。
- 速率限制使OpenAI能够管理其基础架构上的总负载。
如果对API的请求显著增加,可能会对服务器产生负担并导致性能问题。通过设置速率限制,OpenAI可以帮助所有用户保持平稳和一致的体验。
请仔细阅读本文档,以更好地了解OpenAI的速率限制系统如何工作。我们提供了代码示例和常见问题的解决方案。建议在填写(速率限制增加请求表单) (opens in a new tab)之前,请遵循本文档中的指导,最后一个部分提供了如何填写的详细说明。
我们的API有哪些速率限制?
您可以在账户管理页面的 (速率限制) (opens in a new tab)下查看您的组织的速率限制。
我们在(组织级别)强制执行频率限制,而不是用户级别,基于具体使用的终端点(Completion)以及您拥有的账户类型。频率限制有两种衡量方式:RPM(每分钟请求数)和TPM(每分钟令牌数)。下表列出了我们 API 的默认频率限制,但这些限制可以根据您的使用情况填写频率限制增加请求表格后进行提高。
TPM(每分钟令牌数)单位根据模型而异:
type | 1 TPM equals |
---|---|
davinci | 每分钟 1 个令牌 |
curie | 每分钟 25 个令牌 |
babbage | 每分钟 100 个令牌 |
ada | 每分钟 200 个令牌 |
实际上,这意味着您可以每分钟向ada
模型发送的令牌数比向davinci
模型发送的令牌数多大约200倍。
文本与嵌入 | 聊天 | Codex | 编辑 | 图像 | 音频 | |
---|---|---|---|---|---|---|
免费试用用户 | 3 RPM 150,000 TPM | 3 RPM 40,000 TPM | 3 RPM 40,000 TPM | 3 RPM 150,000 TPM | 每分钟5张图片 | 3 RPM |
按使用量付费的用户(前48小时) | 60 RPM 250,000 TPM | 60 RPM 60,000 TPM | 20 RPM 40,000 TPM | 20 RPM 150,000 TPM | 每分钟50张图片 | 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张图片 | 50 RPM |
需要注意的是频率限制可以被任一选项命中,取决于哪个先发生。例如,您可能会发送 20 次请求并使用了仅有的 100 个令牌,那么您的限制就已经填满了,即使在这 20 次请求中没有发送 40k 个令牌。
GPT-4的限速 (GPT-4 rate limits)
在GPT-4的有限内测期间,为满足需求,该模型将设置更为严格的速率限制。
gpt-4
/ gpt-4-0314
的默认速率限制为40k TPM和200 RPM。
gpt-4-32k
/ gpt-4-32k-0314
的默认速率限制为80k TPM和400 RPM。
由于容量限制,我们无法满足速率限制增加的请求。
在其当前状态下,该模型旨在进行实验和原型设计,而不是面向高容量的生产用例。
限速是如何工作的?(How do rate limits work?)
如果您的速率限制为每分钟60个请求和每分钟150k davinci
令牌,则您将受到限制,直到其中一个先达到。例如,如果您的最大请求/分钟为60,则应能够每秒发送1个请求。
如果您每800毫秒发送1个请求,则一旦达到速率限制,您只需要让程序休眠200毫秒即可发送另一个请求,否则后续请求将失败。
使用默认最大值为3,000个请求/分钟,客户可以在有效时间内每20毫秒或每0.02秒发送1个请求。
限速错误的解决 ( What happens if I hit a rate limit error?)
频率限制错误的格式如下:
在组织 org-{id} 上,对于默认文本-davinci-002 每分钟请求数已达到限制 :20.000000 /min。当前:24.000000 /min。
如果您达到了频率限制,这意味着您在短时间内进行了过多的请求,API 拒绝满足更多请求,直到经过指定时间。
限速 vs 最大令牌数 (Rate limits vs max_tokens
)
每个(我们提供的模型) (opens in a new tab)都有一个有限的令牌数,可以将其作为输入传递给请求时使用的模型。
您无法增加模型接受的最大令牌数。
例如,如果您正在使用text-ada-001
,则您可以向该模型发送的最大令牌数为每个请求2,048个令牌。
错误集合(Error Mitigation)
如何避免频率限制错误 (What are some steps I can take to mitigate this?)
OpenAI Cookbook 提供了一个(Python 笔记本) (opens in a new tab),详细说明了如何避免频率限制错误。
当提供编程访问、批量处理功能和自动化社交媒体发布时,您也应该注意谨慎,仅考虑为可信客户启用这些功能。
为了防止自动化和高容量的误用,在特定时间范围(每日、每周或每月)内为单个用户设置使用限制。考虑为超出限制的用户实施硬性上限或手动审查流程。
指数退避重试 ( Retrying with exponential backoff)
避免速率限制错误的一种简单方法是自动重试使用指数退避。
指数退避重试意味着在遇到速率限制错误时执行短暂休眠,然后重试不成功的请求。
如果请求仍然不成功,则增加休眠时间并重复该过程。这将继续进行,直到请求成功或达到最大重试次数。
这种方法有许多好处:
- 自动重试意味着您可以从速率限制错误中恢复,而不会出现崩溃或数据丢失
- 指数退避意味着您的第一次重试可以尝试得很快,同时仍然受益于更长的延迟,如果您的前几次重试失败
- 将随机抖动添加到延迟时间有助于避免所有重试同时发生。
请注意,不成功的请求会对您的每分钟限制造负担,因此不断重新发送请求是行不通的。
下面是几个使用指数退避的Python示例解决方案。
示例解决方案 #1: 使用Tenacitylibrary
Tenacity是一个Apache 2.0许可的通用重试库,用Python编写,用于简化将重试行为添加到几乎任何事物的任务。
要向请求添加指数级退避,您可以使用tenacity.retry
装饰器。下面的示例使用tenacity.wait_random_exponential
函数向请求添加随机指数级回退。
python
import tenacity
@tenacity.retry(wait=tenacity.wait_random_exponential(multiplier=1, max=60))
def make_request():
# Make your request here
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:使用backoff库
另一个提供退避和重试功能装饰器的Python库是(backoff) (opens in a new tab):
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类似,backoff库是一个第三方工具,OpenAI不保证其可靠性或安全性。
示例解决方案 #3:手动退避实现
如果您不想使用第三方库,可以按照以下示例实现自己的退避逻辑:
使用手动退避实施python
import time
def make_request():
# Make your request here
response = ... # The response from your request
while "retry-after" in response.headers:
delay = int(reponse.headers["retry-after"])
time.sleep(delay)
response = ... # Retry the request
# 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调用完全相同,唯一不同的是您需要将一组字符串传递给提示参数,而不是一个字符串。
示例:不使用批处理
没有批处理python
import openai
num_stories = 10
prompt = "Once upon a time,"
# 串行示例,每个请求完成一个故事
for _ in range(num_stories):
response = openai.Completion.create(
model="curie",
prompt=prompt,
max_tokens=20,
)
# print story
print(prompt + response.choices[0].text)
示例:使用批处理
批处理python
import openai
num_stories = 10
prompt = "Once upon a time,"
# create a list of prompts and send a single request for all stories
prompts = [prompt]*num_stories
responses = openai.Completion.create(
engine="curie",
prompt=prompts,
max_tokens=20,
n=1,
stop=None,
temperature=0.5,
frequency_penalty=0,
presence_penalty=0,
)
# print each story from the response
for response in responses.choices:
print(prompt + response.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实现规模和成功。
如何增加速率
我们理解限制速率可能会引起的烦恼,我们很乐意为每个人提高默认限制。
然而,由于共享能力受限,我们只能批准对已经通过我们的限制速率增加申请的付费客户进行增加限制速率的批准。
请通过我们的(限制速率增加申请表单) (opens in a new tab)进行申请。
为了更好地评估您的需求,请在表单的“提供需求证明”部分提供关于您当前使用情况或基于历史用户活动的预测的统计数据。
如果没有这些信息,我们建议采用分阶段发布的方法。
首先以您当前的速率限制将服务发布给一部分用户,在10个工作日内收集使用数据,然后基于这些数据提交正式的限制速率增加申请,以供我们审核和批准。
我们会审查您的申请,如果批准,我们将在7-10个工作日内通知您。
以下是您可能填写此表格的一些示例:
DALL-E API示例
模型 | 每分钟估计标记数 | 每分钟估计请求数 | 用户数量 | 需求证明 | 1小时最大吞吐量成本 |
---|---|---|---|---|---|
DALL-E API | 不适用 | 50 | 1000 | 我们的应用程序目前已上线,并且根据过去的流量,我们每分钟进行大约10个请求。 | $60 |
DALL-E API | 不适用 | 150 | 10,000 | 我们的应用在App Store上越来越受欢迎,我们开始遇到速率限制。我们可以获得绝对值为50个img/min的三倍默认限制吗?如果我们需要更多信息,我们会提交一个新的表格。谢谢! | $180 |
Language模型示例
模型 | 每分钟估计标记数 | 每分钟估计请求数 | 用户数量 | 需求证明 | 1小时最大吞吐量成本 |
---|---|---|---|---|---|
text-davinci-003 | 325,000 | 4,000 | 50 | 我们正在发布给一组初始的Alpha测试人员,需要更高的限制来适应他们的初始使用。我们在这里提供我们的谷歌驱动器链接,显示分析和API使用情况。 | $390 |
text-davinci-002 | 750,000 | 10,000 | 10,000 | 我们的应用正在受到很多关注; 我们有50,000人在等待名单上。我们希望每天向1000人的团队推出,直到达到50,000个用户。请参见我们,在过去30天中当前的标记/分钟流量的此 [链接] 。这是针对500个用户的,根据他们的使用情况,我们认为每分钟750,000个标记和10,000个请求将是一个很好的起点。 | $900 |
Code模型示例
模型 | 每分钟估计标记数 | 每分钟估计请求数 | 用户数量 | 需求证明 | 1小时最大吞吐量成本 |
---|---|---|---|---|---|
code-davinci-002 | 150,000 | 1,000 | 15 | 我们是一组正在撰写论文的研究人员。我们估计,为了在月底之前完成我们的研究,我们需要针对code-davinci-002获得更高的速率限制。这些估算是基于以下计算[(...)] | Codex模型目前是免费测试版,因此我们可能无法为这些模型提供即时提高。 |
请注意,这些示例只是一般用例场景,实际使用率将根据具体的实施和使用而有所不同。