Привет, Хабр! В этой статье я расскажу про наш LLM инференс-кластер YADRO: зачем он нужен, что у него под капотом и как в такой конфигурации показывают себя популярные модели. Кроме того, я немного порассуждаю об альтернативных реализациях кластера и поделюсь планами по развитию реализации нашей.

Начну с того, какие ИИ-инструменты мы в YADRO разрабатываем в помощь коллегам:

  • сервис транскрибации и конспектирования встреч,

  • ассистент для написания кода,

  • умный поиск по внутренней документации,

  • автоматизированная техническая поддержка,

  • прямые чаты с моделями для выполнения различных задач.

Все они используют LLM, за работу которых отвечает LLM инференс-кластер в контуре компании. Так сотрудники могут выполнять запросы с чувствительной информацией, не опасаясь ее утечки.

Модели в кластере и взаимодействие с ними

В кластере мы развернули следующие LLM.

Модель

Размер контекста в токенах

Сфера применения

DeepSeek-R1-Distill-Qwen-32B

128k

- автоматизация техподдержки
- чат-бот для разных задач

Qwen2.5-32B-Instruct

128k*

- суммаризация митингов
- чат-бот для разных задач

Qwen2.5-Coder-32B-Instruct

32k

- чат-бот для ассистента по написанию кода

Qwen2.5-Coder-7B-Instruct

32k

- автодополнения для ассистента по написанию кода

T-lite-it-1.0

32k

- чат-бот для разных задач

T-pro-it-1.0

128k*

- суммаризация митингов
- чат-бот для разных задач

multilingual-e5-large

512

- эмбеддинги для поиска по векторной БД общего содержания

bge-m3

8k

- эмбеддинги для поиска по векторной БД общего содержания

nomic-embed-text-v1

8k

- эмбеддинги поиска по векторной БД для ассистента по написанию кода

bge-reranker-v2-m3

8k

- ранжирование результатов поиска по векторной БД

* Размер контекста модели увеличен с 32k до 128k с помощью YARN в настройках запуска инференс-сервера

В контуре YADRO с моделями можно работать через веб-оболочки. Пообщаться с некоторыми в режиме диалога — на «LLM-арене» на базе платформы Open WebUI. Для продвинутых пользователей развернут сервис Dify, где можно создавать свои приложения в визуальном редакторе. Разработчики могут использовать модели через код-ассистент Continue.Dev, доступный как плагин для VS Code с нашим кастомизированным конфигом.

Сервисы взаимодействуют с кластером через стандартный OpenAI-подобный REST API. Вот пример эндпойнта для работы с LLM:

Через него можно посылать сырые запросы в наш кластер. Либо использовать библиотеки, предоставляющие более удобные API для взаимодействия с LLM, — OpenAI SDK или LiteLLM.

Архитектура кластера

LLM инференс-кластер работает на общей MLOps инфраструктуре компании и представляет собой набор сервисов в Kubernetes. Аппаратная основа кластера — ноды с GPU NVIDIA: RTX 4090 для легких и H100 для более тяжелых моделей.

Для запуска и инференса моделей мы используем популярный, активно разрабатываемый фреймворк vLLM с открытым исходным кодом и большим комьюнити. Фреймворк поддерживает мультимодальные модели, модели с рассуждением, включает много разных техник оптимизации LLM и вообще очень функционален. При этом, что немаловажно, vLLM прост в использовании по сравнению с некоторыми аналогами, не требует конвертации модели в свой формат, а читает их напрямую в формате Hugging Face. Это облегчает развертывание моделей. Фреймворк умеет работать с GPU не только NVIDIA, но и других производителей — пока нам это не нужно, но в перспективе может пригодиться.

Модели мы стараемся запускать при точности FP8, если аккуратность в наших задачах нас устраивает. Используем либо готовые квантованные версии с Hugging Face (например, из репозитория RedHatAI), либо динамическую квантизацию vLLM. Так мы достигаем компромисса между качеством и скоростью работы, а также экономим память, чтобы запускать на доступном железе больше инстансов моделей. Некоторые небольшие модели работают на одном GPU, более крупные запускаются на двух или на четырех в режиме tensor parallel inference. Последний вариант используется на серверах с NVIDIA H100, связанных через NVLink, что обеспечивает эффективный обмен данными между видеокартами. Модели с Hugging Face мы заранее скачиваем во внутреннее хранилище, откуда их уже загружают vLLM-сервера.

Второй компонент инференс-кластера – это сервер LLM Gateway на базе прокси-сервера LiteLLM. На него возложено несколько задач:

  • Сбор информации по всем запущенным инференс-серверам: каждый инстанс vLLM отвечает за одну модель.

  • Роутинг и проксирование запросов от вызывающих сервисов к серверам моделей.

  • Унифицированный API для вызывающих сервисов.

  • Контроль доступа по API-ключам. 

В кластере предусмотрено и масштабирование: часть моделей, в том числе для код-ассистентов, имеет заранее установленное число запущенных инстансов. Мы подбирали его на основе требований по масштабированию и результатов бенчмаркинга.

Для остальных моделей число инстансов определяется автоматически — в Kubernetes это называется horizontal pod autoscaling. Автоматическое масштабирование инференс-серверов моделей ориентируется на метрику загрузки GPU, а масштабирование сервера LLM Gateway — на загрузку процессора.

Запуск новых инстансов сервером vLLM занимает некоторое время, так как серверу нужно загрузить большой объем весов в память GPU и сконвертировать модель во внутреннее представление. Именно по этой причине для особо критичных моделей мы используем статически заданное число инстансов — чтобы при увеличении нагрузки не тратить время на развертывание новых серверов. 

Мониторинг кластера

Для мониторинга доступности моделей настроены сторожевые таймеры (watchdogs), причем на сервисах поверх инференс-кластера. Доступность всех инстансов LLM по времени, их метрики и нагрузку на оборудование мы отслеживаем с помощью Grafana. Валидация аккуратности именно на уровне инференс-кластера сейчас не предусмотрена — она работает на базе приложений, которые используют кластер (RAG-пайплайн, сервис суммаризации и т. д.).

Трудности и альтернативные решения

Расскажу про некоторые трудности, с которыми мы столкнулись, а также об альтернативных технологиях, которые мы использовали раньше или рассматриваем на будущее.

До фреймворка vLLM мы использовали NVIDIA Triton в паре с TensorRT LLM бэкендом. Но перешли на vLLM, потому что с ним оказалось намного проще добавлять новые модели. Да и по стабильности vLLM показал себя лучше: нормально работал под нагрузками там, где связка Triton и TensorRT начинала сбоить и падать. К тому же инференс-сервер vLLM изначально предоставляет OpenAI-совместимые REST API, что упрощает его использование в других продуктах. А инференс-сервер Triton работает с более обобщенным KServe REST API, который сложнее интегрировать в другие продукты.

Не обошлось без проблем и с vLLM: на наших валидационных тестах модель давала неконсистентные ответы даже с нулевой температурой. Оказалось, что это известная особенность vLLM, даже упомянутая в документации. Мы нашли несколько советов, как минимизировать этот эффект: отключать prefix caching опцией --no-enable-prefix-caching и фиксировать random seed опцией --seed. Это помогало при одном запущенном инстансе модели, но при нескольких, даже работающих на одном железе и версии софта, проблема всплывала снова. Также неконсистентность ответов возникает при больших нагрузках — например, когда тесты запускаются одновременно с бенчмарком.

Еще один вызов — это накладные расходы от litellm-proxy и его масштабирование под нагрузками. LLM Gateway, в качестве которого мы используем LiteLLM, превращается в боттлнек кластера, так как все другие сервисы взаимодействуют с кластером именно через него. То есть именно на него идет суммарная нагрузка от всех возможных пользователей, которая потом распределяется между разными моделями и их инференс-серверами.

Эксперименты, о которых я расскажу далее, показали, что начиная с некоторой нагрузки накладные расходы LiteLLM начинают расти почти экспоненциально, причем на каждый генерируемый токен. Это приводит к существенному замедлению ответа модели. Пока мы боремся с этим двумя способами:

  • Минимизация работы litellm-proxy с БД. По умолчанию litellm-proxy логирует в свою базу данных информацию о каждом запросе. Как следствие — неограниченное увеличение размера БД и деградация операций по работе с ней.

  • Увеличение максимального числа запущенных инстансов сервиса.

Кроме того, мы экспериментируем с альтернативными решениями для LLM Gateway — например, с дошедшим в этом году до релиза vLLM Production Stack и входящим в его состав vllm-router. Переход на другое решения для LLM Gateway усложняется тем, что мы изначально стали использовать LiteLLM для авторизации и контроля доступа по ключам. Это сильно привязывает нас к LiteLLM, и сейчас мы рассматриваем вариант переноса этой функциональности на отдельный API Gateway, который будет стоять над LLM Gateway.

Производительность кластера

Для анализа производительности кластера мы используем инструмент бенчмаркинга от vLLM. Результаты ниже были получены на датасете philschmid/mt-bench. В нем собраны небольшие запросы на разные тематики — в среднем около 70 токенов. Ответы модели в среднем занимают около 200 токенов. Графики ниже показывают производительность моделей при различных нагрузках:

Теперь сравним работу модели T-lite-it-1.0 при разном числе запущенных инстансов:

А на этих графиках — сравнение разных режимов работы LLM Gateway под нагрузками при одном инференс-сервере:

Видно, что после определенной нагрузки (более 50 одновременных запросов) четыре инстанса LiteLLM перестают справляться и накладные расходы от них начинают расти. Десять же инстансов с подобной нагрузкой справляются. При этом vllm-router держит подобные нагрузки даже с одним запущенным инстансом.

Выводы

LLM-кластер YADRO начинался с одной небольшой LLM и одной модели эмбеддингов для экспериментов с RAG, запущенных на одном инференс-сервере NVIDIA Triton. Теперь у нас в кластере есть целый набор ИИ-сервисов и моделей под разные задачи. Коллегам интересна наша работа, приходят запросы на добавление новых и обновление существующих моделей. Растет число пользователей и нагрузка на кластер.

Поделюсь важными выводами, которые мы сделали за время развития кластера:

  • Под разные задачи модели нужно сравнивать и внимательно подбирать. Например, для техподдержки в нашем случае DeepSeek-R1-Distill-Qwen-32B показала себя лучше, чем аналоги. В задачах суммаризации митингов отличились модели семейства Qwen (Qwen2.5-32B-Instruct и T-pro-it-1.0). При этом, судя по результатам опросов, лучше справлялась с русским языком T-pro-it-1.0. Что неудивительно, так как под русский язык ее и шлифовали.

  • Важно понимать требования моделей и рассчитывать использование доступных ресурсов с учетом планируемых нагрузок.

  • Необходимо проводить нагрузочное тестирование для анализа пропускной способности кластера и поиска боттлнеков в нем.

  • Нужно четко определить требования к компонентам кластера. Например, использование LLM Gateway для авторизации привязало нас к конкретному решению и затруднило переход на альтернативные.

Надеюсь, наш опыт окажется полезным, если вы решите развертывать подобные решения в своей компании.

Кстати, сейчас мы ищем в команду техлида на LLM и дата-сайентиста. Будем рады вашим откликам!

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


  1. SabMakc
    30.07.2025 18:41

    По идее, что 20 инстансов DeepSeek-R1-Distill-Qwen-32B, что один полноценный deepseek-r1 - по скорости и ресурсам должно быть сопоставимо. Но качество будет за "полной" моделью.
    P.S. qwen3 не тестировали? Что-то модели в целом не самые свежие...