محدودیتها
سقف نرخ درخواست API دانا، هدرهای پاسخ و روش درست مدیریت خطای ۴۲۹
هر کلید API سقف نرخ خودش را دارد. پیشفرض ۶۰ درخواست در دقیقه است و از رد شدن یک کلید، بقیه کلیدهای شما آسیب نمیبینند.
پنجره چطور شمرده میشود
شمارش روی پنجره ثابت است، نه لغزان. دقیقه به بازههای سرراست تقسیم میشود و شمارنده سر هر بازه از صفر شروع میکند.
این یک نتیجه عملی دارد. فرض کنید ۶۰ درخواست را در ثانیههای پایانی یک بازه بفرستید و ۶۰ تای بعدی را در ثانیههای آغازین بازه بعد. هر دو دسته میگذرند، یعنی برای یک لحظه دو برابر سقف رد شده است. پس بار سنگین را پخش کنید و به مرز پنجره تکیه نکنید.
هدرهای پاسخ روی ۴۲۹
وقتی از سقف رد شوید، پاسخ 429 این چهار هدر را همراه دارد:
| هدر | معنا |
|---|---|
Retry-After | چند ثانیه دیگر پنجره باز میشود |
X-RateLimit-Limit | سقف همین کلید |
X-RateLimit-Remaining | باقیمانده، که اینجا همیشه صفر است |
X-RateLimit-Reset | زمان باز شدن پنجره به شکل unix timestamp |
بدنه پاسخ روی رابط OpenAI:
{
"error": {
"message": "Rate limit exceeded.",
"type": "rate_limit_error",
"param": null,
"code": null
}
}اول type را بخوانید
کد 429 چهار علت جدا دارد و دو موردشان با تلاش مجدد حل میشوند. پیش از تلاش مجدد، فیلد type را نگاه کنید:
مقدار type | معنا | تلاش مجدد؟ |
|---|---|---|
rate_limit_error | سقف نرخ همین کلید | بله، بعد از Retry-After |
capacity_busy | صف موقت سرویس | بله، بعد از eta_seconds |
insufficient_quota | اعتبار تمام شده | خیر، باید شارژ کنید |
window_cap | سقف پنجره توکن | خیر، تا زمان reset_at صبر کنید |
شرح کامل هر چهار حالت با نمونه بدنه در خطاها آمده است.
مدیریت خطا در کد
به Retry-After گوش بدهید؛ حدس زدن فاصله، یا زودتر میزند یا بیخود صبر میکند. کمی jitter هم اضافه کنید تا چند worker همزمان دوباره به دیوار نخورند.
import random
import time
import httpx
def call_with_retry(payload, api_key, max_attempts=3):
for attempt in range(max_attempts):
response = httpx.post(
"https://api.dana.expert/v1/chat/completions",
headers={"Authorization": f"Bearer {api_key}"},
json=payload,
timeout=120,
)
if response.status_code != 429:
response.raise_for_status()
return response.json()
kind = response.json().get("error", {}).get("type")
if kind not in ("rate_limit_error", "capacity_busy"):
raise RuntimeError(f"۴۲۹ غیرقابل تلاش مجدد: {kind}")
wait = float(response.headers.get("Retry-After", 2**attempt))
time.sleep(wait + random.random())
raise RuntimeError("سقف نرخ بعد از سه تلاش هنوز باز نشده بود")سقف هر کلید
سقف روی خودِ کلید مینشیند، نه روی حساب. در کنسول دانا میتوانید برای هر کلید مقدار جداگانه بگذارید.
الگویی که معمولا جواب میدهد: یک کلید پرسقف برای سرویس اصلی، یک کلید کمسقف برای اسکریپتهای آزمایشی. اسکریپتی که از کنترل خارج شود، آنوقت فقط سهم خودش را میسوزاند.
نکتهها
- درخواستهای ناموفق هم شمرده میشوند. شمارش پیش از رسیدن به مدل انجام میشود، پس یک
400هم یک درخواست است. - streaming و non-streaming فرقی ندارند؛ هر کدام یک درخواستاند، هرچند پاسخ streaming دقایقی طول بکشد.
- شمارش با شناسه کلید انجام میشود. چند سرور که یک کلید مشترک دارند، در یک پنجره سهیماند.
- برای حجم بالا با پشتیبانی دانا تماس بگیرید.
صفحههای مرتبط
- خطاها - همه کدها و پاکتهای خطا
- احراز هویت - ساخت و باطل کردن کلید
- قیمت و توکن - سقف اعتبار و شمارش توکن