← Все статьи
2026-05-04 14:01 · 🌐 СНГ (tech/AI)

Self-hosted LLM в проде: где всё ломается и что мерить

Команда AI Platform Битрикс24 вскрыла реальные причины падений self-hosted LLM в продакшене — и это не GPU и не «неправильная» модель. Проблема в наблюдаемости: не видишь — не чинишь.

Self-hosted LLM в проде: где всё ломается и что мерить

Инженеры AI Platform Битрикс24 опубликовали разбор того, как self-hosted LLM ведёт себя под реальной нагрузкой. Ключевой вывод: устойчивость зависит не от выбора модели, а от того, насколько хорошо видно, где именно система деградирует. Увеличение контекстного окна с 64k до 85k токенов сняло 73.5% ошибок — но хвост проблем никуда не делся, потому что причины оказались в нескольких разных слоях сразу.

Контекст

Self-hosted LLM — это не нишевая экзотика. Компании уходят с MaaS-провайдеров по трём причинам: ПДн и внутренние документы в промптах создают комплаенс-риск, предсказуемость затрат при высокой нагрузке лучше у своего стека, и появляется контроль над маршрутизацией и деградацией. MaaS выигрывает скоростью запуска — API-ключ, пара дней интеграции — и это честный выбор для MVP. Но как только трафик системный и данные чувствительные, self-hosted становится не роскошью, а обязательством.

Битрикс24 использует vLLM — стандартный выбор для self-hosted: хорошая пропускная способность, OpenAI-совместимый API, зрелая экосистема. Проблемы, описанные в разборе, не специфичны для vLLM — они следуют из математики контекстного окна и архитектуры очередей и воспроизводятся на любом инференс-фреймворке.

Ключевая архитектурная ставка — очередь между API и инференсом. Без неё синхронные запросы рассыпаются на пиках. С ней появляется backpressure и, что важнее, наблюдаемость: можно разложить деградацию по слоям и понять, где именно сломалось.

Аналитика

Главный инсайт статьи: в проде LLM ломается не там, где ожидаешь. Три независимых класса проблем выглядят похоже снаружи, но требуют разных ответов. Первый — нехватка GPU: queue depth растёт, воркеры на максимуме. Второй — «токсичная» задача на предобработке: воркер падает по OOM не из-за инференса, а потому что zip-архив после распаковки занял в десятки раз больше памяти. Задача при этом остаётся в очереди, воркер перезапускается и снова берёт её — цикличный коллапс. Третий — контекстное окно: запрос не помещается, и вместо деградации вы получаете тихий отказ.

Рост p95/p99 latency при стабильной длине очереди — ранний сигнал деградации, который большинство команд пропускает. К моменту, когда очередь «взрывается» визуально, система уже давно работает плохо. Это принципиально меняет подход к алертингу: смотреть нужно на перцентили и корреляции, а не на абсолютные значения.

Отдельная тема — стоимость длинного контекста. 128K токенов в model card — это не бесплатно. Под полный контекст Qwen3-235B нужно около 640 ГБ aggregate VRAM (8× H200). Для большинства реальных задач дешевле держать основной трафик на коротком окне (16–32K), а длинные запросы выносить в отдельный пул. Или решать проблему до инференса: суммаризация, обрезка истории, жёсткие лимиты на RAG-вставки.

Кейсы применения в бизнесе

B2B-SaaS стартап с собственным AI-модулем. Типичная ситуация: MVP работал на OpenAI API, теперь переходим на self-hosted ради маржи и контроля данных. Что внедрить: очередь с приоритизацией (пользовательский чат — выше, фоновая разметка — ниже), Prometheus + Grafana с пятью базовыми метриками из статьи, алерт на worker_memory_usage. Ожидаемый результат: видимость инцидентов до того, как пользователи начнут жаловаться, и понимание реального bottleneck — GPU или предобработка.

Корпорация с legacy и ПДн в промптах. Внешний MaaS закрыт по комплаенсу, self-hosted — необходимость. Проблема: смешанные типы задач (транскрибация, генерация, structured output) в одном пуле. Что внедрить: роутинг по отдельным пулам моделей под разные SLA, лимиты на входной файл до распаковки и после, отдельный класс воркеров для тяжёлых архивов. Это снимает риск того, что один «токсичный» запрос блокирует весь поток.

SMB и локальный бизнес в КР/СНГ. Если бюджет на GPU ограничен, правильная стратегия — не гнаться за большим окном на всём кластере. Для чата и типичных RAG-запросов на русском языке 16–32K токенов покрывают подавляющую часть реального трафика (по ориентирам из статьи: ~3–4 символа на токен для русского текста). Держать max_model_len на всём кластере в 128K — дорого и не нужно. Лучше: меньшее окно на основном пуле, анализ логов ошибок для понимания реального хвоста.

Кейсы в личной жизни

Разработчик, разворачивающий локальную модель. Ollama, LM Studio, vLLM на домашнем сервере — стандартная история. Что взять из статьи: не ставить max_model_len на максимум «на всякий случай» — это прямая стоимость в VRAM. Для большинства задач (чат, code review, structured output) 16–32K достаточно. Если запросы стали падать — смотреть на processing latency, а не на перезапуск модели.

Контент-мейкер или аналитик, работающий с большими документами. RAG-пайплайн на локальной модели под длинные тексты: закладывать не менее 32K окна, оставлять 4K+ под ответ, не забивать контекст «в ноль». Для русских текстов токенизация плотнее — ~3–3.3 символа на токен у Qwen3, что означает больший эффективный размер документа при том же окне.

Студент или исследователь, строящий агентную цепочку. Reasoning-задачи и multi-step агенты жрут токены быстро — планировать от 32K и выше, явно ограничивать reasoning-бюджет если нужен короткий финальный ответ, иначе reasoning сломает финальный JSON в structured output. Это не баг модели — это архитектурное ограничение, которое нужно проектировать заранее.

Как применить сегодня

  • Поднять пять базовых метрик: queue depth, active workers, processing latency (гистограмма), TTFB, worker memory usage — в Prometheus + Grafana. Это минимум для любого self-hosted LLM.
  • Настроить алерт на рост p95/p99 latency относительно базовой линии — не ждать пока очередь «взорвётся».
  • Добавить мониторинг памяти воркеров и алерт на OOMKill/рестарты — ранний индикатор «токсичных» задач на предобработке.
  • Проанализировать реальное распределение длин запросов в логах ошибок — построить кривую «размер окна → доля устраняемых ошибок» и выбрать max_model_len осознанно, а не по паспорту модели.
  • Для смешанных задач (чат + RAG + structured output + транскрибация) — настроить роутинг в отдельные пулы вместо единой очереди. Это снижает взаимовлияние задач разного веса.
← Все статьи