Решения

Мультимодельный сервинг LLM: VRAM и планирование

Задача страницы. Объяснить, как одновременно держать несколько моделей на кластере GPU: планировать VRAM, выбирать топологию, строить пулы моделей, маршрутизировать трафик, задавать квоты/лимиты, считать стоимость за 1M токенов и поддерживать SLA.

TL;DR

  • Держите пулы: short (короткие запросы), long (длинные), domain (RU/код/индустрии), canary (обновления).
  • Планируйте VRAM по формуле:
    VRAM ≈ Weights + KV_peak + Runtime_overhead (5–15%). Снижайте через квантизацию и лимиты длины.
  • Грузите модели слоями: hot (в VRAM), warm (NVMe, быстрый подъём), cold (реестр).
  • Маршрутизируйте по модели, длине, приоритету, тенанту. Обязательно — стриминг и ограничения (max_tokens, max context).
  • Для цены/1M токенов комбинируйте INT4/INT8, квантизованный KV, continuous batching и prefix‑кэш (где доступен).

Сценарии, когда нужен мультимодельный хостинг

  • SaaS/мульти‑тенант: несколько клиентов/доменов → каждая модель/адаптер со своими лимитами.
  • Продуктовые роли: general‑chat, code‑assistant, RU‑assistant, summarizer.
  • A/B и canary: безопасные обновления версий, сравнение качества/стоимости.
  • Ограничения железа: разные модели требуют разного VRAM → распределяем по пулам/узлам.

Связанные разделы: /solutions/llm-inference/, /solutions/llm-inference/streaming/, /solutions/llm-inference/quantization/, /solutions/multi-gpu/, /solutions/mig/.

Архитектура (минимальная)

Gateway/RouterModel Pools (несколько сервисов сервинга) → GPU‑узлыхранилище моделей/адаптеровлогирование/метрики.
Роль гейтвея — распознать модель/длину/приоритет, выбрать пул и соблюсти квоты.

Типичные стеки пулов:

Пулы моделей (паттерны)

По длине:

  • short‑pool: короткие запросы, строгая p95, маленький max_tokens.
  • long‑pool: анализ/код/длинные контексты, мягкая p95.

По домену: RU‑дообученная, code‑assistant, медиа/банк/ретейл.

По стадии: prod (стабильные веса), canary (новые версии), staging (эксперименты).

Горячность:

  • hot — модель в VRAM (нулевой холодный старт).
  • warm — веса на NVMe, поднимается по спросу.
  • cold — только в реестре, разворачивается по расписанию/ручному триггеру.

VRAM: как посчитать и уложиться

Память весов (грубо):

				
					Weights_bytes ≈ N_params × bits_per_weight / 8
# 7B: FP16/BF16 ≈ ~14 ГБ; INT8 ≈ ~7 ГБ; INT4 ≈ ~3.5 ГБ

				
			

KV‑кэш (упрощённо):

				
					KV_bytes ≈ 2 × L_layers × (L_in + L_out_avg) × H_heads × d_head × bytes_per_elem
				
			

Полный бюджет на модель:

				
					VRAM_model ≈ Weights + KV_peak + Runtime_overhead(5–15%)
				
			

Как экономить VRAM:

  • Ужесточить max context и max_tokens.
  • Включить INT8/INT4 веса и (если поддерживается стеком) INT8/FP8 KV‑кэш.
  • Использовать prefix‑кэш одинаковых системных подсказок.
  • Разнести «длинные» запросы в отдельный пул.
  • При необходимости — MIG‑партиционирование и «тонкие» модели в отдельные MIG‑слайсы (см. /solutions/mig/).

Стратегии загрузки моделей

  • Static: весь набор в VRAM. Минимальная латентность, максимальная цена.
  • Hot/Warm/Cold: держим горячее ядро, остальное — поднимаем по спросу. Нужны LRU‑эвикции и лимиты по VRAM/времени простоя.
  • База + адаптеры (LoRA): одна «база» + несколько адаптеров (RU, код, индустрии). Быстрая смена стиля/домена без полной перезагрузки. См. /solutions/llm-training/finetune-lora/.

Маршрутизация и шедулинг

Критерии маршрутизации: model, tenant, оценка длины (estimated_total_tokens), SLA‑класс (priority), наличие hot‑слота в пуле.

Пример логики (псевдо‑Python):

				
					def estimate_tokens(text):       # грубо: ~4 символа = 1 токен
    return max(1, len(text) // 4)

def route(req):
    model = req.get("model", "llama3-8b-ru")
    Lin = estimate_tokens(req.get("prompt","")) + sum(map(estimate_tokens, req.get("history",[])))
    Lout = req.get("max_tokens", 256)
    total = Lin + Lout

    # приоритет short-пула
    if total <= 4096 and model in {"llama3-8b-ru","llama3-8b"}:
        return "pool_short_ru"
    # длинные и код - в отдельные
    if "code" in model or req.get("use_code_tools"):
        return "pool_code"
    if total > 4096:
        return "pool_long"
    return "pool_default"

				
			

Очереди и fairness: разделите очереди по пулам, используйте приоритеты/квоты, защиту от «длинных» запросов в коротком пуле (circuit‑breaker).

Квоты и мульти‑тенант

  • Тарифы/квоты: req/sec, tokens/sec, max context, одновременные сессии.
  • Изоляция: лимиты на VRAM/CPU/диск по пулу/тенанту.
  • Учёт стоимости: счётчики токенов по модели/тенанту → стоимость за 1M.
  • Политики деградации: при перегрузе — снижение max_tokens, маршрутизация в long‑pool, фоллбек на меньшую модель.

Стоимость и производительность (быстрые формулы)

Обозначим: L_in, L_out, P (prefill ток/с), D (decode ток/с на батч), B — фактический батч, T — латентность.

Латентность:

T ≈ (L_in / P) + (L_out / (D / B)) + overhead

QPS и цена:

QPS ≈ B / T

Tokens_per_hour ≈ D × 3600

Cost_per_1M ≈ (GPU_hour_price × Num_GPU) / (Tokens_per_hour / 1e6)

Для детальной экономии см.: /solutions/llm-inference/costs/, /solutions/cost-planner/.

Совместимость со стеками

Операции: версии, релизы, безопасность

  • Версионирование: model:base@vX + adapter@y + quant@int4/int8/fp8.
  • Релизы: canary 5–10% трафика, затем постепенное повышение доли.
  • Откат: храните предыдущие веса «warm» для быстрого rollback.
  • Безопасность: токены/ключи, лимиты запросов, guardrails/фильтрация. См. /solutions/security/, /solutions/llm-inference/guardrails/.

Наблюдаемость

Минимум дашбордов по каждому пулу и агрегированно:

  • Latency p50/p95/p99, timeouts, ошибки.
  • TPS_decode/prefill_rate, QPS, длины входа/выхода.
  • GPU: utilization, HBM, KV‑кэш (занято/эвикции).
  • Кэш префиксов (где доступно): hit‑rate.
  • Квоты/тенанты: расход токенов, отказы по лимитам.

См. /solutions/llm-inference/observability/, /solutions/monitoring-logging/.

Примеры конфигураций

A) Short/Long + Domain

				
					pools:
  short_ru:
    stack: vllm
    model: llama3-8b-ru
    limits: {max_tokens: 256, max_context: 4096}
    replicas: 3
  long_ru:
    stack: tgi
    model: llama3-8b-ru
    limits: {max_tokens: 2048, max_context: 8192}
    replicas: 2
  code:
    stack: sglang
    model: code-7b
    limits: {max_tokens: 512, max_context: 4096}
    replicas: 2
routing:
  rules:
    - if: {model: "llama3-8b-ru", total_tokens_lte: 4096} -> short_ru
    - if: {model: "llama3-8b-ru"} -> long_ru
    - if: {model: "code-7b"} -> code

				
			

B) Canary‑релиз

				
					routing:
  rules:
    - if: {model: "llama3-8b-ru", total_tokens_lte: 4096}
      split:
        - {pool: "short_ru@v1", weight: 0.9}
        - {pool: "short_ru@v2", weight: 0.1}

				
			

Траблшутинг

  • Хвосты p95 в short‑пуле. Ужесточите max_tokens, изолируйте длинные в long‑пул, увеличьте реплики short.
  • GPU‑OOM при нескольких моделях. Проверьте VRAM‑бюджет, включите INT8/INT4, уменьшите max context, разделите модели по узлам/MIG.
  • Непредсказуемый TPS. Унифицируйте системные промпты (prefill), увеличьте одновременность, проверьте CPU‑токенизацию.
  • Долгие холодные старты. Переведите ключевые модели в hot/ warm, храните веса на локальном NVMe, добавьте прогрев.
  • Съедание кэша одной моделью. Введите лимиты KV на пул/сессию, приоритеты эвикции, разнесите пулы.

Как это запустить в cloudcompute.ru

  • В /solutions/templates/ используйте профиль “Multi‑Model Gateway”:
    – роутер (short/long/domain/canary), лимиты и квоты;
    – готовые сервисы пулов (vLLM/TGI/TensorRT‑LLM/SGLang/llama.cpp);
    – healthcheck, логи запросов, базовые дашборды.
  • Планирование стоимости и режимов инстансов: /solutions/cost-planner/, /solutions/llm-inference/costs/.

Чек‑лист перед продом

  • Зафиксированы SLA (p95, QPS/TPS) по моделям/пулам.
  • Спроектированы пулы (short/long/domain/canary) и правила маршрутизации.
  • Рассчитан VRAM‑бюджет: Weights + KV_peak + overhead; подтверждена совместимость по стеку и квантизации.
  • Установлены лимиты max_tokens/max context, квоты по тенантам.
  • Включены метрики/трейсы/алерты (latency, TPS, KV, ошибки).
  • Описан фоллбек‑план: меньшая модель, снижение лимитов, переводы трафика между пулами.