什么是速率限制?
速率限制是 API 對用戶或客戶端在指定時間段內可以訪問服務器的次數(shù)施加的限制。
為什么我們有速率限制?
速率限制是 API 的常見做法,它們的實施有幾個不同的原因:
它們有助于防止濫用或誤用 API。例如,惡意行為者可能會向 API 發(fā)送大量請求,以試圖使其過載或導致服務中斷。通過設置速率限制,OpenAI 可以防止此類活動。
速率限制有助于確保每個人都能公平地訪問 API。如果一個人或組織發(fā)出過多的請求,可能會使其他人的 API 陷入困境。通過限制單個用戶可以發(fā)出的請求數(shù)量,OpenAI 確保大多數(shù)人有機會使用 API 而不會遇到速度下降的情況。
速率限制可以幫助 OpenAI 管理其基礎設施上的聚合負載。如果對 API 的請求急劇增加,可能會對服務器造成負擔并導致性能問題。通過設置速率限制,OpenAI 可以幫助為所有用戶保持流暢和一致的體驗。
請完整閱讀本文檔,以更好地了解 OpenAI 的速率限制系統(tǒng)的工作原理。我們包括代碼示例和可能的解決方案來處理常見問題。建議在填寫速率限制增加請求表之前遵循此指南,并在最后一部分中詳細說明如何填寫。
我們的 API 有哪些速率限制?
我們根據(jù)使用的特定端點以及您擁有的帳戶類型,在組織級別而非用戶級別實施速率限制。速率限制以兩種方式衡量:RPM(每分鐘請求數(shù))和 TPM(每分鐘令牌數(shù))。下表突出顯示了我們 API 的默認速率限制,但在填寫速率限制增加請求表后,可以根據(jù)您的用例增加這些限制。
TPM(每分鐘令牌數(shù))單位因型號而異:
類型 | 1 TPM 等于 |
---|---|
davinci | 每分鐘 1 個令牌 |
curie | 每分鐘 25 個令牌 |
babbage | 每分鐘 100 個令牌 |
ada | 每分鐘 200 個令牌 |
實際上,這意味著與 davinci 模型相比,您每分鐘可以向 ada 模型發(fā)送大約 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 |
重要的是要注意,根據(jù)首先發(fā)生的情況,任一選項都可能達到速率限制。例如,您可能會向 Codex 端點發(fā)送僅包含 100 個令牌的 20 個請求,這將達到您的限制,即使您沒有在這 20 個請求中發(fā)送 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。聯(lián)系我們請求提高速率限制或訂購專用容量;請注意,我們可能無法方便地滿足所有請求。
速率限制如何工作?
如果您的速率限制是每分鐘 60 個請求和每分鐘 150k davinci 令牌,您將受到限制,要么達到請求/分鐘上限,要么用完令牌——以先發(fā)生者為準。例如,如果您的最大請求數(shù)/分鐘為 60,則您應該能夠每秒發(fā)送 1 個請求。如果您每 800 毫秒發(fā)送 1 個請求,一旦達到速率限制,您只需讓程序休眠 200 毫秒即可再發(fā)送一個請求,否則后續(xù)請求將失敗。默認值為 3,000 個請求/分鐘,客戶可以有效地每 20 毫秒或每 .02 秒發(fā)送 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.
如果您達到速率限制,這意味著您在短時間內發(fā)出了太多請求,并且 API 將拒絕滿足進一步的請求,直到經(jīng)過指定的時間量。
我們提供的每個模型都有有限數(shù)量的令牌,可以在發(fā)出請求時作為輸入傳遞。您不能增加模型接收的最大令牌數(shù)。例如,如果您使用的是 text-ada-001,則可以向該模型發(fā)送的最大令牌數(shù)是每個請求 2,048 個令牌。
錯誤緩解
我可以采取哪些措施來緩解這種情況?
OpenAI Cookbook 有一個 python notebook,詳細解釋了如何避免速率限制錯誤。
在提供編程訪問、批量處理功能和自動社交媒體發(fā)布時,您還應該謹慎行事 - 考慮只為受信任的客戶啟用這些功能。
為防止自動和大量濫用,請在指定時間范圍內(每天、每周或每月)為單個用戶設置使用限制??紤]對超出限制的用戶實施硬上限或人工審查流程。
使用指數(shù)退避重試
避免速率限制錯誤的一種簡單方法是使用隨機指數(shù)退避自動重試請求。使用指數(shù)退避重試意味著在遇到速率限制錯誤時執(zhí)行短暫的休眠,然后重試不成功的請求。如果請求仍然不成功,則增加睡眠時間并重復該過程。這一直持續(xù)到請求成功或達到最大重試次數(shù)為止。這種方法有很多好處:
自動重試意味著您可以從速率限制錯誤中恢復而不會崩潰或丟失數(shù)據(jù)
指數(shù)退避意味著您可以快速嘗試第一次重試,同時如果您的前幾次重試失敗,仍然可以從更長的延遲中獲益
將隨機抖動添加到延遲有助于重試所有同時命中。
請注意,不成功的請求會影響您的每分鐘限制,因此不斷重新發(fā)送請求將不起作用。
下面是一些使用指數(shù)退避算法的 Python 示例解決方案。
示例 #1:使用 Tenacity 庫
Tenacity 是一個 Apache 2.0 許可的通用重試庫,用 Python 編寫,用于簡化將重試行為添加到幾乎所有內容的任務。要為您的請求添加指數(shù)退避,您可以使用 tenacity.retry 裝飾器。下面的示例使用 tenacity.wait_random_exponential 函數(shù)向請求添加隨機指數(shù)退避。
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:使用退避庫
另一個提供退步和重試的函數(shù)裝飾器的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:手動退避實現(xiàn)
如果你不想使用第三方庫,你可以按照這個例子實現(xiàn)你自己的退避邏輯:
# 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 對每分鐘的請求數(shù)和每分鐘的令牌數(shù)有單獨的限制。
如果您達到每分鐘請求的限制,但每分鐘有可用的令牌容量,您可以通過將多個任務分批處理到每個請求中來提高吞吐量。這將使您每分鐘可以處理更多的令牌,尤其是對于我們較小的模型。
發(fā)送一批提示與普通的 API 調用完全相同,只是您將字符串列表而不是單個字符串傳遞給提示參數(shù)。
沒有批處理的例子
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)
警告:響應對象可能不會按照提示的順序返回完成,因此請始終記住使用索引字段將響應匹配回提示。
請求增加
我什么時候應該考慮申請?zhí)岣呃氏拗疲?/p>
我們的默認速率限制幫助我們最大限度地提高穩(wěn)定性并防止濫用我們的 API。我們增加限制以啟用高流量應用程序,因此申請?zhí)岣咚俾氏拗频淖罴褧r間是當您認為您擁有必要的流量數(shù)據(jù)來支持提高速率限制的有力案例時。沒有支持數(shù)據(jù)的大型速率限制增加請求不太可能獲得批準。如果您正在為產(chǎn)品發(fā)布做準備,請通過10天以上的階段性發(fā)布獲取相關數(shù)據(jù)。
請記住,速率限制的增加有時可能需要 7-10 天,因此如果有數(shù)據(jù)支持您將達到您當前的增長數(shù)字,那么嘗試提前計劃并盡早提交是有意義的。
我的速率限制提高請求會被拒絕嗎?
速率限制增加請求通常被拒絕,因為它缺乏證明增加的合理性所需的數(shù)據(jù)。我們在下面提供了數(shù)字示例,展示了如何最好地支持提高速率限制的請求,并盡力批準符合我們的安全政策并顯示支持數(shù)據(jù)的所有請求。我們致力于使開發(fā)人員能夠擴展我們的 API 并取得成功。
我已經(jīng)為我的文本/代碼 API 實現(xiàn)了指數(shù)退避,但我仍然遇到這個錯誤。如何提高速率限制?
目前,我們不支持增加我們的免費測試端點,例如編輯端點。我們也不會提高 ChatGPT 速率限制,但您可以加入 ChatGPT Professional 訪問的候補名單。
我們理解有限的速率限制可能導致的挫敗感,我們很樂意為每個人提高默認值。但是,由于共享容量限制,我們只能批準通過我們的速率限制增加請求表證明有需求的付費客戶增加速率限制。為了幫助我們正確評估您的需求,我們要求您在表格的“分享需求證據(jù)”部分提供您當前使用情況的統(tǒng)計數(shù)據(jù)或基于歷史用戶活動的預測。如果此信息不可用,我們建議采用分階段發(fā)布方法。首先按照您當前的速率限制向部分用戶發(fā)布服務,收集 10 個工作日的使用數(shù)據(jù),然后根據(jù)該數(shù)據(jù)提交正式的速率限制提高請求,以供我們審核和批準。
我們將審核您的請求,如果獲得批準,我們將在 7-10 個工作日內通知您批準情況。
以下是您可以如何填寫此表格的一些示例:
DALL-E API 示例
模型 | 估計代幣/分鐘 | 估計請求/分鐘 | # 用戶 | 需要的證據(jù) | 1 小時最大吞吐量成本 |
---|---|---|---|---|---|
DALL-E API | N/A | 50 | 1000 | 我們的應用程序目前正在生產(chǎn)中,根據(jù)我們過去的流量,我們每分鐘發(fā)出大約 10 個請求。 | $60 |
DALL-E API | N/A | 150 | 10,000 | 我們的應用程序在 App Store 中越來越受歡迎,我們開始達到速率限制。我們能否獲得默認限制 50 img/min 的三倍?如果我們需要更多,我們將提交一份新表格。謝謝! | $180 |
語言模型示例
模型 | 估計代幣/分鐘 | 估計請求/分鐘 | # 用戶 | 需要的證據(jù) | 1 小時最大吞吐量成本 |
---|---|---|---|---|---|
text-davinci-003 | 325,000 | 4,0000 | 50 | 我們正在向最初的一組 alpha 測試人員發(fā)布,需要更高的限制來適應他們的初始使用。我們在這里有一個指向我們的谷歌驅動器的鏈接,它顯示了分析和 api 使用情況。 | $390 |
text-davinci-002 | 750,000 | 10,000 | 10,000 | 我們的應用程序受到了很多關注;我們的候補名單上有 50,000 人。我們希望每天向 1,000 人的群組推出,直到我們達到 50,000 名用戶。請查看過去 30 天我們當前令牌/分鐘流量的鏈接。這是針對 500 個用戶的,根據(jù)他們的使用情況,我們認為 750,000 個令牌/分鐘和 10,000 個請求/分鐘將是一個很好的起點。 | $900 |
代碼模型示例
模型 | 估計代幣/分鐘 | 估計請求/分鐘 | # 用戶 | 需要的證據(jù) | 1 小時最大吞吐量成本 |
---|---|---|---|---|---|
code-davinci-002 | 150,000 | 1,000 | 15 | 我們是一群研究論文的研究人員。我們估計我們需要對 code-davinci-002 進行更高的速率限制,以便在月底前完成我們的研究。這些估計基于以下計算 [...] | Codex 模型目前處于免費測試階段,因此我們可能無法為這些模型提供立即增加。 |
請注意,這些示例只是一般用例場景,實際使用率會因具體實施和使用情況而異。
更多建議: