Все цифры сняты с работающего стенда: потребление токенов — за календарную неделю по данным шлюза, метрики движка — кумулятивно за период аптайма (11 426 обработанных запросов). Продолжение — про выбор модели по замерам, а не по бенчмаркам — будет отдельной статьёй.
Для кого эта статья
Для тех, кто держит или собирается держать LLM внутри контура: тимлидов, DevOps, архитекторов. Здесь конфиги, цифры и грабли, а не введение в трансформеры.
Что вы унесёте: историю пяти последовательных конфигураций с тем, что каждая дала и чего стоила; рабочий набор флагов vLLM под одну карту Blackwell; три неочевидных бага и обходы; разбор реального счёта с отношением вход/выход 452:1.
Главный вывод, если дальше читать некогда: на агентской нагрузке кэш префикса решает больше, чем выбор модели, размер карты и всё остальное вместе взятое. Мы шли к этому через четыре промежуточных стенда и потратили лишние месяцы, потому что не понимали, что именно меряем.
1. Стенд
|
Параметр |
Значение |
|---|---|
|
GPU |
RTX PRO 6000 Blackwell 96 GB (sm120) |
|
Владение железом |
аренда, 131 000 ₽/мес |
|
Модель |
Qwen3-Coder‑Next‑FP8, 80B MoE / 3B активных, 262K контекста |
|
Движок |
vLLM 0.27.1 в Docker |
|
Шлюз |
LiteLLM 1.95.0 + Postgres |
|
Фронт |
nginx + TLS |
|
Пользователи |
25 подключено, 16 активных (ежедневно, постоянный поток запросов) |
|
TTFT (среднее) |
1.4 с |
|
Профиль нагрузки |
агентский кодинг: 1С/BSL, ReactJS, Java, PHP. Claude Code и Claude Desktop в режиме third‑party |
|
Ограничение |
закрытый контур, код заказчиков не покидает периметр |
Последняя строка — не формальность, а причина существования стенда.
2. Как мы сюда пришли: пять конфигураций
Это не хронология ради хронологии. Каждый переход что‑то ломал, и понятно это становилось только на следующем шаге.
Конфигурация 1. Qwen3 30B, dense, без MoE. Кэширование работало из коробки, стенд вёл себя предсказуемо. Проблема была одна и непреодолимая: на реальных задачах модель не тянула — не замыкала агентский цикл, требовала ручных подталкиваний. Быстро и бесполезно.
Конфигурация 2. Qwen3-Coder‑Next 30B, MoE. Качество выросло, стенд остался живым. Но модель для 24-гигабайтных карт на 96 GB занимала четверть железа — мы гоняли малолитражку в грузовике.
Конфигурация 3. Qwen3-Coder‑Next 80B, MoE. Та же архитектура и tokenizer, вся обвязка перенеслась один в один — переход занял вечер. Качество стало приемлемым. Но кэша для гибридной архитектуры в нашей сборке vLLM не было, а мы этого не знали: работали на общем ключе, без разбивки, и видели только «иногда медленно».
Конфигурация 4. Подключили LiteLLM. Здесь начинается интересное. Шлюз дал разбивку по типам токенов — и стало видно, что запросы читают на порядки больше, чем пишут. До этого у нас была одна цифра «токенов потрачено», из которой не следовало ничего. Диагностика появилась раньше, чем лечение, и это нормальный порядок вещей.
Конфигурация 5. vLLM с поддержкой кэша под нашу архитектуру. --enable-prefix-caching для гибридных моделей не включается автоматически — флаг нужно указывать явно, и до 0.27.1 он для нашей связки не работал вовсе.
|
Метрика |
До |
После |
|---|---|---|
|
Prefix cache hit rate |
0% |
96.9% |
|
Латентность на повторном префиксе |
31.9 с |
0.24 с |
Цифра подтверждается с двух независимых сторон, и это стоит проверять всем: биллинг шлюза считает 96.9% чтения из кэша, а собственные счётчики движка за период аптайма дают 97.3% (1 345 481 136 попаданий на 1 383 053 896 запрошенных токенов). Сходятся — значит меряем одно и то же.
Это не оптимизация на проценты. Это смена режима работы стенда: высвободились и время, и VRAM, и терпение команды.
Что из этой истории следует для читателя: если у вас гибридная или MoE архитектура и вы не видите строку cache read в статистике — вы, скорее всего, платите тридцатикратную латентность и не знаете об этом. Проверять надо не «есть ли кэш в vLLM» (он есть), а «работает ли он для вашей конкретной архитектуры в вашей версии».
3. Экономика: разбор реального трафика
Потребление за календарную неделю:
|
Метрика |
За неделю |
В пересчёте на месяц |
|---|---|---|
|
Input tokens |
993 534 718 |
~4.26 млрд |
|
Cache read tokens |
962 273 296 |
~4.12 млрд |
|
Некэшированный вход |
31 261 422 |
~135 млн |
|
Output tokens |
2 197 078 |
~9.5 млн |
|
Запросов |
8 030 |
~34 800 |
|
Доля попаданий в кэш |
96.9% |
|
|
Отношение вход/выход |
452:1 |
|
В пересчёте на один запрос: ~123 700 токенов входного контекста, из них ~119 800 прочитано из кэша и лишь ~3 900 обработано реально; сгенерировано — 274 токена. Средний шаг агента тащит сто двадцать тысяч токенов и выдаёт двести семьдесят четыре. Нагрузка на 16 активных пользователей — около 500 запросов на человека в неделю, примерно сотня за рабочий день.
Отсюда два практических следствия. Первое: на агентской нагрузке оптимизация чтения контекста важнее скорости генерации — бенчмарки, меряющие tok/s на выходе, описывают 0.2% реального трафика. Второе: сравнивать с облаком надо по фактическому биллингу с учётом кэша, а не по сырому объёму входа — кто считает по сырому, рисует себе выгодную картинку.
С чем вообще корректно сравнивать
Вопрос методологический, и от ответа результат зависит сильнее, чем от любой технической детали. Баз сравнения четыре, и они дают разные ответы.
API, нижняя граница — модель сопоставимого качества. Наша по публичным метрикам агентского кодинга в нижнем‑среднем тире, честное сравнение по качеству даёт самый дешёвый тариф.
API, верхняя граница — модель, которую команда реально использовала бы, не будь стенда. Это средний тир. Сравнивать со старшим мы считаем некорректным: Жигули против Мерседеса.
Подписки — младший и старший тариф. Про них отдельно ниже, потому что там решают не деньги.
Расчёт по опубликованным тарифам, проверено 22.08.2026. Курс берём не биржевой, а платёжный — 88.36 ₽ плюс комиссия платёжных систем, итого 96 ₽ за доллар; разница между двумя курсами и есть первая строка счёта, о которой обычно забывают.
|
Строка |
Объём/мес |
Нижняя граница |
Верхняя граница |
|---|---|---|---|
|
Некэшированный вход |
~135 млн |
$135 |
$271 |
|
Чтение кэша |
~4.17 млрд |
$417 |
$833 |
|
Выход |
~9.5 млн |
$48 |
$95 |
|
Итого в месяц |
|
~$600 (57 600 ₽) |
~$1 200 (115 200 ₽) |
|
Тот же объём без кэша |
4.30 млрд входа |
~$4 350 |
~$8 700 |
Последняя строка поучительнее остальных: без кэширования счёт вырастает примерно в семь раз — и это верно для облака тоже, кэш там стоит 10% от обычного входного тарифа.
Три оговорки, без которых таблица врёт. Наш кэш и облачный — разные механизмы: у нас prefix caching включается флагом и работает на всём подряд, в облаке кэш объявляется явными точками разрыва, имеет TTL и отдельную цену записи, так что 96.9% попаданий туда не переносятся. Тарифы падают — расчёт, сделанный при закупке, к моменту окупаемости может устареть не в вашу пользу. Из РФ прямой биллинг недоступен, наценку реселлера надо закладывать явной строкой; она сдвигает верхнюю границу в паритет с нашей арендой.
Подписка: пятичасовое окно решает больше, чем цена
Тот, кто подписывает счёт, считает не в токенах, а в рублях на человека. Подписочные тарифы с налогом — $24 и $121 в месяц, по курсу 96 это примерно 2 300 ₽ и 11 600 ₽ за место. Наша аренда — 131 000 ₽ независимо от числа людей.
|
Вариант |
На 16 активных |
На 25 подключённых |
Держит нашу нагрузку |
|---|---|---|---|
|
Младшая подписка |
~36 900 ₽ |
~57 600 ₽ |
нет |
|
Старшая подписка |
~185 900 ₽ |
~290 400 ₽ |
да |
|
Наша аренда |
131 000 ₽ |
131 000 ₽ |
да |
Почему первая строка нерабочая. Подписка продаёт не токены, а доступ с лимитами, и лимитов два: недельный и — что менее известно — скользящее пятичасовое окно. Мы пробовали оба тарифа по месяцу, один senior‑разработчик на своих задачах. На младшем лимит пятичасового окна вырабатывался за два — два с половиной часа, дальше человек ждал обновления: примерно четыре продуктивных часа из восьми. На старшем не упирались ни разу.
Экономия младшего тарифа против нашей аренды — около 5 900 ₽ на человека в месяц, то есть 280 ₽ за рабочий день. Платой за эти 280 ₽ становятся два‑три часа простоя разработчика ежедневно. Это не экономия.
Границы замера назовём сами: тестировал один senior, работающий с агентом плотно, — верхняя граница потребления, а не средняя, и разработчик с лёгким профилем в младший тариф, вероятно, уложится. Зато переносимость на команду здесь выше, чем кажется: подписки не делят общий ресурс, лимит у каждого свой, поэтому число пользователей наблюдение не искажает.
Две колонки в таблице — не для красоты. Подписка покупается на человека: платить придётся за всех, кому доступ выдан, а не за тех, кто им сегодня пользуется. Возразить легко — «не выдавайте лишних лицензий», — но заранее неизвестно, кто окажется активным: состав шестнадцати плавает, и подписочная модель требует ежемесячно перетасовывать лицензии вручную, всё равно оставляя риск, что доступа не окажется в нужный момент.
Отсюда самая короткая формулировка всей экономики: каждый следующий пользователь на своём стенде стоит ноль до упора в KV‑пул, на подписке — полную цену места.
Честное возражение против нас самих: можно было раздать старший тариф тяжёлым разработчикам, а младший остальным, и выйти дешевле аренды. Не выбрали по двум причинам, и обе не про деньги — код всё равно уезжает наружу, а администрировать смесь тарифов на 25 человек без централизованного учёта, аудита и отзыва доступа это отдельная работа.
Аренда вместо покупки, и во что она обходится
Сервер мы арендуем. Покупка — это кап. затраты, амортизация и вопрос «за сколько отобьётся»; аренда кап. затрат не создаёт, и понятие срока окупаемости исчезает, остаётся вопрос «что дешевле в этом месяце».
Почему аренда: железо устаревает быстрее, чем амортизируется — требования к VRAM растут быстрее любого разумного срока списания; не нужно замораживать крупную сумму; не нужны стойка, питание, охлаждение и руки, которые это обслуживают. Чего она стоит: платёж не заканчивается никогда — при нашей ставке аренда догоняет стоимость покупки сопоставимой конфигурации примерно за два года; плюс зависимость от арендодателя по SLA и доступу.
Себестоимость. 131 000 ₽/мес. на ~4.31 млрд токенов дают ~30 ₽ за 1M токенов, ~3.8 ₽ за запрос, ~8 200 ₽ в месяц на активного пользователя.
|
Метрика |
Наша аренда |
Младший тир |
Средний тир |
Старший тир |
|---|---|---|---|---|
|
₽ за 1M токенов |
30.4 |
13.4 |
26.7 |
66.8 |
|
₽ за запрос |
3.8 |
1.7 |
3.3 |
8.3 |
Плюс человек, который всё это держит — строка, которую в подобных расчётах обычно опускают, хотя именно она отличает свой стенд от подписки:
|
Работа |
Трудозатраты |
Частота |
|---|---|---|
|
Первичное развёртывание и тесты |
~1 неделя |
разово |
|
Переезд на другую модель с прогоном |
2–3 дня |
по мере смены моделей |
|
Эксплуатация: инциденты, апгрейды, разбор жалоб |
не измеряли |
постоянно |
В деньги не пересчитываем: результат зависит от вашей ставки и от горизонта, на который размазывается разовое внедрение, — на годовом и на двухмесячном цифры отличаются в разы. Третью строку мы честно не мерили; судя по разделу 7, эксплуатация не бесплатна, и «не считали» корректнее нуля. Существенно то, что администрирование не переворачивает ни одну строку сравнения — меняет величины, не знаки.
Итог по деньгам
|
База сравнения |
Итог для аренды |
|---|---|
|
API, младший тир |
проигрыш в 2.3 раза |
|
API, средний тир |
проигрыш ~14% (с наценкой реселлера — паритет) |
|
Подписка, младший тариф |
несравнимо: нагрузку не держит |
|
Подписка, старший тариф |
выигрыш от 30% до 2.2 раз |
По токенам мы проигрываем, по посадочным местам выигрываем. И поскольку аренда фиксирована, а любая альтернатива линейна по числу людей, правильный вопрос звучит не «выгодно ли своё железо», а «с какого числа пользователей оно становится выгодным»: против среднего API‑тира это ~18 активных пользователей, против старшей подписки — 12. У нас 16 активных при 25 подключённых, то есть подписку мы уже обошли, а до API‑тира не хватает двух человек из девяти уже подключённых, но неработающих.
Отдельная ирония: кэширование, которое спасло наш стенд, ровно так же удешевляет облако. Один механизм играет за обе стороны, и главное техническое достижение экономического преимущества не создаёт.
Поэтому вывод, которого мы не планировали: свой инференс берут не за экономию. Берут за то, что кодовая база заказчиков не уезжает к внешнему провайдеру моделей и не попадает в чужие обучающие данные, а доступность инференса не зависит от чужих решений.
Честная оговорка про периметр. Арендованный сервер стоит не у нас, а у хостера: данные не покидают контролируемый нами контур, но физически лежат на чужом железе. Подробности — договор, доступ, шифрование — тема отдельного текста. Здесь ограничимся формулировкой: аренда сужает выигрыш по контуру, но не отменяет его, и считать периметр полностью своим было бы неправдой.
4. Тюнинг: что дало прирост, а что нет
Три находки, которых нет в документации.
VLLM_USE_DEEP_GEMM=0. DeepGEMM падает на sm120 с FP8-чекпоинтами. Симптом — падение при старте, причина неочевидна.
--enable-prefix-caching указывать явно — см. раздел 2. Стократное ускорение на одном флаге.
Занижение --max-model-len не экономит память. Мы держали 131 072 вместо родных 262144, считая, что это освободит VRAM. Не освободило ничего, но вдвое урезало контекст. Плата за полный контекст — меньше параллельных сессий (1.13x против 2.27x), при нашем числе пользователей несущественно.
Оговорка, которую мы поняли позже: рычага --gpu-memory-utilization у нас уже нет — он выставлен в 0.95, поднимать некуда. Если понадобится параллельность, останется только квантование или укорачивание контекста, и это надо учитывать при планировании, а не обнаруживать в момент, когда упёрлись.
KV‑кэш в FP8 (--kv-cache-dtype fp8):
|
Конфигурация |
Размер KV‑пула, токенов |
|---|---|
|
Исходная |
497 000 |
|
|
878 000 |
|
То же на vLLM 0.27.1 |
1 032 910 |
Фактическая конфигурация KV‑кэша, как её сообщает сам движок:
|
Параметр |
Значение |
|---|---|
|
|
1 032 910 |
|
|
3.94 (при |
|
|
989 |
|
|
1072 |
|
|
fp8 |
|
|
0.95 |
|
|
align |
|
|
sha256 |
Скорость генерации 186.5 tok/s.
Про block_size 1072 стоит сказать отдельно. Мы его не задавали — для гибридной архитектуры vLLM вычисляет размер блока сам, отталкиваясь от страницы Mamba‑состояния, и получает величину на два порядка больше привычных шестнадцати. Практическое следствие: гранулярность кэша грубая. На наших контекстах в сто с лишним тысяч токенов это неважно, но на коротких запросах кэш работал бы заметно хуже, чем ожидаешь по документации.
Где на самом деле потолок по числу пользователей. Не в скорости и не в вычислениях: при среднем контексте ~124 000 токенов на запрос и пуле в 1 032 910 токенов одновременно помещается примерно восемь‑девять запросов с полным контекстом. Кэш префикса эту цифру улучшает, потому что общие префиксы делят одни и те же блоки, но насколько — вопрос к нагрузочному тесту, а не к арифметике.
Про кванты под Blackwell — порядок предпочтения оказался обратным интуиции: NVFP4, затем FP8, затем BF16. Замера качества FP8 против BF16 на своих задачах мы не делали, так что это выбор по размеру и скорости, а не по качеству, и честнее назвать его так.
Полный набор флагов:
--max-model-len 262144--kv-cache-dtype fp8--enable-prefix-caching--tool-call-parser qwen3_xml--served-model-name <алиасы>--gpu-memory-utilization <значение>
Латентность в эксплуатации. Здесь важнее не средние, а распределение — и оно объясняет, почему стенд «ощущается быстрым», хотя средний TTFT равен 1.4 секунды.
|
Перцентиль |
TTFT |
Полное время запроса |
Время на токен генерации |
|---|---|---|---|
|
p50 |
0.43 с |
1.3 с |
< 10 мс (> 100 tok/s) |
|
p90 |
0.90 с |
5.0 с |
< 10 мс |
|
p95 |
1.8 с |
9.1 с |
< 10 мс |
|
p99 |
5.9 с |
23 с |
21 мс |
|
максимум |
20–40 с |
120–240 с |
— |
Посчитано по кумулятивным гистограммам движка за весь период аптайма, 11 426 завершённых запросов.
Медиана TTFT втрое ниже среднего — 0.43 против 1.4 секунды. Средняя величина здесь вводит в заблуждение: её тянет вверх хвост из девятнадцати запросов, где первый токен ждали от двадцати до сорока секунд. Это, скорее всего, холодные старты — первые обращения в новой сессии, где префикс ещё не лежит в кэше и контекст в сто с лишним тысяч токенов приходится обрабатывать целиком. Ровно тот сценарий, который до включения кэша был не исключением, а нормой (31.9 с, раздел 2).
Практический вывод для тех, кто будет мерить у себя: публикуйте медиану и перцентили, а не среднее. На агентской нагрузке с кэшем распределение двугорбое — попадание в кэш и промах отличаются на два порядка, и любая средняя величина описывает несуществующего пользователя.
Отдельная мелочь, которую видно только в счётчиках: первых токенов отдано 11 444, а завершённых запросов 11 426. Восемнадцать запросов клиент оборвал после начала генерации — обычное поведение агента, отменяющего ветку.
Есть ли запас по нагрузке. 8 030 запросов за неделю — это в среднем один запрос в 18 секунд по всему стенду; при полном запросе около трёх секунд получается порядка 16% занятости в сорока рабочих часах. Но арифметику можно не защищать: движок ведёт кумулятивную статистику, и она отвечает строго, без сэмплирования и графиков.
Очередь. На 11 426 запросов суммарное время ожидания — 161.6 секунды на все вместе, в среднем 14 миллисекунд; 99.7% запросов не ждали дольше 0.3 с. Хвост назовём честно: два запроса простояли 20–30 секунд, ещё восемь дольше пяти, свыше тридцати — никто.
Батчинг. Число, закрывающее вопрос окончательно: движок сделал 3 023 220 шагов, и 96.5% из них обработали ровно один токен. То есть карта подавляющую часть времени генерирует одиночный поток, батча просто нет. Стенд не «загружен на 16%» — он почти всегда обслуживает один запрос при аппаратной способности обслуживать несколько.
Сходимость. Суммарно движок обработал 39.9 млн токенов при 1.38 млрд запрошенных — ровно остаток после кэша: ~37.5 млн некэшированного входа плюс сгенерированное. Биллинг шлюза, счётчики кэша и счётчики итераций сходятся между собой, и это лучшее подтверждение, что мы меряем то, что думаем.
Потолок стенда, таким образом, не в вычислениях, а в KV‑пуле: около восьми‑девяти одновременных запросов с полным контекстом. И второй эффект, менее очевидный: кэш префикса — общий ресурс, с ростом числа пользователей растёт вытеснение чужих префиксов, так что 96.9% попаданий при пятидесяти активных никто не гарантирует. Это проверяется нагрузочным тестом, а не экстраполяцией.
5. Архитектура
Claude Code CLI ─┐ ├─→ nginx (TLS) ─→ LiteLLM ─→ vLLM ─→ Qwen3-Coder-Next-FP8Claude Desktop ──┘ │ Postgres (ключи, учёт токенов)
Периметр заканчивается на nginx: наружу торчит только он, vLLM и Postgres видны исключительно изнутри. Клиенты — Claude Code в терминале и Claude Desktop в режиме third‑party — ходят по одному адресу и не знают, что за ним стоит.
6. Зачем LiteLLM, если vLLM уже OpenAI‑совместим
Вопрос задают первым, отвечаем сразу: vLLM не умеет отвечать на вопрос «кто сколько потратил и на что».
В нашей истории (раздел 2) шлюз сыграл роль не удобства, а диагностического прибора: пока стенд работал на одном общем ключе, у нас была единственная цифра «токенов потрачено», из которой не следовало ничего. Разбивка по типам токенов показала перекос 452:1 — и только после этого стало понятно, что чинить.
Что ещё даёт:
-
виртуальные ключи по пользователям и учёт в Postgres — на 25 пользователях без этого не понять, кто работает, а кто подключился и забыл
-
сравнительный учёт стоимости: ставки внешних провайдеров прописываются в
model_info -
fallback между инстансами, маршрутизация, централизованный отзыв доступа
Плата — ещё один процесс, который умеет падать. См. раздел 7.
7. Что сломалось
LiteLLM зависает примерно раз в сутки. Причина — блокирующий реконнект Prisma к базе, вешающий event loop; совпадает с известным постмортемом. Лечится вотчдогом: cron дёргает /health/readiness каждые 3 минуты и перезапускает контейнер при отсутствии ответа. Некрасиво, работает.
Лавина 405 от подсчёта токенов. Клиент регулярно дёргает /v1/messages/count_tokens, которого в цепочке нет. Флаг disable_token_counter не помог. Помогла заглушка в nginx, отдающая {"input_tokens":0}.
Model discovery не заработает никогда. vLLM отдаёт список моделей в формате OpenAI, без полей семейства и тира — сопоставлять нечего. Обход только ручным списком. И объявлять надо три модели разных тиров: агентские сценарии внутри себя обращаются к разным тирам, при одном объявленном чат работает, а агент падает на первом фоновом вызове. Алиасы — через --served-model-name.
Стриминг рвётся на TLS. ssl_buffer_size 4k в блоке server, gzip off в location. Диагностика — SSH‑туннель на loopback: если через туннель стрим идёт, а через домен нет, проблема в nginx, а не в модели.
8. Что сделали бы иначе
Поставили бы шлюз с разбивкой по типам токенов первым делом. Это главный урок всей истории: пока была одна цифра «токенов потрачено», мы чинили вслепую и не знали, что кэш не работает. Диагностика стоит дешевле любой оптимизации и должна идти раньше неё.
Брали бы модель под размер карты сразу. Две первые конфигурации ушли на то, чтобы понять очевидное: модель для 24-гигабайтных карт на 96 GB занимает четверть железа.
Фиксировали бы образ по digest, а не по :latest. На стенде, где версия движка решает, работает кэш или нет, плавающий тег — источник необъяснимых изменений поведения.
Снимали бы baseline перед каждой сменой модели. Пять переездов по два‑три дня каждый — это около двух недель инженерного времени, потраченных на поиск вслепую. Зафиксированный протокол сравнения окупился бы уже на третьем.
9. Что дальше: возврат к dense
Следующий эксперимент — Qwen3.8–27B‑FP8, dense, без MoE (~33 GB весов). Заявленный SWE‑bench Pro 61.7 против 44.3 у текущей модели.
Гипотеза, которую проверяем: даёт ли рост качества достаточно, чтобы компенсировать переход с 3B активных параметров на 27B. Ожидаемая просадка — на prefill, а при отношении 452:1 именно prefill и есть наша основная нагрузка.
Круг замыкается: мы начинали с dense‑модели (конфигурация 1) и ушли от неё из‑за качества. Возвращаемся к dense, но на другом уровне качества и с уже работающим кэшем.
Главное, чему нас научили пять переездов: baseline снимается до переключения, а не после. Половины цифр «до» у нас просто нет — именно поэтому история из раздела 2 местами описана прилагательными, а не измерениями. В этот раз сравнение будет по одинаковому протоколу с обеих сторон, и оно станет темой второй статьи.
10. Итог
Три вещи, ради которых стоило писать этот текст.
Кэш префикса важнее всего остального. При отношении вход/выход 452:1 агентская нагрузка почти целиком состоит из перечитывания контекста. Один флаг превратил тридцать секунд ожидания в четверть секунды и высвободил столько ресурса, что вопрос производительности с повестки снялся. Проверьте, работает ли кэш для вашей архитектуры в вашей версии, — «он есть в vLLM» не значит «он работает у вас».
Своё железо не экономит денег — экономит их профиль нагрузки. По цене за токен мы проигрываем облачным API. По цене за посадочное место выигрываем у подписки, и выигрыш растёт с каждым новым пользователем, потому что аренда фиксирована, а подписка линейна. Считайте не «дешевле ли своё», а «с какого числа людей оно становится дешевле» — у нас это двенадцать.
Меряйте раньше, чем оптимизируете. Мы прошли пять конфигураций, прежде чем поняли, что смотрели не на ту метрику. Разбивка по типам токенов стоила одного вечера и объяснила всё, что до этого объяснялось словом «иногда медленно».
ссылка на оригинал статьи https://habr.com/ru/articles/1073300/