← The Practical AI Product Engineering Playbook
09 / 10 · 90 min

Deployment and optimization: serving a model fast and cheap

Anatomy of LLM serving (prefill/decode, continuous batching, KV cache), optimization knobs and their cost, SLOs and backpressure, and a rollout where speed-ups don’t break quality.

Lesson content is currently available in Russian.

What you will learn

  • →Понимать prefill/decode, continuous batching, PagedAttention и их влияние на throughput.
  • →Применять prompt caching, speculative decoding и streaming с пониманием их цены.
  • →Определять SLO по TTFT/p95, строить backpressure и канареечный rollout с quality gate.

Анатомия LLM serving: prefill, decode, batching

Инференс LLM состоит из двух фаз с противоположными характерами, и без понимания этого невозможно осмысленно оптимизировать:

  • Prefill: весь промпт обрабатывается за один проход, параллельно по токенам. Фаза compute-bound — упирается в вычислительную мощность GPU. Её длительность определяет TTFT (time to first token) — то, как быстро пользователь видит начало ответа.
  • Decode: токены ответа генерируются строго по одному, и на каждый нужно прочитать из памяти веса и весь KV cache. Фаза memory-bandwidth-bound — упирается в пропускную способность памяти, а не в вычисления. Определяет скорость печати ответа (time per output token).

Из этой асимметрии следует главный источник эффективности серверов: GPU при декоде одного запроса простаивает по вычислениям — значит, декодировать надо много запросов одновременно. Continuous batching (vLLM, TGI, TensorRT-LLM) добавляет и убирает запросы из батча на каждой итерации генерации, не дожидаясь окончания самого длинного — по сравнению с наивным статическим батчингом это даёт кратный прирост throughput на реальном трафике с разной длиной ответов.

Вторая ключевая идея — PagedAttention (vLLM): KV cache хранится страницами, как виртуальная память ОС, вместо сплошного преаллоцированного буфера под максимальный контекст. Это убирает фрагментацию памяти и позволяет держать в батче в разы больше параллельных запросов на том же железе.

Практический вывод: если вы обслуживаете open-weight модель, выбор serving-движка с continuous batching — это не оптимизация, а гигиена: разница с наивным циклом инференса — порядок величины по throughput.

Ручки оптимизации и их цена

У каждой оптимизации есть выигрыш, условие применимости и цена. Держите все четыре в голове как таблицу:

  • Prompt caching: KV cache общего префикса (системный промпт, few-shot примеры, схемы инструментов) вычисляется один раз и переиспользуется. У hosted-провайдеров кэшированные входные токены стоят в разы дешевле (типично скидка 50–90%), а TTFT на длинных промптах падает кратно. Условие: префикс должен быть бит-в-бит стабильным — кладите переменные части (дата, имя пользователя) в конец промпта, а не в начало, иначе кэш инвалидируется каждым запросом. На уникальных промптах бесполезен.
  • Speculative decoding: малая draft-модель предлагает несколько токенов вперёд, большая проверяет их за один проход. Принятые токены выходят пачкой — ускорение декода в 2–3 раза. Принципиально: верификация гарантирует то же распределение, что у большой модели, — качество не деградирует. Цена: память под вторую модель и выигрыш, зависящий от предсказуемости текста (код и шаблонные ответы ускоряются сильнее свободной прозы).
  • Квантизация для serving (fp8, int8/int4): меньше памяти → больше батч → выше throughput, плюс быстрее чтение весов в memory-bound декоде. Цена — риск деградации качества: прогон golden set на квантованной конфигурации обязателен до выкатки, а не после жалоб.
  • Streaming: не ускоряет генерацию вовсе, но радикально меняет восприятие — пользователь читает начало, пока генерируется хвост. Для интерактивных сценариев обязателен; заодно требует продумать обработку обрыва посреди ответа и валидацию структурированного вывода, который приходит частями.

Общий принцип: каждая ручка проходит через quality gate. Ускорение, не прошедшее golden set, — это быстрый способ доставлять плохие ответы.

SLO, backpressure и экономика запроса

SLO для LLM-сервиса формулируются иначе, чем для обычного API, потому что «время ответа» распадается на два разных ощущения:

  • TTFT — насколько быстро сервис «откликнулся»: для интерактива целятся в сотни миллисекунд, максимум 1–2 секунды на p95.
  • Полное время ответа — зависит от длины генерации; для длинных ответов честнее нормировать на токен или фиксировать SLO по типам запросов.

Всегда p50/p95/p99, никогда среднее: хвост латентности формирует впечатление о сервисе сильнее медианы. И отдельно следите за длиной очереди на GPU — это опережающий индикатор: очередь растёт за минуты до того, как поплывёт p95.

Backpressure обязателен, потому что GPU-ёмкость конечна и не масштабируется мгновенно: ограниченная очередь с отбрасыванием на входе (лучше быстрый честный 429 с Retry-After, чем таймаут после минуты ожидания), приоритизация (интерактивные запросы вперёд, batch-задачи в фон), таймауты с отменой генерации — запрос, от которого клиент отвалился, не должен догенерировать в никуда, съедая батч.

Экономика считается на запрос и на фичу: cost = input_tokens × цена + output_tokens × цена (output обычно в разы дороже). Рычаги в порядке эффективности: срезать раздутый системный промпт (он платится в каждом запросе), включить prompt caching, ограничить max_tokens сверху разумным потолком, роутить простые задачи на дешёвые модели (каскад из урока про local-модели). Дашборд «cost per feature в день» — обязателен: без него рост счёта замечают из бухгалтерии, а не из инженерии.

Rollout: shadow, canary и quality gate

Любое изменение serving-конфигурации — новая модель, квантизация, новый движок, даже «безобидное» обновление драйвера — выкатывается как рискованный релиз, потому что деградация LLM-систем бывает тихой: сервис отвечает, метрики инфраструктуры зелёные, а ответы стали хуже.

Последовательность зрелого rollout:

  1. Offline gate: golden set на новой конфигурации. Не прошёл — дальше не идём, это самый дешёвый фильтр.
  2. Shadow traffic: копия реального трафика идёт на новую конфигурацию, ответы пишутся в лог, но пользователям не отдаются. Сравнивается всё: latency, стоимость, а качество — автоматическим судьёй на выборке пар старый/новый ответ. Shadow ловит то, чего нет в golden set: реальное распределение запросов, пиковые нагрузки, редкие языки.
  3. Canary: 5% живого трафика → наблюдение → 25–50% → 100%. На каждой ступени — автоматические пороги: p95 TTFT, error rate, доля провалов валидации структурированного вывода, eval score на онлайн-выборке. Прошито заранее: какие цифры откатывают канарейку автоматически, без совещания.
  4. Rollback — это переключение маршрута на предыдущую конфигурацию за секунды. Значит, предыдущая конфигурация остаётся горячей до конца наблюдательного окна, а не выключается в момент достижения 100%.

Антипаттерн, который встречается чаще всего: «мы ускорили инференс на 40% и сразу выкатили на всех — латентность же улучшилась!» Улучшение одной метрики — не доказательство отсутствия деградации других: квантизация, ускорившая декод, могла просадить качество на классе запросов, которого не было в golden set. Именно поэтому shadow и canary не пропускаются даже для «очевидных улучшений».

Practice

Tuning модельного endpoint под SLO

Разверните open-weight модель через vLLM (или используйте hosted API с prompt caching). Дайте нагрузку 20–50 параллельных клиентов, снимите TTFT и полное время (p50/p95), throughput и cost per request. Затем примените две оптимизации (prompt caching + ограничение max_tokens, или квантизация) и покажите изменение метрик вместе с прогоном golden set до и после.

Deliverable

График p50/p95 TTFT и полного времени до и после оптимизаций, throughput, cost per request, и результат quality gate, подтверждающий отсутствие регрессии качества.

Checkpoint

Почему оптимизация без quality gate опасна и как выглядит правильный rollout ускорения?

  • ✓ Есть p95 TTFT, полное время и cost per request как отдельные метрики.
  • ✓ Rollout проходит offline gate → shadow → canary с заранее прошитыми порогами авто-отката.
  • ✓ Потеря качества обнаруживается измерениями (golden set, онлайн-eval), а не жалобами.

Check yourself

Почему фаза decode упирается в пропускную способность памяти, а не в вычисления?

01Почему фаза decode упирается в пропускную способность памяти, а не в вычисления?

Что нужно для эффективной работы prompt caching?

02Что нужно для эффективной работы prompt caching?

Деградирует ли качество от speculative decoding?

03Деградирует ли качество от speculative decoding?

Зачем нужен shadow traffic, если golden set уже пройден?

04Зачем нужен shadow traffic, если golden set уже пройден?

Очередь запросов к GPU переполнена. Правильное поведение сервиса?

05Очередь запросов к GPU переполнена. Правильное поведение сервиса?

Sources

Deployment and optimization: serving a model fast and cheap · The Practical AI Product Engineering Playbook · VORCL