Model serving — как проектировать и эксплуатировать продовый инференс LLM

Model serving — это организация надёжного, масштабируемого и предсказуемого инференса больших моделей (LLM) в проде. Хороший сервисинг обеспечивает стабильные SLO (p50/p95/пиковая латентность, tokens/s, доступность), экономичность (GPU-утилизация, стоимость ответа) и безопасность (guardrails, защита от инъекций). Техническая основа — правильная компоновка движка инференса, планировщика, кэшей и масштабирования.

Model serving — как проектировать и эксплуатировать продовый инференс LLM

Связанные страницы: KV cache, Prefill cache, Top-k, Top-p, Контекстное окно, Evals, RAG-хаб, Prompt injection.

SLO и ключевые метрики

Метрика Что означает Комментарии по целям
Latency p50/p95/p99 задержка ответа Мерите отдельно префилл и декод; p95 важнее среднего
Tokens/s (decode) скорость генерации На пользователя/на GPU/на ноду; влияет планировщик и кэш
Throughput (req/s) пропускная способность Зависит от батчинга и параллелизма
Acceptance rate доля принятых запросов Управляется Admission Control (очереди/квоты)
GPU util / memory утилизация и запас Следите за фрагментацией KV и OOM
Cost/answer стоимость ответа Бюджетная метрика, связана с tokens/out и TCO

Мини-цели: стабильный p95, отсутствие head-of-line blocking, предсказуемый tokens/s при росте конкуренции.

Архитектуры и движки инференса

Один узел (single-GPU/мульти-GPU) *Плюсы:* простота, низкая латентность. *Минусы:* предел памяти/модели, ручное шардирование.

Кластер (Kubernetes/Ray/мульти-узел) *Плюсы:* автомасштабирование, смешение профилей моделей. *Минусы:* сложность планировщика и сети.

Типовые движки/серверы

  • vLLM-класс: непрерывный батчинг, paged KV, совместимость OpenAI API.
  • TGI-класс: ориентир на стабильный прод, хорошая телеметрия.
  • TensorRT-LLM / Triton: ядро высокопроизводительных фьюзов/Kernel-оптимизаций на NVIDIA.
  • llama.cpp-класс (CPU/Mac/Mobile): лёгкий рантайм, GGUF/квантование для edge.

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

Планирование: префилл и декод

Инференс LLM делится на две разные по характеру фазы:

  • Prefill — «заливка» промпта батчем (математика → GEMM, хорошо параллелится).
  • Decode — токен-за-токеном, memory-bound, упирается в скорость доступа к KV.

Современные планировщики используют:

  • Непрерывный батчинг (continuous batching) — динамически подмешивают новые запросы между шагами декода, не дожидаясь «опустошения» батча.
  • Sequence packing — плотная укладка коротких запросов с масками.
  • Paged KV — блочная организация кэша, чтобы избегать копирований и фрагментации.
  • Admission control — лимит на одновременные последовательности, «кредит» токенов, таймауты очереди.

Цель — максимально заполнять GPU, не разрушая p95.

Кэширование: KV и префиксы

  • KV cache хранит K/V уже пройденных токенов; растёт линейно по длине контекста и веткам (beam).
  • Prefill cache позволяет шарить общий префикс между сессиями (системные инструкции/рамки ответа).
  • Политики: горячие префиксы — на GPU, холодные — на CPU; TTL/LRU, запрет на шаринг между доверенными/недоверенными потоками.

Считайте память: bytes ≈ layers × seq_len × n_kv_heads × head_dim × 2 × sizeof(dtype).

Параллелизм и шардирование модели

Вид Суть Когда применять
Data parallel дубли модели на разных GPU Масштаб по пользователям, просто
Tensor parallel шард слоёв/голов по GPU Большие модели, треб. быстрая связь (NVLink)
Pipeline parallel слои по стадиям/узлам Очень большие модели; усложняет планировщик
Sequence/Context parallel деление по длине/позициям Длинные окна; тонко с RoPE/позициями

Практически: стремитесь влезть в один ускоритель с квантованием/Low-RAM весами; если нет — Tensor-parallel c быстрой межсвязью.

Квантование и оптимизации

  • Weights: INT8/INT4 (GPTQ/AWQ/RTN), FP8/BF16/FP16.
  • KV cache: INT8/FP8 — экономит память без заметной потери качества для многих задач.
  • Fused kernels / FlashAttention: ускоряют префилл/внимание.
  • PagedAttention: доступ к KV страницами.
  • Activation checkpointing: компромисс память↔скорость в префилле.

На проде квантование — инструмент вместимости и стоимости, но валидируйте качество на своих evals.

Декод: скорость и качество

Выбор стратегий влияет на латентность и стиль ответа:

  • Top-k / Top-p / температура — управляют разнообразием и стабильностью.
  • Спекулятивный декод (draft-модель, проверка «большой») — даёт 2–3× ускорение на длинных ответах при хорошей валидации.
  • Assisted/Lookahead — вариации с дешёвыми предсказателями токенов.
  • Beam-search редко нужен для open-ended; увеличивает память и p95.

Для JSON/строгих форматов снижайте «смелость» и добавляйте пост-валидацию.

Мульти-тенантность и справедливость

Проблемы: разные длины контекстов, «жадные» запросы, HoLB (head-of-line blocking).

  • Time-slicing декода: «кванты» по токенам на запрос.
  • Квоты и бюджет токенов: лимит prefill_tokens и decode_tokens на клиента/ключ.
  • Отсечка больших контекстов: честные ошибки «слишком длинно», рекомендации сокращения.
  • Приёмка: остановка на очереди, ранний отказ при переполнении, «Warm pool» для мгновенного старта.

Стриминг и API-контракты

  • Протоколы: HTTP SSE для токен-стрима, gRPC/WebSocket для низкой задержки.
  • Контракты: совместимость с OpenAI API (chat/completions, функции), JSON-форматы, токен-usage.
  • Функции/инструменты: строгое JSONSchema, валидация до вызова.
  • Версионирование: model_id, prompt_template_id, tokenizer_id — отдельные сущности.

Наблюдаемость и эксплуатация

Минимальный Observability-набор:

  • Метрики: префилл/декод-время, tokens/s, принятые/отклонённые, OOM, KV-футпринт, GPU-util.
  • Трейсинг: спаны «admission → prefill → decode → stream out», контекст запроса (анонимизирован).
  • Логи: ошибки, таймауты, отказы, эвакуации с GPU.
  • Алерты: рост p95/p99, резкий спад tokens/s, частые OOM/почти OOM, снижение acceptance rate.

Для качества — онлайн-evals/канареечные запросы, feedback-петля «плохих» кейсов.

Масштабирование и стоимость

  • Autoscaling: HPA/KEDA по tokens/s, GPU-util, очереди; anti-thrash (гистерезис).
  • MIG / профили GPU: логическое деление A100/H100 под разные модели.
  • Spot/прерываемые: удешевляют, но требуют graceful drain (дослать поток/сохранить KV-префикс).
  • Bin-packing: смешивайте «тяжёлые» и «лёгкие» модели; избегайте «девственно пустых» карт.
  • Edge/CPU-offload: часть KV/весов на CPU; компромисс задержки.

Считайте Cost/answer = ($/час × доля часу на ответ) / ответы; бенчмарки на реальных промптах.

Безопасность и комплаенс

  • Guardrails (политики/валидаторы): проверка форматов, фильтры PII/токсичности, правило «данные ≠ инструкции».
  • Защита от инъекций, утечек промптов, supply-chain рисков (подписи весов/адаптеров).
  • Изоляция кэшей (префиксы/KV) по уровням доверия; маскирование логов.
  • Региональные требования к данным и аудит (лог-хранение, политика доступа).

Интеграция с RAG и инструментами

  • На вход подавайте очищенные и цитируемые чанки (ретривер/переранжирование — см. retriever, vector index).
  • Контракты функций: белые списки, статическая схема, dry-run, квоты на действия.
  • Рамки промптов короткие, без секретов; длинные стили — через prefill cache.

Плейбук внедрения (пошагово)

  1. Цели и SLO: p95, tokens/s, стоимость; целевые окна контекста и длины ответов.
  2. Бенчсценарии: 50–200 реальных промптов; измерьте базовые метрики на одном узле.
  3. Движок: выберите класс (vLLM/TGI/TensorRT-LLM/llama.cpp) под вашу модель и железо.
  4. Квантование/вместимость: попробуйте INT8/INT4 для весов и KV, проверьте качество по evals.
  5. Планировщик: включите непрерывный батчинг, лимиты очереди, max_tokens на клиента.
  6. Кэши: подключите prefill cache для общих прологов; настройте блочный KV.
  7. Стриминг: SSE/API-совместимость, функции с JSONSchema.
  8. Observability: метрики/трейсы/логи + алерты по p95, OOM, acceptance.
  9. Autoscaling: HPA по очереди и tokens/s; warm-pool.
  10. Безопасность: guardrails, фильтры, разделение кэшей, подписи весов; red-team по инъекциям/утечкам.
  11. Непрерывные evals: nightly регрессы; release-gate по SLO/безопасности.

Частые ошибки (и как их исправить)

  • Один гигантский батч: p95 «гуляет», пользователи с короткими запросами страдают. → Непрерывный батчинг, admission-кредиты.
  • Общий префикс не кэшируется: переплата префилла. → Prefill cache и пул «горячих» префиксов.
  • KV-фрагментация и копирования → падение tokens/s. → Paged KV, выравнивание блоков, дефраг-пул.
  • Агрессивное квантование ломает код/арифметику. → Смешанные режимы: INT8 KV + BF16 на последних слоях.
  • Нет лимитов на токены → «залипание» последовательностей. → max_new_tokens, бюджет на клиента, ранняя остановка.
  • Отсутствие наблюдаемости: «летим вслепую». → Метрики/трейсы с разрезом prefill/decode.
  • Сырые промпты в логахутечки. → Маскирование/ролевая сегрегация логов.
  • Beam-search по умолчанию → память×N. → Для open-ended держать greedy/top-k/p.

Мини-FAQ

Как увеличить tokens/s без ухудшения качества?

Непрерывный батчинг + Paged KV + FlashAttention; аккуратное квантование весов/KV; спекулятивный декод с быстрой «черновой» моделью.

Что делать, если p95 рвано растёт при пиках?

Включить admission control (кредиты на токены), ограничить prefill_tokens, держать warm pool и авто-масштабирование по длине очереди/tokens/s.

Чем помочь длинным контекстам без OOM?

Квантование KV, «скользящее окно», offload дальнего префикса на CPU, sequence-/context-parallel при необходимости.

Почему greedy иногда быстрее и «чище»?

k=1 убирает сэмплирование и экономит выбор; для кода/форматов это снижает ошибки и ускоряет декод (см. Top-k).

Можно ли делить один GPU между несколькими моделями?

Да, через MIG/временную мультиплексцию, но следите за изоляцией кэшей и стабильностью p95; маленькие модели лучше «упаковывать» вместе.

Нужен ли RAG, чтобы снизить галлюцинации?

В проде почти всегда. Но RAG требует чистого ретрива и цитирования (см. RAG-хаб, retriever).

Мини-глоссарий

  • Prefill — батч-прогон промпта до генерации.
  • Decode — по-токенная генерация с опорой на KV.
  • Continuous batching — динамическое смешивание запросов между шагами декода.
  • Paged KV — блочный кэш для уменьшения копирований/фрагментации.
  • Speculative decoding — ускорение за счёт «черновой» модели.
  • SLO — целевые показатели качества сервиса (латентность, стабильность, стоимость).

См. также

Task Runner