Конспект 6: LLM в Production - Deployment и мониторинг
Оглавление
- Введение в Production LLM
- Инфраструктура и облачные платформы
- Развертывание моделей
- API дизайн
- Оптимизация latency
- Кэширование
- Rate limiting и throttling
- Cost monitoring
- Observability и логирование
- Обработка ошибок и fallback
- A/B тестирование в production
- Rollback стратегии
- Лучшие практики
Введение в Production LLM
Что означает Production?
Определение: Production — это окружение, где реальные пользователи взаимодействуют с LLM системой в масштабе.
Отличия от Development:
| Параметр | Development | Production |
|---|---|---|
| Масштаб | 1-10 запросов/сек | 1000+ запросов/сек |
| SLA | Не требуется | 99.9% uptime |
| Стоимость | Низкая | Высокая |
| Мониторинг | Минимальный | Полный стек |
| Отказоустойчивость | Нет требований | Critical |
| Backtesting | Опционально | Обязательно |
| Rollback | Instant | Planned |
Жизненный цикл Production системы
Research/Dev
↓
Staging (тестирование)
↓
Canary deployment (1% трафика)
↓
Rolling deployment (постепенное расширение)
↓
Full production (100% трафика)
↓
Monitoring & Maintenance
↓
Rollback (if needed)
Инфраструктура и облачные платформы
Главные облачные провайдеры
1. AWS (Amazon Web Services)
Сервисы для LLM: - SageMaker — полноценная платформа ML/LLM - EC2 — виртуальные машины с GPU - ECS/EKS — контейнеризация (Docker/Kubernetes) - Lambda — serverless функции - CloudFront — CDN для кэширования - DynamoDB — NoSQL БД - S3 — хранилище файлов
Пример конфигурации EC2 для LLM:
Instance type: p3.8xlarge
GPUs: 8 x NVIDIA V100
Memory: 488 GB RAM
vCPUs: 32
Стоимость: ~$24/час
2. Google Cloud Platform (GCP)
Сервисы для LLM: - Vertex AI — управляемые LLM сервисы - Cloud Run — контейнеризованные приложения - Compute Engine — виртуальные машины - Cloud TPU — специализированные процессоры для AI - BigQuery — аналитика больших данных - Cloud Storage — объектное хранилище
Vertex AI Pricing:
Input: $0.00025 per 1K tokens (Gemini)
Output: $0.0005 per 1K tokens
Минимум: нет
3. Microsoft Azure
Сервисы для LLM: - Azure OpenAI Service — доступ к GPT-4, GPT-3.5 - Azure Cognitive Services — готовые API - Azure ML — платформа машинного обучения - Azure Container Instances — контейнеризация - Azure Kubernetes Service (AKS) — Kubernetes
Azure OpenAI Pricing:
GPT-4 Input: $0.03 per 1K tokens
GPT-4 Output: $0.06 per 1K tokens
Commitment tier: скидка 20-30%
Сравнение провайдеров
| Критерий | AWS | GCP | Azure | Perplexity |
|---|---|---|---|---|
| Моделей доступно | Много | Gemini, PaLM | GPT, GPT-4 | Proprietary |
| Цена | Средняя | Низкая | Высокая | Средняя |
| Поддержка | Хорошая | Хорошая | Отличная | Хорошая |
| Уникальные фичи | SageMaker | TPU | Интеграция MS | Real-time web |
Развертывание моделей
Локальное развертывание (Self-hosted)
Плюсы: - ✅ Полный контроль - ✅ Нет зависимости от API провайдеров - ✅ Можно использовать proprietary модели - ✅ Полная приватность данных
Минусы: - ❌ Нужна мощная инфраструктура (GPU) - ❌ Сложнее масштабировать - ❌ Нужна собственная команда DevOps - ❌ Высокие начальные затраты
Стек для self-hosted:
Framework: vLLM, TensorRT-LLM, Ollama
Container: Docker
Orchestration: Kubernetes
Monitoring: Prometheus + Grafana
Database: PostgreSQL, Redis
Message Queue: RabbitMQ, Kafka
Пример Docker файла:
FROM nvidia/cuda:12.0-runtime-ubuntu22.04
WORKDIR /app
RUN pip install vllm torch transformers
COPY model_weights ./weights
ENV VLLM_TENSOR_PARALLEL_SIZE=4
ENV CUDA_VISIBLE_DEVICES=0,1,2,3
EXPOSE 8000
CMD ["python", "-m", "vllm.entrypoints.openai.api_server", \
"--model", "./weights/llama-13b", \
"--tensor-parallel-size", "4", \
"--max-model-len", "2048"]
Облачные API (Managed services)
Плюсы: - ✅ Быстро и просто - ✅ Автоматическое масштабирование - ✅ Нет управления инфраструктурой - ✅ Встроенный мониторинг
Минусы: - ❌ Зависимость от провайдера - ❌ Дорого при большом масштабе - ❌ Менее контроля над моделью - ❌ Rate limits
Популярные сервисы:
OpenAI API (GPT-4, GPT-3.5)
Anthropic (Claude)
Google Vertex AI (Gemini, PaLM)
Azure OpenAI (GPT-4, GPT-3.5)
Perplexity API
Replicate (много open-source моделей)
Together AI (масштабирование)
Гибридный подход
Архитектура:
User Request
↓
Load Balancer
↓
Cache Layer (Redis)
↓
┌─────────────────────────┐
│ Primary: OpenAI API │
└─────────────────────────┘
↓ (если откажет)
┌─────────────────────────┐
│ Fallback: Azure OpenAI │
└─────────────────────────┘
↓ (если откажет)
┌─────────────────────────┐
│ Last resort: Local model│
└─────────────────────────┘
API дизайн
REST API для LLM
Базовый endpoint:
POST /api/v1/completions
Request:
{
"model": "gpt-4-turbo",
"messages": [
{
"role": "user",
"content": "Что такое N8N?"
}
],
"temperature": 0.7,
"max_tokens": 1000,
"timeout": 30
}
Response:
{
"id": "chatcmpl-8N8t...",
"object": "chat.completion",
"created": 1702508400,
"model": "gpt-4-turbo",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "N8N это платформа для автоматизации..."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 25,
"completion_tokens": 150,
"total_tokens": 175
}
}
Streaming API
Для длинных ответов:
POST /api/v1/completions/stream
Response (Server-Sent Events):
data: {"choices": [{"delta": {"content": "N8N"}}]}
data: {"choices": [{"delta": {"content": " это"}}]}
data: {"choices": [{"delta": {"content": " платформа"}}]}
...
data: [DONE]
Преимущества: - ✅ Пользователь видит ответ в реальном времени - ✅ Более быстрый perceived response time - ✅ Экономит bandwidth (частичные ответы)
Batch API
Для асинхронной обработки:
POST /api/v1/batch
Request:
{
"requests": [
{"prompt": "Вопрос 1"},
{"prompt": "Вопрос 2"},
{"prompt": "Вопрос 3"}
],
"callback_url": "https://yourserver.com/webhook"
}
Response:
{
"batch_id": "batch_123",
"status": "processing"
}
Webhook callback (через 5-10 минут):
POST https://yourserver.com/webhook
{
"batch_id": "batch_123",
"status": "completed",
"results": [...]
}
Оптимизация latency
Что такое latency?
Определение: Время от запроса до первого токена (TTFT) и время между токенами (TBT).
Request Time
|
├─ Queue time (ожидание в очереди)
│
├─ Processing time (обработка запроса)
│
├─ TTFT (Time To First Token) ← Критично!
│
├─ Token generation (генерация остальных токенов)
│
└─ Total latency
Техники оптимизации
1. Speculative Decoding
Идея: Предсказать несколько следующих токенов параллельно
Обычно:
Token 1 → Token 2 → Token 3 → Token 4
Speculative:
Token 1 → {2, 3, 4} предсказываются параллельно
Проверка и коррекция
→ Token 2, 3, 4
Улучшение: -20-30% latency
2. Batch processing
Обработка нескольких запросов одновременно:
Request 1: "Что такое AI?"
Request 2: "Что такое ML?"
Request 3: "Что такое DL?"
↓
Batch processing:
Все 3 запроса обрабатываются за раз
(пакетная обработка быстрее)
↓
Результаты возвращаются почти одновременно
3. Token pipelining
Не ждать полного ответа, отправлять токены сразу:
Обычно:
[Генерируем все токены] → [Отправляем все]
С pipelining:
[Генерируем токен 1] → [Отправляем 1]
[Генерируем токен 2] → [Отправляем 2]
[Генерируем токен 3] → [Отправляем 3]
Улучшение: -10-15% TTFT
4. Quantization
Уменьшение размера модели без потери качества:
Full precision (FP32): 4 байта per weight
Half precision (FP16): 2 байта per weight
8-bit quantization: 1 байт per weight
4-bit quantization: 0.5 байта per weight
Размер модели: 13B → 3.25B
Скорость: +2-3x быстрее
Качество: -5% (приемлемо)
Метрики latency
TTFT (Time To First Token):
- Цель: < 100ms для хорошего UX
- Хорошо: < 500ms
- Приемлемо: < 1s
TBT (Time Between Tokens):
- Цель: < 50ms
- Хорошо: < 100ms
E2E Latency:
- Зависит от длины ответа
- Пример: 2s для 100 токенов
Кэширование
Типы кэширования
1. Prompt caching
Кэширование часто используемых промптов:
Первый запрос:
"Ты эксперт по N8N. Ответь на вопрос: Как подключить API?"
→ Полная обработка
→ Кэширование промпта
Второй запрос (тот же промпт):
"Ты эксперт по N8N. Ответь на вопрос: Как использовать webhook?"
→ Промпт загружается из кэша
→ Только новый вопрос обрабатывается
→ Экономия: -80% токенов и времени
Где использовать: - System prompts - RAG контекст - Few-shot примеры
2. KV cache (Key-Value cache)
Кэширование вычисленных токенов в attention механизме:
При генерации 100 токенов:
- Токен 1: вычисляется полностью
- Токен 2: переиспользует вычисления токена 1
- Токен 3: переиспользует вычисления токенов 1-2
- ...
- Токен 100: переиспользует вычисления 1-99
Результат: -70% вычислений при длинных ответах
3. Response caching
Кэширование полных ответов:
Запрос: "Как работает RAG?"
Ответ: [full response]
Cache TTL: 24 часа
Если такой запрос придет еще раз:
→ Сразу возвращаем кэшированный ответ
→ Экономия: 100% на этом запросе
Стратегия кэширования:
- Exact match: запрос совпадает на 100%
- Semantic match: запросы похожи по смыслу
- Partial match: система находит похожий кэш
Реализация кэширования в N8N
Redis cache:
const cacheKey = hash(model + prompt);
const cached = await redis.get(cacheKey);
if (cached) {
return JSON.parse(cached);
}
const response = await openai.createCompletion({
model: "gpt-4-turbo",
messages: messages
});
// TTL 24 часа
await redis.setex(cacheKey, 86400, JSON.stringify(response));
return response;
Rate limiting и throttling
Почему нужен Rate Limiting?
Без rate limiting:
1000 запросов/сек × $0.00003 = $30/сек = $2.6M/день 😱
С rate limiting:
100 запросов/сек × $0.00003 = $3/сек = $260K/день (контролируемо)
Стратегии rate limiting
1. Token Bucket Algorithm
Идея: Каждый пользователь имеет "ведро" токенов
Максимум: 100 запросов/минуту
Инициализация:
bucket = 100 токенов
Каждый запрос:
if bucket > 0:
bucket -= 1
execute request
else:
return 429 Too Many Requests
Каждую минуту:
bucket = min(100, bucket + 100)
2. Sliding Window
Подсчет запросов за последние N секунд:
Лимит: 100 запросов/60 секунд
Запросы:
[10:00:10] request 1
[10:00:15] request 2
[10:00:20] request 3
...
[10:01:00] request 100
[10:01:05] request 101 ← За последние 60 сек 101 запрос → Reject
3. Fixed Window
Простой счетчик за период:
Период: каждая минута
Лимит: 100 запросов
10:00-10:01: счетчик = 0
10:00:05: request 1 → счетчик = 1
10:00:10: request 2 → счетчик = 2
...
10:00:59: request 100 → счетчик = 100
10:01:00: request 101 → счетчик = 1 (новый период)
Rate Limiting в N8N
Function Node:
const userId = $json.user_id;
const limit = 100; // requests per minute
const window = 60; // seconds
const key = `rate_limit:${userId}`;
const count = await redis.incr(key);
if (count === 1) {
await redis.expire(key, window);
}
if (count > limit) {
const ttl = await redis.ttl(key);
return {
error: "Rate limit exceeded",
retry_after: ttl,
status: 429
};
}
// Продолжить обработку
Cost monitoring
Отслеживание расходов
1. Per-request logging
Что логировать:
const costLog = {
timestamp: new Date().toISOString(),
user_id: $json.user_id,
model: "gpt-4-turbo",
prompt_tokens: 250,
completion_tokens: 150,
total_tokens: 400,
// Расчет стоимости
input_cost: 250 * 0.00003, // $0.0075
output_cost: 150 * 0.00006, // $0.009
total_cost: 0.0165,
latency_ms: 2340,
status: "success"
};
await db.cost_logs.insert(costLog);
2. Aggregated billing
SQL запрос для месячного отчета:
SELECT
DATE_TRUNC('day', timestamp) as day,
model,
COUNT(*) as request_count,
SUM(total_tokens) as total_tokens,
SUM(total_cost) as daily_cost,
AVG(latency_ms) as avg_latency,
MAX(latency_ms) as max_latency
FROM cost_logs
WHERE timestamp >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY day, model
ORDER BY day DESC;
3. Budget alerts
Если превышен бюджет:
const dailyBudget = 100; // $100/day
const currentSpend = await db.cost_logs.sum('total_cost', {
date: today
});
if (currentSpend > dailyBudget) {
await sendAlert({
severity: "HIGH",
message: `Daily spend ($${currentSpend}) exceeds budget ($${dailyBudget})`,
action: "Reduce rate limit or use cheaper model"
});
}
Стратегии экономии
| Стратегия | Эффект | Сложность |
|---|---|---|
| Кэширование | -30-50% | Средняя |
| Model switching | -40-70% | Низкая |
| Token optimization | -20-30% | Средняя |
| Batch processing | -10-20% | Средняя |
| Local models | -80-90% | Высокая |
Observability и логирование
3 Pillars of Observability
1. Metrics (Метрики)
Количественные данные:
- Requests per second (RPS)
- Tokens per second (TPS)
- Latency (p50, p95, p99)
- Error rate
- Cost per request
- Model uptime
Пример Prometheus метрики:
llm_requests_total{model="gpt-4",status="success"} 15234
llm_tokens_used_total{model="gpt-4",token_type="input"} 1234567
llm_latency_seconds{model="gpt-4",percentile="p95"} 1.23
llm_cost_total{model="gpt-4"} 45.67
2. Logs (Логи)
Текстовая информация о событиях:
{
"timestamp": "2025-12-13T22:00:00Z",
"level": "INFO",
"service": "llm_service",
"request_id": "req_12345",
"user_id": "user_456",
"model": "gpt-4-turbo",
"action": "completion_request",
"prompt_length": 250,
"max_tokens": 1000,
"temperature": 0.7,
"latency_ms": 2340,
"tokens_used": 400,
"cost": 0.0165,
"status": "success"
}
Уровни логирования:
DEBUG: Детальная информация (только в разработке)
INFO: Общая информация о ходе выполнения
WARN: Предупреждение (не критично)
ERROR: Ошибка (требует внимания)
FATAL: Критическая ошибка (система падает)
3. Traces (Трейсы)
Отслеживание пути запроса через систему:
Request enters API
├─ [0ms] Authentication
├─ [5ms] Cache lookup
├─ [10ms] Load balancer
├─ [15ms] OpenAI API call starts
├─ [2340ms] OpenAI API response
├─ [2345ms] Response formatting
└─ [2350ms] Response sent to client
Total: 2350ms
Инструменты мониторинга
Метрики:
Prometheus + Grafana
DataDog
New Relic
CloudWatch (AWS)
Логи:
ELK Stack (Elasticsearch + Logstash + Kibana)
Datadog
Splunk
CloudWatch (AWS)
Трейсы:
Jaeger
Zipkin
DataDog
New Relic
Dashboards для LLM
Что мониторить:
🟢 System Health:
- Model availability (% uptime)
- API response status codes
- Error rate by type
📊 Performance:
- RPS (requests per second)
- Latency distribution (p50, p95, p99)
- Token throughput
💰 Cost:
- Daily spend vs budget
- Cost per request
- Cost by model
- Cost by user
⚠️ Alerts:
- High latency (>2s)
- Error rate >5%
- Cost spike
- Model unavailable
Обработка ошибок и fallback
Типы ошибок
1. API errors
429 Too Many Requests
→ Rate limit exceeded
500 Internal Server Error
→ Model crashed
503 Service Unavailable
→ Maintenance или overload
504 Gateway Timeout
→ Долгий ответ
2. Model errors
"context_length_exceeded"
→ Промпт + контекст слишком большой
"content_filter"
→ Модель отказалась по политике
"max_tokens_exceeded"
→ Ответ не влезает в лимит
Fallback стратегия
Каскадный fallback:
Запрос
↓
Попробуй Primary (OpenAI GPT-4)
├─ Успех → Вернуть ответ
└─ Ошибка → Логировать, перейти к Secondary
↓
Попробуй Secondary (Azure OpenAI)
├─ Успех → Вернуть ответ
└─ Ошибка → Логировать, перейти к Tertiary
↓
Попробуй Tertiary (Local model)
├─ Успех → Вернуть ответ
└─ Ошибка → Вернуть кэшированный ответ
↓
Если всё не сработало
└─ Вернуть default ответ + ошибка пользователю
Реализация в N8N
Function Node (Retry Logic):
const maxRetries = 3;
const retryDelay = 1000; // 1 second
async function executeWithRetry(fn) {
let lastError;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error;
if (attempt < maxRetries) {
await sleep(retryDelay * attempt);
}
}
}
throw lastError;
}
// Использование
const response = await executeWithRetry(() =>
openai.createCompletion({ ... })
);
Fallback implementation:
const fallbacks = [
{ provider: "openai", model: "gpt-4-turbo" },
{ provider: "azure", model: "gpt-4" },
{ provider: "local", model: "llama2-13b" }
];
for (const fallback of fallbacks) {
try {
const response = await callModel(fallback);
return response;
} catch (error) {
console.log(`${fallback.provider} failed, trying next...`);
}
}
return getCachedResponse();
A/B тестирование в production
Setup для A/B теста
Распределение трафика:
const userId = $json.user_id;
const testGroup = hash(userId) % 2;
if (testGroup === 0) {
// Группа A: GPT-4
model = "gpt-4-turbo";
temperature = 0.7;
} else {
// Группа B: GPT-3.5-turbo
model = "gpt-3.5-turbo";
temperature = 0.8;
}
const response = await openai.createCompletion({ model, ... });
// Логируем результат
await db.experiments.insert({
user_id: userId,
group: testGroup === 0 ? "A" : "B",
model: model,
latency: response.latency,
cost: response.cost,
user_rating: null // заполним позже
});
Метрики A/B теста
Метрика A (GPT-4) vs Метрика B (GPT-3.5):
Стоимость:
A: $0.03 per request
B: $0.01 per request
Экономия B: 67%
Качество:
A: 0.92 (среднее юзерское rating)
B: 0.85
Проигрыш B: -7.6%
Latency:
A: 2.3s (p95)
B: 1.8s (p95)
Выигрыш B: 21.7%
Вывод: B дешевле и быстрее, но качество ниже.
Рекомендация: Использовать B для простых запросов.
Rollback стратегии
Blue-Green deployment
Архитектура:
Текущее окружение (Blue - v1.0)
↓
Протестирован, работает стабильно
↓
Новое окружение (Green - v1.1)
↓
Развернуть новый код
Запустить smoke tests
↓
Если OK: перенаправить трафик
↓
Если проблемы: откатить на Blue
Преимущества: - Instant rollback (переключение в 1 клик) - Возможность полного тестирования перед свичем - Ноль downtime
Canary deployment
Постепенный roll-out:
Версия 1.0: 100% трафика
↓
Версия 1.1: 5% трафика (canary)
Мониторим ошибки в течение часа
↓
Если ошибок <0.1%:
Версия 1.1: 25% трафика
Мониторим еще час
↓
Версия 1.1: 50% трафика
Мониторим еще час
↓
Версия 1.1: 100% трафика
↓
Версия 1.0: Удалить
Если проблемы обнаружены:
[Ошибка обнаружена]
↓
[Автоматический rollback к v1.0]
↓
[Инцидент залогирован и алерт отправлен]
↓
[Версия v1.1 отправлена на анализ]
Лучшие практики
Do's ✅
-
Мониторьте всё
Metrics + Logs + Traces -
Имейте fallback стратегию
Primary → Secondary → Tertiary → Cache -
Контролируйте стоимость
Daily budget alerts Token optimization -
Тестируйте перед production
Staging environment Load testing -
Логируйте каждый запрос
user_id, model, tokens, cost, latency, status -
Используйте кэширование
Prompt cache, KV cache, Response cache -
Постепенные развертывания
Canary или Blue-Green
Don'ts ❌
-
Не полагайтесь на одного провайдера
Имейте fallback на другого провайдера -
Не деплойте напрямую в production
Staging → Canary → Full rollout -
Не игнорируйте latency ```
2s = плохой UX ```
-
Не забывайте про обработку ошибок
Try/catch, retries, fallbacks -
Не развертывайте в пятницу вечером
(классический DevOps совет)
Чек-лист перед production
☑️ Мониторинг настроено (metrics, logs, traces)
☑️ Alerting система работает
☑️ Rate limiting активировано
☑️ Cost monitoring включено
☑️ Fallback стратегия реализована
☑️ Load tests пройдены
☑️ Security review выполнен
☑️ Документация написана
☑️ Runbooks для инцидентов готовы
☑️ Rollback процедура протестирована
☑️ SLAs определены
☑️ Disaster recovery plan есть
Дата создания: December 2025
Версия: 1.0
Автор: Pavel
Применение: Production LLM Systems, DevOps, Infrastructure