Model Serving
FastAPI, TorchServe, Triton, vLLM — деплой моделей, батчинг, кеширование.
Model Serving — модель без API бесполезна
Ты обучил модель, получил отличные метрики, похвастался коллегам. Но пока модель сидит в .pkl файле на твоём ноутбуке — она не приносит ни одного рубля. Бизнесу нужны предсказания, а не модели. Model serving — это всё, что превращает обученную модель в работающий сервис: API, инфраструктура, масштабирование, оптимизации.
Аналогия: обучить модель — это приготовить блюдо на домашней кухне. Model serving — это открыть ресторан: тебе нужны повара (inference серверы), официанты (API), менеджер зала (load balancer), система доставки (batch pipeline), контроль качества (мониторинг). И всё это должно работать 24/7, даже когда наплыв гостей в 10× больше обычного.

Большая картина: от модели до production-сервиса
Путь модели в продакшн выглядит так:
1. Модель — обученный артефакт (.pkl, .onnx, .pt, SavedModel). Загружается из Model Registry или S3.
2. Inference-сервер — процесс, который держит модель в памяти и отвечает на запросы. Это может быть FastAPI, Triton, TorchServe, vLLM — зависит от модели.
3. API Gateway / Load Balancer — распределяет запросы между несколькими репликами сервера. Nginx, Envoy, или облачный ALB.
4. Мониторинг — Prometheus + Grafana. Следит за latency, throughput, error rate, GPU utilization. Алертит, когда что-то пошло не так.
5. Auto-scaling — Kubernetes HPA или облачный аналог. Поднимает новые реплики при нагрузке, убирает лишние в тишине.
Весь pipeline: пользователь → API Gateway → один из N inference-серверов → модель делает предсказание → ответ обратно. Параллельно: Prometheus скрейпит метрики, Grafana рисует дашборды, HPA масштабирует при необходимости.
Batch vs Online inference: когда что использовать
Первый вопрос, который задаёшь перед деплоем: нужны ли предсказания в реальном времени? От ответа зависит вся архитектура.
Batch inference — предсказания заранее, для всех. Ставишь cron-джобу: каждую ночь прогоняешь модель на всей базе клиентов, результаты складываешь в таблицу. Утром маркетинг берёт оттуда скоры для email-рассылки.
• Рекомендации для email-рассылки (персонализация раз в день) • Кредитный скоринг всех заявок за ночь • Предсказание оттока — обновляется раз в неделю • Генерация эмбеддингов для каталога товаров
Online inference — предсказание по запросу, в реальном времени. Пользователь открыл приложение → backend отправил фичи в модель → модель ответила за 50ms → пользователь видит персональные рекомендации.
• Антифрод: блокировать транзакцию за <50ms • Поисковая выдача: ранжировать результаты за <100ms • Чат-бот: ответить пользователю за <2s • Автокомплит: предложить варианты за <30ms
Latency budget — ключевое ограничение для online serving. Типичные требования: автокомплит 30ms, антифрод 50ms, рекомендации 100-200ms, LLM генерация 1-5s (с streaming). Если модель не укладывается — оптимизируй (ONNX, квантизация) или переходи на batch.
💡 На практике
FastAPI: REST API для модели за 20 минут
Для CatBoost, LightGBM, sklearn, маленьких нейронок — FastAPI закрывает 80% задач. Асинхронный, быстрый, с автодокументацией (Swagger UI). Модель загружается один раз при старте приложения, дальше просто отвечает на запросы.
from fastapi import FastAPI
from pydantic import BaseModel
import joblib, numpy as np
app = FastAPI(title="Churn Prediction API")
model = joblib.load("models/churn_v3.pkl") # загружаем ОДИН РАЗ при старте
class Features(BaseModel):
age: int
tenure_months: int
monthly_charges: float
total_charges: float
@app.post("/predict")
async def predict(f: Features):
X = np.array([[f.age, f.tenure_months, f.monthly_charges, f.total_charges]])
proba = model.predict_proba(X)[0][1]
return {"churn_probability": round(float(proba), 4)}
@app.get("/health")
async def health():
return {"status": "ok", "model_version": "v3"}Для production — запускай через gunicorn с несколькими workers: gunicorn app:app -w 4 -k uvicorn.workers.UvicornWorker. Каждый worker — отдельный процесс с копией модели в памяти. 4 workers ≈ 4 параллельных предсказания. Для GPU-моделей обычно 1 worker (GPU не шарится между процессами просто так).
gRPC: когда REST недостаточно быстр
REST (JSON over HTTP/1.1) — универсальный и простой. Но у него есть overhead: JSON-сериализация, текстовый формат, HTTP/1.1 без мультиплексирования. Когда нужна максимальная скорость — используют gRPC: бинарный протокол (Protobuf) поверх HTTP/2.
Когда gRPC: • Микросервисная архитектура — сервисы общаются друг с другом тысячи раз в секунду • Latency-critical — экономишь 2-5ms на сериализации (важно, когда бюджет 30ms) • Большие payloads — Protobuf в 5-10× компактнее JSON • Streaming — gRPC поддерживает server-side streaming из коробки (для LLM генерации) Когда REST: • Внешнее API для клиентов (браузер, мобилка) — REST проще интегрировать • Прототип / MVP — FastAPI поднимается за 20 минут • Отладка — JSON читаемый, Protobuf — нет
// prediction.proto API
syntax = "proto3";
service PredictionService {
rpc Predict (PredictRequest) returns (PredictResponse);
rpc PredictStream (PredictRequest) returns (stream Token); // LLM
}
message PredictRequest {
repeated float features = 1;
string model_name = 2;
}
message PredictResponse {
float score = 1;
string label = 2;
}На практике: внутри ML-системы (между сервисами) — gRPC. Наружу для клиентов — REST. Triton и TorchServe поддерживают оба протокола из коробки.
Форматы моделей: ONNX, TorchScript, SavedModel
Обучил модель в PyTorch — но inference-сервер не обязан знать про PyTorch. Модель можно экспортировать в оптимизированный формат, который работает быстрее и не требует тяжёлых зависимостей.
ONNX (Open Neural Network Exchange) — универсальный формат. Конвертируешь из PyTorch, TensorFlow, sklearn — запускаешь через ONNX Runtime. Inference в 2-5× быстрее за счёт graph-level оптимизаций (operator fusion, constant folding). Поддерживается Triton, Azure ML, многими edge-платформами.
# Экспорт PyTorch → ONNX → inference
import torch
import onnxruntime as ort
# Экспорт
dummy_input = torch.randn(1, 768) # пример входа
torch.onnx.export(model, dummy_input, "model.onnx",
input_names=["input"], output_names=["output"],
dynamic_axes={"input": {0: "batch"}}) # динамический batch
# Inference через ONNX Runtime (не нужен PyTorch!)
session = ort.InferenceSession("model.onnx", providers=["CUDAExecutionProvider"])
result = session.run(None, {"input": input_array}) # numpy in → numpy outTorchScript — формат PyTorch. Два режима: torch.jit.trace (записывает execution graph на примере) и torch.jit.script (компилирует Python-код). Быстрее чистого PyTorch, не нужен Python runtime для inference. Используется в TorchServe и C++ inference.
SavedModel — формат TensorFlow/Keras. Содержит граф вычислений + веса. Используется в TF Serving и Vertex AI.
Что выбрать: ONNX — если нужна переносимость и скорость (самый универсальный). TorchScript — если экосистема PyTorch. SavedModel — если TensorFlow. Для классических ML-моделей (sklearn, CatBoost) — просто joblib.dump(), ONNX не нужен.
Масштабирование: горизонтальное, GPU sharing, batching
Один inference-сервер обрабатывает 100 RPS (requests per second). Тебе нужно 1000 RPS. Как масштабироваться?
Горизонтальное масштабирование — запускаешь N реплик сервера за load balancer. В Kubernetes: Deployment с replicas: 10 + Service + HPA (Horizontal Pod Autoscaler). HPA мониторит CPU/GPU utilization или custom metrics (queue length, latency p99) и автоматически добавляет/убирает поды.
Dynamic Batching — главная оптимизация для GPU. GPU эффективна на батчах: обработать 32 запроса одним батчем почти так же быстро, как 1 запрос. Inference-сервер накапливает входящие запросы за окно 1-10ms, собирает в батч, прогоняет через GPU одним вызовом. Throughput вырастает в 10-30×, latency увеличивается лишь на размер окна.
GPU sharing — одна GPU дорогая, а CPU-bound модели (CatBoost) не нужна вся GPU. Решения: • Multi-process service (MPS) — несколько процессов на одной GPU (NVIDIA MPS) • Time-slicing — GPU делит время между несколькими подами в Kubernetes • Multi-model serving — Triton держит несколько моделей на одной GPU, переключается по запросу • Правильный подход — CPU-модели на CPU-подах, GPU-модели на GPU-подах. Не ставь CatBoost на GPU-ноду.
Inference-серверы: Triton, TorchServe, BentoML
Когда FastAPI не хватает — есть специализированные inference-серверы, заточенные под production ML.
NVIDIA Triton Inference Server — Swiss Army knife для inference. Поддерживает PyTorch, TensorFlow, ONNX, XGBoost, Python-модели. Dynamic batching, multi-GPU, model ensembles (цепочка моделей в одном запросе), A/B testing между версиями модели. Ты кладёшь модель в model_repository/, пишешь config.pbtxt — Triton делает остальное.
# Структура Triton model repository
model_repository/
churn_model/
config.pbtxt # конфигурация модели
1/ # версия 1
model.onnx # сама модель
embedding_model/
config.pbtxt
1/
model.pt
# Запуск Triton
docker run --gpus all -p 8000:8000 -p 8001:8001
-v (pwd)/model_repository:/models
nvcr.io/nvidia/tritonserver:24.01-py3
tritonserver --model-repository=/models
# HTTP: localhost:8000, gRPC: localhost:8001TorchServe — inference-сервер от PyTorch. Проще Triton для чисто PyTorch-моделей. Поддерживает model versioning, logging, metrics из коробки. Батчинг, multi-GPU, custom handlers для пре/постпроцессинга.
BentoML — Python-first фреймворк: пишешь serving-логику как обычный Python-код, BentoML упаковывает в Docker, добавляет batching, API, метрики. Идеален для DS-ов, которые не хотят разбираться в Kubernetes. Код → bentoml build → Docker image → деплой куда угодно.
vLLM — специализированный сервер для LLM (GPT, LLaMA, Mistral). PagedAttention для эффективного использования GPU-памяти, continuous batching, OpenAI-совместимый API одной командой. Если деплоишь LLM — это стандарт де-факто.
💡 Что выбрать
A/B testing и canary deployment для моделей
Новая модель показала AUC +2% на offline-метриках. Деплоим на 100% трафика? Нет. Offline-метрики не гарантируют улучшение бизнес-метрик. Нужно проверить на реальном трафике.
Shadow mode — новая модель получает тот же трафик, что и старая, но её предсказания никому не показываются. Ты сравниваешь ответы двух моделей без риска. Идеально для начала: ловишь баги, проверяешь latency, убеждаешься что модель не падает.
Canary deployment — направляешь 5% трафика на новую модель, 95% — на старую. Следишь за метриками: latency, error rate, бизнес-показатели (CTR, конверсия). Если всё ок — увеличиваешь до 25%, 50%, 100%. Если нет — мгновенный rollback на старую версию.
A/B test — полноценный эксперимент: 50/50 (или другое соотношение), рандомизация по пользователям, статистический критерий для принятия решения. Длится дни-недели. Измеряешь бизнес-метрику (revenue, retention), а не только ML-метрику.
Типичный rollout: shadow mode (1-2 дня) → canary 5% (1 день) → canary 25% (2-3 дня) → A/B 50/50 (1-2 недели) → full rollout 100%. В Kubernetes реализуется через Istio/Argo Rollouts, в Triton — через model versioning.
🎯 На собеседовании
Junior
/predict. Docker для упаковки, gunicorn для нескольких workers.
• Batch vs online inference? Batch: предсказания заранее, cron + pandas/Spark. Online: по запросу в реальном времени, API с latency <200ms.
• Что такое ONNX? Универсальный формат моделей. Конвертируешь из PyTorch/TF → inference через ONNX Runtime, в 2-5× быстрее.
• Зачем health check endpoint? Load balancer проверяет, жив ли сервис. Если /health не отвечает — перестаёт слать трафик на этот инстанс.Middle
Senior
Собираем всё вместе
Model serving — это мост между обученной моделью и пользователем. Batch inference — для предсказаний заранее (cron + Spark). Online inference — для реального времени (API + load balancer + autoscaling). FastAPI — для старта и простых моделей. Triton/TorchServe/BentoML — для production GPU-моделей. vLLM — для LLM. ONNX — для ускорения и переносимости. Dynamic batching — для эффективного использования GPU. Canary deployment — для безопасного обновления.
Если запомнить одну вещь из этой ноды: модель приносит ценность только когда она отвечает на запросы в продакшне. Всё остальное — инструменты, чтобы это было надёжно, быстро и масштабируемо.
Дальше на роадмапе: Monitoring — как отслеживать деградацию модели на проде, A/B Testing — полный цикл ML-эксперимента, Docker — упаковка модели в контейнер.
Материалы
Практическое руководство по созданию API. Старт за 20 минут.
Официальная документация Triton: dynamic batching, model repository, config.
Serving LLM с PagedAttention и continuous batching.
Ускорение inference: ONNX-формат, graph-level оптимизации, GPU/CPU.
Python-first serving: от кода к Docker image с батчингом и метриками.
Полный курс: FastAPI, Docker, CI/CD, мониторинг ML-моделей.