Почему обычный рестарт — моветон
Представь: ты сидишь за клавиатурой, тестишь новую фичу RAG, крутишь промпты, а потом понимаешь — для ответов на английском нужна модель поменьше, а для русского — побольше. Ты нажимаешь Ctrl+C, ждёшь, пока сервер освободит порт 8080, запускаешь новый процесс с флагом --model, и наблюдаешь, как загружаются веса. 3 минуты, 5 минут — время утекает, контекст всех диалогов теряется, а коллеги уже смотрят на тебя как на человека, который застрял в 2024 году.
Горячая замена моделей — не роскошь, а необходимость для любого, кто работает с LLM в продакшене или в активной разработке. Проблема стара: каждый раз перезапускать сервер — это как выключать электропитание, чтобы заменить лампочку. В этой статье я покажу, как менять модель за 30 секунд, не теряя ни одного запроса и не убивая процесс.
Важно: инструкция проверена на llama.cpp сборок от начала 2026 года и актуальна на момент публикации. Если вы используете древнюю версию — обновитесь.
Что нам предлагает llama.cpp (и его друзья)
В аргументах llama.cpp я уже разбирал флаги запуска. Так вот, стандартный llama-server (llama-server) позволяет загрузить несколько моделей через слоты (флаг --slots), но их набор фиксирован при старте. Хочешь добавить новую модель — прощай, перезапуск.
На помощь приходит llama-swap — легковесный прокси, который управляет жизненным циклом моделей внутри llama.cpp сервера. Он умеет выгружать неактивные модели из памяти и загружать новые по запросу. При этом сервер не перезапускается, кэш KV сохраняется для активного слота, а время простоя сводится к минутам загрузки весов. В связке с правильной настройкой --threads и --batch-size (читай разбор бага с threads -1) получаешь стабильную производительность даже при переключениях.
Есть и альтернативный путь — использовать нативное API /v1/models с параметром model в каждом запросе, но это требует предзагрузки всех моделей в память, что для 70B моделей на 48GB VRAM — смертельный номер. Поэтому я буду строить решение на основе llama-swap как наиболее практичного инструмента.
Пошаговый план: как сделать hot swap за 30 секунд
Мы будем использовать три сущности:
- back-end: один экземпляр llama-server, запущенный с минимальным набором флагов.
- mid-end: llama-swap, который будет проксировать запросы и управлять слотами.
- front-end: любой клиент (curl, Open WebUI, ваш код).
1 Собираем и запускаем llama-server
git clone https://github.com/ggerganov/llama.cpp.git
cd llama.cpp
make LLAMA_CUDA=1 -j$(nproc)
./llama-server --host 0.0.0.0 --port 8081 --slots 2 --no-mmap
Здесь ключевой момент: --slots 2 даёт нам два слота, но мы не указываем модели при старте. Это позволяет llama-swap управлять ими динамически. Если твоя видеокарта не может удерживать две модели одновременно, оставь один слот — память будет освобождаться при выгрузке.
2 Ставим и настраиваем llama-swap
git clone https://github.com/yourusername/llama-swap.git # или последняя версия из crates.io
cd llama-swap
cargo build --release
./target/release/llama-swap --config config.yaml
Пример конфига config.yaml:
server:
listen: 0.0.0.0
port: 8080
backend: http://localhost:8081
cache_dir: /tmp/llama-swap-cache
models:
- name: llama3.1-8b
path: /models/llama-3.1-8b-instruct.Q4_K_M.gguf
alias: small
- name: qwen2.5-32b
path: /models/qwen2.5-32b-instruct.Q4_K_M.gguf
alias: big
- name: deepseek-coder-6.7b
path: /models/deepseek-coder-6.7b-instruct.Q4_K_M.gguf
alias: code
Обрати внимание: alias — это короткое имя, которое можно передавать в HTTP-заголовке X-Model или как параметр model в теле запроса.
3 Тестируем горячую замену
Отправляем запрос на порт 8080 (llama-swap). Он сам решит, какая модель сейчас активна, и если модель не загружена — загрузит её:
curl http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-H "X-Model: big" \
-d '{"messages":[{"role":"user","content":"Привет!"}]}'
В первый раз подожди 10–30 секунд — загружается модель. Последующие запросы идут мгновенно, потому что модель остаётся в памяти. Если хочешь сменить модель на small, просто меняешь заголовок. При этом предыдущая модель не выгружается — она остаётся в другом слоте (если слотов хватает). Если слот закончился, llama-swap сначала освободит наименее используемый слот, а потом загрузит новую модель.
Но что, если нужно принудительно выгрузить модель и освободить память? Для этого есть API:
curl -X POST http://localhost:8080/slots/0/release
curl -X POST http://localhost:8080/slots/0/load?model=qwen2.5-32b
Комбинация этих двух вызовов даёт те самые 30 секунд на переключение — сервер не перезапускается, все соединения остаются активными.
Грабли, которые я уже собрал
Ошибка 1: Каждый раз при смене модели сбрасывается KV-кэш. Если вы переключаетесь туда-сюда, промпты приходится пересчитывать заново. Проблема повторной обработки больших промптов решается предварительным кэшированием контекста в файл, но это тема отдельной статьи.
Ошибка 2: Неправильные флаги для llama-server. Если не указать --no-mmap, при загрузке новой модели может произойти фатальная ошибка памяти. Всегда используй --no-mmap и --mlock на серверах с большими моделями.
Ошибка 3: Забыть про --slots. Без этого флага llama-server работает в однопоточном режиме и не позволяет менять модели динамически. Мониторы отладки покажут, что слот недоступен.
Ещё один нюанс: если используешь Open WebUI, сравнение движков показывает, что Open WebUI лучше всего дружит с llama-swap через заголовок X-Model. Просто настрой интерфейс на сервер http://localhost:8080 и всё.
Краткий FAQ
| Вопрос | Ответ |
|---|---|
| Можно ли сделать hot swap без llama-swap, только штатными средствами llama.cpp? | Да, через API /v1/models с предзагрузкой всех моделей, но это требует много памяти. Практичнее использовать прокси. |
| Что делать, если модель не влезает в VRAM? | Используй offloading части слоёв на CPU с флагом --n-gpu-layers или подключай вторую видеокарту через RPC-сервер. |
| Как ускорить загрузку модели при смене? | Храни модели на NVMe SSD. Формат GGUF с Q4_K_M даёт баланс скорости и качества. Используй --no-mmap для быстрого отображения файлов. |
| Пропадают ли активные соединения при смене модели? | Нет, если ты используешь llama-swap со слотами. Он перенаправляет запросы на активный слот, а не убивает соединение. |
| А что, если нужно одновременно держать две модели в памяти? | Просто увеличь количество слотов (--slots 2) и убедись, что суммарная память обеих моделей укладывается в VRAM. Иначе возможны OOM-крахи. |
На этом всё. Hot swap — не магия, а правильная утилизация слотов и прокси. Если у тебя остались вопросы, пиши в комментарии — я или другие читатели помогут. А чтобы не пропускать новые гайды, подписывайся на блог.