# llama.cpp или vLLM: что выбрать для локального инференса LLM

> AI Release · @ai_release1 · https://ai-release.org/guides/llama-cpp-ili-vllm-chto-vybrat-dlya-lokalnogo-inferensa.html

## TL;DR

- **Время выполнения:** 30–40 минут (плюс время на скачивание весов модели).
- **Уровень сложности:** Intermediate.
- **Понадобится:** Linux (Ubuntu 22.04+ или WSL2), NVIDIA GPU + драйвер (`nvidia-smi` в PATH), Python 3 (версию, поддерживаемую vLLM, сверьте с документацией), `cmake` и компилятор C++ для сборки llama.cpp, `curl`, файл модели в формате GGUF (для llama.cpp) или веса в формате Hugging Face safetensors (для vLLM).

## Требования и подготовка
![Иллюстрация к разделу «Требования и подготовка»](https://ai-release.org/guides/img/llama-cpp-ili-vllm-chto-vybrat-dlya-lokalnogo-inferensa-ru-1.jpg)


- **ОС и железо.** llama.cpp работает на CPU и на GPU, vLLM требует NVIDIA GPU с поддержкой CUDA. Проверьте видеокарту и драйвер.
- **Права.** Нужна возможность ставить системные пакеты (`sudo`) и создавать виртуальное окружение Python.
- **Свободное место.** Не меньше размера файла модели плюс запас на кэш; точный объём смотрите в карточке конкретной модели.
- **Сеть.** Доступ к репозиториям пакетов и к источнику весов модели.
- **Уточните по документации:** актуальные версии llama.cpp и vLLM, поддерживаемые версии Python и CUDA — они меняются, в этом гайде конкретные номера версий намеренно не фиксируются.

Проверка базы:

```bash
nvidia-smi
df -h .
python3 --version
cmake --version
```

**Пример:** `nvidia-smi` печатает таблицу с именем GPU, объёмом памяти и версией драйвера. Если команда не найдена или таблица пустая — GPU не проброшен, дальше идти нет смысла: у vLLM нет CPU-режима.

Если вы ещё выбираете железо под локальный инференс (в том числе мини-ПК с NPU), начните с материала [Что такое NPU и как выбрать мини-ПК для локального запуска ИИ](https://ai-release.org/guides/chto-takoe-npu-i-kak-vybrat-mini-pk-dlya-lokalnogo-zapu.html?utm_source=tg&utm_medium=channel&utm_campaign=guide_inline&utm_content=guide_to_guide) — там разобрано, какой класс устройств под какие задачи подходит.

## Шаг 1. Определите сценарий и выберите движок
![Иллюстрация к разделу «Шаг 1. Определите сценарий и выберите движок»](https://ai-release.org/guides/img/llama-cpp-ili-vllm-chto-vybrat-dlya-lokalnogo-inferensa-ru-2.jpg)


**Что сделать:** ответьте на четыре вопроса и сверьте ответ с таблицей ниже. Это отсекает половину проблем ещё до установки.

1. Сколько запросов одновременно? Один разработчик → llama.cpp; десятки параллельных → vLLM.
2. Какое железо? Только CPU или слабая GPU → llama.cpp; нормальная NVIDIA GPU → оба варианта.
3. Какие веса есть на диске? GGUF → llama.cpp; safetensors из Hugging Face → vLLM (llama.cpp их напрямую не грузит).
4. Нужен ли OpenAI-совместимый HTTP API? Оба движка его отдают, но разными бинарниками и на разных портах по умолчанию.

**Зачем:** движки оптимизированы под разные профили нагрузки. llama.cpp — компактный C++-движок, удобный для одиночных запросов и квантованных GGUF-весов. vLLM — серверный движок на Python с PagedAttention (механизм управления памятью под KV-кэш — кэш состояний внимания, который растёт с длиной контекста) и непрерывным батчингом: он держит много запросов в одном проходе по GPU.

| Критерий | llama.cpp | vLLM |
|---|---|---|
| Формат весов | GGUF, в т.ч. квантованные | safetensors (Hugging Face) |
| Железо | CPU, GPU, Apple Silicon | NVIDIA GPU |
| Профиль нагрузки | 1–2 пользователя, локальный чат, встраивание в приложение | Много параллельных запросов, сервис |
| HTTP API | `llama-server` (OpenAI-совместимый) | `vllm serve` (OpenAI-совместимый) |
| Порт по умолчанию | 8080 | 8000 |
| Установка | сборка через CMake | `pip install vllm` |

**Как проверить:** заполните чек-лист — если хотя бы один пункт в правой колонке отмечен, берите vLLM.

- [ ] Нужно обслуживать больше 2 одновременных запросов
- [ ] Веса есть только в safetensors
- [ ] Нужен непрерывный батчинг под нагрузкой
- [ ] GPU NVIDIA с достаточным объёмом памяти под веса целиком

**Пример:** стажёр поднимает локальную модель, чтобы подключить её к редактору кода как персонального ассистента — один пользователь, GGUF-файл на диске, ноутбук с дискретной GPU. По таблице выигрывает llama.cpp.

## Шаг 2. Соберите и запустите выбранный движок

**Что сделать:** поднимите сервер того движка, который выбрали на шаге 1. Оба поднимают HTTP-сервер с OpenAI-совместимым API, поэтому клиентская часть потом не меняется — меняется только порт.

**Зачем:** именно серверный режим (а не интерактивный чат в терминале) даёт endpoint `/v1/chat/completions`, к которому подключаются сторонние клиенты.

### Вариант A. llama.cpp

```bash
cmake -B build -DGGML_CUDA=ON
cmake --build build --config Release -j
./build/bin/llama-server \
  --model ./models/<имя-модели>.gguf \
  --host 0.0.0.0 --port 8080 \
  -ngl 99 -c 8192
```

`-ngl 99` означает «выгрузить на GPU все слои» (число слоёв больше реального = все), `-c 8192` задаёт размер контекста в токенах (токен — кусочек слова, единица, которой модель считает текст). Флаг `-DGGML_CUDA=ON` включает CUDA-сборку — без него движок соберётся под CPU и будет медленным.

**Пример:** адрес репозитория и актуальный список флагов сборки сверьте с документацией проекта — набор CMake-опций между релизами меняется.

### Вариант B. vLLM

```bash
python3 -m venv .venv
source .venv/bin/activate
pip install vllm
vllm serve <org>/<модель> \
  --host 0.0.0.0 --port 8000 \
  --gpu-memory-utilization 0.90 \
  --max-model-len 8192
```

`--gpu-memory-utilization 0.90` разрешает движку занять до 90% памяти GPU под веса и KV-кэш; `--max-model-len` ограничивает длину контекста, чтобы кэш не съел всю память.

**Как проверить:** сервер должен ответить списком моделей. Для llama.cpp:

```bash
curl -s http://localhost:8080/v1/models
```

Для vLLM:

```bash
curl -s http://localhost:8000/v1/models
```

**Пример ожидаемого вывода:** JSON вида `{"object":"list","data":[{"id":"<имя-модели>", ...}]}`. Если `data` пустой или соединение отклонено — сервер не поднялся, смотрите его лог в терминале.

## Шаг 3. Проверьте генерацию и снимите свой замер
![Иллюстрация к разделу «Шаг 3. Проверьте генерацию и снимите свой замер»](https://ai-release.org/guides/img/llama-cpp-ili-vllm-chto-vybrat-dlya-lokalnogo-inferensa-ru-3.jpg)


**Что сделать:** отправьте реальный запрос на генерацию и измерьте время и число выданных токенов.

**Зачем:** `/v1/models` подтверждает только то, что процесс жив. Генерация проверяет весь тракт: загрузку весов, токенизатор, выделение памяти под KV-кэш и работу сэмплера.

```bash
curl -s http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "<имя-модели>",
    "messages": [{"role": "user", "content": "Перечисли три способа проверить связь с сервером."}],
    "max_tokens": 128,
    "temperature": 0.2
  }'
```

Для vLLM та же команда, но порт `8000`; в поле `model` подставьте идентификатор из ответа `/v1/models`.

**Как проверить:** в ответе есть `choices[0].message.content` с текстом и блок `usage` с полями `prompt_tokens`, `completion_tokens`, `total_tokens`. Зафиксируйте свой замер:

```bash
time curl -s http://localhost:8000/v1/chat/completions -H "Content-Type: application/json" -d @request.json
```

**Пример:** `usage.completion_tokens` = 96, `time` показывает `real 0m2,4s` — это ваши собственные цифры для вашей карты и модели. Готовых цифр в гайде нет специально: они зависят от GPU, квантования и длины контекста, поэтому корректно сравнивать только два движка на одной машине и одной модели.

Дальше сервер можно подключать к клиентам: пошаговая схема подключения локальной модели к Claude Code разобрана в [Как подключить локальную модель к Claude Code: llama-server, OpenAI-совместимый API и лаунчер](https://ai-release.org/guides/kak-podklyuchit-lokalnuyu-model-k-claude-code-llama-ser.html?utm_source=tg&utm_medium=channel&utm_campaign=guide_inline&utm_content=guide_to_guide) — там показано, как прописать базовый URL и имя модели в конфиге.

## Возможные проблемы и решения

**Проблема. vLLM падает при старте, GPU-память занята.** Симптом: процесс завершается через несколько секунд после загрузки весов.
- Ошибка: `torch.OutOfMemoryError: CUDA out of memory. Tried to allocate ...`
- Причина: веса плюс KV-кэш не влезают в память при заданном `--gpu-memory-utilization` и `--max-model-len`, либо на карте висят другие процессы.
- Решение: проверьте занятость (`nvidia-smi`), остановите лишние процессы, затем снизьте лимиты: `vllm serve <org>/<модель> --gpu-memory-utilization 0.80 --max-model-len 4096`. Если не помогает — нужна модель меньшего размера или квантизация.

**Проблема. llama.cpp не грузит файл модели.**
- Ошибка: `error: unable to load model from file: ./models/<имя-модели>.gguf`
- Причина: неверный путь, файл докачался не полностью или это не GGUF (например, safetensors из Hugging Face — llama.cpp такой формат напрямую не читает).
- Решение: проверьте путь и целостность файла, затем перезапустите с абсолютным путём: `./build/bin/llama-server --model "$(pwd)/models/<имя-модели>.gguf" --port 8080`. Если файл в safetensors — конвертируйте его в GGUF скриптом из репозитория llama.cpp (актуальную команду сверьте с документацией) либо используйте vLLM.

**Проблема. Клиент не видит сервер.** Симптом: запрос из скрипта падает мгновенно.
- Ошибка: `curl: (7) Failed to connect to localhost port 8000 after 0 ms: Couldn't connect to server`
- Причина: перепутан порт (llama.cpp по умолчанию 8080, vLLM — 8000) или сервер слушает только `127.0.0.1`, а клиент обращается с другой машины.
- Решение: сверьте порт в команде запуска и убедитесь, что указан `--host 0.0.0.0`. Проверка: `curl -s http://<ip-сервера>:8000/v1/models` (для llama.cpp — `:8080`).

## Резюме и следующие шаги

Выберите llama.cpp для одиночных запросов, CPU и GGUF-весов, а vLLM — для сервиса с параллельными запросами на NVIDIA GPU; клиентский код при этом одинаковый, меняется только порт. Следующий шаг — подключить поднятый endpoint к рабочему клиенту и снять собственный замер на вашей модели.

## FAQ

**llama.cpp или vLLM — что быстрее?**
На одиночном запросе разница зависит от квантования и карты; на потоке параллельных запросов vLLM выигрывает за счёт непрерывного батчинга. Корректно сравнивать только на одной машине, одной модели и одинаковой длине контекста — снимите замер по Шагу 3.

**Можно ли запустить vLLM без GPU?**
Нет, vLLM рассчитан на NVIDIA GPU с CUDA. Для CPU-инференса берите llama.cpp.

**Загрузит ли llama.cpp модель в формате safetensors?**
Напрямую — нет, нужен формат GGUF. Конвертация выполняется скриптом из репозитория llama.cpp; актуальную команду сверьте с документацией проекта.

**Почему curl возвращает ошибку соединения, хотя сервер запущен?**
Почти всегда несовпадение порта: llama.cpp слушает 8080, vLLM — 8000. Плюс проверьте `--host 0.0.0.0`, если обращаетесь не с localhost.
