
Привет, Хабр! Меня зовут Антон, я DevOps-инженер в команде Data/ML-продуктов Selectel. Если вам нужно запустить небольшой инференс одной ML-модели, можно взять команду бэкендеров, дать им эту модель, они обернут ее в эндпоинт — и готово. Достаточно короткого скрипта из нескольких строк на Python. Но что если нужно запускать несколько моделей, оптимизировать выполнение, работать с ансамблем моделей, задействовать CPU и GPU одновременно и т. д.? Все эти проблемы решает NVIDIA Triton Inference Server. Правда, он добавляет одну новую: разобраться с ним и его документацией — тот еще квест.
В статье посмотрим, насколько сложной задачей может оказаться создание собственного инференса и какие аспекты нужно учитывать. Научимся запускать различные форматы моделей, посмотрим на основные фичи Inference-платформы Selectel, запустим несколько популярных LLM и моделей, а также познакомимся со способами оптимизации конфигурации и проектирования интерфейса для модели.
Используете Terraform? Помогите нам сделать новый сервис лучше. Пройдите короткий опрос — мы выберем самые интересные кейсы и пригласим вас на онлайн-интервью. За участие — плюшевый Тирекс или бонусы на услуги Selectel.
Используйте навигацию, если не хотите читать текст целиком:
→ Немного предыстории
→ Демо Inference-платформы
→ Рецепты приготовления Triton Inference Server
→ Заключение
Немного предыстории
В конце 2024 года мы анонсировали новый продукт — частную инсталляцию Inference-платформы Selectel. За время проведения демонстраций, общения с клиентами и эксплуатации платформы мы пришли к вполне очевидному выводу — для работы с ней пользователям нужны туториалы и грамотные инструкции по NVIDIA Triton Inference Server. Сначала я написал небольшую книгу рецептов с туториалами по работе с Inference-платформой Selectel и NVIDIA Triton Inference Server в целом. Но сейчас очевидно, что нужно копнуть чуть глубже и датальнее разобрать примеры.
Кстати, подробная статья о миграции на Triton и о том, зачем нужен специализированный инференс-сервер, есть в документации NVIDIA. Правда, она на английском, но я уверен, вас это не остановит.
Мы же тем временем перейдем к разбору примеров работы с Inference-платформой и NVIDIA Triton Inference Server.

Демо Inference-платформы
В этой главе я расскажу о трех сценариях, которые мы показываем на демонстрации нашего продукта. Их можно воспроизвести у себя самостоятельно, обладая следующей инфраструктурой:
- Kubernetes,
- объектное хранилище — для модели,
- файловое хранилище — для кэша весов модели.
Также понадобятся ноды с GPU. Для их настройки можно использовать GPU-оператор. Как это сделать, я описывал в статье на Хабре. Также не забываем на шаблонах групп нод включить автоскейлинг! О нем тоже есть подробная статья.
Что касается слоя Application, нам понадобятся следующие сервисы.
- Prometheus Stack. Он поставит нам Grafana и Prometheus. В Prometheus мы будем собирать логи с наших «трайтонов», в Grafana — смотреть на дашборды. Helm-чарт можно взять из репозитория.
- Prometheus Adapter. Этот сервис конвертирует наши метрики Triton в кастомные метрики K8s. По метрикам будет происходить автоскейлинг. Helm-чарт доступен в репозитории.
- Istio. Он нужен для наших Ingress и Canary-деплоя. Создаем Virtual Service для наших трайтонов и перенаправляем трафик в нужные сервисы через единый балансировщик нагрузки. Helm-чарт также можно взять с GitHub.
Подробные примеры с кодом для каждого сценария лежат в директории нашего репозитория. Я же обозначу основные моменты в данной статье.
Для всех сценариев нужно задать конфигурацию для модели. Используем Falcon7b как базовый пример деплоя с бэкендом на Python. Структуру репозитория можно посмотреть на GitHub. Сам же пример был взят из другого репозитория — здесь мы хотели показать, как использовать бэкенд Python для работы с моделями с Hugging Face. Сейчас же лучше использовать формат VLLM или TensorRT, если вы хотите деплоить такие модели в продакшн.
Все файлы заливаем в объектное хранилище, например, утилитой Rclone. Заполним конфигурационный файл:
provider = other
env_auth = false
access_key_id = #сюда вставьте ваш access key от объектного хранилища
secret_access_key = #сюда вставьте ваш secret key от объектного хранилища
region = ru-1
endpoint = s3.ru-1.storage.selcloud.ru
```
И загрузим конфигурацию модели в бакет S3:
```
rclone copy model_repository/ selectel:<bucket_name>/model_repository
На этом базовая подготовка закончена, можно приступать к деплою Triton!
Базовый сценарий
Суть сценария заключается в получении эндпоинта из нашей модели.

Ничего сложного — просто получение эндпоинта HTTP/GRPC нашей модели.
Мы взяли за основу чарт с GitHub. Дописали работу с Istio, объектным и файловым хранилищами. Для своих опытов вы можете использовать пример от NVIDIA, в случае работы с нашей платформой — следуйте инструкциям в репозитории.
После деплоя вам будет доступен дашборд Grafana, где указываются статусы Triton, метрики насыщения, данные GPU, логи и трафик.

Дашборд Inference-платформы.
В целом, вы сами сможете реализовать такой дашборд с помощью этих референсов:
Проверим работоспособность инференса:

Проверить работу инференса можно с помощью Curl.
В следующем сценарии рассмотрим, что будет с инференсом под нагрузкой.
Автоскейлинг
В этом сценарии мы подадим нагрузку на наш инференс-сервер. В values чарта укажем параметры автоскейлинга и таргет, по которому будет происходит масштабирование.
autoscaling:
minReplicas: 1
maxReplicas: 2
metrics:
- type: Pods
pods:
metric:
name: avg_time_queue_us
target:
type: AverageValue
averageValue: 1000000000m

Этапы автоскейлинга. Подробнее я описывал в статье об автоскейлинге инференса на GPU в Kubernetes.
Метрику avg_time_queue_us создает Prometheus-адаптер, используя формулу:
- seriesQuery: 'nv_inference_queue_duration_us{namespace!="",pod!=""}'
resources:
overrides:
namespace:
resource: "namespace"
pod:
resource: "pod"
name:
matches: "nv_inference_queue_duration_us"
as: "avg_time_queue_us"
metricsQuery: 'avg(rate(nv_inference_queue_duration_us{<<.LabelMatchers>>}[30s])/(1+rate(nv_inference_request_success{<<.LabelMatchers>>}[30s]))) by (<<.GroupBy>>)'
Нагрузку я подаю с помощью утилиты perf_analzyer. Вы же можете использовать locust, k6 и другие инструменты нагрузочного тестирования. Отправим десять одновременных запросов от пользователей в течении 100 секунд.
perf_client -u $INFERENCE_URL -m falcon7b --input-data data.json -v --output-tensor-format=json --input-tensor-format=json --concurrency-range 10 -p 200000 --request-period 100

Как видно из графика, нагрузка уменьшилась в два раза после аллоцирования новой реплики.
Перейдем к последнему сценарию. Проверим возможность обновлять модели без даунтаймов.
Canary-деплой
Мы задеплоим две версии модели и подадим 90% трафика на первую версию, 10% — на вторую.

Канареечный деплой работает и для инференсов тоже.
В этом сценарии активно участвуют Istio и kiali. Istio перенаправляет трафик на нужные версии Triton. В нашем случае это отдельные инсталляции деплоймента в values.
После деплоя и подачи трафика на эндпоинт мы можем посмотреть анимацию трафика в kiali. В этом сервисе можно отслеживать статусы ошибок запросов на каждую версию, а также изменить процентное соотношение трафика.

Kiali предоставляет интерфейс для отслеживания трафика между версиями моделей.
В следующей главе мы рассмотрим альтернативные сценарии работы с Triton: как он работает с различными форматами моделей, популярными LLM и как можно подобрать оптимальный конфигурационный файл.
Рецепты приготовления Triton Inference Server
Итак, мы посмотрели, как работают основные фичи Inference-платформы Selectel. В этой главе расширим список доступных для нас функциональностей за счет использования ядра платформы Triton Inference Server.
Работа с различными форматами моделей
Я подготовил несколько примеров по использованию различных форматов моделей. Для каждого формата у Triton реализован отдельный бэкенд. Он также предоставляет возможность реализовывать свои бэкенды, если готовые не подходят.
- ONNX. Демонстрирует, как развернуть модель в формате ONNX на Triton Inference Server. ONNX позволяет обмениваться моделями между различными фреймворками, обеспечивая совместимость.
- OpenVINO. Показывает, как использовать OpenVINO для оптимизации и развертывания моделей на CPU-ресурсах. Это позволяет ускорять инференс на различных аппаратных платформах. Если нет GPU, это must have.
- TensorFlow. Пример развертывания модели TensorFlow в формате SavedModel. Это демонстрирует, как Triton может использовать популярные фреймворки для инференса.
- Python. Пример использования бэкенда на Python для выполнения пользовательской логики, такой как простая арифметическая операция. Это позволяет интегрировать пользовательские обработки данных и использовать библиотеки Python.
- PyTorch. Демонстрирует, как развернуть модель PyTorch на Triton Inference Server. PyTorch широко используется для исследований и разработки в области глубокого обучения.
- TensorRT. Пример использования TensorRT для оптимизации и развертывания моделей. Это позволяет значительно ускорить инференс на GPU,
- FIL backend. Позволяет работать с моделями на основе дерева решений. К сожалению, пока нет поддержки catboost.
Эти примеры предназначены для демонстрации гибкости Triton Inference Server в работе с различными форматами моделей и бэкендами, а также для предоставления практических примеров развертывания и использования моделей в различных сценариях.
Популярные модели и LLM — foundation models
Достаточно популярная на данный момент модель предоставления LLM as a Service — Foundation models. В Triton мы можем использовать два бэкенда: TensorRT LLM и vLLM.
- Первый запускает LLM в формате TensorRT и дает большую производительность (по бенчмаркам NVIDIA). Поддерживаемые модели можно найти в репозитории NVIDIA.
- Второй — удобный фреймворк для запуска инференса, который поддерживает многочисленный парк моделей. Их список доступен в документации vLLM.
Как выбрать между двумя? Если нужны удобство и большой парк моделей, выбирайте VLLM. Если в приоритете производительность инференса, но есть сложности в конфигурации, присмотритесь к TensorRT.
Для импорта конфигурации модели каждого из бэкендов я рекомендую использовать утилиту triton_cli. С помощью простых команд она создаст для вас конфигурацию как для VLLM, так и для TensorRT.
В наших рецептах есть примеры работы как с vLLM, так и с TensorRT для Whisper. Вы можете попробовать развернуть эти модели через Helm-чарт или в Docker-контейнере.
Также вы можете найти примеры с использованием импорта моделей из Hugging Face с помощью бэкенда Python и использованием Stable Diffusion, где реализован собственный бэкенд для работы с этой моделью в формате TensorRT.
Подбор оптимальной конфигурации инференса
При использовании Triton, возможно, вы задаетесь вопросом, как правильно подобрать формат модели и конфигурацию инференс-сервера. Как вы могли заметить, конфигураций бывает достаточно много. Концептуально я отвечал на этот вопрос в ретроспективе разработки нашей Inference-модели.

Как может выглядеть пайплайн поиска лучшего формата модели и конфигурации.
В нашем репозитории с рецептами я выделил два примера: с Model Navigator и Model Analyzer.
Model Navigator
Model Navigator — это инструмент для оптимизации и развертывания моделей глубокого обучения, разработанный для работы с NVIDIA GPU. Он автоматизирует процессы экспорта, конверсии, тестирования корректности и профилирования моделей, поддерживая такие фреймворки, как PyTorch, TensorFlow и ONNX. Model Navigator позволяет пользователям эффективно искать лучшие варианты развертывания моделей, предоставляя единый интерфейс для различных фреймворков.
Для подготовки моделей к эксплуатации на NVIDIA Triton Inference Server необходимо выполнить несколько действий.
- Экспортировать модель. Преобразовать ее в один из поддерживаемых форматов, таких как ONNX или TensorRT.
- Оптимизировать модель. Использовать Model Navigator для оптимизации модели, чтобы достичь максимальной производительности.
- Создать конфигурацию модели. Определить конфигурацию для Triton, включая спецификации входных и выходных тензоров.
- Развернуть модель. Использовать API Triton для добавления модели в репозиторий и развертывания на сервере.
Model Analyzer
Model Analyzer — это инструмент CLI, который поможет найти оптимальную конфигурацию на имеющемся оборудовании для одиночной, множественной, ансамблевой или BLS-модели, запущенной на Triton Inference Server. Сервис также генерирует отчеты, чтобы помочь лучше понять компромиссы различных конфигураций и их требования к вычислительным ресурсам и памяти. Он запускает несколько инференс-сервисов с Triton и подает нагрузку на них с помощью perf_client — утилиты для высоконагруженных тестов. Далее формирует отчет, в котором указана оптимальная конфигурация, где perf_client показал лучшую производительность.
Стоит отметить, что для подбора конфигурации LLM Model Analyzer работать не будет, для подробностей смотрите pull request. Разработчики рекомендуют для подбора конфигурации в этом случае использовать genai perf в режиме analyze.
User Interface
После деплоя модели в Infererence-платформу вы получается эндпоинт. Но это не конечное приложение для пользователей. Оно скорее нужно, если вы хотите предоставить им интерфейс для работы с моделями. Например, для личного ChatGPT это может быть OpenWebUI, а для собственного генератора картинок — Automatic1111.
Если рассматривать небольшие приложения, можно использовать несколько рецептов из нашего репозитория. Например, вы хотите создать Telegram-бота. Рецепт достаточно прост — деплоим Whisper в Inference-платформу, подключаем эндпоинт и самого бота. Теперь вам доступен транскибатор аудио даже без премиум-аккаунта в Telegram!

Сравниваем транскрибатор Telegram и наш собственный.
Также стоит упомянуть отличный фреймворк Gradio. Мы также подготовили рецепт его сборки для нашего эндпоинта. Он позволяет на Python достаточно просто создать интерфейс для взаимодействия с моделями.
Заключение
Как вы могли заметить, в текущей версии Inference-платформы нужно обладать навыками работы с Kubernetes. Она задумывалась как частная инсталляция в проект клиента с возможностью кастомизировать каждый параметр платформы под его нужды. Следовательно, инсталляция скорее всего подойдет в случаях, когда у вас есть команда инженеров, способных работать с K8s.
Сейчас мы разрабатываем PaaS-версии платформы, где первым этапом вы сможете запускать уже известные LLM по концепции foundation models. В этой версии вы не будете напрямую взаимодействовать с K8s — только через API и веб-интерфейс! И здесь мы ищем Gо-разработчика, который поможет нашей команде создать качественный продукт.