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

Повторить запрос LLM API или переключить модель: пять проверок

7 мин чтенияAPI Guide

Повторяйте только временный и безопасно воспроизводимый вызов в пределах общего бюджета. Переключайтесь только на маршрут, заранее принятый для этого процесса.

Пять проверок LLM API — владелец сбоя, фиксация результата, бюджет восстановления, эквивалентность резервного маршрута и здоровье — ведут к повтору, переключению, очереди, деградации или остановке.

Повторяйте тот же запрос к LLM API, только если сбой выглядит временным, операция безопасно воспроизводится и общий бюджет процесса ещё не исчерпан. Резервную модель включайте лишь после проверки того же контракта: вход, схема ответа, инструменты, безопасность, данные, задержка, стоимость и качество. Если условия не выполнены, правильным действием может быть очередь, ограниченный ответ без генерации или контролируемый отказ.

Это не выбор из двух кнопок. Сначала пройдите пять проверок:

ПроверкаУсловие продолженияЕсли условие не выполнено
Владелец сбояОшибка действительно временная либо имеет отдельный бюджет на резервном маршрутеИсправить запрос, доступ, политику или лимит
Состояние фиксацииНет видимого вывода и внешнего эффекта; статус не неизвестенСверить состояние, явно продолжить или остановить
Общий бюджет восстановленияОстались попытки, время, стоимость и допустимое снижение качестваОчередь, утверждённый ограниченный режим или остановка
Эквивалентность резерваРезерв прошёл проверки схемы, инструментов, безопасности, данных и качестваНе переключать автоматически
Здоровье маршрутаОсновной маршрут допускает ограниченную пробу либо резервный маршрут исправенРазомкнуть цепь и выбрать безопасный режим

После этих проверок выберите ровно один результат: повтор, резервную модель, очередь, утверждённый ограниченный ответ или контролируемый отказ.

Сначала определите владельца сбоя

Одинаковый HTTP-код не всегда означает одинаковое действие. В текущем справочнике OpenAI один 429 означает слишком быстрый трафик, другой — исчерпанную квоту или лимит расходов. Первый может восстановиться после снижения скорости; второй требует изменения бюджета.

Рабочая классификация:

  • 5xx или перегрузка, которую данные провайдера относят к временной: небольшой бюджет повторов с джиттером; сам HTTP-код этого не доказывает.
  • 429 с коротким окном ожидания: соблюсти сигнал провайдера и снизить параллелизм.
  • исчерпана квота или лимит расходов: остановить синхронные попытки или поставить разрешённую работу в очередь.
  • 400, неверная схема, контекст или неподдерживаемый параметр: изменить запрос.
  • 401/403: исправить учётные данные, права или владельца маршрута.
  • ограничение безопасности или политики: не обходить менее строгой моделью.
  • частичный поток ответа или неопределённый результат инструмента: сначала сверить состояние.

Проверьте, сколько попыток уже делает библиотека. В документации Anthropic указано, что официальные SDK по умолчанию дважды повторяют временные ошибки соединения, ограничения частоты и 5xx, учитывая retry-after. Руководство по устранению ошибок Gemini API также описывает автоматические повторы SDK. Три попытки в вашем catch могут оказаться далеко не тремя сетевыми вызовами.

Фиксация результата важнее номера попытки

Тайм-аут говорит, что клиент не получил ожидаемый результат. Он не доказывает, что провайдер ничего не сделал.

До приёма запроса повтор обычно проще. После приёма статус может быть неизвестен. После первого видимого токена новая модель не может прозрачно продолжить старый поток. После записи в базу, веб-хука, вызова инструмента или внешнего действия повтор может создать дубликат.

Поэтому для действий используйте operation ID или idempotency key приложения. Храните переходы requested → started → committed → acknowledged. При неопределённом состоянии сначала запросите фактический результат. Второй вызов модели не является проверкой.

Для потоковой выдачи зафиксируйте продуктовый контракт:

  • до первого видимого события можно сбросить состояние и выбрать одобренный маршрут, только если подтверждено отсутствие уже зафиксированного внешнего эффекта;
  • после первого события показать прерывание, предложить пользователю явный повторный запуск или использовать проверенный протокол продолжения;
  • не склеивать новый ответ с уже выданным фрагментом.

Один бюджет на SDK, шлюз, приложение и очередь

Формула должна быть видна оператору:

text
workflow_attempts = initial + sdk_internal + gateway + application_retry + fallback + queue_redelivery

Добавьте три независимых потолка: полное время, дополнительные токены/стоимость и допустимое ухудшение качества. Интерактивный чат и ночная обработка не должны делить одинаковую политику.

Рекомендации AWS по тайм-аутам, повторам и задержке с джиттером объясняют риск: повторы на нескольких уровнях умножают нагрузку, а перегруженный сервис восстанавливается медленнее. Выберите одну точку принятия решения; остальные уровни должны сообщать фактические попытки и подчиняться общему бюджету.

yaml
workflow: live-classification max_total_attempts: 3 max_elapsed_ms: 5000 max_extra_cost_usd: 0.01 replay_safe_until: result_persisted approved_fallback: compact-classifier-backup queue_allowed: true stop_on: [auth, policy, unknown_commit, unapproved_route]

Значения — пример. Настройте их по своему SLO и подтвердите инъекцией отказов.

Резервный маршрут должен доказать эквивалентность

До автоматического переключения прогоните одинаковые тестовые наборы:

  1. Вход: контекст, файлы, изображения, языки и ограничения.
  2. Выход: JSON Schema, обязательные поля, отказ модели и усечение ответа.
  3. Инструменты: имена, аргументы, параллельные вызовы, возврат результата и идемпотентность.
  4. Безопасность: блокировки, границы решений с серьёзными последствиями и эскалация.
  5. Данные: регион, срок хранения, арендатор и допустимый класс данных.
  6. Эксплуатация: задержка p95/p99, потоковая выдача, ID запросов и видимость состояния.
  7. Экономика: единицы цены, кэш, владелец квоты и предел расходов.
  8. Качество: единый набор оценок и порог для конкретного процесса.

Резервная модель может быть принята для классификации и отклонена для ответа о политике клиенту. Одна конечная точка, совместимая с OpenAI, упрощает адаптер, но не делает модели одинаковыми.

Пример функции решения

ts
type Action = "retry" | "fallback" | "queue" | "degrade" | "fail_closed"; function nextAction(input: { owner: "transient" | "rate" | "quota" | "request" | "auth" | "policy" | "unknown"; commitState: "none" | "committed" | "unknown"; attemptsLeft: number; elapsedMsLeft: number; costLeft: number; retryAfterMs: number; retryExpectedMs: number; retryExpectedCost: number; fallbackExpectedMs: number; fallbackExpectedCost: number; primaryRoute: "healthy" | "degraded" | "open"; fallbackRoute: "healthy" | "unhealthy"; fallbackApproved: boolean; queueAllowed: boolean; degradeApproved: boolean; }): Action { if (["request", "auth", "policy"].includes(input.owner)) return "fail_closed"; if (input.commitState !== "none") return "fail_closed"; if (input.owner === "unknown") return input.queueAllowed ? "queue" : "fail_closed"; const canRetry = input.attemptsLeft > 0 && input.elapsedMsLeft >= input.retryAfterMs + input.retryExpectedMs && input.costLeft >= input.retryExpectedCost; const canFallback = input.attemptsLeft > 0 && input.elapsedMsLeft >= input.fallbackExpectedMs && input.costLeft >= input.fallbackExpectedCost; if ( canRetry && ["transient", "rate"].includes(input.owner) && input.primaryRoute !== "open" ) return "retry"; if ( canFallback && ["transient", "rate", "quota"].includes(input.owner) && input.fallbackApproved && input.fallbackRoute === "healthy" ) return "fallback"; if (input.queueAllowed) return "queue"; return input.degradeApproved ? "degrade" : "fail_closed"; }

retryAfterMs относится только к повтору основного маршрута. Для резерва используются собственные ожидаемые время и стоимость, а fallbackApproved включает отдельную проверку его квоты. Поэтому долгий retry-after основного маршрута не блокирует исправный резерв, если тот укладывается в общий срок. Состояния committed и unknown требуют сверки или явно проверенного протокола продолжения/идемпотентности. Перед каждой новой отправкой сохраните запись попытки. Учтите и то, что 500 может быть связан с самим запросом: текущая справка Gemini, например, указывает слишком длинный входной контекст как одну из причин.

Проверка в тестовой среде

Воспроизведите 429 из-за скорости, 429 из-за квоты, 503 до начала потока, обрыв после видимых токенов, тайм-аут после фиксации действия инструмента, неверную схему резервного ответа и разомкнутую цепь. Отдельно задайте основному маршруту retry-after: 60000 при остатке SLO 8 секунд, а исправному и одобренному резерву — ожидаемое время 2 секунды и достаточный независимый бюджет: ожидаемым действием должен быть fallback, а не очередь. Для каждого сценария задайте одно ожидаемое действие.

В журнале нужны ID процесса, номер попытки, запрошенный и выбранный маршруты, request ID провайдера, класс ошибки, задержка, токены, стоимость, состояние фиксации, причина переключения и итог. Метрики разделяйте на успех основного маршрута, восстановление повтором, восстановление резервом, ограниченный режим и контролируемый отказ. Иначе высокий итоговый процент успеха скроет ухудшение основного маршрута.

Для конкретной ошибки сначала используйте узкое руководство владельца: OpenAI 429, ограничение частоты Claude API или ограничения Gemini API. После определения владельца применяйте общую политику.

Если нужно проверить несколько уже одобренных моделей через совместимую конечную точку, используйте тестовую среду и текущую документацию LaoZhang AI. Единый маршрут не отменяет проверку схемы, инструментов, данных, стоимости, качества и полной цепочки попыток.

Готовая система объясняет каждое действие восстановления, считает все попытки одним бюджетом и не превращает конечный HTTP 200 в доказательство здоровья основного маршрута.

#LLM API#Повторные попытки#Резервная модель#Отказоустойчивость
Поделиться: