Serving: adapter merging, quantization, cost
Merge the adapter into the weights or serve a fleet of LoRAs on one base, GGUF versus AWQ, re-running the eval after quantization — and an honest cost calculation of your own GPU versus an API.
Lesson content is currently available in Russian.
What you will learn
- →Выбирать между merge_and_unload и multi-LoRA-сервингом под свой сценарий.
- →Квантовать модель под инференс (GGUF, AWQ) и перепроверять качество на квантованном артефакте.
- →Считать стоимость самостоятельного сервинга против API из пропускной способности и загрузки.
Мёрж или адаптеры
После обучения у вас база и адаптер на десятки мегабайт. Дальше два пути.
Мёрж: merge_and_unload() вливает поправку B·A прямо в веса — получается обычная standalone-модель без LoRA-зависимостей:
from peft import PeftModel
from transformers import AutoModelForCausalLM
base = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen2.5-7B-Instruct", torch_dtype="bfloat16"
)
merged = PeftModel.from_pretrained(base, "out/adapter").merge_and_unload()
merged.save_pretrained("out/merged")
Плюсы: нулевой оверхед на инференсе, совместимость с любым движком, дальше можно квантовать как обычную модель. Минус: модель фиксируется — обновление адаптера означает новый мёрж и новый деплой.
Критичная деталь: мёржить нужно в полновесную (bf16/fp16) базу. Влить адаптер в 4-битную базу без потерь нельзя — веса уже округлены; порядок всегда «мёрж в bf16 → потом квантизация результата».
Раздельный сервинг: движки вроде vLLM умеют держать одну базу и подключать много LoRA-адаптеров одновременно (--enable-lora), маршрутизируя запросы по имени адаптера. Это выигрывает, когда специалистов много: десять адаптеров по 50 МБ на общей базе против десяти полных копий модели. Цена — небольшой оверхед латентности и привязка к движку с поддержкой LoRA.
Эвристика: один специалист в проде — мёржьте; парк специалистов или мультитенантность — сервите адаптеры раздельно.
Квантизация под инференс
Квантизация обучения (NF4 в QLoRA) и квантизация сервинга — разные вещи с разными форматами. Для инференса выбор диктуется железом.
GGUF (llama.cpp) — формат для CPU, Apple Silicon и малых GPU. Уровни именуются как Q4_K_M, Q5_K_M, Q8_0: для 8B-модели Q4_K_M весит около 5 ГБ и считается сбалансированным дефолтом, Q8_0 — почти без потерь, но вдвое тяжелее. Конвертация — скриптом convert_hf_to_gguf.py из репозитория llama.cpp плюс утилита квантизации.
AWQ и GPTQ — 4-битные форматы для GPU-сервинга под vLLM и другие движки: калибруются на небольшом наборе данных и держат высокую пропускную способность батчевого инференса.
Главное правило: после квантизации ваш eval прогоняется заново на квантованном артефакте. Perplexity, которой любят отчитываться, — слабый прокси: она может почти не сдвинуться, в то время как именно ваш узкий навык — тот самый тюненый формат или точность разбора — просядет заметно. Квантизация срезает «тонкие» веса, а тонкой как раз может оказаться ваша свежеобученная поправка. Сравните win rate fp16 против Q4: просадка на пару пунктов обычно приемлема, двузначная — повод подняться на уровень выше (Q5/Q6 или 8 бит) или пересмотреть формат.
Стоимость: свой GPU против API
Стоимость самостоятельного сервинга считается из трёх чисел: цена GPU-часа, пропускная способность и загрузка.
цена за 1 млн токенов = (цена GPU в час) / (токенов_в_сек × 3600 / 1 000 000)
Пример: L4 или A10G в облаке стоит порядка 0,6–1,2 доллара в час. Квантованная 8B под vLLM с батчингом выдаёт на такой карте порядка 1000–2500 токенов в секунду суммарной пропускной способности. При полной загрузке выходит примерно 0,1–0,3 доллара за миллион выходных токенов — конкурентно с ценами API на модели этого класса.
Ключевое слово — «при полной загрузке». GPU, арендованный на месяц и загруженный на 5%, умножает вашу фактическую цену за токен в двадцать раз, и API становится дешевле при всех его наценках. Отсюда правила:
- Малый или рваный трафик → API или serverless-инференс со scale-to-zero; постоянный GPU не окупится.
- Стабильный высокий трафик → свой GPU с батчингом; следите за метрикой утилизации, а не только за ценой инстанса.
- Средний случай → хостинг тюненых весов у провайдеров (многие сервят кастомные модели с оплатой по токенам) как компромисс без DevOps.
И не забывайте нестоимостные факторы, которые часто и решают: приватность (веса и данные не покидают контур), латентность (малая модель рядом с приложением быстрее фронтирного API) и независимость от чужих ценников и депрекаций.
vLLM в бою и последняя ловушка
Поднять смёрженную модель в vLLM — одна команда:
vllm serve out/merged --max-model-len 8192
# или парк адаптеров поверх общей базы:
vllm serve Qwen/Qwen2.5-7B-Instruct \
--enable-lora \
--lora-modules reviewer=out/adapter
Сервер отдаёт OpenAI-совместимый API: клиентский код с чат-комплишенами работает без изменений, для мульти-LoRA имя адаптера передаётся в поле model.
Последняя ловушка развёртывания — снова chat-шаблон. Движок применяет шаблон из tokenizer_config.json; если при обучении вы кастомизировали шаблон или спецтокены, а в прод уехал дефолтный, получите ту же тихую деградацию, что и в уроке про данные, — только теперь в проде. Смоук-тест обязателен: отправьте на боевой эндпоинт три точных промпта из held-out и сравните ответы с локальной генерацией.
Финальный чек-лист сервинга: мёрж в bf16 → квантизация → повторный eval на артефакте → совпадение chat-шаблона → смоук-тест на боевом эндпоинте → мониторинг латентности и утилизации. После этого модель можно отдавать пользователям.
Practice
Задеплоить и переоценить
Смёржите адаптер в bf16-базу, квантуйте (GGUF Q4_K_M или AWQ), поднимите эндпоинт (llama.cpp или vLLM), прогоните eval из прошлого урока на квантованном артефакте и посчитайте стоимость миллиона токенов для вашего трафика.
Deliverable
Работающий эндпоинт, таблица «fp16 против квант» по вашей метрике, расчёт цены за миллион токенов при реальной загрузке и вывод: свой GPU, serverless или API.
Checkpoint
Обоснуйте свой план сервинга: мёрж или адаптеры, формат квантизации и почему экономика сходится.
- ✓ Выбор мёрж/мульти-LoRA обоснован сценарием: один специалист или парк адаптеров.
- ✓ Eval прогнан заново на квантованном артефакте, а не только на fp16.
- ✓ Стоимость миллиона токенов посчитана из реальной пропускной способности и загрузки.
Check yourself
Sources