Кто виноват? Что делать?(с)

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

— Как дела с проектом?
— Мы на финальной стадии!
— Супер, сдаете?
— Нет, ищем виноватого!

Итак — вот пришли к вам с типичными требованиями — хотим все в закрытом периметре. Чтобы Железный Болван болтал с клиентами на их языке, не выходил за периметр корпоративной сети, отвечал только по проверенным бумагам и, едва запахнет сомнением, — тут же переключал на живого оператора. А заодно — связывал воедино все отделы, рисовал отчёты для начальства, конверсию поднял нам до небес, рулил всеми бизнес-процессами, проходил проверки регуляторов и ещё, пожалуйста, уложился бы в фиксированный бюджет с гарантией на несколько лет. И да, демонстрацию можно посмотреть послезавтра?

И тут возникает туман вопросов:

  • А какие открытые ЛЛМ это всё потянут?

  • А по железу чего им надо?

  • А авто-скейлинг как обеспечить?

  • А сколько стоит?

  • А если сломается?

  • А инференс приемлемый как обеспечить на 5000 пользователей?

  • А данные точно не уйдут за периметр?

  • А если нужен голосовой ввод — это вообще другое железо?

  • А лицензия у открытых моделей — без ограничений на коммерцию?

  • А какая команда нужна, чтобы это всё поддерживать?

    Поехали

    Ну вот давайте разбираться. Первое с чем ассоциируется это все — это конечно GPU. Какие‑то нам надо для этого…

    Таак вот это лишь часть всего организма — для начала введём понятие инференс‑узел — это один физический сервер, на котором запущена модель и который обрабатывает запросы к ней. GPU — считает. И вот тут вопрос «что в нём главное?» не имеет одного ответа: важны и вычислительная мощность (терафлопсы), и объём видеопамяти (VRAM) с её пропускной способностью (ГБ/с). Что из этого станет узким местом — зависит от того, что именно модель делает в данный момент. А делает она две разные вещи.

    Фаза обработки промпта (prefill). Сюда заходит весь ваш входной текст разом, и GPU обрабатывает все токены одновременно. Веса модели прочитали из VRAM один раз — и тут же прогнали через них тысячи токенов. Вычислений много, чтений памяти относительно мало. На этой фазе GPU реально загружен работой и упирается в вычислительную мощность.

    Фаза генерации (decode). А вот ответ рождается принципиально иначе — по одному токену за раз, строго последовательно, потому что каждый следующий токен зависит от предыдущего. И чтобы выдать всего один токен, GPU обязан заново прочитать все веса модели из VRAM (это упрощение — в MoE-архитектуре читается лишь подмножество весов, но суть та же). Получается, что протащить через шину памяти надо весь объём модели, а вычислений при этом — кот наплакал (по сути простое умножение матрицы на вектор). GPU почти всё время просто ждёт, пока приедут данные из памяти. На этой фазе главное — не терафлопсы, а скорость памяти.

    То есть по итогу: декодирование выдаёт мало токенов, но времени съедает много, потому что каждый токен — это отдельное полное чтение модели. Префилл наоборот: токенов прогоняет тысячи, а по времени может уложиться в доли секунды.

    Рис. 1. Две фазы инференса LLM: prefill упирается в вычисления GPU, decode — в пропускную способность памяти
    Рис. 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-кэш и накладные расходы
    Рис. 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. Путь запроса выглядит так:

  1. Запрос попадает на prefill‑узел. Тот читает промпт и считает по нему KV‑кэш — это, как мы помним, самая дорогая, вычислительная часть.

  2. Готовый KV‑кэш передаётся на decode‑узел.

  3. 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% токенов в секунду по мере роста числа одновременных пользователей.

Разброс большой и сильно зависит от нагрузки, но вывод общий: на подходящем профиле (особенно когда промпты длинные) разнесение даёт кратный, а не процентный выигрыш.

Рис. 3. Архитектура disaggregated serving: prefill и decode на разных узлах
Рис. 3. Архитектура disaggregated serving: prefill и decode на разных узлах

Чем это собирают. Готовых вариантов уже несколько:

  • 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 из прошлого раздела, чтобы длинные запросы не убивали задержку остальным.

Рис. 4. Архитектура платформы для финансового заказчика: пулы моделей, шлюз и RAG-слой
Рис. 4. Архитектура платформы для финансового заказчика: пулы моделей, шлюз и RAG‑слой

А вот где это всё физически стоит — обычно три варианта, и выбор тут уже про деньги, сроки и аппетит регулятора к риску:

  • Полностью on‑prem. Свой дата‑центр, стартовый под из ~8 × H100 (это десятки киловатт и серьёзная электрика). Максимальная защита: данные физически никуда не уходят. Минус — большие капзатраты, долгая поставка GPU и 2–3 человека на эксплуатацию.

  • Гибрид. Чувствительное (голос, персональные данные, индекс по клиентам) — на небольшом on‑prem (хватит 2 × H100 или 4 × L40S), а тяжёлый обезличенный инференс — в суверенном облаке внутри страны. На границе — токенизирующий шлюз: он заменяет персональные данные на обезличенные токены до того, как запрос уйдёт в облако. Обычно это лучший баланс: меньше капзатрат, быстрее старт, периметр соблюдён.

  • Аплайанс под ключ. Готовая коробка (DGX BasePOD, Dell AI Factory) — если своей инфра‑команды нет, но есть деньги. Чуть позже пример

Для регулируемого финансового заказчика на практике чаще всего выигрывает гибрид: сильная защита (сырые данные не покидают периметр), умеренные капзатраты и возможность начать разработку в облачной части, пока on‑prem железо ещё едет. Полный on‑prem берут, когда комитет по рискам не приемлет вообще никакой внешней зависимости — даже суверенной.

Сколько это держит пользователей — и как нам масштабировать

Мы помним что у самой модели нет ни «пользователей», ни «сессий»: она обрабатывает отдельные запросы и между ними ничего не помнит — каждый запрос приходит со своим контекстом целиком. Диалог в приложении для неё — просто череда независимых запросов. Поэтому железо считают не по людям и не по разговорам, а по запросам «в полёте» — сколько запросов модель генерирует прямо сейчас, в один и тот же момент. «5000 сотрудников» не значит «5000 запросов разом»: большинство в любой момент ничего не спрашивает. Нам нужна пиковая одновременная нагрузка — сколько запросов в полёте в худшую минуту дня.

Грубая прикидка по шагам:

  1. Сколько всего пользователей. Пусть 5000 внутренних сотрудников.

  2. Сколько активны на пике. Для внутреннего инструмента это обычно 10–20% одновременно онлайн — возьмём 15%, то есть около 750 человек. Где‑то натыкался на статистику загрузки колл‑центров, но уже не найду — там примерно такие цифры были.

  3. Сколько из них прямо сейчас ждут ответ. Человек читает ответ, думает, печатает — собственно генерация занимает малую долю его времени. Если активный пользователь держит запрос «в полёте» условно 5% времени, то из 750 онлайн одновременно генерируется 30–40 ответов. Даже с запасом втрое — это около сотни одновременных запросов, а не пять тысяч.

  4. Сколько держит один пул. Это берётся из замера (раздел «Сколько потянет»): например, узел 8 × H100 при приемлемых задержках тянет N одновременных запросов. Допустим, N ≈ 150.

  5. Делим и округляем вверх, добавляя запас на отказ узла: нужно «одновременные ÷ 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 заточен под две вещи: обучение моделей‑гигантов (тех самых на триллион параметров) и инференс «фабричного» масштаба — когда обслуживаешь не тысячи, а миллионы пользователей или гоняешь фронтирные модели на пределе. То есть другой масштаб.

Рис. 5. Архитектура DGX SuperPOD: масштабируемые единицы (SU), InfiniBand-фабрика и общее хранилище
Рис. 5. Архитектура DGX SuperPOD: масштабируемые единицы (SU), InfiniBand‑фабрика и общее хранилище

Что даёт:

  • Масштаб сразу из коробки. Тысячи 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 дороже своего железа, или где регулятор просто не оставил выбора.

Корова — ваша. Теперь доите правильно.

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


  1. vasvas788
    09.06.2026 15:59

    Можно просто купить сервак с буквально ЛЮБОЙ локальной ллмкой. Яндех уже такие продает