Конспект 6: LLM в Production - Deployment и мониторинг

Pavel 13.12.2025 22:07 13 просмотров

Оглавление

  1. Введение в Production LLM
  2. Инфраструктура и облачные платформы
  3. Развертывание моделей
  4. API дизайн
  5. Оптимизация latency
  6. Кэширование
  7. Rate limiting и throttling
  8. Cost monitoring
  9. Observability и логирование
  10. Обработка ошибок и fallback
  11. A/B тестирование в production
  12. Rollback стратегии
  13. Лучшие практики

Введение в 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 ✅

  1. Мониторьте всё Metrics + Logs + Traces

  2. Имейте fallback стратегию Primary → Secondary → Tertiary → Cache

  3. Контролируйте стоимость Daily budget alerts Token optimization

  4. Тестируйте перед production Staging environment Load testing

  5. Логируйте каждый запрос user_id, model, tokens, cost, latency, status

  6. Используйте кэширование Prompt cache, KV cache, Response cache

  7. Постепенные развертывания Canary или Blue-Green

Don'ts ❌

  1. Не полагайтесь на одного провайдера Имейте fallback на другого провайдера

  2. Не деплойте напрямую в production Staging → Canary → Full rollout

  3. Не игнорируйте latency ```

    2s = плохой UX ```

  4. Не забывайте про обработку ошибок Try/catch, retries, fallbacks

  5. Не развертывайте в пятницу вечером (классический 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

Комментарии (0)

Для добавления комментария необходимо войти в аккаунт

Войти / Зарегистрироваться