Когда основная LLM ложится: как мы держим российские ИИ-агенты на плаву

Разгар рабочего дня, вторник. Менеджер дилерского центра просит нашего ИИ-агента посчитать лизинг для клиента, который уже сидит в переговорке. Спиннер. Секунд двадцать. Ещё двадцать. Таймаут. Он жмёт «повторить» — снова таймаут. Через пару минут в мониторинге начинает пухнуть очередь неудачных попыток от разных клиентов, а в Slack прилетает первое «у вас всё сломано?».
GigaChat Pro в этот момент отдавал 502 Bad Gateway всем подряд. Не у нас одних — публичный статус провайдера подтвердил инцидент чуть позже. Но клиенту, у которого срывается сделка, неинтересны чужие инциденты. Ему интересно, почему сервис, за который он платит, молчит.
В тот день мы успели поднять резерв за считанные минуты, и большинство пользователей вообще не заметили, что что-то упало. Ниже — как именно устроено это «решение с ИИ-агентом, которое переживает падение поставщика», почему одного try/except тут не хватает и на каких граблях мы прыгали, пока учились.
Почему «просто retry» не работает
Первая интуиция инженера, который ещё не получал в лицо отказом провайдера на полчаса: «ну поставим retry с exponential backoff». На бумаге звучит разумно. На практике — это лечение симптома.
Retry помогает против трёх вещей: транзиентных сетевых сбоев, единичных 5xx и rate limit. Против полного простоя апстрима он бесполезен. Когда модель лежит, тысяча повторов в минуту — это просто более изобретательный способ повесить свой собственный сервис на пулах коннектов и пользовательских таймаутах.
Мы это поняли в первый же серьёзный инцидент: ретраи съели всё свободное место в очереди FastAPI, и сервис лёг даже для тех запросов, которые в принципе не требовали LLM — статусы заявок, выгрузка истории, авторизация. Урок болезненный, но простой: ретраи — это микро-уровень. Fallback — это макро-уровень. Им нужны разные механизмы, и путать их нельзя.
Архитектура каскада: три модели, три роли
Сейчас платформа ИИ-агентов у нас в проде опирается на такой каскад:
- Основная — GigaChat Pro. Качество, function calling, лучшие метрики на наших offline-тестах.
- Резервная — YandexGPT 5 Pro. Сравнимое качество на большинстве задач, заметно проигрывает на сложном JSON-структурировании, зато стабильнее в моменты, когда основной поставщик капризничает.
- Аварийная — self-hosted T-Lite на собственном GPU. По сути тот же «ИИ-агент на ПК», только этот ПК — наш сервер в стойке. Не зависит от чужой инфраструктуры, держит нагрузку, но требует упрощённых промптов и умеет заметно меньше старших моделей.
Каждый уровень — это отдельный класс задач. Не «более слабая копия предыдущего», а другая роль с другими ограничениями. Это принципиально: пытаться скормить T-Lite промпт, рассчитанный на GigaChat Pro с function calling, — рецепт галлюцинаций. Мы попробовали, посмотрели на результат, больше не пробуем.
Circuit breaker, а не if-else
Наивная реализация выглядит так:
try:
return giga_client.chat(prompt)
except Exception:
return yandex_client.chat(prompt)
Не делайте так. На первом же длинном инциденте каждый запрос будет сначала ждать таймаута GigaChat (15–30 секунд по умолчанию), и только потом идти в Yandex. Пользователь смотрит в спиннер вместо пары секунд — почти минуту. И это ещё в лучшем случае, если ваш собственный прокси не рубит соединение раньше по своему лимиту в 100 секунд.
Правильнее — circuit breaker. Простой автомат на три состояния: closed (всё ок, идём в основной), open (основной сломан, пропускаем сразу к резерву), half-open (пробуем основной одним запросом, чтобы понять, починилось ли).
У нас самописный брейкер строк на пятьдесят поверх Redis: счётчик ошибок за короткое окно, порог — несколько подряд или заметная доля от объёма. При срабатывании — уходим в open на пару минут. После — пускаем один пробный запрос. Сломался — снова open. Ответил — closed, поехали дальше. Никакой магии, никаких сторонних библиотек, за которые потом стыдно.
В тот вторник брейкер ушёл в open буквально через минуту после начала инцидента — после серии подряд идущих 502. С этого момента весь трафик летел в Yandex, не тратя ни секунды на основной, а мы получили возможность спокойно разбираться, что вообще происходит.
Где сломались промпты (и как мы это чинили)
Скажу честно: первая версия fallback не работала. Технически — да, переключались. По качеству ответов — катастрофа.
Промпты, оптимизированные под GigaChat Pro, у Yandex выдавали мусор. Например, мы просили классифицировать обращение клиента по десятку категорий и возвращать строгий JSON. GigaChat это делал стабильно. Yandex на тех же инструкциях регулярно оборачивал JSON в Markdown-блок с тремя обратными кавычками, иногда добавлял пояснение «Вот ваш ответ:» перед ним, а время от времени вообще менял названия полей на синонимы (category превращалось в категория). Один раз, помню, вернул совершенно валидный JSON — но описывающий другую задачу, которую мы ему не задавали.
Чинили в три приёма:
- Свой промпт под каждую модель. Не один универсальный — три параллельных, версионированных, с отдельными тестами. Да, это ощутимо больше работы по поддержке. Это цена надёжности.
- Слой нормализации ответа. Между LLM и бизнес-логикой сидит функция, которая выдирает JSON из код-блока, чинит частые опечатки в названиях полей и валидирует через pydantic. Невалидно — один retry на этой же модели с уточняющим промптом, дальше — downgrade на следующий уровень каскада.
- Согласованные function call интерфейсы. Описание инструментов держим в одном месте и генерируем под каждый провайдер автоматически, потому что YandexGPT и GigaChat хотят слегка разный синтаксис, и вручную это поддерживать — верный способ забыть про какую-нибудь функцию и словить продовый баг.
После этих правок Yandex стал давать заметно больше валидных ответов — в аварийном режиме уже приемлемо. Не идеально, но задачу «удержать сервис на ногах, пока основной провайдер отходит» решает.
Как это выглядело со стороны пользователя
GigaChat Pro лежал больше получаса. За это время через каскад прошло много запросов — я специально не привожу точные цифры, потому что важнее логика, чем красивое число в отчёте.
Подавляющее большинство запросов ушли в YandexGPT и вернулись нормально. Небольшая часть не прошла валидацию схемы после Yandex, и их добила T-Lite на упрощённом промпте. И совсем скромный хвост не получил приемлемого ответа ни на одном уровне — эти уехали в очередь на ручную обработку оператору.
С точки зрения клиента: средняя задержка немного подросла (Yandex на наших запросах чуть медленнее). Никаких 502, никаких таймаутов. На дашборде поддержки за это время — считанные жалобы вместо потока, который мы получили бы без резерва.
Что важно: тот скромный хвост «упавших» запросов — это не баг архитектуры, а сознательный выбор. Если три уровня не справились, лучше честно сказать «оператор посмотрит в течение получаса», чем выдать клиенту галлюцинацию про несуществующую программу лизинга.
Где это не работает
Fallback не лечит проблемы, которые касаются не доступности, а корректности. Если GigaChat возвращает ответы, но плохого качества (например, после обновления модели поведение поехало) — circuit breaker этого не увидит, потому что HTTP 200. Тут нужны отдельные метрики качества и canary-релизы, это отдельная большая история.
Ещё одна засада — стоимость. YandexGPT 5 Pro на наших сценариях выходит дороже GigaChat Pro за запрос. Длинный инцидент основной модели — это незапланированный счёт в конце месяца. Мы держим алерт: если резерв обрабатывает существенную долю трафика дольше десяти минут, инженеру летит оповещение. Не «о, надо чинить» — это уже автоматика сделала. А «надо садиться и думать, не пора ли пересматривать, кто у нас основной».
И третье — не всё лечится каскадом моделей. Иногда падает не LLM, а ваш собственный векторный поиск, или база, или очередь. Полноценные российские ИИ-агенты — это не только «модель + промпт», это ещё и вся инфраструктура вокруг: retrieval, память, инструменты, авторизация. Каждый из этих кусков умеет ломаться по-своему, и на каждый нужен свой план Б.
Что отсюда забрать
Если у вас в проде стоит один LLM-провайдер — у вас есть SPOF, который однажды положит сервис в самый неудобный момент. Это не вопрос «если», это вопрос «когда». В нашем случае это был вторник посреди рабочего дня. У вас может быть ночь перед закрытием квартала.
Минимальная конфигурация, которую стоит закладывать с первого дня, когда собираешь платформу ИИ-агентов:
- два провайдера (основной + резерв) с независимой инфраструктурой;
- circuit breaker, а не try/except;
- отдельные промпты под каждую модель, версионированные и покрытые тестами;
- слой нормализации ответа между LLM и бизнес-логикой;
- честный путь «дальше разберётся человек» как последняя линия обороны.
Российский ландшафт LLM сейчас как раз достаточно зрелый, чтобы такое решение с ИИ-агентами собиралось без героических усилий: GigaChat Pro, YandexGPT, T-Lite, Saiga — выбирайте под задачу и бюджет. Главное — не ждать инцидента, чтобы понять, что у вас нет плана Б. Он наступит. Вопрос только в том, заметят ли это ваши клиенты.
Похожие статьи
- Как мы научили ИИ-агента на GigaChat Pro не путать живого клиента с ночным батчем
- Как мы настроили ИИ-агента для поиска в 1С: MCP-сервер вместо метаний между окнами
- Один вопрос — три темы: как мы научили ИИ-агента разбирать составные запросы
- Text2SQL для 340 таблиц: как мы собирали ИИ-агента для анализа корпоративных данных на GigaChat Pro




