Коды ошибок#
Все ошибки — в OpenAI-совместимом формате:
json
{
"error": {
"message": "Описание",
"type": "rate_limit"
}
}
Таблица#
| HTTP | type |
Когда | Что делать |
|---|---|---|---|
400 |
invalid_request |
Битый JSON, отсутствует model |
Проверь тело запроса |
401 |
auth |
Нет/невалидный/отозванный ключ | Создай новый ключ через /new_token |
402 |
insufficient_funds |
Баланс ниже $0.10 | Пополни через /topup |
403 |
auth |
Пользователь заблокирован | Пиши в @Byffee |
403 |
permission |
Модель не разрешена для этого ключа | Используй другой ключ или модель |
429 |
rate_limit |
Превышен RPM (per-key или per-user) | Снизь частоту, см. Rate limits |
429 |
daily_limit |
Превышен дневной cap трат на ключе | Жди UTC-полночи или подними cap |
5xx |
upstream |
Провайдер модели лёг | Retry с экспоненциальной задержкой |
Retry-стратегия#
Простой retry на 429/5xx
import os
import time
from openai import OpenAI, APIStatusError
client = OpenAI(
base_url="https://api.ml-router.su/v1",
api_key=os.environ["ORB_API_KEY"],
)
def chat_with_retry(messages, max_attempts=4):
for attempt in range(max_attempts):
try:
return client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=messages,
)
except APIStatusError as e:
if e.status_code in (429, 500, 502, 503, 504):
# экспоненциальная задержка: удваиваем паузу на каждой попытке
delay = 2 ** attempt # 1с → 2с → 4с → 8с
time.sleep(delay)
continue
raise
raise RuntimeError("max retries exceeded")
Не ретрай 4xx (кроме 429)
400, 401, 402, 403 — это твои ошибки, ретрай не поможет. Только
429 и 5xx имеет смысл повторять.
Идемпотентность#
Идемпотентность — свойство запроса давать тот же результат при повторе.
Если запрос завершился без 200 (timeout, 5xx), не считай что он не
исполнился: возможно, провайдер уже сгенерировал ответ. Безопасно
ретраить только запросы с temperature=0 или с задаваемым seed,
чтобы получить тот же ответ.