速率限制open in new window

概述

什么是速率限制?

速率限制是 API 对用户或客户端在指定时间段内可以访问服务器的次数施加的限制。

为什么我们有速率限制?

速率限制是 API 的常见做法,它们的实施有几个不同的原因:

  • 它们有助于防止滥用或误用 API。例如,恶意行为者可能会向 API 发送大量请求,以试图使其过载或导致服务中断。通过设置速率限制,OpenAI 可以防止此类活动。
  • 速率限制有助于确保每个人都能公平地访问 API。如果一个人或组织发出过多的请求,可能会使其他人的 API 陷入困境。通过限制单个用户可以发出的请求数量,OpenAI 确保大多数人有机会使用 API 而不会遇到速度下降的情况。
  • **速率限制可以帮助 OpenAI 管理其基础设施上的聚合负载。**如果对 API 的请求急剧增加,可能会对服务器造成负担并导致性能问题。通过设置速率限制,OpenAI 可以帮助为所有用户保持流畅和一致的体验。

提示

请完整阅读本文档,以更好地了解 OpenAI 的速率限制系统的工作原理。我们包括代码示例和可能的解决方案来处理常见问题。建议在填写速率限制增加申请表open in new window之前遵循此指南,并在最后一部分中详细说明如何填写。

我们的 API 有哪些速率限制

我们根据使用的特定端点以及您拥有的帐户类型,在组织级别open in new window而非用户级别实施速率限制。速率限制以两种方式衡量:RPM(每分钟请求数)和TPM(每分钟标记数)。下表突出显示了我们 API 的默认速率限制,但在填写速率限制增加申请表后,可以根据您的用例增加这些限制。

TPM (每分钟标记数)单位因型号而异:

类型1 TPM 等于
davinci每分钟 1 个标记
curie每分钟 25 个标记
babbage每分钟 100 个标记
ada每分钟 200 个标记

实际上,这意味着ada与模型相比,您每分钟可以向模型发送大约 200 倍的标记davinci

文本和嵌入CODEX编辑图像
免费试用用户•20 RPM •150,000 TPM•20 RPM •40,000 TPM•20 RPM •150,000 TPM50 张图片/分钟
按需付费用户(前 48 小时)•60 RPM •250,000 TPM*•20 RPM •40,000 TPM•20 RPM •150,000 TPM50 张图片/分钟
按量付费用户(48小时后)•3,000 RPM •250,000 TPM*•20 RPM •40,000 TPM•20 RPM •150,000 TPM50 张图片/分钟

重要的是要注意,根据首先发生的情况,任一选项都可能达到速率限制。例如,您可能会向 Codex 端点发送仅包含 100 个标记的 20 个请求,这将达到您的限制,即使您没有在这 20 个请求中发送 40k 个标记。

速率限制如何工作?

如果您的速率限制是每分钟 60 个请求和每分钟 15 万davinci个标记,您将受到限制,要么达到请求/分钟上限,要么用完标记——以先发生者为准。例如,如果您的最大请求数/分钟为 60,则您应该能够每秒发送 1 个请求。如果您每 800 毫秒发送 1 个请求,一旦达到速率限制,您只需让程序休眠 200 毫秒即可再发送一个请求,否则后续请求将失败。默认值为 3,000 个请求/分钟,客户可以有效地每 20 毫秒或每 .02 秒发送 1 个请求。

如果我遇到速率限制错误会怎样

速率限制错误如下所示:

已达到组织 `default-text-davinci-002` 中 `org-{id}` 每分钟请求的速率限制。限制:20.0000000/分钟。当前:24.000000/分钟。

如果您达到速率限制,这意味着您在短时间内发出了太多请求,并且 API 将拒绝满足进一步的请求,直到经过指定的时间量。

速率限制与max_tokens

我们提供的每个模型都有有限数量的标记,可以在发出请求时作为输入传递。您不能增加模型接收的最大标记数。例如,如果您正在使用text-ada-001,则您可以向该模型发送的最大标记数是每个请求 2,048 个标记。

错误缓解

我可以采取哪些措施来缓解这种情况

OpenAI Cookbook 有一个python 笔记本open in new window,详细解释了如何避免速率限制错误。

在提供编程访问、批量处理功能和自动社交媒体发布时,您还应该谨慎行事 - 考虑只为受信任的客户启用这些功能。

为防止自动和大量滥用,请在指定时间范围内(每天、每周或每月)为单个用户设置使用限制。考虑对超出限制的用户实施硬上限或人工审查流程。

使用指数退避重试

避免速率限制错误的一种简单方法是使用随机指数退避自动重试请求。使用指数退避重试意味着在遇到速率限制错误时执行短暂的休眠,然后重试不成功的请求。如果请求仍然不成功,则增加睡眠时间并重复该过程。这一直持续到请求成功或达到最大重试次数为止。这种方法有很多好处:

  • 自动重试意味着您可以从速率限制错误中恢复而不会崩溃或丢失数据
  • 指数退避意味着您可以快速尝试第一次重试,同时如果您的前几次重试失败,仍然可以从更长的延迟中获益
  • 将随机抖动添加到延迟有助于重试所有同时命中。

请注意,不成功的请求会影响您的每分钟限制,因此不断重新发送请求将不起作用。

下面是一些使用指数退避算法的 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 库是退避open in new window

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)

WARNING

警告:响应对象可能不会按照提示的顺序返回完成,因此请始终记住使用索引字段将响应匹配回提示。

速率限制增加

我什么时候应该考虑申请提高利率限制?

我们的默认速率限制帮助我们最大限度地提高稳定性并防止滥用我们的 API。我们增加限制以启用高流量应用程序,因此申请提高速率限制的最佳时间是当您认为您拥有必要的流量数据来支持提高速率限制的有力案例时。没有支持数据的大型速率限制增加请求不太可能获得批准。如果您正在为产品发布做准备,请通过10天以上的阶段性发布获取相关数据。

请记住,速率限制的增加有时可能需要 7-10 天,因此如果有数据支持您将达到您当前的增长数字,那么尝试提前计划并尽早提交是有意义的。

我的速率限制提高请求会被拒绝吗?

速率限制增加请求通常被拒绝,因为它缺乏证明增加的合理性所需的数据。我们在下面提供了数字示例,展示了如何最好地支持提高速率限制的请求,并尽力批准符合我们的安全政策并显示支持数据的所有请求。我们致力于使开发人员能够扩展我们的 API 并取得成功。

我已经为我的文本/代码 API 实施了指数退避,但我仍然遇到此错误。如何提高速率限制?

目前,我们不支持增加我们的免费测试端点,例如编辑端点。我们也不会提高 ChatGPT速率限制,但您可以加入ChatGPT Professional 访问open in new window的候补名单。

我们理解有限的速率限制可能导致的挫败感,我们很乐意为每个人提高默认值。但是,由于共享容量限制,我们只能批准通过我们的速率限制增加请求表open in new window证明有需求的付费客户增加速率限制。为了帮助我们正确评估您的需求,我们要求您在表格的“分享需求证据”部分提供您当前使用情况的统计数据或基于历史用户活动的预测。如果此信息不可用,我们建议采用分阶段发布方法。首先按照您当前的速率限制向部分用户发布服务,收集 10 个工作日的使用数据,然后根据该数据提交正式的速率限制提高请求,以供我们审核和批准。

我们将审核您的请求,如果获得批准,我们将在 7-10 个工作日内通知您批准情况。

以下是您可以如何填写此表格的一些示例:

DALL-E API 示例
模型预估代币/分钟估计请求/分钟# 用户需要的证据1 小时最大吞吐量成本
DALL-E API不适用501000我们的应用程序目前正在生产中,根据我们过去的流量,我们每分钟发出大约 10 个请求。$60
DALL-E API不适用15010,000我们的应用程序在 App Store 中越来越受欢迎,我们开始达到速率限制。我们能否获得默认限制 50 img/min 的三倍?如果我们需要更多,我们将提交新表格。谢谢!$180
语言模型示例
模型预估代币/分钟估计请求/分钟# 用户需要的证据1 小时最大吞吐量成本
text-davinci-003325,0004,000050我们正在向一组初始的 alpha 测试人员发布,并且需要更高的限制来适应他们的初始使用。我们在这里有一个指向我们的谷歌驱动器的链接,它显示了分析和 api 使用情况。$390
text-davinci-002750,00010,00010,000我们的应用程序受到了很多关注;我们的候补名单上有 50,000 人。我们希望每天向 1,000 人的群组推出,直到我们达到 50,000 名用户。请查看过去 30 天我们当前标记/分钟流量的链接。这是针对 500 个用户的,根据他们的使用情况,我们认为 750,000 个标记/分钟和 10,000 个请求/分钟将是一个很好的起点。$900
代码模型示例
模型预估代币/分钟估计请求/分钟# 用户需要的证据1 小时最大吞吐量成本
code-davinci-002150,0001,00015我们是一群研究论文的研究人员。我们估计我们需要对 code-davinci-002 进行更高的速率限制,以便在月底前完成我们的研究。这些估计基于以下计算[...]Codex 模型目前处于免费测试阶段,因此我们可能无法为这些模型提供立即增加。

请注意,这些示例只是一般用例场景,实际使用率会因具体实施和使用情况而异。

Last Updated:
Contributors: fmm