Самостоятельный инференс на одной GPU: лимиты, стоимость, приватность
Думаете о self-hosted inference на одном сервере с GPU? Разберитесь в ограничениях батчинга, базовом мониторинге, плюсах приватности и компромиссах до того, как принимать решение.

Почему команды смотрят на шлюз для моделей
Команды обычно начинают думать о шлюзе для моделей тогда, когда использование модели перестаёт быть побочным экспериментом. Одному приложению нужен локальный кодовый модельный помощник, другому — чат-модель, а кому-то ещё нужны эмбеддинги для поиска. Без шлюза каждый инструмент обращается к каждой модели по-своему. Очень быстро это превращается в хаос.
Шлюз для моделей даёт команде одну точку входа для всего этого трафика. Приложения отправляют запросы в одно место, а шлюз решает, какая модель должна их обработать. На первый взгляд это мелочь, но на практике она сильно убирает повседневное трение. Разработчикам не нужно каждый раз заново собирать одну и ту же интеграцию, когда они тестируют новую модель или меняют одну модель на другую.
Второй важный повод — контроль. Командам нужно одно место, где можно задавать лимиты, смотреть использование и держать правила едиными. Если менеджер продукта хочет ограничить число запросов для внутренних инструментов, а инженер — блокировать промпты с секретами, шлюз даёт одну точку управления вместо настроек, разбросанных по разным приложениям.
Небольшие команды также переживают из-за зависимости от одного поставщика. Когда всё завязано на один API вендора, менять курс потом становится дорого. Растут расходы, меняется качество модели, меняются условия. Шлюз упрощает тестирование, потому что приложение может почти не меняться, пока команда сравнивает модели за кулисами.
На практике шлюз обычно выполняет четыре базовые задачи: направляет запросы к нужной модели, применяет лимиты по пользователю или приложению, хранит логи и данные об использовании в одном месте и скрывает особенности конкретных моделей за одним API.
Это не значит, что команде нужна тяжёлая платформа. Обычно им нужно обратное. Им хочется, чтобы self-hosted inference ощущался скучным: один сервер, одна точка входа, понятные логи и минимум лишних движущихся частей. Если шлюзу нужно постоянное внимание, он теряет смысл.
Хороший пример — продуктовая команда из пяти человек. Они могут использовать локальную чат-модель для внутренней поддержки, кодовую модель для инструментов разработчиков и модель для эмбеддингов в поиске. Шлюз позволяет управлять этой смесью, не превращая каждое приложение в отдельный AI-проект.
На что на самом деле способен один GPU-сервер
Сервер с одной GPU может казаться быстрым в демо и медленным в реальной работе. Обычно разрыв объясняется тремя вещами: размером модели, длиной промпта и тем, сколько людей обращаются к ней одновременно.
Начните не со скорости, а с памяти. Если модель еле помещается в VRAM, все остальные сравнения становятся размытыми. Более длинный контекст требует больше памяти, как и кеш, который модель строит во время ответа. Модель на 7B или 8B часто намного комфортнее чувствует себя на карте с 24 ГБ, чем модель на 13B. Более крупные модели обычно заставляют идти на жёсткие компромиссы: сокращать контекст, сильнее квантизировать или медленнее выгружать данные.
Поэтому цифры вроде токенов в секунду легко вводят в заблуждение. Сервер может выглядеть быстрым на коротких промптах и одном пользователе, а потом почти ползти, когда кто-то вставит длинный документ. В self-hosted inference длина контекста, размер батча и время ответа постоянно тянут друг друга в разные стороны. Пропускную способность можно поднять батчингом, но тогда пользователи могут дольше ждать появления первого токена.
Длинные запросы только усугубляют это. Если два человека почти одновременно отправят большие промпты, замедление редко будет плавным. Один запрос может занять GPU так надолго, что второй встанет в очередь, и оба пользователя почувствуют задержку. Команды часто планируют по средним значениям за день, но реальный предел проявляется во время коротких всплесков после встречи, релиза или наплыва обращений в поддержку.
Не вся система — это и есть модель. Шлюзу тоже нужны CPU и RAM для маршрутизации, токенизации, логирования, авторизации и других фоновых задач. Если вы рассчитаете машину слишком впритык, так что модель заберёт почти всё, мелкие процессы вокруг неё начнут добавлять задержку.
Простой способ думать об одном сервере такой: он хорошо справляется со стабильным небольшим трафиком, с короткими всплесками — уже с трудом, а с одновременными длинными запросами — плохо. Если нескольким людям нужен быстрый ответ сразу, закладывайте запас, а не надейтесь, что средняя нагрузка всё спасёт.
Где батчинг помогает, а где ломается
На сервере с одной GPU батчинг часто становится первым, что пробуют команды, потому что он быстро повышает пропускную способность. Если пять коротких запросов приходят в очень маленьком временном окне, GPU обычно обрабатывает их эффективнее вместе, чем по одному. Особенно это хорошо работает для задач вроде тегирования, классификации или коротких резюме, где никто не ждёт каждый токен отдельно.
Но тут есть простая проблема. Пользователи не чувствуют пропускную способность. Они чувствуют задержку. В чате люди замечают паузу до появления первого токена. Большой батч может улучшить общее число токенов в секунду, но при этом заставит каждого человека дольше ждать в очереди. Именно из-за этого многие self-hosted-системы начинают казаться медленными, даже когда по графикам GPU загружен отлично.
Полезно соблюдать простое правило: объединяйте короткие запросы, которые приходят почти одновременно, но держите окно ожидания небольшим. Если слишком долго удерживать запросы ради более крупного батча, настоящим узким местом станет очередь.
Хорошие сценарии для батчинга
Батчинг лучше всего работает там, где работа предсказуема и не срочная. Короткие промпты с короткими ответами, фоновые резюме, тегирование, модерация и ночная обработка подходят отлично. Такие задачи могут подождать несколько сотен миллисекунд, иногда дольше, и пользователи этого даже не заметят.
Где он ломается
Интерактивный чат — другая история. Длинные промпты, длинные ответы и инструменты, которые обращаются к другим сервисам, делают поведение батча неровным. Один медленный запрос может задержать несколько других. Батч, который в начале выглядел эффективным, может ухудшить время ответа для всех, кто в него попал.
Командам стоит рано разделять трафик. Поместите живой чат и другие интерактивные запросы в один канал, а офлайн-работу вроде резюме, разметки или очистки документов — в другой. Одна эта мера не даст фоновой работе съедать очередь, когда реальным пользователям нужны быстрые ответы.
Ещё нужно смотреть не только на время генерации, но и на время в очереди. Измеряйте, сколько каждый запрос ждёт до того, как модель начнёт выдавать токены. Если задержка в очереди постоянно растёт, значит, настройки батчинга слишком агрессивны, сервер слишком мал или и то и другое сразу.
Задайте максимальный возраст очереди и соблюдайте его. Если интерактивный запрос ждёт дольше лимита, перенаправьте его на меньшую модель, отправьте другому воркеру или отклоните с понятной ошибкой. Просроченная работа хуже неудачной, потому что зря расходует GPU-время и всё равно раздражает пользователей.
Что мониторить с первого дня
Большинство команд сначала смотрит на среднюю задержку. Это полезно, но длина очереди обычно предупреждает раньше. Если запросы начинают выстраиваться на сервере с одной GPU, пользователи почувствуют замедление ещё до того, как дашборд начнёт выглядеть тревожно.
Отслеживайте два временных показателя для каждого запроса: время до первого токена и полное время ответа. Время до первого токена показывает, как долго пользователь ждёт, прежде чем вообще что-то появится. Полное время ответа показывает, сколько заняла вся задача. В чат-инструменте первый показатель часто важнее: люди легче прощают медленное завершение, если ответ начинается быстро.
Использование ресурсов не менее важно, чем задержка. С первого дня смотрите на память GPU, загрузку GPU, загрузку CPU и заполнение диска. Всплески памяти GPU могут блокировать новые запросы, даже когда загрузка GPU выглядит умеренной. Узкие места на CPU тоже возникают чаще, чем многие ожидают, особенно если токенизация, логирование и маршрутизация происходят на одной машине.
Считайте количество входных токенов, выходных токенов и неудачных запросов для каждой модели. По числу токенов видно, какие сценарии дороги и какие команды по привычке отправляют огромные промпты. У неудачных запросов должен быть код причины, а не просто общий счётчик. Таймаут, ошибка нехватки памяти и ошибка маршрутизации — это три разные проблемы.
Если вы направляете трафик на несколько моделей, логируйте, какая модель ответила на каждый запрос и почему шлюз выбрал именно её. Одна эта деталь позже сэкономит часы. Когда пользователи жалуются, что ответы стали хуже или медленнее, вы сможете проверить, не отправил ли роутер трафик на меньшую модель, не сработало ли правило fallback или не было ли повторной попытки после ошибки.
На старте достаточно простых алертов. Следите, не держится ли длина очереди выше обычного диапазона несколько минут, не прыгает ли время до первого токена выше лимита, не падает ли свободная память GPU слишком низко, не падают ли и не перезапускаются ли процессы инференса и не растёт ли использование диска из-за логов или кешированных файлов.
Если вы уже используете Prometheus, Grafana, Loki или Sentry, добавьте туда же метрики инференса вместо того, чтобы собирать отдельный стек. Первый дашборд должен быть скучным и понятным. Один экран должен показывать, быстрый ли сервер, заполнен ли он, падает ли он или тихо строит очередь.
Что приватность улучшает, а что всё ещё остаётся рискованным
Запуск моделей на своём сервере меняет то, куда уходят данные. Промпты, файлы и ответы могут оставаться внутри вашей сети, а это часто упрощает юридическую проверку и обязательства перед клиентами. Если по политике какие-то данные не должны покидать вашу среду, self-hosted inference может решить настоящую проблему.
Плюс здесь очень понятный: меньше внешних компаний обрабатывают сообщения клиентов, внутренние заметки, баг-репорты, контракты и черновики продуктов. Это снижает риск третьих сторон и уменьшает число систем, которые могут хранить копии чувствительного текста.
Особенно это важно для команд, которые работают с тикетами поддержки, заметками отдела продаж, медицинскими данными, финансовыми записями или закрытым исходным кодом. Облачный API добавляет ещё одну сторону к каждому запросу. Локальный шлюз убирает этот лишний шаг.
Но self-hosting не отменяет риски приватности. Он просто переносит большую часть риска на вашу собственную инфраструктуру и ваших людей. Если вы храните сырые промпты в логах приложения, логах прокси, резервных копиях, аналитических инструментах или скопированных тестовых файлах, утечка может произойти и внутри компании.
Маленькие команды чаще всего страдают от обычных ошибок. Слишком много администраторов видят сырые промпты и ответы. Резервные копии хранят чувствительные логи месяцами. На дашбордах отображается текст клиента в открытом виде. Инженеры тестируют на реальных данных вместо обезличенных примеров.
Редактирование данных помогает сильнее, чем многие думают. Если сотруднику не нужен полный email, номер телефона, ID аккаунта или платёжные данные, чтобы получить полезный ответ модели, уберите это до инференса. Сводка тикета без имён и ID часто работает не хуже.
Правила доступа нужно не предполагать, а записывать. Решите, кто может видеть промпты, кто может видеть ответы, кто может открывать сырые логи и кто может экспортировать данные из шлюза. Держите этот список коротким, регулярно пересматривайте его и убирайте доступ, когда меняются роли.
Приватность становится лучше, когда вы храните данные ближе, собираете меньше и ограничиваете круг тех, кто может их смотреть. Она становится хуже, когда логи тихо разрастаются в фоне. Вот и весь компромисс: больше контроля, но и больше ежедневной ответственности.
Как протестировать self-hosted inference до принятия решения
Выберите одну задачу, которая происходит каждый день и имеет понятный критерий успеха. Подойдут черновики ответов для поддержки, тегирование тикетов, короткие резюме документов или ответы для внутреннего поиска. Избегайте слишком широких пилотов вроде «весь трафик ассистента». Нужен один сценарий с известным ежедневным объёмом, примерным размером промптов и целевым временем ответа, которое команда сможет оценить.
Запишите цифры до запуска. Сколько запросов приходит в час? Сколько из них могут подождать две секунды, а сколько должны получить ответ меньше чем за 500 мс? Если после обеда инструментом пользуются 80 человек одновременно, ваш сервер с одной GPU должен пережить этот всплеск, а не просто хорошо выглядеть в полночь.
Запустите одну и ту же нагрузку дважды: в спокойные часы и в самый загруженный час, который вы ожидаете. Эта разница важна. Система, которая кажется быстрой при пяти параллельных запросах, может выглядеть сломанной при тридцати, даже если сама модель остаётся стабильной.
С первого дня отслеживайте небольшой набор метрик: время в очереди, время до первого токена, общее время ответа, качество на фиксированном наборе примеров и стоимость в день, включая электричество и время на поддержку.
Качество нужно проверять по фиксированной схеме, а не по ощущениям. Оставьте 20–50 реальных промптов, оцените ответы и сравните их с тем, что даёт ваш текущий API. Если self-hosted-модель дешевле, но заставляет больше редактировать руками, экономия может исчезнуть уже через неделю.
Специально ломайте по одной вещи за раз. Переполните очередь и посмотрите, что видят пользователи. Завершите процесс модели и проверьте, как быстро он поднимется снова. Отрубите одну зависимость, например шлюз или сервис токенизации, и посмотрите, заканчиваются ли запросы чистой ошибкой или зависают, пока пользователь не обновит страницу.
Сравнение бок о бок важнее, чем многим кажется. Прогоните один и тот же набор промптов через ваш текущий API и через шлюз. Сравните скорость, качество ответов, поведение при отказах и ежедневную стоимость эксплуатации. Используйте для обоих одинаковый формат промпта, иначе тест вас обманет.
Небольшая команда может сделать это за неделю. Один инженер может написать скрипт для прогонки, один продуктовый человек — оценить ответы, а CTO или советник — просмотреть логи с ошибками. Обычно этого достаточно, чтобы понять, подходит ли self-hosted inference на самом деле или это просто интересный лабораторный проект.
Простой пример от небольшой команды
Команда поддержки из восьми человек отправляет сводки тикетов через один шлюз для моделей на сервере с одной GPU. В рабочее время они не просят модель писать длинные отчёты или массово просматривать старые тикеты. Они держат её на коротких задачах: кратко пересказать переписку, предложить ответ и выделить следующий шаг.
Это важно, потому что агентам нужен ответ за несколько секунд, пока клиент ждёт. Если команда смешает живой трафик с большими пакетными задачами в 14:00, очередь быстро вырастет и это почувствуют все. Один сервер может выглядеть нормально при низкой нагрузке, а потом сильно замедлиться, когда несколько агентов одновременно вставят длинные тикеты.
После 18:00 команда меняет режим. Они батчат накопившуюся работу: старые нерешённые тикеты, последующие касания после оценки удовлетворённости и еженедельную очистку тегов. Эти задачи могут подождать по минуте-две на каждую запись, поэтому шлюз может объединять запросы и лучше использовать GPU. Дневной трафик остаётся живым, а вечерний — делает тяжёлую работу.
Менеджеры не добавляют ещё одну модель только потому, что люди просят. Сначала они две недели смотрят на несколько базовых сигналов: длину очереди в пиковые часы, среднее и худшее время ответа по запросу, использование памяти GPU и сбои из-за слишком длинного контекста, а также объём токенов по задачам, чтобы замечать промпты, которые зря съедают мощность.
Так они понимают, нужна ли им ещё одна модель, вторая GPU или просто более короткие промпты. Во многих случаях чистка промптов помогает больше, чем новое железо.
Приватность тоже стала практической причиной, почему они выбрали self-hosting. Их тикеты содержат имена, платёжные заметки, историю аккаунта и иногда споры по возвратам. Хранение этих данных в собственной системе снижает внешнее exposure и упрощает проверку. Но оно не убирает риск полностью. Команде всё равно нужны правила доступа, фильтрация логов, сроки хранения и понятное правило, кто может просматривать промпты и ответы. Один GPU в одном офисе не делает систему приватной автоматически. Всё работает только если команда относится к шлюзу как к любому другому внутреннему сервису, который обрабатывает данные клиентов.
Ошибки, которые рано создают проблемы
Многие команды начинают с самой большой модели, которую только удаётся уместить на карте. Обычно это оборачивается против них. Если задача — ответы поддержки, черновики резюме или лёгкая помощь с кодом, меньшая модель часто ощущается лучше, потому что отвечает быстро и остаётся доступной. На одном GPU модель, которая отвечает за одну секунду, выигрывает у более крупной, из-за которой все ждут по двенадцать секунд.
Шлюз может скрыть эту ошибку, потому что интерфейс выглядит аккуратно, даже если сервер внутри уже задыхается. Чистое демо прячет рост очереди, давление на память и долгие времена прогрева. Модель может выглядеть нормально, когда её тестируют два человека, а потом зависнуть, когда вся команда открывает её после стендапа.
Проектирование очереди
Ещё одна ранняя проблема — смешивать короткие чат-запросы с долгой пакетной работой в одной очереди. Несколько задач по документам, эмбеддинги или большие прогоны промптов могут задерживать интерактивных пользователей на минуты. Люди читают такую задержку как «модель плохая», хотя на самом деле проблема в планировании. Разделите трафик по типу задачи, задайте лимиты по времени и защитите чат-задержку до того, как добавлять новые сценарии.
Логи тоже слишком долго игнорируют. Команды часто ждут, пока пользователи не начнут жаловаться, что ответы стали медленными или пропадают. К тому моменту у вас уже догадки вместо фактов. Начните с базового мониторинга в первый же день: число запросов, время в очереди, токенов в секунду, использование памяти GPU, процент ошибок и процент таймаутов. Большой observability-стек не нужен, но данных должно быть достаточно, чтобы заметить проблему до того, как накопятся обращения в поддержку.
Ошибки с приватностью тише, но живут дольше. Self-hosted inference действительно улучшает приватность, потому что данные остаются на вашем сервере. Но это не значит, что нужно хранить каждый промпт вечно. Полные промпты могут содержать данные клиентов, пароли, которые кто-то случайно вставил, текст контрактов или внутренние планы. Раннее задайте правило хранения, по возможности маскируйте чувствительные поля и решите, кто может читать логи.
Хорошая пятничная демо-сессия почти ничего не доказывает. Настоящая проверка — утро понедельника. Десять человек, которые одновременно задают короткие вопросы, могут сломать систему, которая в тихой комнате выглядела идеальной. Перед тем как переходить на сервер с одной GPU, прогоните нагрузочные тесты с реалистичными размерами промптов, длиной ответов и уровнем параллельности.
Короткая проверка и следующие шаги
Прежде чем кто-то закажет железо, запишите трафик, который вы ожидаете в загруженный час, а не за средний день. Сервер с одной GPU может выглядеть отлично в демо и всё равно захлебнуться, когда одновременно придут несколько длинных промптов.
Начните с чисел, по которым команда сможет себя проверить. Зафиксируйте пиковое число запросов в минуту, самый длинный ожидаемый промпт и то, сколько времени пользователи готовы ждать, прежде чем продукт начнёт казаться медленным.
Приватность требует таких же простых правил. Если в промптах могут быть данные клиентов, сейчас же решите, что может оставаться в логах, что нужно редактировать и кто может читать сырые трассы, когда что-то ломается.
Короткий план пилота обычно достаточен:
- Зафиксируйте пиковую частоту запросов, максимальный размер промпта и ожидаемую длину ответа.
- Настройте правила редактирования для логов, отчётов об ошибках и скриншотов поддержки до первого реального теста.
- Выберите точку остановки для пилота, например p95 задержку, процент таймаутов или качество ответов, которое упадёт ниже согласованного уровня.
- Назначьте ответственных за мониторинг, дежурства, обновления модели и откат, если новая модель начнёт работать хуже.
Команды часто недооценивают скучную работу. Дашборды, алерты, обновления модели, очистка диска и ночные перезапуски требуют времени даже на одном сервере.
Это важно, потому что self-hosted inference может улучшить приватность, но сам по себе не убирает риски. Чувствительный текст всё ещё может утечь через логи, инструменты трассировки, скопированные промпты в чате или дампы после сбоев, если никто не установит жёсткие правила.
Небольшая команда может оставить пилот простым. Запустите одну модель, один шлюз, один дашборд и один путь алертов на неделю под реалистичным трафиком. Если задержка растёт слишком быстро, батчинг перестаёт помогать или пользователи замечают более слабые ответы, остановитесь и пересмотрите решение, прежде чем покупать ещё железо.
Если нужен второй взгляд, Oleg Sotnikov на oleg.is может посмотреть на внедрение как Fractional CTO. Он работает со стартапами и небольшими компаниями над AI-first development, инфраструктурой и практичной автоматизацией, что может оказаться дешевле, чем изучать эти ограничения уже после того, как пользователи столкнутся с ними в продакшене.