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

Привет, Хабр! Меня зовут Михаил Шпаков, я развиваю Statuser — сервис мониторинга доступности сайтов. Раньше я рассказывал, как он появился и что я узнал за год, мониторя 6 500 сайтов.

Недавно мне написал пользователь Statuser. В его продукте модель разбирала обращения клиентов и готовила для операторов черновики ответов. В какой-то момент эта функция перестала работать, хотя обычный HTTP-монитор, настроенный на адрес ИИ-гейтвея, продолжал показывать зелёный статус. О проблеме сообщили операторы поддержки, а не мониторинг.

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

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

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

❯ Как это устроено под капотом

Сейчас Statuser проверяет текстовые модели, доступные через OpenAI- или Anthropic-совместимый чатовый API. Адрес при этом может вести на официальное API провайдера, сторонний гейтвей, корпоративный прокси или модель, развёрнутую у себя.

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

Форма добавления монитора ИИ-модели
Форма добавления монитора ИИ-модели

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

У проверки два режима. Без ключа Statuser запрашивает список моделей и проверяет только доступность гейтвея. Даже ответ с требованием авторизации здесь считается успехом: сервис на месте и просто ждёт ключ. Токены в таком режиме не расходуются.

С ключом Statuser отправляет настоящий запрос на генерацию: POST /chat/completions для OpenAI-совместимого API или POST /messages для Anthropic-совместимого. В первом случае проверка ждёт структуру ответа с choices, во втором — с content. Одного успешного HTTP-кода недостаточно: ответ должен соответствовать контракту выбранного API. Первый режим входит в тариф Pro, второй — в Team.

Причину сбоя Statuser ищет не только в HTTP-коде, но и в теле ответа провайдера. Например, 401 означает, что ключ не приняли, а 410 — что модель снята с обслуживания.

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

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

Карточка инцидента с причиной «Модель снята с обслуживания»
Карточка инцидента с причиной «Модель снята с обслуживания»

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

При интервале в пять минут и трёх регионах получается около 26 тысяч запросов в месяц. Оценить расход по ценам своего провайдера можно калькулятором прямо в форме монитора.

Ключ хранится в зашифрованном виде. Statuser шифрует его AES-256-GCM, а в интерфейсе и API остаётся только маска. Использовать ключ можно лишь для адреса, привязанного к монитору.

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

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

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

❯ Почему один запрос на все модели не сработал

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

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

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

Второе различие обнаружилось уже среди чат-моделей, причём в родном API OpenAI. Обычным моделям можно передать max_tokens: 1, получить короткий ответ и потратить минимум. o-серия и GPT-5 вместо этого требуют max_completion_tokens, а бюджет сначала расходуют на скрытые рассуждения. С единицей запрос отклоняется, и минимальным рабочим лимитом оказались шестнадцать токенов.

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

❯ В заключение

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

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

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

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

А если захочется проверить свой эндпоинт таким же образом, мониторинг ИИ-моделей уже доступен в Statuser.

Может быть интересно:
Перейти ↩

Новости, обзоры продуктов и конкурсы от команды Timeweb.Cloud — в нашем Telegram‑канале 

Комментарии (0)