حساب و محدودیتها
خطاها و تلاش مجدد
خطاهای API هوشی همان قالب خطای OpenAI را دارند؛ پس SDKهای رسمی آنها را به exceptionهای آشنا (AuthenticationError، RateLimitError و…) تبدیل میکنند.
قالب خطا
JSON
{
"error": {
"message": "Model `openai/gpt-9` does not exist or is not available. See GET /v1/models.",
"type": "invalid_request_error",
"code": "model_not_found",
"param": null
}
}| فیلد | توضیح |
|---|---|
message | توضیح قابلخواندن برای انسان (برخی پیامها دوزبانه فارسی/انگلیسیاند). برای منطق برنامه به آن تکیه نکن. |
type | دستهٔ کلی خطا. |
code | کد دقیق و پایدار؛ برای تصمیمگیری در کد از این استفاده کن. اگر کد جداگانهای نباشد، برابر type است. |
param | فعلاً همیشه null. |
جدول کدها
| HTTP | type | code | علت | تلاش مجدد؟ |
|---|---|---|---|---|
| 400 | invalid_request_error | model_required | فیلد model ارسال نشده. | خیر |
| 400 | invalid_request_error | invalid_request_error | messages خالی یا نامعتبر است، یا پروایدر درخواست را رد کرده (پیام دقیق در message). | خیر |
| 401 | invalid_api_key | invalid_api_key | کلید ارسال نشده، با hk- شروع نمیشود، حذف/غیرفعال/منقضی شده یا حساب غیرفعال است. | خیر |
| 402 | insufficient_quota | insufficient_quota | موجودی کیف پول API کمتر از حداقل لازم است. | بعد از شارژ |
| 402 | spend_limit_reached | spend_limit_reached | سقف هزینهٔ ماهانهٔ این کلید پر شده. | ماه بعد / افزایش سقف |
| 403 | ip_not_allowed | ip_not_allowed | IP درخواست در فهرست IPهای مجاز کلید نیست. | خیر |
| 403 | permission_error | model_not_allowed | این کلید اجازهٔ استفاده از این مدل را ندارد. | خیر |
| 404 | invalid_request_error | model_not_found | مدل وجود ندارد، غیرفعال است یا در API در دسترس نیست (یا نوعش با endpoint نمیخواند). | خیر |
| 404 | invalid_request_error | provider_not_found | پروایدر در API بومی فعال نیست. | خیر |
| 404 | invalid_request_error | endpoint_not_supported | این مسیر در API بومی پشتیبانی نمیشود. | خیر |
| 413 / 422 | invalid_request_error | invalid_request_error | درخواست بزرگتر از حد مدل یا نامعتبر از نظر پروایدر. | خیر |
| 422 | — | — | خطای اعتبارسنجی فیلدها در endpointهای تصویر و صدا (قالب {message, errors}). | خیر |
| 429 | rate_limit_exceeded | rate_limit_exceeded | سقف درخواست در دقیقهٔ کلید پر شده. هدر Retry-After دارد. | بله، بعد از Retry-After |
| 429 | rate_limit_error | rate_limit_error | پروایدر بالادستی موقتاً محدودیت اعمال کرده (بعد از امتحان همهٔ مسیرها). | بله، با backoff |
| 502 | upstream_error | upstream_error | خطای سمت پروایدر یا پروایدر موقتاً در دسترس نیست. | بله، با backoff |
| 503 | upstream_error | upstream_error | API بومی: هیچ مسیر بالادستی سالمی در دسترس نیست. | بله، با backoff |
| 504 | — | — | اتصال به پروایدر برقرار نشد (timeout). | بله، با backoff |
API بومی
در API بومی، خطاهای هوشی (جدول بالا) با همین قالب برمیگردند، ولی خطاهای اعتبارسنجی خود پروایدر (مثلاً 400 از Anthropic) عیناً با قالب همان پروایدر عبور داده میشوند. جزئیات در API بومی.
خطا در میانهٔ استریم
وقتی استریم شروع شده باشد (کد 200 ارسال شده)، خطای بعدی پروایدر بهصورت یک رویداد SSE میآید و بلافاصله [DONE] ارسال میشود. در این رویداد code کد وضعیت HTTP پروایدر (عدد) است:
Text
data: {"id":"chatcmpl-x","object":"chat.completion.chunk",...,"choices":[{"index":0,"delta":{"content":"بخشی از"},...}]}
data: {"error":{"message":"Overloaded","type":"upstream_error","code":529}}
data: [DONE]SDKهای رسمی OpenAI این رویداد را به exception تبدیل میکنند. اگر خودت SSE را میخوانی، هر data را برای کلید error بررسی کن. درخواستهایی که با خطا تمام شوند هزینهای ندارند.
راهنمای تلاش مجدد
- فقط روی 429، 5xx و خطاهای شبکه تلاش مجدد کن؛ 4xxهای دیگر با تکرار درست نمیشوند.
- در 429 با کد
rate_limit_exceeded، به اندازهٔ هدرRetry-After(ثانیه) صبر کن. - در بقیهٔ موارد از exponential backoff با jitter استفاده کن (مثلاً ۱، ۲، ۴، ۸ ثانیه + عدد تصادفی) و حداکثر ۴–۵ بار.
- برای پایداری بیشتر، بعد از چند شکست به یک مدل جایگزین از پروایدر دیگر سوییچ کن (نمونهٔ fallback).
- شناسهٔ
X-Request-Idپاسخ را لاگ کن تا پشتیبانی بتواند درخواست را پیدا کند.
نمونه کد
from openai import OpenAI
# SDK رسمی خودش روی 408/409/429/5xx با backoff تلاش مجدد میکند
client = OpenAI(base_url="https://api.hooshi.ai/v1", api_key="hk-...", max_retries=4, timeout=120)
import openai
try:
r = client.chat.completions.create(model="openai/gpt-5.5", messages=[{"role": "user", "content": "سلام"}])
except openai.AuthenticationError:
... # 401: کلید را بررسی کن
except openai.PermissionDeniedError as e:
... # 403: ip_not_allowed یا model_not_allowed
except openai.APIStatusError as e:
if e.status_code == 402:
code = e.body.get("code") if isinstance(e.body, dict) else None
... # insufficient_quota یا spend_limit_reached → هشدار به تیم
else:
raise