Резервные модели: что происходит, когда основная недоступна

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

ОТКАЗОУСТОЙЧИВОСТЬОсновная недоступна — запрос уходит на запаснуюПользователь получает ответ, а не сообщение об ошибкеЗапрособычное обращениеЛогика повторов ивыбора модели живётв одном местеОсновная модельтаймаут · 5xx · перегрузкаЗапасная модельтот же формат запросаОтвет пользователюСбой заметен тольков журнале
При сбое основной модели запрос уходит на запасную тем же кодом

Почему это дёшево сделать

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

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

Когда переключаться

ПРАВИЛАКогда переключаться, а когда нетТаймаут или сбой на стороне провайдера — переключатьсяПерегрузка и отказ по лимиту — сначала повтор, потом переключение!Неверный ключ — не переключаться, чинить конфигурацию!Слишком длинный запрос — не переключаться, сокращать контекстЗапасная модель не должна быть дороже основной: иначе сбой у провайдера превращается в скачок расхода.
Запасная модель не должна быть дороже основной

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

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

Как выбрать запасную

Три требования, и все важны.

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

**Не дороже основной.** Иначе сбой у провайдера превращается в скачок расхода, и это обнаруживается в конце месяца.

**Другой поставщик.** Резерв внутри одного провайдера не спасает, когда недоступен именно он.

Что сломается незаметно

Три места, где схема подводит чаще всего.

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

Второе — длина ответа. Разные модели по-разному реагируют на одну и ту же инструкцию, и «ответь одним абзацем» может превратиться в страницу.

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

Лечится это одним действием: прогоняйте тестовый набор на обеих моделях, а не только на основной.

Обязательно логируйте факт переключения

Иначе вы не узнаете, что система работает на резерве. Самый неприятный сценарий выглядит так: основная модель недоступна третью неделю, всё «работает», а качество тихо просело, и никто не связывает одно с другим.

Заведите отдельный счётчик переключений и уведомление, если их доля превысила несколько процентов.

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

Чего делать не стоит

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

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

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

Деградация вместо отказа

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

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

Где хранить настройку резерва

Пара «основная модель — запасная» должна лежать в конфигурации, а не в коде. Причина простая: состав пары меняется чаще, чем логика переключения. Вышла новая версия, изменились условия, появилась модель подешевле — и вы правите одну строку, а не выкатываете релиз.

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

Сколько это стоит

Резервирование почти ничего не стоит в спокойное время: пока основная модель отвечает, запасная не вызывается вовсе. Расходы возникают в момент аварии, и вот их стоит прикинуть заранее.

Считается просто: доля запросов, которые в плохой день уйдут на резерв, умножается на разницу в ставке. Если запасная модель дороже вдвое, а недоступность основной длится сутки, вы получите заметный скачок в отчёте за месяц.

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

Что показать пользователю

Ничего. В этом и смысл: переключение должно быть незаметным. Исключение — сценарии, где вы обязаны раскрыть, что ответ подготовлен другой моделью. Тогда пометка нужна, и лучше продумать её формулировку заранее.

Что сделать сегодня

Выберите запасную модель, прогоните на ней свой тестовый набор и добавьте переключение в обёртку вызова. Затем намеренно сломайте основную в тестовой среде — например, подставив неверный адрес — и убедитесь, что схема действительно срабатывает.

Непроверенный резерв не считается резервом. Проверка занимает полчаса и делается один раз.

Написать