Налаштування моніторингу latency AI-інференсу
Користувач надсилає запит до LLM і чекає перший токен. Якщо TTFT перевищує дві секунди, UX різко падає — клієнти йдуть. Ми, MLOps-інженери з досвідом роботи з vLLM та TGI, налаштовуємо моніторинг latency під ключ: від збору метрик до алертів у Grafana. Пишіть — оцінимо ваш проект.
Що таке P50, P95, P99 latency і як їх інтерпретувати?
Latency LLM-інференсу вимірюється в перцентилях. P50 — медіанна затримка, P95 — 95% запитів швидші за це значення, P99 — 99%. Для real-time сервісів критичний P99, для batch — достатньо P95. Приклад: якщо P99 total latency > 30s, 1% користувачів відчувають неприпустиму затримку. Моніторинг перцентилів дозволяє виявити викиди та long-tail.
| Перцентиль | Призначення | Типовий поріг |
|---|---|---|
| P50 | Медіанна якість | < 2s для TTFT |
| P95 | Більшість користувачів | < 5s для TTFT |
| P99 | Граничні випадки | < 10s для TTFT |
Проблеми, які вирішуємо
Latency LLM-інференсу складається з трьох компонентів: Queuing time (час у черзі рантайму), Prefill time (обробка вхідного контексту) та Decode time (генерація токенів). Кожен потребує своєї метрики та порогу алерту. Наприклад, при довгих системних промптах prefill time зростає, і потрібне кешування KV-cache. Порівняння: vLLM з PagedAttention знижує decode latency до 2 разів порівняно з наївною реалізацією.
Чому моніторинг TTFT критичний для LLM-сервісів?
TTFT — перший сигнал проблем з інференсом. Якщо p50 TTFT > 1s, користувачі масово покидають сервіс. Ми налаштовуємо алерти на p95 > 3s. Емпірично: при TTFT > 5s падіння конверсії сягає 40%.
Як налаштувати алерти на P99 latency у Grafana?
Використовуємо Prometheus Alertmanager з правилами на основі histogram_quantile. Приклад алерту:
- alert: LLMHighTTFT expr: histogram_quantile(0.95, rate(llm_time_to_first_token_seconds_bucket[5m])) > 3 for: 5m annotations: summary: "TTFT p95 > 3 секунди" - alert: LLMHighTotalLatency expr: histogram_quantile(0.99, rate(llm_total_latency_seconds_bucket[5m])) > 30 for: 5m annotations: summary: "Total latency p99 > 30 секунд" Як ми це робимо: стек і конфіги
Ключовий інструмент — гістограми Prometheus. buckets підбираються під типову latency:
from prometheus_client import Histogram, Summary import time # Гістограми latency TTFT_HISTOGRAM = Histogram( "llm_time_to_first_token_seconds", "Time to first token", buckets=[0.1, 0.3, 0.5, 1.0, 2.0, 5.0, 10.0] ) TOTAL_LATENCY = Histogram( "llm_total_latency_seconds", "Total request latency", labelnames=["model", "endpoint"], buckets=[0.5, 1.0, 2.0, 5.0, 10.0, 30.0, 60.0] ) TPOT_HISTOGRAM = Histogram( "llm_time_per_output_token_ms", "Time per output token in milliseconds", buckets=[5, 10, 20, 50, 100, 200] ) class LatencyTracker: def track_streaming_request(self, request_id: str, model: str): start = time.time() first_token_time = None def on_first_token(): nonlocal first_token_time first_token_time = time.time() TTFT_HISTOGRAM.observe(first_token_time - start) def on_complete(total_tokens: int): end = time.time() total_latency = end - start TOTAL_LATENCY.labels(model=model, endpoint="/v1/chat").observe(total_latency) if first_token_time and total_tokens > 1: decode_time = end - first_token_time tpot_ms = (decode_time / (total_tokens - 1)) * 1000 TPOT_HISTOGRAM.observe(tpot_ms) return on_first_token, on_complete Додатково збираємо метрики vLLM: vllm:time_to_first_token_seconds, vllm:time_per_output_token_seconds, vllm:e2e_request_latency_seconds — вони вже розбиті по percentiles.
Порівняння типів метрик
| Метрика | Що вимірює | Типові buckets | Рекомендований алерт |
|---|---|---|---|
| TTFT | Час до першого токена | [0.1,0.3,0.5,1,2,5,10] | p95 > 3s |
| TPOT | Час на токен (ms) | [5,10,20,50,100,200] | p99 > 200ms |
| Total | Повний час запиту | [0.5,1,2,5,10,30,60] | p99 > 30s |
Порівняння runtime: vLLM vs TGI
| Параметр | vLLM | TGI |
|---|---|---|
| TTFT (p50) | ~0.3s | ~0.5s |
| Decode speed | До 2x швидше | Стабільний |
| Підтримка LoRA | Так | Так |
| Моніторинг | Вбудовані метрики | Prometheus exporter |
Що входить у роботу
- Документація по всіх налаштованих метриках та дашбордах.
- Код дашбордів Grafana (експорт у JSON).
- Інструкція з деплою та алертам.
- Навчання команди: як читати дашборди та реагувати на алерти.
- Пост-релізна підтримка 2 тижні.
Строки орієнтовно
Від 5 до 15 робочих днів залежно від складності інфраструктури та кількості моделей.
Типові помилки
Детальніше про типові помилки
- Використання Summary замість Histogram — неможливо обчислити p99.
- Ігнорування queuing time — зростання QPS маскується під prefill.
- Неправильний вибір buckets: занадто широкі → втрата точності, занадто вузькі → кардинальність.
Детекція деградації інференсу: ковзні вікна та аномалії
Разовий викид latency — не привід для паніки. Стійкий тренд — привід для дій. Ми налаштовуємо детекцію деградації через ковзні вікна:
- 7-денне vs 30-денне вікно: якщо середній p95 TTFT за тиждень виріс на 30% відносно місяця — автоматичний алерт рівня warning.
- Погодинні аномалії: isolation forest на метриках кожної години виявляє аномальні періоди (зростання після деплою нової версії моделі, деградація при зміні батч-розміру).
- Кореляція з метриками GPU: при зростанні TTFT перевіряємо GPU utilization і пам'ять. Зростання latency + низький GPU utilization = проблема в черзі. Зростання latency + високий GPU memory = модель не вміщується.
Автоматична кореляція цих метрик дозволяє знаходити першопричину інциденту в 5 разів швидше ручного аналізу.
Ми гарантуємо SLA: час відповіді алертів — не більше 30 секунд. Досвід нашої команди — 5+ років в MLOps, більше 20 проектів з моніторингу inference. Сертифіковані спеціалісти AWS і GCP. Отримайте консультацію — оцінимо ваш проект. Замовте аудит моніторингу — ми підготуємо план.







