محدودیت نرخ درخواست
محدودیت تعداد درخواست و توکن در دقیقه (RPM و TPM) در هوشوانا، هدرهای محدودیت، مدیریت خطای ۴۲۹ با backoff نمایی و راههای کم کردن برخورد با محدودیت.
آخرین بهروزرسانی:
محدودیت نرخ تعیین میکند هر کلید در هر دقیقه چند درخواست و چند توکن میتواند مصرف کند. این محدودیتها از سرویس شما در برابر حلقههای بیپایان و هزینههای ناگهانی محافظت میکنند و اجازه میدهند سهم سرویسهای مختلف را از هم جدا کنید.
انواع محدودیت
| محدودیت | معنی | کجا تنظیم میشود |
|---|---|---|
| RPM | حداکثر تعداد درخواست در دقیقه | قوانین کلید |
| TPM | حداکثر تعداد توکن (ورودی و خروجی) در دقیقه | قوانین کلید |
| حداکثر RPM حساب | سقف تعداد درخواست همهی کلیدهای حساب با هم | قوانین حساب |
محدودیتهای کلید نمیتوانند از محدودیت حساب بیشتر باشند. مثلاً اگر حداکثر RPM حساب ۶۰۰ باشد و دو کلید هر کدام RPM ۵۰۰ داشته باشند، مجموع درخواستهای دو کلید در یک دقیقه از ۶۰۰ بیشتر نمیشود. نحوهی تنظیم در قوانین کلید آمده است.
علاوه بر این، ارائهدهندههای مدل هم محدودیتهای خودشان را دارند. هوشوانا با توزیع بار بین مسیرهای مختلف تلاش میکند این محدودیتها به شما نرسند، ولی در زمانهای شلوغی ممکن است برخی مدلها کندتر پاسخ دهند.
هدرهای پاسخ
هر پاسخ شامل این هدرهاست تا بدانید چقدر تا محدودیت فاصله دارید:
| هدر | معنی |
|---|---|
x-ratelimit-limit-requests | سقف تعداد درخواست در بازهی فعلی |
x-ratelimit-remaining-requests | تعداد درخواست باقیمانده در این بازه |
x-ratelimit-reset-requests | زمان باقیمانده تا بازنشانی شمارنده |
curl -s -D - -o /dev/null https://hooshvana.ir/api/v1/models \
-H "Authorization: Bearer $HOOSHVANA_API_KEY" | grep -i x-ratelimitخطای ۴۲۹
وقتی از محدودیت عبور کنید، درخواست با وضعیت HTTP ۴۲۹ و کد rate_limited رد میشود. پاسخ هدر Retry-After دارد که میگوید حداقل چند ثانیه صبر کنید:
HTTP/1.1 429 Too Many Requests
Retry-After: 12
Content-Type: application/json
{"error": {"message": "تعداد درخواستهای این کلید از سقف مجاز در دقیقه بیشتر شده است. چند ثانیه بعد دوباره تلاش کنید.", "type": "rate_limit_error", "code": "rate_limited"}}درخواستی که با ۴۲۹ رد شود هزینهای ندارد.
backoff نمایی با jitter
بدترین واکنش به ۴۲۹ تلاش دوبارهی فوری است، چون فقط بار را بیشتر میکند. روش درست:
- اگر هدر
Retry-Afterوجود دارد، حداقل همان مدت صبر کنید. - در غیر این صورت، فاصله را در هر تلاش دو برابر کنید (۱، ۲، ۴، ۸ ثانیه و ...).
- یک مقدار تصادفی (jitter) به فاصله اضافه کنید تا همهی کارگرها همزمان دوباره تلاش نکنند.
- تعداد تلاشها و حداکثر فاصله را محدود کنید.
Python
import os
import random
import time
import openai
from openai import OpenAI
client = OpenAI(base_url="https://hooshvana.ir/api/v1", api_key=os.environ["HOOSHVANA_API_KEY"], max_retries=0)
def with_backoff(fn, max_attempts=6, base=1.0, cap=60.0):
for attempt in range(max_attempts):
try:
return fn()
except openai.RateLimitError as e:
if attempt == max_attempts - 1:
raise
retry_after = e.response.headers.get("retry-after")
if retry_after and retry_after.isdigit():
delay = float(retry_after)
else:
delay = min(cap, base * 2 ** attempt)
time.sleep(delay + random.uniform(0, 1))
result = with_backoff(lambda: client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[{"role": "user", "content": "سلام"}],
))
print(result.choices[0].message.content)Node.js
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://hooshvana.ir/api/v1",
apiKey: process.env.HOOSHVANA_API_KEY,
maxRetries: 0,
});
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
const header = (h, name) => (typeof h?.get === "function" ? h.get(name) : h?.[name]);
async function withBackoff(fn, maxAttempts = 6, baseMs = 1000, capMs = 60000) {
for (let attempt = 0; ; attempt++) {
try {
return await fn();
} catch (err) {
if (!(err instanceof OpenAI.RateLimitError) || attempt >= maxAttempts - 1) throw err;
const retryAfter = Number(header(err.headers, "retry-after"));
const delay = retryAfter > 0 ? retryAfter * 1000 : Math.min(capMs, baseMs * 2 ** attempt);
await sleep(delay + Math.random() * 1000);
}
}
}
const result = await withBackoff(() =>
client.chat.completions.create({
model: "openai/gpt-4o-mini",
messages: [{ role: "user", content: "سلام" }],
}),
);
console.log(result.choices[0].message.content);SDKهای رسمی OpenAI بهطور پیشفرض خودشان چند بار با backoff تلاش دوباره میکنند (max_retries در Python و maxRetries در Node.js). اگر همین رفتار برایتان کافی است، میتوانید فقط تعداد تلاشها را بیشتر کنید و کد بالا را ننویسید.
پیشنهادها برای برخورد کمتر با محدودیت
- دستهای بفرستید: برای embedding، چند متن را در یک درخواست بفرستید. Embeddings را ببینید.
- همزمانی را کنترل کنید: در پردازشهای دستهای از یک صف یا semaphore با تعداد کارگر محدود استفاده کنید، نه هزاران درخواست همزمان.
- max_tokens واقعبینانه بگذارید: TPM بر اساس توکنها حساب میشود و مقدار بزرگ بیدلیل ظرفیت را هدر میدهد.
- نتایج تکراری را کش کنید: اگر پرسشهای یکسان زیاد دارید، پاسخ را در سمت خودتان ذخیره کنید.
- کلیدها را جدا کنید: برای سرویس آنلاین و اسکریپتهای دستهای کلید جدا با محدودیت جدا بسازید تا اسکریپت شبانه سهم کاربران زنده را نگیرد.
- هدرها را پایش کنید: وقتی
x-ratelimit-remaining-requestsبه صفر نزدیک میشود، سرعت ارسال را خودتان کم کنید.
تفاوت با سقف هزینه
محدودیت نرخ دربارهی سرعت مصرف است و پس از چند ثانیه برطرف میشود. سقف هزینه دربارهی مقدار مصرف در روز یا ماه است و تا دورهی بعد ادامه دارد. اولی خطای ۴۲۹ (rate_limited) و دومی خطای ۴۰۲ (spend_cap_reached) میدهد. با خطای ۴۰۲ تلاش دوباره نکنید.
اگر سرویس شما به محدودیت حساب بیشتری نیاز دارد، از طریق تیکت پشتیبانی درخواست دهید.