Skip to content

Инструкция по работе с Llama.cpp

Notifications You must be signed in to change notification settings

dubr1k/llamacpp_guide

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 

Repository files navigation

Полное руководство по llama.cpp: от компиляции до тонкой настройки

Содержание

  1. Установка или сборка проекта
  2. Скачивание моделей
  3. Формат GGUF и квантование
  4. Ключевые флаги запуска
  5. System Prompt (Системный промпт)
  6. Структурированный вывод (JSON/GBNF)
  7. llama-cli: консольный режим
  8. llama-server: API-сервис
  9. Диагностика и мониторинг
  10. Шаблоны команд
  11. Решение типичных проблем
  12. Полезные ссылки

llama.cpp — легковесный движок для инференса LLM, написанный на C++. Позволяет запускать модели в формате GGUF (стандартный формат квантованных моделей), используя CPU (инструкции AVX/AVX512) и GPU (CUDA, Metal, Vulkan). Поддерживаются модели семейств LLaMA, Mistral, Qwen2, Qwen2Moe, Phi3, Bloom, Falcon, StableLM, GPT2, Starcoder2, T5, Mamba, Nemotron, Qwen3, Vistral.


1. Установка или сборка проекта

Установка готового решения

Способ установки Windows Mac Linux
Winget
Homebrew

Winget (Windows)

winget install llama.cpp

Пакет автоматически обновляется с выходом новых версий llama.cpp.

Homebrew (Mac и Linux)

brew install llama.cpp

Пакет автоматически обновляется с выходом новых версий llama.cpp.

Сборка проекта (актуально для ОС на базе Linux, для активации работы c GPU)

Клонирование репозитория

git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp

Варианты сборки

Платформа Команда
NVIDIA (CUDA) cmake -B build -DGGML_CUDA=ON && cmake --build build --config Release
CPU-only cmake -B build && cmake --build build --config Release
Apple Silicon (Metal) Ускорение включено по умолчанию при обычной сборке

После сборки исполняемые файлы находятся в директории build/bin/.

Подробности сборки для каждой платформы

NVIDIA (CUDA): Убедитесь, что установлен CUDA Toolkit. Версия CUDA должна соответствовать вашей видеокарте. После сборки проверьте наличие строки ggml_cuda_init в логах при запуске — это подтверждает активацию GPU-ускорения.

Apple Silicon (Metal): На macOS с процессорами M1/M2/M3/M4 ускорение Metal включается автоматически. При запуске в логах должна появиться строка ggml_metal_init, подтверждающая использование GPU. Unified Memory архитектура Apple Silicon позволяет загружать модели, размер которых превышает объём "видеопамяти", так как RAM и VRAM физически едины.

CPU-only: Подходит для серверов без GPU или для тестирования. Убедитесь, что ваш процессор поддерживает инструкции AVX2 или AVX512 для оптимальной производительности.


2. Скачивание моделей

Скачивание квантованных моделей с HuggingFace через Терминал, powershell.

Установка huggingface-cli

pip install huggingface_hub

Команды скачивания

# Скачивание конкретного файла GGUF
huggingface-cli download <автор>/<репозиторий> <имя_файла.gguf> --local-dir ./models

# Пример: скачивание Qwen2.5-7B в квантовании Q4_K_M
huggingface-cli download Qwen/Qwen2.5-7B-Instruct-GGUF qwen2.5-7b-instruct-q4_k_m.gguf --local-dir ./models

# Скачивание всего репозитория (все квантования)
huggingface-cli download Qwen/Qwen2.5-7B-Instruct-GGUF --local-dir ./models

При поиске моделей на HuggingFace по тегу GGUF рекомендуется обращать внимание на авторов Bartowski и MaziyarPanahi — они известны качественными конвертациями с правильными метаданными и chat templates.

Структура именования файлов

Типичное имя файла GGUF: model-name-7b-instruct-q4_k_m.gguf

  • model-name — название модели (qwen2.5, llama3, mistral)
  • 7b — размер модели в миллиардах параметров
  • instruct — тип модели (instruct/chat для диалогов, base для дообучения)
  • q4_k_m — тип квантования

Скачивание квантованных моделей с HuggingFace напрямую с сайта.

Для ручного скачивания GGUF-файлов через браузер:

1. Переход к файлам модели

Откройте страницу репозитория (например, unsloth/Nemotron-3-Nano-30B-A3B-GGUF) и перейдите во вкладку Files and versions.

2. Выбор квантования

В списке файлов найдите нужный GGUF-файл. Имя файла содержит информацию о квантовании:

  • Q4_K_M — золотой стандарт, баланс качества и размера
  • Q5_K_M — выше качество, больше размер
  • Q8_0 — максимальное качество среди квантованных
  • Q3_K_M, Q2_K — для ограниченной памяти

3. Скачивание файла

Нажмите на имя файла, затем кнопку Download (или иконку загрузки справа от имени файла). Для крупных моделей (10+ ГБ) рекомендуется использовать менеджер загрузок.

4. Размещение файла

Переместите скачанный .gguf файл в директорию с моделями:

# Пример структуры
./models/
  └── Nemotron-3-Nano-30B-A3B-Q4_K_M.gguf

3. Формат GGUF и квантование

Квантование — сжатие весов модели (из 16 бит в 4, 5 или 8 бит). Это ключевая технология, позволяющая запускать большие модели на потребительском железе.

Типы квантования

Тип Описание Применение Потеря качества
Q8_0 8-битное квантование Когда важна точность Минимальная (~0.1%)
Q6_K 6-битное квантование Хороший баланс Очень низкая (~0.3%)
Q5_K_M 5-битное квантование Баланс качества и размера Низкая (~0.5%)
Q4_K_M 4-битное, золотой стандарт Рекомендуется для большинства Приемлемая (~1%)
Q4_K_S 4-битное, меньше размер Экономия памяти Заметная (~1.5%)
Q3_K_M 3-битное квантование Ограниченная память Значительная (~2-3%)
Q2_K 2-битное квантование Экстремальная экономия Существенная (~5-10%)
IQ4_XS Улучшенное 4-битное Очень слабое железо Средняя (~1-2%)
IQ3_XXS Улучшенное 3-битное Минимальные требования Высокая (~3-5%)

Конвертация модели в GGUF

pip install -r requirements.txt
python convert_hf_to_gguf.py models/mymodel/ --outfile model.gguf --outtype q8_0

Расчёт памяти

Для модели с B миллиардами параметров:

Квантование Формула Пример (7B) Пример (70B)
FP16 B × 2.0 ГБ 14 ГБ 140 ГБ
Q8_0 B × 1.0 ГБ 7 ГБ 70 ГБ
Q6_K B × 0.85 ГБ 6 ГБ 60 ГБ
Q5_K_M B × 0.75 ГБ 5.3 ГБ 53 ГБ
Q4_K_M B × 0.7 ГБ 4.9 ГБ 49 ГБ
Q3_K_M B × 0.55 ГБ 3.9 ГБ 39 ГБ
Q2_K B × 0.4 ГБ 2.8 ГБ 28 ГБ

Дополнительно для контекста (KV-кэш):

Размер контекста Дополнительная память
2048 токенов +0.25 ГБ
4096 токенов +0.5 ГБ
8192 токенов +1.0 ГБ
16384 токенов +2.0 ГБ
32768 токенов +4.0 ГБ
65536 токенов +8.0 ГБ
131072 токенов +16.0 ГБ

Пример: модель 7B в Q4_K_M с контекстом 8192 займёт ~5.9 ГБ VRAM.

Рекомендации по выбору квантования

Объём VRAM Рекомендуемый размер модели Квантование
4 ГБ 3B-7B Q4_K_M или Q3_K_M
6 ГБ 7B Q4_K_M или Q5_K_M
8 ГБ 7B-13B Q4_K_M
12 ГБ 13B Q5_K_M или Q6_K
16 ГБ 13B-24B Q4_K_M
24 ГБ 24B-34B Q4_K_M или Q5_K_M
32 ГБ 34B-70B Q4_K_M
48 ГБ 70B Q4_K_M или Q5_K_M
64+ ГБ 70B+ Q5_K_M или Q6_K

4. Ключевые флаги запуска

Ресурсы железа

Флаг Полная форма Описание Рекомендация
-m --model Путь к файлу модели Обязательный
-ngl --n-gpu-layers Количество слоёв на GPU 99 — загрузить максимум
-t --threads Ядер CPU для генерации Физические ядра (не потоки!)
-tb --threads-batch Ядер CPU для обработки промпта Может быть выше -t
-mg --main-gpu Индекс основной видеокарты При нескольких GPU (0, 1, 2...)
-sm --split-mode Режим разделения между GPU none, layer, row
-ts --tensor-split Распределение памяти между GPU Пропорции через запятую

Управление потоками (подробно)

Критически важно: указывайте количество физических ядер, а не логических потоков (Hyper-Threading / SMT).

# Пример: CPU с 8 ядрами / 16 потоков
-t 8        # Правильно: используем физические ядра
-t 16       # Неправильно: HT/SMT потоки замедляют инференс

Использование виртуальных потоков часто замедляет инференс из-за конкуренции за кэш процессора и задержек при переключении контекста.

Параметр Назначение Рекомендуемое значение
--threads (-t) Генерация токенов (последовательная работа) Физические ядра CPU
--threads-batch (-tb) Обработка prompt (параллельная работа) Все ядра или больше

Как определить количество физических ядер:

ОС Команда
Linux lscpu | grep "Core(s) per socket" или nproc --all
macOS sysctl -n hw.physicalcpu
Windows wmic cpu get NumberOfCores

Рекомендации по платформам:

Платформа -t (threads) -tb (threads-batch)
Apple M1 4 8
Apple M1 Pro/Max 6-8 10
Apple M2 4 8
Apple M2 Pro/Max 6-8 12
Apple M3 4 8
Apple M3 Pro/Max 4-6 12-14
Apple M4 4 10
Apple M4 Pro 6-8 12-14
Apple M4 Max 8-10 14-16
Apple M5 4-6 10-12
Intel i7 (8 ядер) 8 8
Intel i9 (16 ядер) 16 16
AMD Ryzen 7 (8 ядер) 8 8
AMD Ryzen 9 (16 ядер) 16 16

Память и контекст

Флаг Полная форма Описание Значения
-c --ctx-size Размер контекста (токены) 2048, 4096, 8192, 16384, 32768, 65536, 131072
-b --batch-size Токенов за раз при чтении промпта 512 оптимально, 128 для снижения нагрева
-ub --ubatch-size Размер микро-батча 512 для большинства, 128 для экономии памяти
-fa --flash-attn Flash Attention (on/off/auto) Обязательно для экономии VRAM

Подробнее о размере контекста:

Контекст определяет, сколько текста модель может "помнить" в рамках одного разговора. Один токен ≈ 0.75 слова для английского языка и ≈ 0.5 слова для русского (кириллица кодируется менее эффективно).

Контекст Примерный объём текста Применение
2048 ~1500 слов / ~2-3 страницы Короткие диалоги
4096 ~3000 слов / ~5-6 страниц Стандартные диалоги
8192 ~6000 слов / ~10-12 страниц Длинные разговоры, анализ документов
16384 ~12000 слов / ~20-25 страниц Работа с большими текстами
32768 ~24000 слов / ~40-50 страниц Анализ книг, длинный код
65536 ~48000 слов / ~80-100 страниц Очень большие документы
131072 ~96000 слов / ~150-200 страниц Максимальные задачи

Подробнее о batch-size:

Параметры -b и -ub влияют на то, как модель обрабатывает входной текст (prompt). Большие значения ускоряют обработку длинных промптов, но увеличивают пиковое потребление памяти и нагрев GPU.

Значение Эффект Когда использовать
512 Стандартная скорость, умеренный нагрев По умолчанию
256 Чуть медленнее, меньше нагрев Ноутбуки, тихая работа
128 Медленнее, минимальный нагрев Apple Silicon (для снижения температуры)
64 Самая медленная обработка, холодная работа Критически важно избежать перегрева
1024 Быстрее обработка, больше нагрев Мощные десктопные GPU
2048 Максимальная скорость обработки Серверные GPU (A100, H100)

Flash Attention

Flash Attention — оптимизированный алгоритм вычисления механизма внимания, который значительно снижает потребление памяти и ускоряет работу с длинными контекстами.

--flash-attn on     # Включить принудительно
--flash-attn off    # Выключить
--flash-attn auto   # Автоматический выбор (по умолчанию)

Преимущества Flash Attention:

  • Снижение потребления VRAM на 20-40% при больших контекстах
  • Ускорение обработки длинных промптов
  • Меньший нагрев GPU
  • Возможность использовать больший контекст на том же железе

Когда выключать:

  • При возникновении ошибок или артефактов в генерации (редко)
  • На очень старых GPU без поддержки

Memory Mapping (mmap)

Memory mapping — механизм ОС, который отображает файл модели в виртуальную память без полной загрузки в RAM. По умолчанию включено.

Флаг Описание
--mmap Включить memory mapping (по умолчанию)
--no-mmap Отключить mmap, загружать модель полностью в RAM
--mlock Заблокировать модель в RAM, предотвращая swapping*
*Swapping — механизм операционной системы, при котором данные из оперативной памяти (RAM) выгружаются на диск (SSD/HDD), когда физической памяти не хватает.

При работе с LLM это критично: если часть весов модели попадает в swap, каждое обращение к ним вызывает чтение с диска вместо RAM. Скорость падает в десятки раз — генерация токенов замедляется с миллисекунд до секунд.

Флаг --mlock в llama.cpp блокирует модель в RAM, запрещая системе выгружать её в swap. Это гарантирует стабильную производительность, но требует достаточного объёма физической памяти для всей модели.

Когда использовать --no-mmap:

  • Нужна стабильная производительность без непредсказуемых задержек
  • Работа с сетевыми или виртуальными файловыми системами
  • Достаточно RAM для полной загрузки модели

Когда использовать --mlock:

  • Хотите гарантировать, что модель не будет выгружена в swap
  • Достаточно RAM и хотите максимальную стабильность отклика
  • Особенно полезно на системах с большим объёмом RAM (64+ ГБ)

Комбинация --no-mmap --mlock: Полная загрузка модели в RAM с блокировкой от выгрузки. Требует достаточного объёма памяти, но обеспечивает максимально стабильную производительность.

Особенность: при mmap утилиты мониторинга (htop) могут показывать заниженное потребление RAM, поскольку memory-mapped файлы учитываются как "cache".

Ограничение длины ответа

Флаг Полная форма Описание Значения
-n --n-predict Максимум токенов в ответе 256, 512, 1024, 2048, 4096, -1, -2

Особые значения -n:

  • -n 256 — очень короткие ответы
  • -n 512 — стандартное значение для коротких ответов
  • -n 1024 — средние ответы
  • -n 2048 — для развёрнутых ответов и генерации кода
  • -n 4096 — для очень длинных ответов, больших блоков кода
  • -n 8192 — максимально длинные ответы
  • -n -1 — генерация без ограничений (до заполнения контекста)
  • -n -2 — генерация до заполнения контекста с остановкой на EOS-токене

EOS-токен (End Of Sequence) — специальный токен, который модель генерирует, когда считает ответ завершённым. Это сигнал "я закончил говорить".

Разница между -n -1 и -n -2:

При -n -1 модель генерирует токены до полного заполнения контекстного окна, игнорируя EOS. Это может привести к "бреду" после логического завершения ответа — модель продолжит генерировать текст, даже если уже ответила на вопрос.

При -n -2 модель останавливается в двух случаях: либо при генерации EOS-токена (естественное завершение), либо при заполнении контекста. Это более разумное поведение — ответ заканчивается там, где модель сама решила остановиться.

Практический пример:

Вопрос: "Сколько будет 2+2?"

С -n -1: "4. Это базовая арифметика. Кстати, математика — наука о числах... [продолжает до конца контекста]"

С -n -2: "4." [остановка на EOS]

Для большинства задач -n -2 предпочтительнее, если не указано конкретное ограничение длины.

Параметры генерации (сэмплинг)

Флаг Полная форма Описание Диапазон По умолчанию
--temp --temperature Температура 0.0–2.0 0.8
--top-k --top-k Топ-K токенов 1–100 40
--top-p --top-p Nucleus sampling 0.0–1.0 0.95
--min-p --min-p Минимальная вероятность 0.0–1.0 0.05
--repeat-penalty --repeat-penalty Штраф за повторы 1.0–2.0 1.1
--presence-penalty --presence-penalty Штраф за присутствие 0.0–2.0 0.0
--frequency-penalty --frequency-penalty Штраф за частоту 0.0–2.0 0.0

Подробнее о температуре:

Температура Эффект Применение
0.0 Детерминированный вывод (всегда одинаковый) Точные ответы, факты
0.1–0.3 Очень консервативный, предсказуемый Код, математика, перевод
0.4–0.6 Умеренно творческий Рерайт, суммаризация
0.7–0.8 Стандартный баланс Обычные диалоги
0.9–1.0 Творческий Креативное письмо, истории
1.1–1.5 Очень творческий, может быть нестабильным Брейншторминг
1.5–2.0 Хаотичный, часто бессмысленный Экспериментальные цели

Подробнее о top-k и top-p:

  • top-k: Из всех возможных следующих токенов выбирает только K наиболее вероятных. top-k 40 означает выбор из 40 лучших кандидатов.
  • top-p (nucleus sampling): Выбирает минимальное количество токенов, суммарная вероятность которых >= p. top-p 0.95 означает выбор из токенов, покрывающих 95% вероятностной массы.

Рекомендуемые комбинации:

Задача temp top-k top-p repeat-penalty
Код 0.1–0.2 40 0.9 1.1
Математика 0.0–0.1 40 0.9 1.0
Перевод 0.2–0.3 40 0.95 1.1
Чат 0.7–0.8 40 0.95 1.1
Креатив 0.9–1.0 50 0.95 1.15
Ролевая игра 0.8–1.0 60 0.98 1.2

Специальные флаги

Флаг Описание
--seed Seed для воспроизводимости результатов (число)
--keep Количество токенов промпта для сохранения при очистке контекста
--escape Обрабатывать escape-последовательности (\n, \t и др.)
--no-penalize-nl Не штрафовать за символы новой строки
--prompt-cache Путь к файлу кэша промпта
--prompt-cache-all Кэшировать весь промпт
Для каждой модели эти параметры могут варьироваться.
Например, коллеги из команды Vikhr пишут, что для их модели Vistral рекомендуемые параметры температуры от 0,1 до 0,5.

5. System Prompt (Системный промпт)

System prompt — это специальная инструкция, которая задаёт поведение, роль и ограничения модели на протяжении всего диалога. Системный промпт обрабатывается перед пользовательскими сообщениями и влияет на стиль, тон и содержание всех ответов.

Флаги для системного промпта

Флаг Описание Применение
-p --prompt Начальный промпт (может включать системный)
-f --file Файл с промптом
-sp --system-prompt Системный промпт напрямую
-spf --system-prompt-file Файл с системным промптом

Использование в llama-cli

Через флаг -p (inline):

llama-cli -m model.gguf -ngl 99 -c 8192 -p "Ты — опытный программист на Python. Отвечай кратко и по делу." -i -ins --color

Через файл -f:

# Создаём файл system.txt:
# Ты — профессиональный переводчик. Переводи тексты с английского на русский,
# сохраняя стиль и тон оригинала.

llama-cli -m model.gguf -ngl 99 -c 8192 -f system.txt -i -ins --color

Через флаг --system-prompt:

llama-cli -m model.gguf -ngl 99 -c 8192 --system-prompt "Ты — дружелюбный ассистент." -i -ins --color

Использование в llama-server

Через флаг --system-prompt-file:

# Создаём файл system_prompt.txt с инструкциями
llama-server -m model.gguf --port 8080 -ngl 99 -c 8192 --system-prompt-file system_prompt.txt

Через API (в каждом запросе):

from openai import OpenAI

client = OpenAI(base_url="http://localhost:8080/v1", api_key="sk-no-key-required")

response = client.chat.completions.create(
    model="local-model",
    messages=[
        {
            "role": "system",
            "content": "Ты — эксперт по кибербезопасности. Отвечай технически точно, приводи примеры кода когда уместно."
        },
        {
            "role": "user",
            "content": "Как защититься от SQL-инъекций?"
        }
    ],
    max_tokens=1024
)

cURL с системным промптом:

curl http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "local-model",
    "messages": [
      {"role": "system", "content": "Ты — краткий и точный ассистент. Отвечай максимум в 2-3 предложениях."},
      {"role": "user", "content": "Что такое Docker?"}
    ],
    "max_tokens": 256
  }'

Примеры эффективных системных промптов

Для программирования:

Ты — Senior Software Engineer с 15-летним опытом. 
Правила:
- Пиши чистый, документированный код
- Следуй принципам SOLID и DRY
- Всегда объясняй сложные решения
- Предупреждай о потенциальных проблемах безопасности
- Используй современные best practices

Для анализа данных:

Ты — Data Scientist. 
При анализе данных:
1. Сначала задавай уточняющие вопросы о данных
2. Предлагай несколько подходов к решению
3. Объясняй статистические методы простым языком
4. Всегда указывай на ограничения анализа

Для перевода:

Ты — профессиональный переводчик EN↔RU.
Правила перевода:
- Сохраняй стиль и тон оригинала
- Технические термины оставляй на английском с пояснением
- Идиомы адаптируй под целевую культуру
- При неоднозначности предлагай варианты

Для ролевой игры:

Ты — мудрый волшебник из средневекового фэнтези-мира.
- Говори архаичным, но понятным языком
- Отвечай загадками и метафорами
- Никогда не выходи из роли
- Ссылайся на магические законы и древние тексты

Для JSON-ответов:

Ты — API-ассистент. 
ВАЖНО: Отвечай ТОЛЬКО валидным JSON без дополнительного текста.
Формат ответа: {"answer": "...", "confidence": 0.0-1.0, "sources": [...]}

Рекомендации по написанию системных промптов

Аспект Рекомендация
Длина Оптимально 100-500 токенов. Слишком длинный промпт съедает контекст
Структура Используйте списки и чёткие правила
Роль Начните с определения роли ("Ты — ...")
Ограничения Явно укажите, чего делать нельзя
Формат Опишите желаемый формат ответов
Примеры Для сложных задач добавьте few-shot примеры
Язык Укажите язык ответов, если важно

6. Структурированный вывод (JSON Schema, Grammar)

llama.cpp поддерживает принудительное ограничение формата вывода модели. Это критически важно для интеграции с приложениями или для построения автоматизаций, в которых нужен строго валидный JSON или другой структурированный формат.

Методы ограничения вывода

Метод Описание Надёжность Сложность
JSON Schema Определение структуры через JSON Schema Высокая Низкая
Grammar (GBNF) Формальная грамматика в формате GBNF Максимальная Высокая
Response Format Простое указание типа (json_object) Средняя Минимальная

JSON Schema

Флаги:

Флаг Описание
--json-schema JSON Schema для ограничения вывода (inline)
--json-schema-file Путь к файлу с JSON Schema

Пример использования в llama-cli:

llama-cli -m model.gguf -ngl 99 -c 4096 \
  -p "Извлеки информацию о человеке из текста: John Smith, 35 лет, инженер из Нью-Йорка" \
  --json-schema '{"type":"object","properties":{"name":{"type":"string"},"age":{"type":"integer"},"occupation":{"type":"string"},"city":{"type":"string"}},"required":["name","age"]}' \
  -n 256

Пример схемы (файл schema.json):

{
  "type": "object",
  "properties": {
    "sentiment": {
      "type": "string",
      "enum": ["positive", "negative", "neutral"]
    },
    "confidence": {
      "type": "number",
      "minimum": 0,
      "maximum": 1
    },
    "keywords": {
      "type": "array",
      "items": {"type": "string"},
      "maxItems": 5
    },
    "summary": {
      "type": "string",
      "maxLength": 200
    }
  },
  "required": ["sentiment", "confidence", "summary"]
}

Запуск с файлом схемы:

llama-cli -m model.gguf -ngl 99 -p "Проанализируй отзыв: Отличный продукт!" --json-schema-file schema.json -n 256

Использование JSON Schema через API

Python (OpenAI SDK):

from openai import OpenAI
import json

client = OpenAI(base_url="http://localhost:8080/v1", api_key="sk-no-key-required")

# Определяем схему
schema = {
    "type": "object",
    "properties": {
        "product_name": {"type": "string"},
        "rating": {"type": "integer", "minimum": 1, "maximum": 5},
        "pros": {"type": "array", "items": {"type": "string"}},
        "cons": {"type": "array", "items": {"type": "string"}},
        "recommendation": {"type": "boolean"}
    },
    "required": ["product_name", "rating", "recommendation"]
}

response = client.chat.completions.create(
    model="local-model",
    messages=[
        {"role": "system", "content": "Извлекай структурированную информацию из отзывов о товарах."},
        {"role": "user", "content": "iPhone 15 Pro — отличный телефон! Камера супер, батарея держит весь день. Минус только цена. Рекомендую!"}
    ],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "product_review",
            "strict": True,
            "schema": schema
        }
    },
    max_tokens=512
)

result = json.loads(response.choices[0].message.content)
print(json.dumps(result, indent=2, ensure_ascii=False))

cURL с JSON Schema:

curl http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "local-model",
    "messages": [
      {"role": "system", "content": "Извлекай данные в JSON."},
      {"role": "user", "content": "Москва — столица России, население около 12 миллионов."}
    ],
    "response_format": {
      "type": "json_schema",
      "json_schema": {
        "name": "city_info",
        "strict": true,
        "schema": {
          "type": "object",
          "properties": {
            "city": {"type": "string"},
            "country": {"type": "string"},
            "population": {"type": "integer"},
            "is_capital": {"type": "boolean"}
          },
          "required": ["city", "country"]
        }
      }
    },
    "max_tokens": 256
  }'

Простой JSON Mode

Для случаев, когда нужен просто валидный JSON без строгой схемы:

Python:

response = client.chat.completions.create(
    model="local-model",
    messages=[
        {"role": "system", "content": "Отвечай только валидным JSON."},
        {"role": "user", "content": "Перечисли 3 языка программирования с их годом создания."}
    ],
    response_format={"type": "json_object"},
    max_tokens=256
)

cURL:

curl http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "local-model",
    "messages": [
      {"role": "system", "content": "Отвечай в формате JSON."},
      {"role": "user", "content": "Какая сегодня погода? (придумай)"}
    ],
    "response_format": {"type": "json_object"},
    "max_tokens": 256
  }'

Grammar (GBNF)

Grammar — более мощный инструмент, позволяющий описать любой формат вывода с помощью формальной грамматики в формате GBNF (GGML BNF).

Флаги:

Флаг Описание
--grammar Грамматика GBNF (inline)
--grammar-file Путь к файлу с грамматикой

Пример простой грамматики (json.gbnf):

root   ::= object
value  ::= object | array | string | number | ("true" | "false" | "null") ws

object ::=
  "{" ws (
            string ":" ws value
    ("," ws string ":" ws value)*
  )? "}" ws

array  ::=
  "[" ws (
            value
    ("," ws value)*
  )? "]" ws

string ::=
  "\"" (
    [^"\\\x7F\x00-\x1F] |
    "\\" (["\\/bfnrt] | "u" [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F])
  )* "\"" ws

number ::= ("-"? ([0-9] | [1-9] [0-9]*)) ("." [0-9]+)? ([eE] [-+]? [0-9]+)? ws

ws ::= ([ \t\n] ws)?

Запуск с грамматикой:

llama-cli -m model.gguf -ngl 99 -p "Создай JSON с информацией о книге" --grammar-file json.gbnf -n 256

Грамматика для списка (list.gbnf):

root ::= "- " item ("\n- " item)*
item ::= [a-zA-Zа-яА-ЯёЁ0-9 ]+

Грамматика для да/нет ответов (yesno.gbnf):

root ::= "да" | "нет" | "Да" | "Нет" | "ДА" | "НЕТ"

Грамматика для email (email.gbnf):

root ::= local "@" domain
local ::= [a-zA-Z0-9._%+-]+
domain ::= [a-zA-Z0-9.-]+ "." [a-zA-Z]{2,}

Грамматика для структурированного ответа:

root ::= "ОТВЕТ: " answer "\nУВЕРЕННОСТЬ: " confidence "\nИСТОЧНИК: " source
answer ::= [a-zA-Zа-яА-ЯёЁ0-9 .,!?-]+
confidence ::= "высокая" | "средняя" | "низкая"
source ::= [a-zA-Zа-яА-ЯёЁ0-9 .,://-]+

Примеры сложных JSON Schema

Для извлечения сущностей (NER):

{
  "type": "object",
  "properties": {
    "entities": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "text": {"type": "string"},
          "type": {
            "type": "string",
            "enum": ["PERSON", "ORGANIZATION", "LOCATION", "DATE", "MONEY", "PRODUCT"]
          },
          "start": {"type": "integer"},
          "end": {"type": "integer"}
        },
        "required": ["text", "type"]
      }
    }
  },
  "required": ["entities"]
}

Для классификации:

{
  "type": "object",
  "properties": {
    "category": {
      "type": "string",
      "enum": ["technology", "sports", "politics", "entertainment", "science", "business"]
    },
    "subcategory": {"type": "string"},
    "confidence": {"type": "number", "minimum": 0, "maximum": 1},
    "reasoning": {"type": "string", "maxLength": 500}
  },
  "required": ["category", "confidence"]
}

Для генерации API-ответов:

{
  "type": "object",
  "properties": {
    "success": {"type": "boolean"},
    "data": {
      "type": "object",
      "properties": {
        "id": {"type": "string"},
        "created_at": {"type": "string", "format": "date-time"},
        "result": {}
      }
    },
    "error": {
      "type": "object",
      "properties": {
        "code": {"type": "string"},
        "message": {"type": "string"}
      }
    },
    "meta": {
      "type": "object",
      "properties": {
        "processing_time_ms": {"type": "integer"},
        "model_version": {"type": "string"}
      }
    }
  },
  "required": ["success"]
}

Встроенные грамматики

llama.cpp включает набор готовых грамматик в директории grammars/:

Файл Описание
json.gbnf Валидный JSON
json_arr.gbnf JSON-массив
list.gbnf Маркированный список
c.gbnf Код на C
chess.gbnf Шахматная нотация
arithmetic.gbnf Арифметические выражения

Рекомендации по структурированному выводу

Сценарий Рекомендуемый метод
Простой JSON-ответ response_format: {"type": "json_object"}
Строгая структура данных JSON Schema с strict: true
Нестандартный формат Grammar (GBNF)
Извлечение сущностей JSON Schema с enum для типов
Да/Нет ответы Grammar
Числовые ответы JSON Schema с min/max

Советы:

  • Используйте низкую температуру (--temp 0.1-0.3) для структурированного вывода
  • Добавляйте примеры в системный промпт (few-shot)
  • При использовании JSON Schema всегда указывайте required поля
  • Тестируйте грамматики на простых примерах перед продакшном

7. llama-cli: консольный режим

llama-cli — интерактивный интерфейс командной строки для работы с моделью в режиме диалога или однократной генерации.

Флаги CLI

Флаг Полная форма Описание
-i --interactive Интерактивный режим
-ins --instruct Режим инструкций (автоматически подставляет шаблоны диалога)
--color Подсветка текста (синий — ввод, белый — ответ)
-p --prompt Начальный промпт
-f --file Файл с промптом
-sp --system-prompt Системный промпт
--conv-template Шаблон диалога (mistral, llama2, llama3, chatml, gemma и др.)
-r --reverse-prompt Строка для возврата управления пользователю
--in-prefix Префикс перед вводом пользователя
--in-suffix Суффикс после ввода пользователя
-cnv --conversation Режим разговора (упрощённый интерактивный)
--multiline-input Многострочный ввод
--simple-io Простой ввод-вывод без спецсимволов
--json-schema JSON Schema для структурированного вывода
--grammar-file Файл с грамматикой GBNF

Режимы работы

Однократная генерация:

llama-cli -m model.gguf -p "Напиши стихотворение о весне" -n 256

Интерактивный режим:

llama-cli -m model.gguf -i

Режим инструкций (instruct):

llama-cli -m model.gguf -i -ins

Режим разговора (conversation):

llama-cli -m model.gguf -cnv

Примеры команд

Базовый запуск:

llama-cli -m models/model.gguf -ngl 99 -c 4096 -n 512

Интерактивный с GPU и оптимизациями:

llama-cli -m models/model.gguf -ngl 99 -c 8192 -b 512 -t 8 -tb 12 -n 2048 --temp 0.7 --repeat-penalty 1.1 --flash-attn on --mlock --color -i -ins

С системным промптом:

llama-cli -m models/model.gguf -ngl 99 -c 8192 --system-prompt "Ты — опытный Python-разработчик." -i -ins --color

Для Apple Silicon (оптимизация температуры):

llama-cli -m models/model.gguf -ngl 99 -c 8192 -b 128 -ub 128 -t 4 -tb 12 -n 4096 --flash-attn on --mlock --no-mmap --color -i -ins

С JSON Schema:

llama-cli -m models/model.gguf -ngl 99 -c 4096 -p "Извлеки данные: Иван Петров, 30 лет" --json-schema '{"type":"object","properties":{"name":{"type":"string"},"age":{"type":"integer"}}}' -n 128

С грамматикой:

llama-cli -m models/model.gguf -ngl 99 -c 4096 -p "Ответь да или нет: Земля круглая?" --grammar-file yesno.gbnf -n 8

Горячие клавиши в интерактивном режиме

Клавиша Действие
Enter Отправить сообщение
Ctrl+C Прервать генерацию
Ctrl+D Выйти из программы

8. llama-server: API-сервис

Запуск llama-server превращает модель в постоянно работающий микросервис, совместимый с OpenAI API. Это позволяет использовать модель из любых приложений, поддерживающих OpenAI API.

Флаги сервера

Флаг Полная форма Описание По умолчанию
--host Адрес для прослушивания 127.0.0.1
--port Порт сервера 8080
-np --n-parallel Количество параллельных запросов (слотов) 1
-cb --cont-batching Непрерывный батчинг (подмешивание новых запросов) Выключено
--alias Имя модели для API Имя файла
--embedding Режим эмбеддингов (для RAG) Выключено
--reranking Режим ранжирования Выключено
-spf --system-prompt-file Файл с системным промптом по умолчанию
--chat-template Шаблон чата (jinja) Из модели
--slots Показывать информацию о слотах Выключено
--slot-save-path Путь для сохранения состояния слотов
--log-disable Отключить логи
--log-format Формат логов text
--metrics Включить эндпоинт метрик Выключено
-to --timeout Таймаут соединения (секунды) 0 (без лимита)
--api-key API-ключ для авторизации
--api-key-file Файл с API-ключами
--ssl-key-file Путь к SSL-ключу
--ssl-cert-file Путь к SSL-сертификату

Примеры команд

Базовый сервер:

llama-server -m models/model.gguf --port 8080 -n 2048

Сервер с системным промптом:

llama-server -m models/model.gguf --port 8080 -ngl 99 -c 8192 --system-prompt-file system.txt

Продакшн-сервер с параллельными запросами:

llama-server -m models/model.gguf --host 0.0.0.0 --port 8080 -ngl 99 -c 8192 -t 8 -tb 12 -n 4096 --flash-attn on --mlock --cont-batching --n-parallel 4 --metrics

Сервер для Apple Silicon (минимальный нагрев):

llama-server -m models/model.gguf --port 8080 -ngl 99 -c 8192 -b 128 -ub 128 -t 4 -tb 12 -n 4096 --flash-attn on --mlock --no-mmap

Сервер для RAG (эмбеддинги):

llama-server -m models/embedding-model.gguf --embedding --port 8080 -ngl 99

Сервер с авторизацией:

llama-server -m models/model.gguf --port 8080 -ngl 99 --api-key "your-secret-key"

Эндпоинты сервера

URL Метод Назначение
http://localhost:8080 GET Встроенный Web UI
http://localhost:8080/health GET Проверка состояния сервера
http://localhost:8080/v1/models GET Список моделей
http://localhost:8080/v1/chat/completions POST OpenAI-совместимый Chat API
http://localhost:8080/v1/completions POST OpenAI-совместимый Completion API
http://localhost:8080/v1/embeddings POST Эмбеддинги (при --embedding)
http://localhost:8080/tokenize POST Токенизация текста
http://localhost:8080/detokenize POST Детокенизация
http://localhost:8080/slots GET Информация о слотах
http://localhost:8080/metrics GET Prometheus-метрики

Python-клиент (OpenAI SDK)

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:8080/v1",
    api_key="sk-no-key-required"
)

# Обычный запрос с системным промптом
response = client.chat.completions.create(
    model="local-model",
    messages=[
        {"role": "system", "content": "Ты — эксперт по Python."},
        {"role": "user", "content": "Как отсортировать список словарей по ключу?"}
    ],
    max_tokens=1024,
    temperature=0.7
)

print(response.choices[0].message.content)

# Стриминг
response = client.chat.completions.create(
    model="local-model",
    messages=[
        {"role": "system", "content": "Ты — поэт."},
        {"role": "user", "content": "Напиши хокку о программировании"}
    ],
    max_tokens=256,
    stream=True
)

for chunk in response:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

Python с JSON Schema

from openai import OpenAI
import json

client = OpenAI(base_url="http://localhost:8080/v1", api_key="sk-no-key-required")

response = client.chat.completions.create(
    model="local-model",
    messages=[
        {"role": "system", "content": "Извлекай структурированные данные."},
        {"role": "user", "content": "Apple Inc. основана в 1976 году Стивом Джобсом. Штаб-квартира в Купертино."}
    ],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "company_info",
            "strict": True,
            "schema": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "founded": {"type": "integer"},
                    "founder": {"type": "string"},
                    "headquarters": {"type": "string"}
                },
                "required": ["name", "founded"]
            }
        }
    },
    max_tokens=256
)

data = json.loads(response.choices[0].message.content)
print(json.dumps(data, indent=2, ensure_ascii=False))

cURL-запросы

Chat Completion с системным промптом:

curl http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "local-model",
    "messages": [
      {"role": "system", "content": "Отвечай кратко, в 1-2 предложениях."},
      {"role": "user", "content": "Что такое машинное обучение?"}
    ],
    "max_tokens": 128
  }'

С JSON Schema:

curl http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "local-model",
    "messages": [
      {"role": "user", "content": "Москва, население 12 млн, столица России"}
    ],
    "response_format": {
      "type": "json_schema",
      "json_schema": {
        "name": "city",
        "strict": true,
        "schema": {
          "type": "object",
          "properties": {
            "name": {"type": "string"},
            "population": {"type": "integer"},
            "is_capital": {"type": "boolean"}
          },
          "required": ["name"]
        }
      }
    }
  }'

Простой JSON mode:

curl http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "local-model",
    "messages": [
      {"role": "system", "content": "Отвечай в формате JSON."},
      {"role": "user", "content": "Перечисли 3 цвета"}
    ],
    "response_format": {"type": "json_object"}
  }'

9. Диагностика и мониторинг

Вывод при запуске

При запуске llama-cli или llama-server в консоль выводится информация о системе и модели:

Инициализация бэкенда:

  • ggml_metal_init — инициализация Metal (macOS/Apple Silicon)
  • ggml_cuda_init — инициализация CUDA (NVIDIA)
  • ggml_vulkan_init — инициализация Vulkan (AMD/Intel/NVIDIA)

Информация о GPU:

  • GPU name — название видеокарты
  • GPU family — семейство GPU
  • has unified memory — наличие объединённой памяти (Apple Silicon)
  • recommendedMaxWorkingSetSize — рекомендуемый максимальный объём памяти

Информация о модели:

  • llm_load_tensors — загрузка тензоров модели
  • llama_model_loader — информация о структуре модели
  • n_ctx — размер контекста
  • n_batch — размер батча

Статистика производительности (llama_print_timings)

llama_print_timings:        load time =    1234.56 ms
llama_print_timings:      sample time =      12.34 ms /   100 runs
llama_print_timings: prompt eval time =     234.56 ms /    50 tokens (213.10 tokens per second)
llama_print_timings:        eval time =    5678.90 ms /   100 runs (17.61 tokens per second)
llama_print_timings:       total time =    6000.00 ms /   150 tokens
Метрика Описание
load time Время загрузки модели в память
sample time Время сэмплирования токенов
prompt eval time Время обработки входного промпта
prompt eval tokens/s Скорость обработки промпта
eval time Время генерации ответа
eval tokens/s Скорость генерации (главный показатель)

Целевые показатели производительности

Скорость (t/s) Оценка Комментарий
< 5 Медленно Некомфортно для диалога
5–8 Приемлемо Читать можно
8–15 Комфортно Нормальная скорость
15–30 Быстро Отличная отзывчивость
30+ Очень быстро Почти мгновенно

10. Шаблоны команд

Минимальный запуск CLI

llama-cli -m models/model.gguf -p "Привет!" -n 256

Интерактивный CLI с GPU

llama-cli -m models/model.gguf -ngl 99 -c 8192 -t 8 -n 2048 --temp 0.7 --flash-attn on -i -ins --color

CLI с системным промптом

llama-cli -m models/model.gguf -ngl 99 -c 8192 --system-prompt "Ты — эксперт по Python." -i -ins --color

CLI с JSON Schema

llama-cli -m models/model.gguf -ngl 99 -p "Извлеки: Иван, 25 лет" --json-schema '{"type":"object","properties":{"name":{"type":"string"},"age":{"type":"integer"}}}' -n 128 --temp 0.1

Базовый сервер

llama-server -m models/model.gguf --port 8080 -n 2048

Сервер с системным промптом

llama-server -m models/model.gguf --port 8080 -ngl 99 --system-prompt-file system.txt

Продакшн-сервер

llama-server -m models/model.gguf --host 0.0.0.0 --port 8080 -ngl 99 -c 8192 -t 8 -tb 12 -n 4096 --flash-attn on --mlock --cont-batching --n-parallel 4 --metrics

Apple Silicon (баланс скорости и температуры)

llama-server -m models/model.gguf --port 8080 -ngl 99 -c 8192 -b 128 -ub 128 -t 4 -tb 12 -n 4096 --flash-attn on --mlock --no-mmap

Сервер для RAG

llama-server -m models/embedding-model.gguf --embedding --port 8080 -ngl 99

Генерация кода

llama-cli -m models/codellama.gguf -ngl 99 -c 16384 --system-prompt "Ты — Senior Python Developer." --temp 0.2 --flash-attn on -i -ins --color

Извлечение структурированных данных

llama-cli -m models/model.gguf -ngl 99 -c 4096 --system-prompt "Извлекай данные из текста в JSON." --json-schema-file schema.json --temp 0.1 -i --color

11. Решение типичных проблем

Модель не загружается на GPU

Диагностика: Проверьте наличие ggml_metal_init или ggml_cuda_init в логах.

Решения:

  1. Добавьте -ngl 99
  2. Пересоберите с поддержкой GPU

Нехватка памяти

Решения:

  1. Уменьшите контекст: -c 4096
  2. Используйте Q4_K_M вместо Q8_0
  3. Уменьшите -ngl (частичная загрузка на GPU)
  4. Включите --flash-attn on

Перегрев (Mac)

Решения:

  1. -b 128 -ub 128
  2. -t 4
  3. --flash-attn on

Некорректный формат ответов

Решения:

  1. Укажите --conv-template
  2. Используйте -i -ins
  3. Добавьте системный промпт с инструкциями
  4. Для JSON: используйте --json-schema или response_format

Ошибка парсинга JSON

Решения:

  1. Снизьте температуру: --temp 0.1
  2. Используйте --json-schema с strict: true
  3. Добавьте примеры в системный промпт

12. Полезные ссылки


Руководство составлено на основе официальной документации llama.cpp и практического опыта использования.

About

Инструкция по работе с Llama.cpp

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published