Кто виноват? Что делать?(с)
Заметили, что в наше веселое турбулентное время рождения многополярного мира все больше запросов на он-прем деплоймент ЛЛМ — а так как подводных камней там много, а опыта мало — то попробуем разобраться с вопросом.
— Как дела с проектом?
— Мы на финальной стадии!
— Супер, сдаете?
— Нет, ищем виноватого!
Итак — вот пришли к вам с типичными требованиями — хотим все в закрытом периметре. Чтобы Железный Болван болтал с клиентами на их языке, не выходил за периметр корпоративной сети, отвечал только по проверенным бумагам и, едва запахнет сомнением, — тут же переключал на живого оператора. А заодно — связывал воедино все отделы, рисовал отчёты для начальства, конверсию поднял нам до небес, рулил всеми бизнес-процессами, проходил проверки регуляторов и ещё, пожалуйста, уложился бы в фиксированный бюджет с гарантией на несколько лет. И да, демонстрацию можно посмотреть послезавтра?
И тут возникает туман вопросов:
-
А какие открытые ЛЛМ это всё потянут?
-
А по железу чего им надо?
-
А авто-скейлинг как обеспечить?
-
А сколько стоит?
-
А если сломается?
-
А инференс приемлемый как обеспечить на 5000 пользователей?
-
А данные точно не уйдут за периметр?
-
А если нужен голосовой ввод — это вообще другое железо?
-
А лицензия у открытых моделей — без ограничений на коммерцию?
-
А какая команда нужна, чтобы это всё поддерживать?
Поехали
Ну вот давайте разбираться. Первое с чем ассоциируется это все — это конечно GPU. Какие‑то нам надо для этого…
Таак вот это лишь часть всего организма — для начала введём понятие инференс‑узел — это один физический сервер, на котором запущена модель и который обрабатывает запросы к ней. GPU — считает. И вот тут вопрос «что в нём главное?» не имеет одного ответа: важны и вычислительная мощность (терафлопсы), и объём видеопамяти (VRAM) с её пропускной способностью (ГБ/с). Что из этого станет узким местом — зависит от того, что именно модель делает в данный момент. А делает она две разные вещи.
Фаза обработки промпта (prefill). Сюда заходит весь ваш входной текст разом, и GPU обрабатывает все токены одновременно. Веса модели прочитали из VRAM один раз — и тут же прогнали через них тысячи токенов. Вычислений много, чтений памяти относительно мало. На этой фазе GPU реально загружен работой и упирается в вычислительную мощность.
Фаза генерации (decode). А вот ответ рождается принципиально иначе — по одному токену за раз, строго последовательно, потому что каждый следующий токен зависит от предыдущего. И чтобы выдать всего один токен, GPU обязан заново прочитать все веса модели из VRAM (это упрощение — в MoE-архитектуре читается лишь подмножество весов, но суть та же). Получается, что протащить через шину памяти надо весь объём модели, а вычислений при этом — кот наплакал (по сути простое умножение матрицы на вектор). GPU почти всё время просто ждёт, пока приедут данные из памяти. На этой фазе главное — не терафлопсы, а скорость памяти.
То есть по итогу: декодирование выдаёт мало токенов, но времени съедает много, потому что каждый токен — это отдельное полное чтение модели. Префилл наоборот: токенов прогоняет тысячи, а по времени может уложиться в доли секунды.
Рис. 1. Две фазы инференса LLM: prefill упирается в вычисления GPU, decode — в пропускную способность памяти То есть, в зависимости от сценария, большее значение имеет GPU или память:
-
Длинный вход, короткий выход — суммаризация, RAG, разбор кодовой базы. Доминирует prefill, и узким местом становится вычислительная мощность GPU.
-
Короткий вход, длинный выход — обычный чат, генерация текста, объяснения. Доминирует decode, и всё упирается в пропускную способность VRAM.
А самое интересное (для автора по крайней мере) это работа мультиагентных систем — тут что?
Посмотрим, как устроен один шаг агента. Чтобы решить, что делать дальше, модель каждый раз заново прочитывает весь накопленный контекст — системный промпт, историю диалога, содержимое прочитанных файлов, результаты предыдущих вызовов инструментов. А выдаёт на этом шаге немного — вызов инструмента, небольшой патч, пару строк рассуждения. И таких шагов в одной задаче — десятки. То есть на каждый коротенький выход приходится огромный и постоянно растущий вход.
Получается, что агент почти на каждом шаге делает тяжёлый prefill по большому контексту и лёгкий decode. Чем дольше идёт сессия, тем больше распухает контекст — и тем сильнее перекос в сторону обработки промпта. Поэтому агентная кодогенерация по нагрузке ближе к «длинному входу» — и она упирается в вычислительную мощность GPU.
Но — как всегда, есть нюансы. Потому что есть такая вещь как кэширование контекста (KV‑cache, он же prompt caching) — тут подробнее в статье про трансформеры.
Модель прогоняет входные токены через все слои и для каждого токена считает промежуточные представления — те самые key и value, которые потом используются механизмом внимания. Это и есть самая дорогая часть обработки промпта. Ключевое наблюдение: для одного и того же входного текста эти key/value всегда одинаковые. А значит, их можно посчитать один раз и сохранить.
Теперь смотрим на агентный цикл с этой стороны. Между шагами контекст меняется не весь — он дописывается в конец. Системный промпт не меняется никогда. История предыдущих шагов не меняется. Содержимое уже прочитанных файлов не меняется. Добавляется только небольшой хвост: результат последнего вызова инструмента и новое решение модели. Если key/value для всей неизменной части уже лежат в кэше, то на новом шаге заново прогонять через модель надо не весь распухший контекст, а только этот свежий хвост.
И вот тут тяжёлый prefill схлопывается. Вместо «обработать 80 тысяч токенов заново на каждом шаге» получается «достать 80 тысяч из кэша и досчитать только 500 новых». Реально дорогая работа исчезает, и по времени шаг агента снова смещается в сторону decode — то есть упор возвращается на пропускную способность памяти. Именно поэтому prompt caching так радикально ускоряет и удешевляет агентные сценарии: он бьёт точно по их самому дорогому месту — повторной обработке одного и того же раздувшегося контекста.
Получается такая развилка для агентной нагрузки:
Без кэширования — упор в вычислительную мощность GPU. Каждый шаг — это полноценный prefill по всему контексту, и чем дольше сессия, тем тяжелее. С кэшированием — упор обратно в память. Новый prefill маленький, основное время уходит на decode, как в обычном чате.
Но — KV‑cache живёт в той же VRAM, что и веса модели. И вот здесь всплывает второе назначение видеопамяти, про которое обычно забывают: она держит не только веса, но и весь кэшированный контекст всех активных сессий. На длинных контекстах и при нескольких параллельных агентах этот кэш разрастается до десятков гигабайт и может занимать сравнимый с весами объём.
Отсюда практический вывод, который связывает всё воедино. Для агентных систем важны обе характеристики GPU сразу: вычислительная мощность — чтобы переваривать большие prefill (особенно холодные, когда кэша ещё нет), и пропускная способность памяти — потому что с прогретым кэшем нагрузка возвращается к decode. Плюс к этому — достаточный объём VRAM, потому что в неё должны одновременно поместиться и веса модели, и растущий KV‑cache всех сессий. И если для простого чата можно было сказать «берите карту с быстрой памятью», то для агентной кодогенерации правильный ответ — «берите карту, у которой хорошо со всем сразу».
Ну и еще пройдемся по моментам:
-
Связь между картами (интерконнект). Если модель не помещается в одну карту, её разрезают на несколько — и тогда карты вынуждены постоянно обмениваться промежуточными результатами. Скорость этого обмена критична: пока данные ползут от одной карты к другой, остальные простаивают, и выигрыш от нескольких GPU тает на глазах. Вариантов связи два. NVLink — специальная скоростная шина NVIDIA напрямую между картами: ~900 ГБ/с на архитектуре Hopper (H100/H200) и до 1.8 ТБ/с на Blackwell (B200). И обычный PCIe — универсальная шина материнской платы, через которую подключают любые платы расширения, — даёт всего ~64 ГБ/с, то есть примерно в 14 раз медленнее. Разница принципиальная, поэтому многокарточные сборки берут в форм‑факторе SXM (карта монтируется прямо на плату, NVLink встроен), а не из обычных PCIe‑версий.
-
Хранилище (диск). Нужен быстрый накопитель класса NVMe (твердотельный диск, подключённый напрямую к шине PCIe; он в разы быстрее обычных SATA‑дисков). Причина проста: веса крупной модели занимают сотни гигабайт, и на медленном диске их загрузка в память растягивается на минуты. Особенно больно это бьёт при перезапуске и масштабировании — подробнее дальше.
-
Сеть. Когда узлов несколько, обычной гигабитной сети уже не хватает. Даже 10-гигабитный Ethernet становится узким местом, если модель разрезана между серверами: на фазе генерации карты постоянно синхронизируются по сети, и медленный канал резко роняет скорость ответа. Для таких конфигураций берут InfiniBand (сетевую технологию для высокопроизводительных кластеров) или хотя бы Ethernet на 100/200/400 Гбит/с.
-
Питание и охлаждение. Современное GPU‑железо потребляет очень много: одна стойка GB200 NVL72 — порядка 120 кВт. Это уже не «включить в розетку», а отдельная инженерная задача: подвод мощности, её распределение и, как правило, жидкостное охлаждение. Но это мы оставим.
А теперь — про сами видеокарты: какие вообще бывают и кто что тянет (на данный момент):
GPU
VRAM
Bandwidth
NVLink
FP4
TDP
На что годится
L4 / L40S
24 / 48 ГБ
~0.3 / 0.86 ТБ/с
нет (PCIe)
нет
72 / 350 Вт
Мелочь: распознавание речи, эмбеддинги, маленькие модели, один поток
H100 SXM
80 ГБ HBM3
3.35 ТБ/с
NVLink 4 (900 ГБ/с)
нет
700 Вт
Модели до ~70B (70B — уже впритык, нужно 2 карты)
H200 SXM
141 ГБ HBM3e
4.8 ТБ/с
NVLink 4 (900 ГБ/с)
нет
700 Вт
То же ядро, что у H100, но тянет 70–100B+ и длинный контекст на одной карте
B200 SXM
192 ГБ HBM3e
~8 ТБ/с
NVLink 5 (1.8 ТБ/с)
да
1000 Вт
Blackwell: ~4× к H100, FP4, большие модели влезают в одну карту
GB200 NVL72
~13.4 ТБ (на стойку)
8 ТБ/с на GPU
130 ТБ/с
да
~120 кВт/стойка
Целая жидкостная стойка как «один гигантский GPU», ~30× токенов к Hopper
Пара слов про загадочные сокращения в таблице:
-
HBM — особый тип видеопамяти, очень быстрый, припаянный вплотную к чипу (HBM3, HBM3e — поколения).
-
TDP — сколько ватт карта жрёт и, соответственно, во сколько тепла это превращается (отсюда и требования к охлаждению).
-
FP4/FP8 — форматы «ужатых» чисел, про них в следующем разделе; пока достаточно знать, что «да» в этой колонке = карта умеет считать в самом экономном формате.
И сразу — что из этой таблицы реально экономит деньги:
-
H200 — это та же H100, только с памятью побольше. Чип внутри буквально один и тот же, считают одинаково. Вся разница — в памяти: 141 против 80 ГБ и 4.8 против 3.35 ТБ/с. Переплата за H200 окупается ТОЛЬКО там, где вы упёрлись в память. Модель влезает в 80 ГБ и контекст короткий? H200 не нужна. Не влезает или контекст длинный? Тогда H200 избавляет от возни с разрезанием модели на две карты и окупается.
-
Blackwell (B200) — не «H100 побольше», а новое поколение: нативный FP4, вдвое более толстый NVLink, памяти примерно в два раза больше. То, что на H100 требовало 2–3 карт, влезает в одну B200. Минусы — 1000 Вт аппетита и пока сыроватый софт под FP4.
-
L40S и всё, что младше — для чего‑то попроще: распознавание речи, эмбеддинги, мелкие модельки. NVLink у них нет (только PCIe), так что собирать из них связки бессмысленно.
Сколько влезет — считаем VRAM
Мы уже выяснили: в VRAM одновременно живут две вещи — веса модели и KV‑кэш всех активных сессий. Теперь научимся прикидывать, сколько это в гигабайтах, прямо на салфетке. Плюс есть третий жилец — накладные. Разберём по очереди.
Веса модели
Тут всё просто:
Память на веса = число параметров × сколько байт занимает один параметр
Сколько байт на параметр — зависит от того, насколько сильно модель «ужали» (это и есть квантизация):
-
FP16/BF16 — 2 байта. Эталон качества, но прожорливо.
-
FP8 / INT8 — 1 байт. Минус ~50% памяти, качество проседает на 2–5%, обычно незаметно.
-
FP4 / INT4 — 0.5 байта. Минус ~75% памяти, потеря 10–15%.
Прикинем для примера: ~2 ГБ на каждый миллиард параметров в FP16, ~1 ГБ в INT8, ~0.5 ГБ в INT4. Берём модель на 70B: в FP16 это ~140 ГБ только весов (ни в одну карту не лезет!), в INT8 — ~70 ГБ (влезает в H200), в INT4 — ~35 ГБ (влезает даже в одну H100, ещё и с запасом).
KV‑кэш — проблема
Что такое KV‑кэш и почему он раздувается на агентах, мы уже разобрали выше. Здесь — практическая сторона: сколько он занимает и почему за этим важно следить.
Главное, что нужно помнить: кэш считается отдельно для каждого одновременного запроса. Точную формулу вручную обычно не считают — для этого есть готовые калькуляторы (например, apxml/vram‑calculator). Опасность в том, что его аппетит легко недооценить. Типичная ошибка: модель на 35 ГБ помещается в карту на 80 ГБ, и кажется, что памяти с избытком. Но стоит пустить на неё, скажем, 50 пользователей со 100K контекста — и KV‑кэш занимает все оставшиеся 45 ГБ и требует ещё, а приложение падает с ошибкой нехватки памяти (Out of Memory). Частичное решение — квантизация самого кэша (INT8/INT4): на длинных контекстах она заметно экономит память ценой небольшой потери качества.
Накладные расходы
Кроме весов и кэша, видеопамять занимает разная служебная мелочь: сам CUDA‑контекст (~300–500 МБ, его не убрать), рабочие буферы движка (vLLM и PyTorch резервируют место под промежуточные данные), активации при проходе по сети. По отдельности немного, но в сумме стоит закладывать +15–20% поверх весов и KV‑кэша — то есть умножим на 1.2 да и всё.
Рис. 2. Состав видеопамяти GPU: веса модели, KV‑кэш и накладные расходы -
Особенность MoE
Отдельно стоит сказать про модели типа Mixture‑of‑Experts (MoE). Выше я уже отмечал: на каждый токен такая модель задействует только часть весов — поэтому MoE и быстрые. Но с памятью здесь есть неочевидный момент. У MoE‑модели указывают два числа параметров: total (всего) и active (активных). Например, у Qwen 3 235B активных всего 22B; у DeepSeek V4 Pro — 1.6T total при 49B активных; у Kimi K2 — 1T при 32B.
Возникает соблазн оценить память по активным параметрам: «раз активны всего 22B, то и в память поместится как небольшая модель». Очевидно, что нет. Активные параметры определяют скорость, но в памяти должны лежать все веса целиком — потому что для следующего токена может понадобиться любой из экспертов. Те же Qwen 3 235B в FP8 — это около 235 ГБ весов, то есть минимум два‑три GPU, хотя по скорости модель ведёт себя как 22B. Правильный вывод: MoE экономит вычисления, но не память.
Считаем на примере
Сложим всё вместе. Допустим, нужен основной LLM: 70B плотных (не‑MoE) параметров, квантизация INT8, контекст 32K, до 20 одновременных пользователей.
-
Веса: 70B × 1 байт ≈ 70 ГБ
-
KV‑кэш на 32K × 20 запросов ≈ 15–20 ГБ (зависит от архитектуры)
-
Накладные ×1.2 → итого около 105–110 ГБ
Что это значит по железу: одна H100 (80 ГБ) не подходит. Одна H200 (141 ГБ) подходит, ещё и с запасом. Две H100, связанные NVLink, — тоже подходят. Выбор между «одной H200» и «двумя H100» дальше решается ценой и тем, нужен ли вам NVLink под другие задачи.
Сколько потянет — считаем нагрузку
VRAM отвечает на вопрос «влезет ли модель». Скорость одного потока мы тоже уже разобрали — это про decode и пропускную способность памяти. Остаётся последний практический вопрос: как одной картой обслужить много пользователей одновременно, а не одного.
Ключевая техника называется continuous batching (непрерывная пакетная обработка), и её умеет нормальный движок вроде vLLM. Простой подход выглядел бы так: собрали пачку запросов, обработали целиком, отдали, взяли следующую — и в паузах между пачками карта простаивает. Continuous batching (через механизм PagedAttention) работает иначе: запросы подмешиваются в обработку на ходу — пока один дописывает ответ (фаза decode), другой только зашёл и читает свой промпт (фаза prefill). Карта при этом загружена постоянно. По сравнению со старыми движками это даёт выигрыш в 2–4 раза по пропускной способности — поэтому одна карта обслуживает заметно больше пользователей, чем можно предположить по простому расчёту.
Качество обслуживания меряют двумя метриками — по ним же потом и масштабируются. По сути это те же две фазы, что мы разбирали:
-
TTFT (Time To First Token) — сколько пользователь ждёт до первого слова ответа. Определяется фазой prefill: модель должна прочитать и обработать весь промпт.
-
ITL (Inter‑Token Latency) — пауза между словами в уже идущем ответе. Определяется фазой decode и, соответственно, пропускной способностью памяти.
Планируя ёмкость, рассуждайте так: сколько одновременных запросов карта держит при приемлемых TTFT и ITL — столько она и обслужит. Точное число даёт только замер (бенчмарк на вашей модели и вашем профиле запросов), но порядок прикидывается из VRAM (сколько KV‑кэшей в неё поместится) и пропускной способности (хватит ли скорости на всех в пачке). Чем больше одновременных пользователей, тем больше KV‑кэш и тем выше ITL. В какой‑то момент карта насыщается: добавлять запросы ещё можно, но смысла нет — пропускная способность упёрлась в предел, а задержки только растут. Эту точку насыщения и нужно найти: за ней пора добавлять железо.
Разнесение фаз — отдельные узлы под prefill и decode
Мы уже знаем, что инференс состоит из двух фаз с противоположными характерами: prefill (обработка промпта) упирается в вычисления, а decode (генерация ответа) — в пропускную способность памяти. Continuous batching из прошлого раздела гоняет обе фазы на одной и той же карте вперемешку — и здесь прячется неприятный эффект.
Представьте: карта генерирует ответы двадцати пользователям (decode, по вычислениям фаза лёгкая). И тут приходит запрос с промптом на 100K токенов — карте надо прогнать тяжёлый prefill. Пока она этим занята, генерация у всех остальных замирает: их токены не считаются, пауза между словами растёт. Это называется head‑of‑line blocking — один длинный запрос встаёт в начало очереди и тормозит всех. То есть две фазы, живя на одной карте, мешают друг другу: prefill портит ITL чужим decode«ам. И настроить или отмасштабировать их по отдельности тоже не выходит — они склеены.»
Идея разнесения (disaggregation) простая: развести фазы по разным группам карт. Одни узлы занимаются только prefill, другие — только decode. Путь запроса выглядит так:
-
Запрос попадает на prefill‑узел. Тот читает промпт и считает по нему KV‑кэш — это, как мы помним, самая дорогая, вычислительная часть.
-
Готовый KV‑кэш передаётся на decode‑узел.
-
Decode‑узел берёт этот кэш и спокойно генерирует ответ токен за токеном, ничем не прерываясь.
Сверху всем дирижирует роутер: принимает запрос, отправляет на свободный prefill‑узел, запоминает, куда уехал KV‑кэш, и подключает decode‑узел.
Что это даёт:
-
Фазы перестают мешать друг другу. Тяжёлый prefill одного запроса больше не останавливает генерацию у остальных: decode‑узлы заняты только генерацией, prefill‑узлы — только обработкой промптов.
-
Каждую фазу можно масштабировать отдельно. Много длинных промптов и короткие ответы (суммаризация, RAG, разбор кодовой базы) — добавляете prefill‑узлов. Короткие запросы и длинные ответы (обычный чат) — добавляете decode‑узлов. Соотношение пулов подгоняете под свой трафик.
-
Под каждую фазу — своё железо и свои настройки. Prefill любит вычислительную мощность, decode — широкую память. Под фазы можно поставить даже разные карты: под prefill — посильнее в компьютер, под decode — с быстрой и объёмной памятью. Параллелизм и размер батча тоже тюнятся независимо.
-
TTFT и ITL настраиваются по отдельности. Раньше, ускоряя одно, вы неизбежно портили другое — теперь нет.
Важная оговорка — между prefill‑ и decode‑узлом нужно передать KV‑кэш, а это не короткое сообщение, а целый блок памяти (на длинном контексте — гигабайты). Поэтому узлы обязаны быть связаны быстрым каналом: NVLink внутри сервера или InfiniBand/RoCE (то есть RDMA) между серверами. Если канал медленный (обычный Ethernet поверх TCP), передача кэша превращается в бутылочное горлышко — в замерах NVIDIA TTFT без RDMA подскакивает с ~355 мс до 10+ секунд, то есть примерно в 40 раз (документация NVIDIA Dynamo, Disaggregated Serving). Плюс появляется дополнительная обвязка: роутер, слой передачи кэша, координация узлов. Вывод: разнесение оправдано на большом потоке и при быстрой сети; для одной‑двух карт и скромной нагрузки это лишнее усложнение.
Сколько это даёт на практике — цифры из разных источников, чтобы был понятен порядок:
-
DistServe (научная работа, OSDI 2024) — до 7.4× больше запросов при тех же требованиях к задержкам, либо в 12.6× более жёсткие SLO на том же железе.
-
Splitwise (Microsoft) — 2.35× пропускной способности на тех же ресурсах.
-
Mooncake (Moonshot AI, на нём работает Kimi) — около +525% за счёт архитектуры вокруг KV‑кэша.
-
NVIDIA Dynamo — до 30× на DeepSeek‑R1 (стойка GB200 NVL72) и более чем вдвое на Llama 70B (Hopper).
-
llm‑d на AWS — до +70% токенов в секунду по мере роста числа одновременных пользователей.
Разброс большой и сильно зависит от нагрузки, но вывод общий: на подходящем профиле (особенно когда промпты длинные) разнесение даёт кратный, а не процентный выигрыш.
Чем это собирают. Готовых вариантов уже несколько:
-
NVIDIA Dynamo — оркестратор, то есть надстройка, которая управляет пулами prefill/decode поверх обычных движков инференса (vLLM, SGLang, TensorRT‑LLM — это движки, которые гоняют саму модель). Передачу кэша берёт на себя через свою библиотеку NIXL (NVIDIA Inference Transfer Library): она переносит данные из памяти одной карты в память другой, сама выбирая самый быстрый доступный канал — NVLink, InfiniBand и тому подобное
-
llm‑d — решение, родное для Kubernetes. В марте 2026 принято в CNCF Sandbox (CNCF — фонд Cloud Native Computing Foundation, под крылом которого живёт сам Kubernetes и вся экосистема вокруг него; Sandbox — начальная, «инкубаторская» ступень зрелости проекта в этом фонде).
-
vLLM — у самого движка есть встроенный режим разнесения, его так и называют — disaggregated prefilling (буквально «разнесённый prefill»).
Передачу KV‑кэша между узлами во всех случаях вешают на RDMA (Remote Direct Memory Access — технология, позволяющая одной машине напрямую читать и писать память другой по сети, минуя процессор и операционную систему; отсюда и низкие задержки). Поверх RDMA работают транспортные библиотеки — уже упомянутый NIXL или UCX (Unified Communication X, открытый коммуникационный фреймворк родом из мира суперкомпьютеров).
А давайте пример
Теперь соберём всё, о чём говорили, в сквозной пример — вернёмся к тому самому Железному Болвану из начала и доведём его до конкретного железа и моделей. Заказчик условный, любые совпадения случайны: крупный финансовый институт в жёстко регулируемой юрисдикции в одной жаркой стране, где по закону данные клиентов не должны покидать страну.
Что хочет заказчик, если коротко
Нужна не одна модель, а целая платформа под четыре задачи:
-
Поиск по внутренним документам — вопрос‑ответ по политикам, регламентам и инструкциям, обязательно со ссылкой на источник.
-
Поддержка клиентов — ассистент в чате, мессенджере и по телефону (голосом), который умеет переключить разговор на живого оператора, едва засомневается.
-
Помощник продавца — подсказывает менеджеру, какой продукт предложить клиенту, не выходя за рамки комплаенса.
-
«Поговори со своими данными» — аналитик на естественном языке: пользователь спрашивает словами, система сама ходит в хранилище (по сути генерит SQL) и возвращает цифры со ссылкой на источник.
Плюс сквозные требования, которые в итоге и определяют железо:
-
Два рабочих языка — английский и местный, причём местный ещё и с диалектом, который часть моделей знает плохо.
-
Закрытый периметр: внешние облачные API отпадают, модели только open‑weight и только у себя
-
Задержки: текст — меньше 2 секунд, тяжёлый синтез или отчёт — меньше 5, голос — меньше 1.5.
-
Нагрузка: порядка 1000 одновременных текстовых сессий, до 100 голосовых и до 50 параллельных аналитических запросов; режим 24/7.
-
Каждый ответ — с цитатой; всё логируется; агент ходит в данные только с правами того пользователя, который спросил.
Что из этого влияет на выбор
Переведём пожелания в технические следствия — это и есть половина работы архитектора:
-
«Данные не покидают периметр» → on‑prem или суверенное облако плюс open‑weight модели. Внешнего API быть не может.
-
«Местный язык с диалектом» → модель обязана его реально поддерживать. Это сразу вычёркивает часть популярных моделей (ниже на примере).
-
«Голос» → нужна отдельная ASR‑модель (речь в текст) и карты под неё; основной LLM распознаванием речи не занимается.
-
«Поговори с данными» и «помощник продавца» → это агентные задачи: модель должна хорошо вызывать инструменты и рассуждать, а не просто гладко общаться.
-
«Цитаты и привязка к источнику (grounding)» → нужен RAG: модель эмбеддингов плюс векторная база, и тоже внутри периметра.
-
Задержки и нагрузка → собственно расчёт VRAM и пропускной способности из предыдущих разделов.
Модели‑кандидаты и почему именно они
Одной модели на всё не бывает — под разные задачи берут разные, это нормально.
-
Основной LLM (чат, поиск по документам, суммаризация): многоязычная open‑weight модель с длинным контекстом и удобной лицензией. Хороший кандидат — Qwen 3 235B‑A22B: лицензия Apache 2.0 (коммерческое использование без головной боли), сильная многоязычность, длинный контекст, MoE — то есть быстрая (активных всего 22B, хотя в память лезут все 235B, помните засаду с MoE).
-
Reasoning и агент (аналитика, генерация SQL, многошаговые задачи): модель посильнее в рассуждении и вызове инструментов. Кандидат — DeepSeek V4 Pro: лицензия MIT, очень длинный контекст, сильна именно в reasoning и tool‑use — то, что нужно агенту «поговори с данными».
-
Голос (речь в текст): гигант не нужен, нужна лёгкая ASR‑модель (распознавание голоса) с поддержкой нужного языка — класса Whisper или Qwen3-ASR (порядка 1–2B). Запускается на одной‑двух скромных картах.
-
Эмбеддинги для RAG: маленькая многоязычная модель эмбеддингов — её гоняют отдельно, она дешёвая.
-
Агентный «премиум» под вопросом: есть модели вроде Kimi K2 (сильная в агентных сценариях), но у неё не чистый open‑source, а «комьюнити‑лицензия» с порогами по выручке и числу пользователей. Для регулируемого банка это значит — сначала к юристам, потом в продакшен.
И отдельно — кого не взяли и почему. Сильную саму по себе модель легко вычеркнуть из‑за двух вещей: лицензии и языка. Пример: веса закрыты или лежат за заявкой на одобрение, либо в доступных открытых вариантах нужного языка просто нет — и неважно, как хороша модель на бенчмарках, она не подходит. И наоборот: если под ваш язык или диалект есть узкоспециализированная местная модель, держите её в уме — иногда это способ добить качество там, где обобщённые модели плавают.
Как вообще выбирать модель — короткий чек‑лист
Так ну а теперь на что еще смотреть, кроме размера:
-
Лицензия. Apache 2.0 или MIT — берёте и работаете. «Комьюнити»‑лицензия с порогами, gated‑веса (это когда модель вроде бы открытая, но просто так ее не взять — нужна лицензия или заявка на одобрение, потенциально могут отозвать), запрет на коммерцию (например, запрещено использовать модель для создания своих моделей и тд) — желательно выяснить до анализа бенчмарков.
-
Язык и диалект. Тестируйте на своём языке и своих текстах, а не по англоязычному лидерборду. Хорошая в среднем модель часто проваливается на конкретном диалекте.
-
Агентность и вызов инструментов. Если у вас агент (ходит в инструменты, в данные), смотрите именно на умение вызывать функции и держать многошаговый план.
-
Длина контекста. Для RAG и агентов нужен длинный контекст, иначе не влезут документы и история диалога.
-
Мультимодальность. Когда нужно обрабатывать картинки, звук, документы.
-
Рассуждающие модели (reasoning) против задержки. Это модели, обученные сначала «думать вслух» прогонять длинную цепочку промежуточных рассуждений и только потом давать ответ. За счёт этого они сильнее в сложных задачах (математика, логика, анализ), но медленнее и дороже: на размышления уходит много токенов ещё до первого слова ответа. Поэтому: хороши для аналитики, где можно подождать, и плохи для голоса с лимитом 1.5 секунды.
-
MoE против плотной. MoE быстрее при том же размере, но в память лезут все веса (да, повторяюсь).
-
Экосистема. Поддерживается ли модель в vLLM/SGLang, есть ли готовые квантизации (FP8/FP4). Без этого вы долго пилите инфраструктуру вместо запуска.
-
И главное — свой замер. Соберите небольшой набор вопросов с эталонными ответами на ваших данных и прогоняйте на нём кандидатов. Публичные бенчмарки применительно к вашей задаче могут быть неверными. Может нужно модель дообучить под ваши задачи (это, как правило, относится к маленьким моделям — вот тут пример на практике)
Считаем железо и рисуем деплой
Теперь простая арифметика — берём основной LLM — Qwen 3 235B в FP8:
-
Веса: 235B × 1 байт ≈ 235 ГБ. Это сразу несколько карт.
-
KV‑кэш под высокую конкурентность (сотни одновременных сессий, длинный контекст) — ещё десятки гигабайт.
-
С накладными ×1.2 → нужно порядка 300+ ГБ только под основной LLM.
То есть основной LLM — это узел с несколькими картами (скажем, 4–8 × H100/H200 SXM, связанных по NVLink): модель разрезается на куски по всем картам узла, это и называется tensor parallelism. Голосовая модель распознавания речи маленькая — ей хватит одной‑двух L40S. Модель эмбеддингов и переранжирование результатов — тоже на скромных картах. Модель под аналитику (DeepSeek, та, что посильнее в рассуждении) — отдельный многокарточный узел либо тот же пул, если хватает памяти.
Тут важно отметить: это расчёт памяти. Он отвечает только на вопрос «влезет ли модель» и задаёт размер одного пула — но ещё не говорит, сколько пользователей этот пул потянет. Сколько одновременных запросов он держит при нужных задержках — это уже про пропускную способность (об этом ниже), и считается отдельно. Пока запомним так: один пул — это вот такой многокарточный узел, а сколько таких пулов нужно под реальную нагрузку, посчитаем чуть позже.
Пока вменяемая раскладка получается такой:
-
Пул основного LLM: узел из 8 × H100 SXM на NVLink, на нём движок vLLM с разрезанием модели по картам (tensor parallelism). Сверху — механизм автоматического масштабирования: он сам добавляет и убирает копии модели, когда растут очередь запросов и задержки. Готовая связка для этого — KServe и KEDA поверх Kubernetes (Kubernetes — система, которая управляет контейнерами; KServe раздаёт модель, KEDA следит за нагрузкой и командует, когда добавить копию).
-
Голосовой пул: 1–2 карты под распознавание речи. Голос жёстко ограничен по задержке (1.5 с), поэтому его держат отдельно, чтобы тяжёлый текстовый трафик его не тормозил.
-
Слой поиска по документам (RAG): модель эмбеддингов плюс векторная база (Milvus или pgvector) на шифрованном NVMe — внутри периметра.
-
Шлюз и гавернанс: маскирование персональных данных, проверка цитат и политик до выдачи ответа, журнал аудита — на входе и выходе.
-
При высокой одновременной нагрузке — разнесение prefill/decode из прошлого раздела, чтобы длинные запросы не убивали задержку остальным.
А вот где это всё физически стоит — обычно три варианта, и выбор тут уже про деньги, сроки и аппетит регулятора к риску:
-
Полностью on‑prem. Свой дата‑центр, стартовый под из ~8 × H100 (это десятки киловатт и серьёзная электрика). Максимальная защита: данные физически никуда не уходят. Минус — большие капзатраты, долгая поставка GPU и 2–3 человека на эксплуатацию.
-
Гибрид. Чувствительное (голос, персональные данные, индекс по клиентам) — на небольшом on‑prem (хватит 2 × H100 или 4 × L40S), а тяжёлый обезличенный инференс — в суверенном облаке внутри страны. На границе — токенизирующий шлюз: он заменяет персональные данные на обезличенные токены до того, как запрос уйдёт в облако. Обычно это лучший баланс: меньше капзатрат, быстрее старт, периметр соблюдён.
-
Аплайанс под ключ. Готовая коробка (DGX BasePOD, Dell AI Factory) — если своей инфра‑команды нет, но есть деньги. Чуть позже пример
Для регулируемого финансового заказчика на практике чаще всего выигрывает гибрид: сильная защита (сырые данные не покидают периметр), умеренные капзатраты и возможность начать разработку в облачной части, пока on‑prem железо ещё едет. Полный on‑prem берут, когда комитет по рискам не приемлет вообще никакой внешней зависимости — даже суверенной.
Сколько это держит пользователей — и как нам масштабировать
Мы помним что у самой модели нет ни «пользователей», ни «сессий»: она обрабатывает отдельные запросы и между ними ничего не помнит — каждый запрос приходит со своим контекстом целиком. Диалог в приложении для неё — просто череда независимых запросов. Поэтому железо считают не по людям и не по разговорам, а по запросам «в полёте» — сколько запросов модель генерирует прямо сейчас, в один и тот же момент. «5000 сотрудников» не значит «5000 запросов разом»: большинство в любой момент ничего не спрашивает. Нам нужна пиковая одновременная нагрузка — сколько запросов в полёте в худшую минуту дня.
Грубая прикидка по шагам:
-
Сколько всего пользователей. Пусть 5000 внутренних сотрудников.
-
Сколько активны на пике. Для внутреннего инструмента это обычно 10–20% одновременно онлайн — возьмём 15%, то есть около 750 человек. Где‑то натыкался на статистику загрузки колл‑центров, но уже не найду — там примерно такие цифры были.
-
Сколько из них прямо сейчас ждут ответ. Человек читает ответ, думает, печатает — собственно генерация занимает малую долю его времени. Если активный пользователь держит запрос «в полёте» условно 5% времени, то из 750 онлайн одновременно генерируется 30–40 ответов. Даже с запасом втрое — это около сотни одновременных запросов, а не пять тысяч.
-
Сколько держит один пул. Это берётся из замера (раздел «Сколько потянет»): например, узел 8 × H100 при приемлемых задержках тянет N одновременных запросов. Допустим, N ≈ 150.
-
Делим и округляем вверх, добавляя запас на отказ узла: нужно «одновременные ÷ N», округлённое вверх, плюс ещё один пул в резерв.
Получается контринтуитивная вещь: 5000 внутренних сотрудников в режиме обычного чата — это всего около сотни запросов в полёте, то есть один пул основного LLM плюс пул в резерв. Вообще связь между числом людей и железом нелинейная. Большинство «пользователей» в любой момент молчат, поэтому считать по головам бессмысленно — считают по запросам в полёте.
Но важнее самой цифры вот что: одно и то же число людей даёт совершенно разную нагрузку — смотря что они делают. Те же 5000 человек:
-
Обычный чат и поиск по документам: короткие запросы, генерация пара секунд, долгие паузы на чтение. Доля времени «в полёте» мизерная → около сотни одновременных запросов → 1–2 пула.
-
Агенты и аналитика: каждый запрос работает долго — модель гоняет многошаговый план, ходит в данные, выдаёт длинные ответы. Доля «в полёте» подскакивает в разы → уже сотни одновременных запросов → 4–8 пулов на те же 5000 человек.
-
Длинный контекст: раздувает KV‑кэш, и одна карта держит меньше запросов разом (то самое N падает) → пулов нужно больше.
В общем — основные моменты касательно масштабирования:
-
Размножать копии модели вширь. Размер модели задаётся задачей и качеством, число пользователей — числом копий.
-
Масштабироваться под пик автоматически. Поднимать лишние копии в часы нагрузки и гасить в простой (но помните про холодный старт тяжёлых моделей — держите тёплый резерв).
-
Разносить prefill и decode при высокой одновременности — чтобы длинные запросы не съедали задержку остальным.
-
Сжимать, чтобы влезало больше. Квантизация модели в INT4 и квантизация KV‑кэша освобождают память — на одной карте помещается больше одновременных запросов.
-
Кэшировать контекст (prompt caching) для агентов и повторяющихся промптов — снимает основную нагрузку с prefill.
-
Мерить на своём профиле. Внутренний инструмент и публичный чат‑бот дают совершенно разное соотношение «пользователи → одновременность».
DGX SuperPOD — интересный пример
Сразу оговорюсь, лично я не имел возможности попробовать такое — так что это пока теоретические мои выкладки.
У NVIDIA есть такая штука — DGX SuperPOD. Это как бы готовый AI‑суперкомпьютер дата‑центрового масштаба: NVIDIA привозит и собирает целый кластер из множества DGX‑узлов, связанных сверхбыстрой сетью InfiniBand, с общим хранилищем и софтом для управления.
DGX‑узел — это готовый сервер от самой NVIDIA: собранное на заводе шасси, где уже стоят 8 ускорителей, процессоры, внутренний NVLink и сетевые карты (в поколении GB200 «узел» — это и вовсе целая стойка NVL72 на 72 GPU). По сути это тот же инференс‑узел что описан выше, только в фирменной сборке по принципу «всё готово».
Как устроено. Кластер набирается из одинаковых блоков — масштабируемых единиц (scalable unit, SU). В версии на GB200 одна такая единица — это 8 стоек DGX GB200 NVL72, и она потребляет порядка 1.2 мегаватта. Из этих блоков собирают конфигурации до 128 стоек и больше — это тысячи GPU в единой сети. То есть это конструктор. Начинаешь с одного‑двух блоков, а потом доращиваешь кластер, просто пристыковывая новые SU — точно такие же. Растёшь не по одной карте, а готовыми кубиками, и каждый кубик заранее известного размера, мощности и производительности.
Зачем нужно. SuperPOD заточен под две вещи: обучение моделей‑гигантов (тех самых на триллион параметров) и инференс «фабричного» масштаба — когда обслуживаешь не тысячи, а миллионы пользователей или гоняешь фронтирные модели на пределе. То есть другой масштаб.
Что даёт:
-
Масштаб сразу из коробки. Тысячи GPU работают как единый кластер с предсказуемой производительностью — собрать такое самому из россыпи карт почти нереально.
-
Растёт как конструктор. Сеть, хранилище и питание в эталонной схеме заранее рассчитаны на рост, поэтому добавить ещё один блок (SU) — это пристыковать готовый кубик, а не переделывать всю архитектуру.
-
Быстрый старт. Это готовая, проверенная типовая конфигурация: NVIDIA привозит, монтирует, настраивает сеть и софт. Месяцы интеграции превращаются в недели.
-
Сеть без узких мест. InfiniBand устроен так, что любая пара узлов общается на полной скорости; ради этого всё и затевается — иначе на тысячах карт распределённая работа упрётся в сеть.
-
Поддержка и софт в комплекте. Управление кластером, планировщик задач, мониторинг — всё уже собрано и поддерживается вендором.
Минусы:
-
Цена и питание не для среднего бизнеса. Один DGX‑узел на 8 ускорителей стоит порядка $400–500 тыс. (Blackwell‑поколение — ещё дороже), а целый SuperPOD — это десятки миллионов: например, Texas A&M купил SuperPOD на 760 GPU за $45 млн. По питанию — ~1.2 МВт на один блок (SU) по референс‑архитектуре NVIDIA. Нужен отдельный дата‑центр уровня Tier 3 с жидкостным охлаждением, а не серверная комната.
-
Фиксированная конфигурация и долгая поставка. Это типовой дизайн с листом ожидания; гибкость ограничена, срок поставки — кварталы.
-
Привязка к экосистеме NVIDIA. Железо, сеть и софт — всё одного вендора.
Эпилог
Давайте вернёмся к тому, с чего начали. Пришли к вам с требованием — всё в периметре, всё наше, всё работает, и желательно послезавтра.
GPU — это не монолитная «мощь», а баланс двух ресурсов: prefill хочет терафлопсов, decode хочет ширины памяти. Это меняет всё — и то, как считать железо, и то, как оно ведёт себя под нагрузкой. VRAM считается заранее — иначе узнаете про Out Of Memory в самый неподходящий момент.
Одна модель на всё — тоже не работает. Четыре задачи как в примере выше (чат, голос, аналитика, эмбеддинги) — это четыре разных профиля нагрузки с разными требованиями к железу и к самим моделям. Язык и лицензия вычёркивают кандидата быстрее, чем любой бенчмарк. 5000 пользователей — это обычно 50–150 запросов в полёте, а не 5000.
On‑prem LLM это инфраструктурный проект, не просто «скачать и запустить». Нужен инженер по инференсу, стратегия обновлений, мониторинг по TTFT и ITL. Окупается там, где данные нельзя отдавать наружу, где объём делает внешнее API дороже своего железа, или где регулятор просто не оставил выбора.
Корова — ваша. Теперь доите правильно.
ссылка на оригинал статьи https://habr.com/ru/articles/1045608/