Перейти к содержимому
10 янв. 2026 г.·7 мин чтения

Скоринг здоровья провайдера по своим метрикам для LLM

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

Скоринг здоровья провайдера по своим метрикам для LLM

Почему статус-страница не показывает вашу картину

Статус-страница почти всегда показывает среднюю температуру по больнице. Она отвечает на вопрос "есть ли крупная авария в целом", а не на вопрос "как сейчас идут именно мои запросы". Для оценки здоровья провайдера этого мало.

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

Чаще всего деградирует не провайдер целиком, а что-то одно: конкретная модель, один маршрут, один дата-центр, длинные ответы, стриминг или запросы с tool calling. На общей статус-странице это может вообще не всплыть, потому что остальной трафик идёт нормально.

Если команда работает через единый OpenAI-совместимый шлюз вроде AI Router, разница заметна ещё сильнее. Снаружи у вас один endpoint, а внутри запрос может уйти к разным провайдерам и моделям. Общий зелёный статус не говорит, что нужная вам связка сейчас в порядке.

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

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

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

Здоровье провайдера считают на своей стороне. Не по баннеру "all systems operational", а по тому, как сервис отвечает вашей продовой нагрузке прямо сейчас.

Что считать здоровьем провайдера

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

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

Доступность и качество стоит разделять. Доступность LLM API отвечает на простой вопрос: провайдер принял запрос и отдал ответ без технической ошибки. Качество ответа отвечает на другой вопрос: его можно использовать дальше без ручной починки и повторного вызова.

На практике разница видна быстро. Допустим, бот поддержки просит модель вернуть JSON с категорией обращения и кратким ответом для клиента. Провайдер может быть "доступен" почти весь день, но если 7% ответов приходят с битым форматом, а ещё 3% пустые, для продукта это уже плохой день.

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

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

Стоимость полезно держать рядом с остальными метриками, а не в отдельном отчёте. Если один и тот же успешный ответ у другого провайдера обходится на 30% дешевле, это влияет на здоровье маршрута почти так же, как рост задержки. Хороший скор показывает баланс: ответ дошёл, пришёл вовремя, прошёл проверку и стоил разумных денег.

Какие метрики собирать на своей стороне

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

Начните с кодов ответа. Держите отдельно долю 2xx, 4xx, 5xx и 429. Это сразу показывает, где проблема: ваш запрос сломан, провайдер падает или вы упёрлись в лимиты. Один общий процент успеха скрывает слишком много.

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

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

Качество формата тоже надо мерить числами. Отмечайте долю битого JSON, пустых ответов и обрезанных ответов, где поток закончился раньше времени. Если модель часто отдаёт 200, но ломает схему, для продукта это почти тот же сбой. Особенно в интеграциях, где следующий сервис ждёт строгий JSON, а получает половину объекта.

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

Для первого дашборда обычно хватает такого набора:

  • коды ответа по группам и отдельно 429
  • таймауты, обрывы, отмены
  • P50 и P95 до первого токена
  • P50 и P95 до полного ответа
  • битый JSON, пустые, обрезанные и неожиданные отказы

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

Как разрезать данные без путаницы

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

Сначала разделяйте провайдера и модель. Один и тот же провайдер может держать высокий аптайм в целом, но проседать только на одной модели. Бывает и наоборот: одна модель работает стабильно у двух провайдеров, а у третьего ломается именно на вашем маршруте. Если вы используете шлюз вроде AI Router, в отчётах всё равно нужно хранить и провайдера, и точную модель как отдельные поля, даже если снаружи у вас один OpenAI-совместимый endpoint.

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

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

С регионом и сетью часто ошибаются. Запрос из Алматы через один канал может идти ровно, а тот же вызов из Астаны через другой канал даст скачки по времени и больше 5xx. Это не абстрактная проблема провайдера, а ваш реальный путь до него. Такие группы нужно сравнивать отдельно.

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

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

Хороший срез отвечает на простой вопрос: у кого, на какой модели, для какой задачи и на каком маршруте началась просадка. Тогда решение видно сразу.

Как посчитать итоговый скор

Получайте инвойсы в тенге
Ежемесячный B2B-инвойсинг в тенге удобен для команд из Казахстана и региона.

Итоговый скор нужен для маршрутизации, а не для красивого дашборда. Если он устроен слишком сложно, команда быстро перестаёт ему верить. Если слишком просто, он пропускает сбои. На практике хватает 4-6 метрик, которые прямо влияют на выбор провайдера под вашу нагрузку.

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

Каждую метрику лучше привести к одной шкале от 0 до 100. Иначе 1% таймаутов, 4 секунды задержки и 7% битого JSON нельзя честно сложить. Нормализацию задают не "по рынку", а по своим порогам. Для одного продукта P95 в 3 секунды приемлем, для другого это уже провал.

Простой вариант выглядит так:

скор = 0.30 * availability + 0.20 * latency + 0.20 * quality + 0.15 * api_errors + 0.10 * timeouts + 0.05 * format

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

Штрафы тоже стоит делать разными. Рост P95 с 1,8 до 2,2 секунды обычно не повод резко уводить трафик. А вот скачок таймаутов с 0,2% до 1,5% уже опасен. То же касается битого формата. Если ваш парсер не может разобрать ответ, такой сбой лучше штрафовать сильнее, чем лишние 300-500 мс.

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

И храните не только общий балл, но и причины его падения. Запись вроде "скор 61: таймауты -18, формат -14, качество -5" полезнее, чем просто красный индикатор. Команда сразу понимает, что сломалось, и не тратит час на догадки.

Пример на боевой нагрузке

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

Днём команда отправляет около 200 запросов в минуту. Провайдер A почти не даёт HTTP-ошибок, и по общей статус-странице у него всё в порядке. Но время до первого токена растёт с 0,9 до 1,8 секунды. Для чата поддержки это уже заметно: оператор ждёт дольше, клиент видит паузу, а часть запросов уходит в повтор.

Если смотреть только на доступность LLM API, провайдер A кажется нормальным. Если смотреть на свои метрики, видно другое: сервис жив, но работает хуже для вашего сценария. JSON приходит, но медленно. Для классификации обращений это ещё терпимо, а для диалога уже нет.

Ночью трафик уходит на провайдера B. У него время до первого токена лучше, зато растёт другая проблема: ответы чаще обрываются на середине. HTTP-код остаётся 200, статус-страница тоже зелёная, но доля завершённых ответов падает, например, с 98% до 91%. В логах это видно сразу: закрывающая скобка в JSON не пришла, поле с приоритетом пустое, парсер ломается.

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

Допустим, вы даёте доступности 40% веса, задержке 25%, валидности JSON 20% и завершённости ответа 15%. Днём у провайдера A скор падает из-за задержки до 78 из 100, хотя алерт от него самого ещё не пришёл. Ночью у провайдера B скор уходит до 72 из-за обрывов потока.

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

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

Где команды чаще всего ошибаются

Соберите маршруты в одном слое
Один API-шлюз помогает сравнивать ответы по своим метрикам, а не по статус-страницам.

Если провайдер вернул HTTP 200, это ещё не значит, что запрос прошёл хорошо. Модель могла обрезать ответ, вернуть пустую строку, сломать JSON или ответить слишком поздно для вашего сценария. Для скоринга 200 - это только факт доставки, а не нормальный результат.

Ещё одна частая ошибка - прятать сбои за автоматическими ретраями. Клиент повторил запрос три раза, потом увёл трафик на запасной маршрут, и график вдруг выглядит чистым. Для пользователя это иногда полезно, но для измерений вредно. Храните две цифры: что случилось на первой попытке и чем всё закончилось после ретраев. Иначе доступность LLM API в отчётах окажется лучше, чем в реальной работе.

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

Команды часто портят сравнение сами. Они меняют промпт, температуру, системные инструкции или размер контекста, а потом делают вывод, что провайдер A лучше провайдера B. Это уже другой тест. Если вы сравниваете качество ответа, вход должен оставаться одинаковым на всём окне сравнения.

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

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

Чек-лист перед запуском

Сравните 500 плюс моделей
Держите доступ к 500+ моделям от 68+ провайдеров через один API.

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

Перед боевой нагрузкой проверьте минимум.

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

Есть ещё три проверки, которые часто спасают от долгих ночных разборов.

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

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

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

Что делать дальше

Начните не с большой формулы, а с 3-4 сигналов: доля успешных ответов, P95 задержки, таймауты и процент пустых или сломанных ответов. Этого уже хватает, чтобы увидеть, где провайдер для вашей нагрузки ведёт себя хуже, чем обещает общая статус-страница.

Пересчитывайте метрики каждые 5-15 минут. Такой ритм даёт живую картину, но не дёргает команду из-за случайного всплеска в одной минуте. Если запросов мало, окно лучше немного увеличить, иначе шум начнёт мешать.

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

Потом подключайте действия по шагам:

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

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

Если трафик идёт через AI Router на airouter.kz, собрать такие метрики проще в одном месте: вы меняете base_url на api.airouter.kz и продолжаете работать через OpenAI-совместимый endpoint, даже если внутри сравниваете несколько провайдеров и моделей. Это удобно, когда нужно оценивать маршруты по своим метрикам, а не по статус-страницам разных вендоров.

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