چگونه با محدودیتهای Rate limit برخورد کنیم #
هنگامی که به طور مکرر Gilas API
را فراخوانی میکنید، ممکن است با پیامهای خطایی مانند 429: 'Too Many Requests'
یا RateLimitError
مواجه شوید. این پیامهای خطا به دلیل تجاوز از محدودیتهای Rate limit رخ میدهند.
محدودیتهای Rate limit به منظور حفظ کیفیت خدمات ما برای همه کاربران است. Rate limit بر روی تعداد دفعاتی که یک کاربر میتواند در یک دوره زمانی مشخص به خدمات ما دسترسی پیدا کند، محدودیت اعمال میکند.
این راهنما نکاتی را برای جلوگیری و مدیریت خطاهای محدودیت Rate limit را ارایه میدهد.
چرا محدودیتهای Rate limit وجود دارند #
محدودیتهای Rate limit یک روش معمول برای API
ها هستند و به دلایل مختلفی اعمال میشوند.
- اول، آنها به محافظت در برابر سوءاستفاده یا استفاده نادرست از
API
کمک میکنند. به عنوان مثال، یک عامل مخرب میتواندAPI
را با درخواستهای زیاد اشباع کند تا باعث اختلال در خدمات شود. با تنظیم محدودیتهای Rate limit، میتوان از این نوع فعالیتها جلوگیری کرد. - دوم، محدودیتهای Rate limit به اطمینان از دسترسی عادلانه همه به
API
کمک میکنند. اگر یک فرد یا سازمان تعداد زیادی درخواست ارسال کند، میتواندAPI
را برای دیگران کند کند. با محدود کردن تعداد درخواستهایی که یک کاربر میتواند ارسال کند،Gilas.io
اطمینان میدهد که همه فرصت استفاده ازAPI
را بدون تجربه کندی دارند. - در نهایت، محدودیتهای Rate limit میتوانند به
Gilas.io
در مدیریت بار کلی زیرساختهایش کمک کنند. اگر درخواستها بهAPI
به طور چشمگیری افزایش یابد، میتواند سرورها را تحت فشار قرار دهد و باعث مشکلات عملکردی شود. با تنظیم محدودیتهای Rate limit،Gilas.io
میتواند تجربهای روان و مداوم برای همه کاربران حفظ کند.
اگرچه برخورد به محدودیتهای Rate limit میتواند اعصاب خردکن باشد، اما این محدودیتها برای محافظت از عملکرد قابل اعتماد API
برای کاربرانش وجود دارند.
محدودیتهای Rate limit پیشفرض #
محدودیت Rate limit شما به طور خودکار بر اساس چندین عامل تنظیم میشود. با افزایش استفاده شما از Gilas API
و پرداخت موفقیتآمیز صورتحساب، ما به طور خودکار سطح استفاده شما را افزایش میدهیم.
اطلاعات بیشتر در مورد محدودیتهای Rate limit را اینجا بخوانید: محدودیتهای Rate limit
مثال خطای محدودیت Rate limit #
یک خطای محدودیت Rate limit زمانی رخ میدهد که درخواستهای API
خیلی سریع ارسال شوند. اگر از کتابخانه پایتون OpenAI
استفاده میکنید، آنها به شکل زیر خواهند بود:
RateLimitError: Rate limit reached for default-codex in organization org-{id} on requests per min. Limit: 20.000000 / min. Current: 24.000000 / min. Contact support@openai.com if you continue to have issues or if you’d like to request an increase.
در زیر کد نمونهای برای ایجاد یک خطای محدودیت Rate limit آورده شده است.
برای اجرای کدهای زیر ابتدا باید یک کلید API را از طریق پنل کاربری گیلاس تولید کنید. برای این کار ابتدا یک حساب کاربری جدید بسازید یا اگر صاحب حساب کاربری هستید وارد پنل کاربری خود شوید. سپس، به صفحه کلید API بروید و با کلیک روی دکمه “ساخت کلید API” یک کلید جدید برای دسترسی به Gilas API بسازید.
1
2from openai import OpenAI # for calling the OpenAI API
3import os
4
5client = OpenAI(
6 api_key=os.environ.get(("GILAS_API_KEY", "<کلید API خود را اینجا بسازید https://dashboard.gilas.io/apiKey>")),
7 base_url="https://api.gilas.io/v1/" # Gilas APIs
8)
9
10for _ in range(1000):
11 client.chat.completions.create(
12 model="gpt-4o-mini",
13 messages=[{"role": "user", "content": "Hello"}],
14 max_tokens=10,
15 )
چگونه از خطاهای محدودیت Rate limit جلوگیری کنیم #
تلاش مجدد #
یکی از راههای آسان برای جلوگیری از خطاهای محدودیت Rate limit، تلاش مجدد خودکار درخواستها با بازگشت نمایی تصادفی است. تلاش مجدد با بازگشت نمایی به معنای انجام یک وقفه کوتاه زمانی که یک خطای محدودیت Rate limit رخ میدهد، سپس تلاش مجدد برای درخواست ناموفق است. اگر درخواست همچنان ناموفق باشد، طول وقفه افزایش مییابد و فرآیند تکرار میشود. این کار تا زمانی که درخواست موفق شود یا حداکثر تعداد تلاشها برسد ادامه مییابد.
این روش مزایای زیادی دارد:
- تلاشهای مجدد خودکار به این معناست که میتوانید از خطاهای محدودیت Rate limit بدون خرابی یا از دست دادن دادهها بازیابی کنید.
- بازگشت نمایی به این معناست که تلاشهای مجدد اولیه شما میتوانند سریع انجام شوند، در حالی که همچنان از تأخیرهای طولانیتر در صورت شکست تلاشهای اولیه بهرهمند میشوید.
- افزودن جیتتر تصادفی به تأخیر کمک میکند تا تلاشهای مجدد همه در یک زمان انجام نشوند.
توجه داشته باشید که درخواستهای ناموفق به محدودیت در دقیقه شما کمک میکنند، بنابراین ارسال مداوم یک درخواست کار نخواهد کرد.
در زیر چند راهحل نمونه آورده شده است.
مثال #1: استفاده از کتابخانه Tenacity #
Tenacity یک کتابخانه عمومی برای تلاش مجدد است که تحت مجوز Apache 2.0 نوشته شده و به زبان پایتون است تا وظیفه افزودن رفتار تلاش مجدد به تقریباً هر چیزی را ساده کند.
برای افزودن بازگشت نمایی به درخواستهای خود، میتوانید از tenacity.retry
دکوریتور استفاده کنید. مثال زیر از تابع tenacity.wait_random_exponential
برای افزودن بازگشت نمایی تصادفی به یک درخواست استفاده میکند.
توجه داشته باشید که کتابخانه Tenacity یک ابزار شخص ثالث است و ما هیچ تضمینی در مورد قابلیت اطمینان یا امنیت آن نمیدهد.
1from tenacity import (
2 retry,
3 stop_after_attempt,
4 wait_random_exponential,
5) # برای بازگشت نمایی
6
7@retry(wait=wait_random_exponential(min=1, max=60), stop=stop_after_attempt(6))
8def completion_with_backoff(**kwargs):
9 return client.chat.completions.create(**kwargs)
10
11
12completion_with_backoff(model="gpt-4o-mini", messages=[{"role": "user", "content": "Once upon a time,"}])
مثال #2: استفاده از کتابخانه backoff #
کتابخانه دیگری که دکوریتورهای تابع برای بازگشت و تلاش مجدد فراهم میکند، backoff است.
مانند Tenacity، کتابخانه backoff یک ابزار ثالث است و ما هیچ تضمینی در مورد قابلیت اطمینان یا امنیت آن نمیدهیم.
1import backoff # برای بازگشت نمایی
2
3@backoff.on_exception(backoff.expo, openai.RateLimitError)
4def completions_with_backoff(**kwargs):
5 return client.chat.completions.create(**kwargs)
6
7
8completions_with_backoff(model="gpt-4o-mini", messages=[{"role": "user", "content": "Once upon a time,"}])
مثال 3: پیادهسازی دستی بازگشت #
اگر نمیخواهید از کتابخانههای ثالث استفاده کنید، میتوانید منطق بازگشت خود را پیادهسازی کنید.
1import random
2import time
3
4# تعریف یک دکوریتور تلاش مجدد
5def retry_with_exponential_backoff(
6 func,
7 initial_delay: float = 1,
8 exponential_base: float = 2,
9 jitter: bool = True,
10 max_retries: int = 10,
11 errors: tuple = (openai.RateLimitError,),
12):
13 """تلاش مجدد یک تابع با بازگشت نمایی."""
14
15 def wrapper(*args, **kwargs):
16 num_retries = 0
17 delay = initial_delay
18
19 while True:
20 try:
21 return func(*args, **kwargs)
22 # تلاش مجدد در خطاهای مشخص شده
23 except errors as e:
24 # افزایش تعداد تلاشها
25 num_retries += 1
26 # بررسی اینکه آیا حداکثر تلاشها رسیده است
27 if num_retries > max_retries:
28 raise Exception(
29 f"حداکثر تعداد تلاشها ({max_retries}) تجاوز شده است."
30 )
31 # افزایش تأخیر
32 delay *= exponential_base * (1 + jitter * random.random())
33 # ایجاد وقفه
34 time.sleep(delay)
35 except Exception as e:
36 raise e
37 return wrapper
38
39@retry_with_exponential_backoff
40def completions_with_backoff(**kwargs):
41 return client.chat.completions.create(**kwargs)
42
43completions_with_backoff(model="gpt-4o-mini", messages=[{"role": "user", "content": "Once upon a time,"}])