語言模型 API 同時限制流量有兩種方式:每分鐘發送的請求數量(RPM)和每分鐘使用的代幣數量(TPM)。 即使你一直低於請求上限,還是會因為幾個冗長的提示花光你的代幣預算而被限速。 當你達到任一限制時,API 會以 429 Too Many Requests 回應,且你的應用程式必須等待。
OpenAI、Azure OpenAI 與 Anthropic 的計數方式
| Provider | 哪些項目受限 | 需知事項 |
|---|---|---|
| OpenAI | RPM、每日請求數、TPM、每日代幣數等,依組織、專案與模型分別計算 | 你先達到哪個上限,就以哪個上限為準。 對於權杖限制,請求會按 max_tokens 與根據其字元數的估算值兩者中較高者計算。 失敗的請求也會被計入。 |
| Azure OpenAI | 你為每次部署指派的 TPM,加上與其成比例設定的 RPM 限制 | RPM 會以 1 秒或 10 秒的視窗來檢查,所以即使每分鐘總計沒問題,爆發也會得到 429。 權杖估計包含 max_tokens。 |
| 人為 | RPM,即每分鐘輸入標記數(ITPM)及每分鐘輸出標記數(OTPM),每個模型 | 容量會持續補充,且 60 RPM 可能會被限制為每秒 1 次請求。 對大多數模型來說,快取的輸入標記不計入 ITPM,而 max_tokens 也不計入 OTPM。 |
如果你設定max_tokens為 4,000 代幣並拿回 200 代幣,OpenAI 和 Azure OpenAI 仍會將這 4,000 代幣計入你的上限。 這就是為什麼你可以在使用指標遠低於配額時,收到 429 錯誤。
429 對每位提供者的意義
如果你等著,並不是每個429都會消失。
| Provider | 等一下再試一次 | 停下來告訴別人 |
|---|---|---|
| OpenAI | 429 用於請求或代幣,429 slow_down(你的流量增長太快,即使在限制範圍內也是如此),以及 503 server_is_overloaded。 若已出現,請等待 Retry-After。 |
在 error.code 中的 429、credit_balance_exhausted、organization_spend_limit_exceeded、project_spend_limit_exceeded 或 organization_usage_limit_exceeded 重試無法恢復存取權限。 |
| Azure OpenAI | 429 是因部署的 TPM 或 RPM、系統容量,或暫時降低您的速率限制而發生。 等待 retry-after-ms。 |
在低於核准配額時,正式環境中持續出現 429 錯誤。 檢查部署的 TPM 分配,然後開啟支援請求。 |
| 人為 | 429 rate_limit_error 帶有 retry-after 排氣歧管,包含使用急劇增加後的加速限制,以及 529 overloaded_error。 |
每月消費上限是429。 它沒有 retry-after 標頭, error.details.error_code 是 enforced_spend_limit_reached,且一直失敗直到存取恢復。 |
如何處理大型語言模型(LLM)速率限制
- 檢查你拿到的是哪個429。 帳單、支出和配額錯誤需要有人處理,而不是重試。
- 只要 API 要求,就等多久。 OpenAI 和 Anthropic 幾秒鐘內就送來
retry-after了。 Azure OpenAI 會在幾毫秒內傳送retry-after-ms。 如果沒有任何提示,就用隨機抖動指數式地退後,並且限制嘗試次數和總時間。 - 了解 SDK 已具備的功能。
OpenAI 和 Anthropic Python SDK 預設會重試連線錯誤和
408、409、429、 5xx 回應兩次。 如果你加入自己的重試迴圈,請關閉 SDK 的重試,例如在 Python 中使用max_retries=0,如 Azure OpenAI 建議,否則嘗試次數會倍增。 - 聚焦重要內容。 在 OpenAI 和 Azure OpenAI 上,請設定
max_tokens接近你預期的回應大小。 在 Anthropic 上,將重複的內容(如系統指令)快取起來。 - 逐步增加。 流量急劇增加會觸發 OpenAI
slow_down和 Anthropic 的加速限制,即使未超出你的限制,也會如此。 OpenAI 建議,一旦你達到每分鐘 100 萬個輸入代幣,每 15 分鐘成長的幅度不超過 50%。 - 不要重新播放你已經取用過的串流。 串流開始後出現錯誤可能會以串流事件形式出現, OpenAI 建議 不要在你消費完輸出後自動重播請求。
- 當請求因 429 回應而停滯時,請告訴使用者,而不是顯示旋轉器。
如何測試你的應用程式是否能處理 LLM 速率限制
| Approach | 你發現的 | 你錯過的內容 |
|---|---|---|
| 在測試中模擬 SDK 客戶端,或讓你的編碼代理撰寫 mock 物件 | 不管你的錯誤處理分支是否執行 | 提供者的真實狀態碼、錯誤碼和標頭,以及你 SDK 自己的重試。 你的應用程式也需要一個只供測試使用的開關來連到模擬服務。 |
| 呼叫真正的 API,直到它對你進行速率限制 | 實際行為 | 你每個代幣都要付費,且不能按需觸發 slow_down、過載狀態或隨需支出上限 |
| 攔截你應用程式的真實流量並回傳服務提供者的錯誤,或依應用程式使用的權杖進行節流 | 真實網址、你的 SDK 重試政策,以及提供者的錯誤回應內容,並有你選擇的限制 | 單獨來看你的程式碼。 那種情況留給你的單元測試來處理。 |
在你的應用程式中試試看
Dev Proxy 會攔截你應用程式對語言模型 API 的請求,並回傳提供者自己的錯誤,而你的應用程式則持續呼叫真實的 URL。 若是 OpenAI,請下載預設設定並使用它啟動 Dev Proxy:
devproxy config get openai-throttling
devproxy --config-file "~dataFolder/configs/openai-throttling/.devproxy/devproxyrc.json"
openai-throttling預設對 rate_limit_exceeded 的請求有 90% 會因隨機錯誤而失敗:TPM 或 RPM 的 https://api.openai.com/*、slow_down、credit_balance_exhausted,或 503 server_is_overloaded。
anthropic-throttling 預設對 overloaded_error 的 RPM、輸入標記、輸出標記、加速 429 和 529 https://api.anthropic.com/* 也會套用相同設定。 兩個預設都包含 RetryAfterPlugin,它會在 429 回應中的 retry-after 時間到期前告訴你應用程式何時再次呼叫 API。 它不會檢查503和529的回應。
若要根據應用程式實際使用的權杖數進行速率限制,請使用 LanguageModelRateLimitingPlugin。 它會計算每個回應報告的提示和完成令牌數,當你的應用程式超過設定的限制時,會回傳 429 與 retry-after。 它支援相容的 OpenAI API,包括 Azure OpenAI 及本地模型:
{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/rc.schema.json",
"plugins": [
{
"name": "LanguageModelRateLimitingPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll",
"configSection": "languageModelRateLimitingPlugin"
}
],
"urlsToWatch": [
"https://api.openai.com/*",
"https://*.openai.azure.com/openai/deployments/*/chat/completions*"
],
"languageModelRateLimitingPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/languagemodelratelimitingplugin.schema.json",
"promptTokenLimit": 1000,
"completionTokenLimit": 500,
"resetTimeWindowSeconds": 60
}
}
外掛無法重現這個 max_tokens 估算值。 其預設的 429 回應內容使用該 insufficient_quota 代碼。 要回傳應用程式針對速率限制所預期的錯誤主體,將 whenLimitExceeded 設為 Custom,並將 customResponseFile 指向你自己的回應。 若要安裝 Dev Proxy,請參閱 設定 Dev Proxy。