Перейти к содержанию

Коды ошибок#

Все ошибки — в 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, чтобы получить тот же ответ.