Руководство и понимание

Надежная маршрутизация API LLM: тайм-ауты, повторные попытки и откат модели без семантической регрессии

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

Запасной запрос не удался просто потому, что другая модель вернула HTTP 200. Замена может превысить исходный бюджет задержки, пропустить обязательные поля JSON, вызвать другой инструмент или выдать ответ с существенно другой семантикой. Таким образом, для надежной маршрутизации LLM API требуется нечто большее, чем просто упорядоченный список моделей: для этого требуется контракт, классификатор ошибок, политика ограниченных попыток и проверка перед принятием.

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

Определите контракт маршрутизации перед выбором модели

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

{
  "workload": "invoice_extraction",
  "модальности": ["текст", "изображение"],
  «max_input_tokens»: 50000,
  «requires_tools»: ложь,
  "структурированный_выход": {
    «обязательно»: правда,
    "schema_id": "счет-v3",
    «строгий»: правда
  },
  "allowed_model_classes": ["извлечение документа"],
  «max_cost_usd»: 0,08,
  "deadline_ms": 8000

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

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

Классифицируйте ошибку, прежде чем предпринимать действия

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

<таблица> Класс отказаПримерыДействие по умолчанию <тело> Постоянный сбой запросаНеверные учетные данные, неправильные параметры, неподдерживаемая функцияОстановить и вернуть явную ошибку Несовместимость маршрутаСлишком большой контекст, неподдерживаемый ввод изображения, недоступен режим схемыПопробуйте только совместимый маршрут Временный сбой транспортаСброс соединения, сбой DNS, выбранный тайм-аутПовторить попытку в пределах оставшегося бюджета Сбой емкости или скоростиHTTP 429, перегруженная служба, выбранные ответы 5xxУчитывайте подсказки о повторных попытках или используйте резервный вариант Неверный успешный ответНеверный формат JSON, неизвестный инструмент, отсутствует обязательное полеОтклонить, затем повторить попытку или вернуться назад, если это разрешено политикой Неоднозначное выполнениеСоединение потеряно после того, как провайдер мог принять запросДедупликация перед воспроизведением

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

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

Потратьте один бюджет на сквозную задержку

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

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

оставшееся = крайний срок - текущее_время
требуется = разрешение_подключения + разрешение_поколения + разрешение_проверки
если осталось < требуется:
    stop_without_launching_another_attempt

Для крайнего срока в восемь секунд разумное первоначальное распределение может зарезервировать 300 мс для работы шлюза и окончательной проверки, предоставить до 4,5 секунд для основного маршрута и оставить примерно 3,2 секунды для одного резервного маршрута. Эти значения являются примером, а не эталоном. Они должны быть получены на основе измеренного распределения задержек для реальных поставщиков, моделей, регионов и размеров выходных данных.

Используйте ограниченную экспоненциальную задержку с джиттером для временных повторов:

delay = random(0, min(cap, base * 2^retry_index))

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

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

Выбирать резервные варианты по возможностям, а не по рангу

Запасная таблица должна кодировать совместимость, а не глобальный порядок предпочтений. Отфильтруйте возможные маршруты по контракту, прежде чем учитывать работоспособность, задержку или цену.

кандидаты = маршруты
  .filter(supports_required_modalities)
  .filter(context_limit >= оцененный_входной_размер)
  .filter(supports_required_tools)
  .filter(supports_requested_schema_mode)
  .filter(класс_модели в разрешенных_классах_модели)
  .filter(оценочная_стоимость <= оставшийся_бюджет_затрат)
  .filter(не_временно_подавлено)
выбрано = ранг(кандидаты, работоспособность, задержка, стоимость)

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

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

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

Проверьте ответ, прежде чем принять его

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

<ол>
  • Подтвердите, что транспортировка завершена и конверт ответа можно проанализировать.
  • Проверьте причину завершения и отклоните усечение, если требуется полный вывод.
  • Проверить структурированный вывод на соответствие исходной схеме.
  • Проверьте обязательные поля, значения перечислений и инварианты приложения.
  • Разрешить только зарегистрированные имена инструментов и проверять аргументы по каждой схеме инструмента.
  • Применяйте семантические проверки для конкретной рабочей нагрузки, где ложное принятие может привести к дорогостоящим последствиям.
  • Для извлечения счетов-фактур семантические проверки могут потребовать неотрицательного итога, поддерживаемого кода валюты и итогов по отдельным позициям в пределах явно заданного допуска. Для классификации требуется метка из разрешенного набора. Для генерации кода может подойти синтаксический анализ или компиляция. Эти проверки не подтверждают качество, но не позволяют предсказуемым нарушениям контракта считаться успешными.

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

    Отделение повторных попыток генерации от побочных эффектов

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

    Назначьте идентификатор операции на границе приложения и идентификатор попытки каждому вызову модели. Сохранять состояние выполнения инструмента по детерминированному ключу, например:

    execution_key = идентификатор_операции + имя_инструмента + canonical_arguments_hash

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

    Неоднозначный тайм-аут требует специальной обработки. Если соединение прервется после передачи запроса, шлюз может не узнать, произошла ли генерация. Ключ идемпотентности, поддерживаемый поставщиком, может помочь, если он доступен. В противном случае зарегистрируйте результат как неизвестный и примените политику воспроизведения, специфичную для рабочей нагрузки, вместо того, чтобы предполагать, что ничего не произошло.

    Подавлять неработоспособные маршруты и выявлять каждую попытку

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

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

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

    Контрольный список внедрения

    <ул>
  • Определите контракт маршрутизации с поддержкой версий для каждого класса рабочей нагрузки.
  • Ошибки поставщика карт распределяются по постоянным, временным, несовместимым, неверным ответам и неоднозначным категориям.
  • Выберите одного владельца повторных попыток и ограничьте общее количество попыток.
  • Распространяйте абсолютные сроки с помощью шлюза, клиента поставщика, проверки и выполнения инструментов.
  • Создавайте проверенные резервные группы, а не одну глобальную цепочку моделей.
  • Проверка схем, вызовов инструментов, причин завершения и инвариантов домена.
  • Дедупликация побочных эффектов с помощью ключей операций и выполнения.
  • Добавить подавление маршрутов с помощью ограниченных полуоткрытых зондов.
  • Зарегистрируйте задержку на уровне попыток, токены, стоимость, сбои и результаты принятия.
  • Тайм-ауты внедрения, 429 секунд, выбранные ошибки 5xx, неверный формат JSON, переполнение контекста и медленные успехи при промежуточном этапе.
  • Начните с основного маршрута и одного совместимого резервного маршрута для одной рабочей нагрузки с низким уровнем риска. Прежде чем расширять политику, сравните качество принятых ответов, задержку и стоимость. Целью не является максимально возможный уровень отката. Это ограниченная система, которая либо возвращает ответ, удовлетворяющий исходному контракту, либо явно дает сбой, прежде чем это вызовет дублирование работы или семантический ущерб.

    Связанное чтение

    FAQ

    Часто задаваемые вопросы

    Какие ошибки LLM API должны вызывать повторную попытку?
    Повторяйте только сбои, классифицированные как временные, такие как выбранные сбои подключения, тайм-ауты, ограничения скорости и ошибки сервера поставщика. Не повторяйте автоматически недействительные учетные данные, неверные запросы, неподдерживаемые функции или ошибки ограничения контекста. Ошибка ограничения контекста может оправдать использование совместимого резервного варианта с длинным контекстом, но повторение того же запроса по тому же маршруту не исправит ее.
    Сколько попыток возврата к модели должен допускать шлюз?
    Универсального числа не существует, но предел должен быть небольшим и ограничиваться одним сквозным сроком. Практическая отправная точка — одна основная попытка и один совместимый запасной вариант. Добавляйте еще одну попытку только тогда, когда измеренное повышение надежности оправдывает дополнительную задержку, емкость и стоимость.
    Безопасно ли повторять запросы на вызов инструментов?
    Генерацию модели можно повторить в соответствии с ограниченной политикой, но выполнение внешнего инструмента должно дедуплицироваться отдельно. Используйте идентификатор операции и детерминированный ключ выполнения, сохраняйте результат инструмента и избегайте повторного воспроизведения платежей, сообщений или других побочных эффектов только потому, что генерация повторялась.
    Можно ли использовать более дешевую модель в качестве автоматического запасного варианта?
    Только если он удовлетворяет тому же контракту маршрутизации и проходит приемочные тесты для конкретной рабочей нагрузки. Цена сама по себе не определяет совместимость. Прежде чем помещать любую модель в резервную группу, проверьте модальность, контекст, структурированный вывод, инструмент, задержку и требования к качеству.