Счёт за облачный API растёт, и рано или поздно рядом с ним возникает другая цифра — ценник на сервер. С этого момента вопрос «дешевле ли локальный запуск LLM» выглядит как задача на деление из начальной школы. Арифметика там действительно простая — только не та. Готового ответа не даст и эта статья: вердикт «локально дешевле» — всегда утверждение о конкретной нагрузке, конкретной планке качества и конкретных тарифах. Что здесь можно сделать — собрать модель расчёта, в которую вы подставите свои значения. Что вообще считать стоимостью инференса, мы разбирали в споре «Сколько стоит инференс на реальной нагрузке»; здесь задача уже — сравнить и решить. Но начать придётся с тупика. И вы, скорее всего, в нём уже стояли: сам запрос «сколько стоит локальный запуск» в строке поиска — это первая попытка. Попытка найти готовое число.
Тупик: первым делом ищут готовое число
Первый ход — самый дешёвый из возможных: не считать самому, а найти посчитанное. Чужой разбор в духе «мы ушли из облака и сэкономили», калькулятор на чужом сайте, ответ в профильном чате. Всё уже готово, остаётся перенести вывод на свой счёт.
Не помогает это по устройству, а не потому, что чужие разборы плохи. Вердикт о стоимости — утверждение о трёх вещах сразу: о форме нагрузки (интерактивная она или пакетная), о планке качества (какая модель считается «достаточно хорошей») и о тарифах, по которым выставлен счёт. Все три у вас другие. Автор чужого разбора выровнял очередь планировщиком и получил ровную загрузку — у вас пользователь смотрит на песочные часы. Автор сравнивал с флагманской моделью — у вас планку проходит компактная. Вывод верен для чужого счёта; перенос его на ваш — перенос чужого счёта, в буквальном смысле.
Когда готового не нашлось, пробуют первое собственное вычисление: месячный счёт умножить на горизонт планирования и поделить на ценник сервера. Получается «окупится за столько-то месяцев», и число почти всегда выходит обнадёживающее.
Этот расчёт не помогает по другой причине: он не различает случаи. Счёт выставляется за среднее потребление, железо покупается под пик — ночью и в выходные сервер стоит в смете, но не в деле. Счёт платится за конкретную, как правило самую сильную из пробованных моделей; на ваше железо влезет не она, а то, что влезает. В смете молча отсутствуют электричество, сопровождение, резерв и честный срок списания — и все пропущенные строки смотрят в одну сторону: добавляют стоимости. Наивное деление оптимистично по построению и отвечает «купить» почти всегда. А критерий, который всегда говорит «да», — не критерий: он не отделяет случаи, где локально дешевле, от случаев, где дороже. Принять по нему решение нельзя — можно только получить разрешение на то, что и так хотелось.
Выход из тупика один: построить сравнение, которое различает. Начинается оно с единицы измерения.
Модель расчёта: задача вместо токена
Токен — единица биллинга провайдера, не ваша. Одна и та же работа у разных моделей съедает разное число токенов, поэтому сравнивать цену токена локальной модели с ценой токена облачной — как сравнивать цену топлива у машин с разным расходом. Ваша единица — то, из чего состоит продукт: один запрос, один документ, один обработанный тикет.
Облачная строка: задач в месяц × токенов на задачу × тариф за токен. Объём берите из своей статистики за нормальный период, а не за неделю после запуска фичи; расход на задачу — из статистики провайдера, а не из ощущений. Если вход и выход тарифицируются по-разному — это две подстроки. Если провайдер снижает цену на повторяющийся контекст — отдельная строка: иногда она режет счёт без всякого железа, и это стоит проверить до закупки.
Локальная строка начинается не с цены, а с пропускной способности: сколько задач сервер обязан вытягивать в ваш худший час. Пик берите из логов, а не из памяти — память сглаживает. Подбор конфигурации под эту цифру — отдельное ремесло, у нас для него есть практический разбор «Своё железо под инференс: расчёт на три сценария»; оттуда сюда нужны две вещи — цена конфигурации и срок, за который вы её спишете.
Строки локальной сметы:
- амортизация — цена железа, делённая на срок полезной жизни;
- электричество — потребление под нагрузкой, умноженное на часы работы и на тариф за киловатт-час; офисная стойка вместо серверной — плюс множитель на охлаждение;
- сопровождение — часы инженера в месяц, умноженные на стоимость его часа; разовая настройка идёт отдельной проектной строкой;
- резерв — либо запасная мощность (множитель к первой строке), либо принятый простой — решение, которое надо записать на бумаге.
Самая злая переменная — срок полезной жизни. Железо под инференс устаревает не когда ломается, а когда перестаёт запускать модели, проходящие вашу планку качества. Списывайте до этого момента, не до физической смерти. Заодно исчезает аргумент «железо останется активом»: ускоритель, не тянущий нужные модели, — актив на бумаге.
В ту же модель встаёт аренда выделенных машин: амортизация превращается в часы аренды, умноженные на почасовой тариф, а риск устаревания переходит арендодателю. Дороже в пересчёте на час, дешевле по обязательствам — разумный способ проверить смету, прежде чем подписывать закупку.
Стоимость задачи локально — вся месячная смета, делённая на задач в месяц. Вот её и сравнивают с облачной стоимостью задачи — при одном и том же качестве. Об этом ниже.
Форма нагрузки решает больше, чем объём
Облачная строка растёт с каждой задачей. Локальной всё равно, сколько задач вы успели, пока вы ниже пропускной способности. Вся экономика локального инференса упакована в коэффициент загрузки: задач в месяц, делённые на пропускную способность в час и на часы в месяце.
Отсюда ловушка: железо покупается под пик, а оплачивается по часам. Если нагрузка живёт в рабочие часы, потолок загрузки — это часы, в которые задачи вообще случаются, делённые на все часы месяца; остальное время сервер греет воздух за ваши деньги. Облако в ту же цену неявно продаёт поглощение пиков: вы платите за среднее, максимум остаётся за счёт провайдера.
Дальше развилка, и она главная в этой статье.
Если задачи терпят отложенное выполнение — отчёты, пакетная обработка, всё, на что никто не смотрит в реальном времени, — выровняйте очередь планировщиком. Загрузка подтянется к потолку, и главный аргумент против железа исчезнет сам.
Если задачи интерактивны и пользователь смотрит на песочные часы, ловушка не лечится. Пик остаётся пиком, запас мощности остаётся в смете.
Вот почему два счёта одинакового месячного объёма могут получить противоположные вердикты: одинаковый объём при разной форме — это одна и та же машина с разной загрузкой.
Качество — скрытая строка сметы
Облачный счёт — это счёт за конкретную модель. Фраза «облако дорого» бессмысленна, пока не указано, относительно какого качества дорого. Сравнивать тариф флагмана с тем, что влезает на вашу карту, — подмена, а не сравнение.
Честный порядок такой. Сначала планка качества: ваши задачи и критерии, по которым ответ считается годным. Затем самая дешёвая облачная модель, которая эту планку проходит. Затем самая компактная локальная, проходящая ту же планку, и железо под неё. Сравниваются эти две строки — и только они.
Возможны два сюрприза, оба приятные: самой дешёвой облачной модели хватает — и вопрос закрывается без капекса вообще; локальная модель, проходящая планку, компактнее, чем вы боялись, — и железо выходит дешевле, чем в наивном расчёте.
Возможен и финал другого сорта: ни одна локальная модель на приемлемом железе планку не проходит. Тогда локальный инференс не «дороже» — он недоступен на требуемом качестве. Это другой ответ, и решение будет другим: не «купить», а менять планку, менять задачи или оставаться в облаке.
Позиция редакции
Мы считаем, что вердикт «дешевле ли локально» решается формой нагрузки, а не размером счёта. Ровная или выравниваемая очередь, достижимая планка качества и человек, который возьмёт железо на себя, — при этих условиях локальный инференс выигрывает у облака, как только месячный счёт становится сравним со строкой амортизации.
Интерактивная, пикообразная нагрузка при неопределённом будущем — рациональный дефолт облако. Его эластичность — страховка, уже вшитая в тариф, и бесплатный выход из проекта. У сравнения есть асимметрия во времени: облачная строка следует за объёмом в обе стороны, локальная смета — нет. Рост объёма размазывает её по задачам, падение объёма лишь множит стоимость каждой. И облако стартует в день решения, а закупка — это поставка, сборка, настройка, отладка: если вы отвечаете за сроки, у локального пути есть неявная цена входа, которую никто не вносит в смету.
Наша позиция неверна, если ваши задачи терпят отложенное выполнение. Тогда форму нагрузки можно починить планировщиком, загрузка поднимется к потолку, и решающим станет объём сам по себе: большой ровный объём выигрывает локально даже без всякой интерактивности. Она также неверна там, где данные не могут покинуть периметр: если договоры или требования регулятора запрещают облако, сравнение не нужно — локальный запуск выигрывает по умолчанию, какая бы арифметика ни получилась.
И оговорка против нас самих: расчёт чувствителен к тарифам провайдера. Если за ваш срок списания тариф на нужное качество заметно упадёт, сегодняшняя окупаемость окажется завышенной — капекс не умеет дешеветь вслед за чужим прайсом. Если после всей честной сметы ответ всё ещё «купить» — пересчитайте ещё раз перед подписью: наивное деление из тупика имеет свойство возвращаться на финальных сроках.