کدهای خطای API پیکو هوش و استراتژی Retry (401، 402، 429)
راهنمای کامل خطاهای 400، 401، 402، 403، 404، 429، 502 و 503 در API پیکو هوش، معنی کد error.code، هدر Retry-After و الگوی تلاش مجدد با backoff.
پیکو هوش·انتشار: ·بهروزرسانی: ·۵ دقیقه مطالعه
خلاصه: API پیکو هوش خطاها را با کد وضعیت HTTP استاندارد و یک بدنهی JSON همشکل با OpenAI برمیگرداند. خطاهای 429 و 503 موقتیاند و باید با تأخیر دوباره امتحان شوند؛ 401، 402، 403 و 404 را با تلاش مجدد حل نمیکنید. نکتهی مالی مهم: درخواست ناموفق هزینهای ندارد.
کدهای دقیق ممکن است در آینده افزایش یابد؛ همیشه پارسر خود را برای کدهای ناشناخته آماده نگه دارید (رفتار پیشفرض: بر اساس HTTP status تصمیم بگیرید).
هدر Retry-After
برای 429 و 503 سرور هدر Retry-After (بر حسب ثانیه) میفرستد؛ برای نمونه حدود ۳۰ ثانیه برای محدودیت نرخ و ۳۰ تا ۶۰ ثانیه برای در دسترس نبودن مسیر. این مقدار راهنماست، ثابت تضمینشده نیست. اگر هدر وجود داشت، دستکم همان مقدار صبر کنید.
چرا خطا هزینه ندارد؟
مکانیزم هزینه سه مرحله دارد: (۱) بررسی اولیه: قبل از ارسال درخواست به مدل، اعتبار کلید و موجودی بررسی (و در حسابهای استودیویی، اعتبار لازم رزرو) میشود؛ (۲) اجرا: درخواست با جایگزینی خودکار مسیرها انجام میشود؛ (۳) تسویه: فقط اگر پاسخ موفق بود، هزینهی واقعی بر اساس توکنها کسر میشود. اگر همهی مسیرها شکست بخورند، رزرو آزاد (برگردانده) میشود و چیزی کسر نمیشود. توضیح کامل: تخمین هزینه و توکن.
الگوی Retry درست
قواعد:
فقط 429، 502، 503 و خطاهای شبکه/timeout را retry کنید.
از exponential backoff با jitter استفاده کنید: تأخیر ۱، ۲، ۴، ۸ ثانیه بهعلاوهی مقدار تصادفی.
اگر Retry-After بود، آن را مقدم بدانید.
سقف تلاش (مثلاً ۴ بار) و سقف کل زمان تعیین کنید.
برای 402 و 403 فوراً هشدار بدهید، نه retry.
پایتون
import os, random, time, httpx
URL = "https://api.picoai.ir/v1/chat/completions"
HEADERS = {"Authorization": f"Bearer {os.environ['PICO_API_KEY']}"}
RETRYABLE = {429, 502, 503}
def chat(payload, max_attempts=5):
for attempt in range(max_attempts):
try:
r = httpx.post(URL, headers=HEADERS, json=payload, timeout=60)
except (httpx.TimeoutException, httpx.TransportError):
r = None
if r is not None and r.status_code == 200:
return r.json()
if r is not None and r.status_code not in RETRYABLE:
r.raise_for_status() # 400/401/402/403/404: بیفایده است
wait = min(2 ** attempt, 30) + random.random()
if r is not None and "retry-after" in r.headers:
wait = max(wait, float(r.headers["retry-after"]))
time.sleep(wait)
raise RuntimeError("پس از چند تلاش پاسخی دریافت نشد")
print(chat({"model": "gpt-6-luna",
"messages": [{"role": "user", "content": "سلام"}]}))
JavaScript
async function chat(payload, maxAttempts = 5) {
for (let i = 0; i < maxAttempts; i++) {
let res;
try {
res = await fetch('https://api.picoai.ir/v1/chat/completions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PICO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
signal: AbortSignal.timeout(60_000),
});
} catch { res = null; }
if (res?.ok) return res.json();
if (res && ![429, 502, 503].includes(res.status)) {
const err = await res.json().catch(() => ({}));
throw new Error(`${res.status} ${err?.error?.code ?? ''}`);
}
let wait = Math.min(2 ** i, 30) * 1000 + Math.random() * 1000;
const ra = Number(res?.headers.get('retry-after'));
if (ra) wait = Math.max(wait, ra * 1000);
await new Promise(r => setTimeout(r, wait));
}
throw new Error('no response after retries');
}
اگر از SDK رسمی استفاده میکنید، max_retries همین کار را برای شما انجام میدهد؛ Python و Node.
کاهش 429 در معماری
صف و محدودیت همزمانی در برنامه (semaphore).
batch کردن کارها در طول زمان بهجای انفجار ناگهانی.
کلید جدا برای سرویسهای مختلف تا یکی همهی سهمیه را نخورد.
افزایش سقفrateLimitRpm کلید از داشبورد.
کش پاسخهای تکراری در سمت خودتان.
خطا در استریم
اگر خطا پیش از شروع استریم رخ دهد، پاسخ JSON خطا با کد وضعیت مناسب میگیرید. پس از شروع پاسخ ۲۰۰ دیگر کد را نمیتوان عوض کرد؛ قطع اتصال را بهعنوان خطای شبکه ببینید. جزئیات: راهنمای SSE.
عیبیابی سریع
علامت
اقدام
ناگهان همهی درخواستها 401
کلید ابطال شده؟ کلید جدید بسازید
402 با اینکه شارژ کردهاید
موجودی دقیق در داشبورد؛ کلید به حساب دیگری وصل نیست؟