uttapen

محدودیت نرخ (Rate limits)

سقف درخواست در دقیقهٔ هر کلید، هدرهای X-RateLimit و Retry-After، سقف استریم هم‌زمان، سهم روزانهٔ مدل‌های رایگان و سقف ماهانهٔ کلید با نمونهٔ کد backoff.

به‌روزرسانی: ۱۶ شهریور ۱۴۰۵

چهار محدودیت مستقل روی درخواست‌ها اعمال می‌شود. سه‌تای اول را خودت در داشبورد تنظیم می‌کنی یا از پیش‌فرض استفاده می‌کنی؛ چهارمی مربوط به مدل‌های رایگان است. همه با 429 و یک code مشخص برمی‌گردند تا در کد قابل تفکیک باشند.

درخواست در دقیقه (هر کلید)

هر کلید یک rate_limit_rpm دارد، پیش‌فرض ۶۰ و قابل تنظیم بین ۱ تا ۶۰۰ در داشبورد ← کلیدها. پنجره لغزان است، نه دقیقهٔ تقویمی. همهٔ مسیرهای پولی (chat/completions، completions، embeddings) در همین شمارنده‌اند؛ GET /v1/models و GET /v1/uttapen/* شمرده نمی‌شوند.

روی هر پاسخ این هدرها هست:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1788734238

X-RateLimit-Reset زمان Unix (ثانیه) است که پنجره خالی می‌شود. وقتی سقف پر شد:

HTTP/1.1 429 Too Many Requests
Retry-After: 19
X-RateLimit-Remaining: 0

{"error":{"message":"سقف 60 درخواست در دقیقه برای این کلید پر شده است.","type":"rate_limit_exceeded","code":"rate_limit_exceeded","param":null}}

اگر بیشتر لازم داری، عدد را روی خود کلید بالا ببر؛ نیازی به تماس با ما نیست. برای بارهای موازی سنگین (batch پردازش اسناد)، چند کلید با نام جدا بساز تا هم شمارنده جدا باشد هم گزارش مصرف تفکیک شود.

استریم هم‌زمان (هر کاربر)

هر کاربر حداکثر ۱۰ استریم باز هم‌زمان دارد، مستقل از تعداد کلیدها. درخواست یازدهم 429 too_many_concurrent_streams با Retry-After: 5 می‌گیرد. شمارنده با پایان یا قطع استریم فوراً آزاد می‌شود. درخواست‌های غیراستریم در این شمارنده نیستند و فقط با RPM محدودند.

سقف ماهانهٔ کلید

اگر monthly_limit_toman روی کلید ست باشد، مجموع هزینهٔ درخواست‌های تسویه‌شدهٔ آن کلید در ماه جلالی جاری به‌علاوهٔ رزروهای باز با سقف مقایسه می‌شود. عبور از آن 429 key_monthly_limit_reached با بلوک uttapen شامل monthly_limit_toman و spent_toman می‌دهد. این چک داخل همان تراکنش رزرو انجام می‌شود، پس دو درخواست موازی نمی‌توانند با هم از سقف رد شوند. اول ماه جلالی شمارنده صفر می‌شود.

مدل‌های رایگان

مدل‌های با پسوند :free بدون شارژ کار می‌کنند ولی دو سقف دارند:

  1. سهم روزانهٔ هر کاربر: پیش‌فرض ۵۰ درخواست در روز روی مجموع مدل‌های رایگان. عبور → 429 free_quota_exceeded با Retry-After: 3600 و در بلوک uttapen، alternative_model و قیمت تقریبی‌اش. درخواست‌هایی که provider سرویس نداده (خطای قبل از اولین بایت) به سهم برمی‌گردند.
  2. ظرفیت مشترک provider: ظرفیت رایگان بین همهٔ کاربران یوتاپن مشترک است. وقتی provider 429 بدهد، تو 429 free_capacity_exhausted با Retry-After می‌گیری. این حالت را کنترل نمی‌کنیم؛ در ساعت‌های شلوغ عادی است.

مدل‌های رایگان برای تست و نمونه‌سازی‌اند. برای هر چیزی که کاربر واقعی منتظرش است، مدل پولی ارزان (مثل openai/gpt-5-nano یا google/gemini-2.5-flash-lite) قابل‌اعتمادتر است.

محدودیت provider

گاهی خود provider یک مدل را محدود می‌کند. در این حالت 429 upstream_rate_limited می‌گیری. اگر سه بار پشت سر هم برای یک مدل اتفاق بیفتد، gateway آن مدل را چند ده ثانیه «سرد» علامت می‌زند و بدون رفتن به provider 429 با Retry-After می‌دهد تا وقتت هدر نرود. مدل هم‌رده از provider دیگر (مثلاً google/gemini-2.5-flash به‌جای openai/gpt-5-mini) معمولاً همان لحظه در دسترس است؛ فیلد models برای fallback خودکار همین کار را می‌کند (migration).

backoff درست

import random, time
import openai

def create_with_retry(**kwargs):
    for attempt in range(4):
        try:
            return client.chat.completions.create(**kwargs)
        except openai.RateLimitError as e:
            code = e.code
            if code in ("key_monthly_limit_reached", "free_quota_exceeded"):
                raise  # صبر کردن فایده ندارد
            retry_after = e.response.headers.get("retry-after")
            wait = float(retry_after) if retry_after else min(2 ** attempt, 20)
            time.sleep(wait + random.random())
        except openai.InternalServerError:
            time.sleep(min(2 ** attempt, 20) + random.random())
    raise RuntimeError("uttapen: too many retries")

نکته‌ها:

  • Retry-After را جدی بگیر؛ زودتر زدن فقط شمارنده را پر نگه می‌دارد.
  • کدهای key_monthly_limit_reached و free_quota_exceeded با صبر حل نمی‌شوند؛ آن‌ها را از حلقهٔ تکرار بیرون بگذار.
  • SDK رسمی خودش دو بار تکرار می‌کند (max_retries). اگر لایهٔ تکرار خودت را داری، max_retries=0 بگذار تا تکرارها چند برابر نشوند.
  • برای بار زیاد، یک صف (Redis، RabbitMQ) با نرخ کمی کمتر از rate_limit_rpm ثابت‌تر از تکرار واکنشی است.

پیش‌فرض‌ها در یک نگاه

محدودیتمقدارcode
درخواست در دقیقه، هر کلید۶۰ (۱ تا ۶۰۰)rate_limit_exceeded
استریم هم‌زمان، هر کاربر۱۰too_many_concurrent_streams
سقف ماهانه، هر کلیدبدون سقف مگر تنظیم کنیkey_monthly_limit_reached
مدل رایگان، هر کاربر۵۰ درخواست در روزfree_quota_exceeded
ظرفیت رایگان providerمشترکfree_capacity_exhausted
بدنهٔ درخواست۲۰ مگابایتrequest_too_large (413)