Alerting on quality drift, not just uptime
Why 200 OK says nothing about answer usefulness: online quality signals, LLM-as-judge on a traffic sample, thresholds and burn rate against alert fatigue, and input-distribution drift detection.
Lesson content is currently available in Russian.
What you will learn
- →Объяснять, какие деградации LLM-системы невидимы для классического APM-мониторинга.
- →Собирать онлайн-сигналы качества: фидбэк, поведенческие метрики, судья на сэмпле трафика.
- →Проектировать алёрты с baseline, окнами и burn-rate, не создавая alert fatigue.
Слепота uptime-мониторинга
Классический мониторинг отвечает на вопросы «жив ли сервис» и «быстро ли он отвечает». Для LLM-систем этого мало: система может неделями держать 100% uptime и идеальный p95, выдавая при этом бесполезные ответы. HTTP 200 не означает, что ответ правильный, полезный или безопасный.
Типовые тихие деградации. Провайдер обновил модель за тем же алиасом — стиль и качество ответов поменялись без единого изменения в вашем коде; в трейсах улика: gen_ai.response.model изменился при неизменном gen_ai.request.model. Переиндексация базы знаний прошла с ошибкой — retrieval возвращает нерелевантные документы, агент отвечает «мимо», но все статусы зелёные. Деплой «косметической» правки системного промпта сломал инструкцию про формат — доля отказов тихо выросла втрое. Изменился сам трафик: маркетинг привёл новую аудиторию с вопросами, под которые промпт не писался.
Общее у этих сценариев: ни один не виден в метриках доступности, все видны в метриках качества — если те существуют. Отсюда рамка урока: качество — это отдельное измерение мониторинга со своими сигналами, своей базовой линией и своими алёртами. APM-слой остаётся обязательным (таймауты и 429 никуда не делись), но поверх него нужен контур, который следит за тем, что система отвечает, а не только за тем, что она отвечает быстро.
Онлайн-сигналы качества
Качество в проде измеряют слоями, каждый сигнал пишется скором к трейсу (scores в Langfuse, feedback в LangSmith):
- Явный фидбэк — 👍/👎, оценка, жалоба. Честный, но редкий (единицы процентов) и смещённый: жалуются недовольные, довольные молчат. Тренд информативен, абсолютное значение — нет;
- Неявный фидбэк — поведение: пользователь сразу переспросил то же самое (ответ не помог), скопировал ответ (помог), нажал «позвать человека», оборвал сессию. Сигналов на порядки больше, чем явных, но каждый требует аккуратной интерпретации;
- Guardrail-метрики — доля отказов модели (refusal rate), доля fallback-ответов, срабатывания фильтров безопасности, доля «не знаю». Дёшевы, считаются по каждому запросу;
- Online LLM-as-judge — судья с бинарной рубрикой («опирается ли ответ на предоставленный контекст?») оценивает случайные 1–5% трафика. Это главный тонкий сигнал, но у него есть цена в токенах — поэтому сэмпл, а не весь трафик, и дешёвая модель в роли судьи с периодической калибровкой по человеческой разметке.
Практика: начните с двух guardrail-метрик (refusal rate, fallback rate) и одного судьи на сэмпле — этого достаточно, чтобы поймать все сценарии из предыдущей секции. Каждому сигналу — базовая линия за 7–14 дней, без неё алёртить не на что.
Проектирование алёртов: пороги, окна, burn-rate
Плохой алёртинг хуже его отсутствия: после десятка ложных срабатываний канал мьютят, и настоящий инцидент проходит незамеченным. Принципы:
Порог от базовой линии, а не абсолют. «Refusal rate > 5%» ложно сработает в ночь низкого трафика и промолчит при росте с 1% до 4%. Правильнее: «> 2× медианы того же часа за последние 7 дней» или «> baseline + 3σ».
Окно вместо точки. Мгновенные значения шумны; агрегируйте за 15–60 минут и требуйте удержания условия. Для метрик с малым объёмом (judge на сэмпле) окна длиннее — иначе три неудачных кейса из тридцати дадут ложный «всплеск».
Burn-rate для SLO-метрик. Подход из Google SRE Workbook: алёртить на скорость сжигания бюджета ошибок в двух окнах сразу (например, быстрое 1 час и медленное 6 часов). Быстрое окно ловит резкие инциденты, медленное — ползучую деградацию, а комбинация режет ложные срабатывания.
Стартовый набор для LLM-системы: refusal rate > 2× baseline в течение часа; judge-fail rate на критичной фиче выше порога за 4 часа; cost/hour > +50% к тому же часу прошлой недели; TTFT p95 > 5 с дольше 15 минут; расхождение response.model c request.model — немедленно.
И дисциплина: у каждого алёрта — владелец, runbook и ссылка на сохранённый фильтр трейсов, чтобы дежурный за минуту перешёл от «что-то красное» к конкретным деревьям спанов. Алёрт без runbook — это будущий мьют.
Дрейф входного распределения
Система может деградировать без единого изменения с вашей стороны — если изменились сами входы. Новый сегмент аудитории, сезонные темы, другой язык, вирусный сценарий использования, о котором вы не думали, наконец, волна промпт-инъекций — всё это сдвигает распределение запросов относительно того, под которое писался промпт и собирался eval-сет.
Как ловить. Для структурированных признаков (длина запроса, язык, категория из роутера) работают классические тесты стабильности распределений — PSI (population stability index) или KL-дивергенция между текущим окном и базовым: PSI выше ~0.2 принято считать значимым сдвигом. Для свободного текста признаков нет — работают эмбеддинги: считаете векторы входных запросов, сравниваете текущее окно с базовым через дистанцию центроидов, долю точек дальше порога от ближайшего базового кластера и появление новых плотных кластеров. Инструменты класса Evidently делают это из коробки; на платформах трейсинга то же собирается поверх выгрузки входов.
Что делать с находками — двухтактный процесс. Еженедельный отчёт «новые кластеры входов» смотрит человек: каждый устойчивый новый кластер — это либо кандидат в новые eval-кейсы и правку промпта, либо сегмент для явного «вне области» ответа. Алёрт — только на резкие сдвиги: доля out-of-distribution запросов выросла кратно за часы, что чаще означает атаку или интеграцию нового клиента, о которой вам забыли сказать.
Связка с предыдущими уроками прямая: дрейф объясняет, почему качество упало при неизменном коде, а его детект подсказывает, какими кейсами пора пополнять eval-сет — об этом следующий урок.
Practice
Контур качества с алёртами
Для своего агента добавьте контур качества: refusal/fallback rate как скоры на каждом трейсе, online-судью с бинарной рубрикой на 10% трафика (учебный объём позволяет). Соберите базовую линию на 50+ прогонах, затем «сломайте» систему (испортите системный промпт или подмените retrieval) и покажите, что метрики сдвинулись. Опишите три алёрта с порогами от baseline, окнами и runbook.
Deliverable
Скриншоты скоров до и после поломки плюс документ с тремя алёртами: метрика, порог относительно baseline, окно, владелец, runbook со ссылкой на фильтр трейсов.
Checkpoint
Докажите на своём примере, что uptime-мониторинг не поймал бы вашу «поломку», а контур качества — поймал.
- ✓ Приведён сценарий деградации с зелёным uptime и назван сигнал качества, который его вскрывает.
- ✓ Алёрты сформулированы через baseline и окно (или burn-rate), а не голым абсолютным порогом.
- ✓ Объяснён выбор доли трафика для online-судьи как баланс цены и чувствительности.
Check yourself
Sources