# llama.cpp speculative decoding: draft-модель и проверка ускорения

Источник: https://modelium.tech/zhurnal/llama-cpp-speculative-decoding/

В llama.cpp speculative decoding предлагает несколько токенов заранее и проверяет их основной моделью; есть режим с отдельной draft-моделью и варианты n-gram без второй модели. Сначала получите базовый ответ и время без спекуляции, затем повторите те же запросы при одинаковых настройках. Выигрыш зависит от задачи и доли принятых токенов: дополнительный draft может как ускорить, так и замедлить ответ.

**Документация проверена 29 сентября 2026 года:** llama.cpp v0.5.0, Git-коммит `7fe450e`. Это инструкция по исходникам и документации авторов, а не прогон Modelium; модель, CPU/GPU и запросы не запускались. При другой версии сверяйте `llama-server --help` заново. [s1](#src-s1) [s2](#src-s2) [s8](#src-s8)

## Зачем speculative decoding и когда он полезен?

Обычная генерация последовательно получает токены основной моделью. При speculative decoding быстрый источник предлагает несколько следующих токенов, а основная модель проверяет их блоком. Часто принятые предложения могут повысить скорость вывода, но стоимость работы второго источника и характер запросов меняют результат. Никакого гарантированного коэффициента ускорения документация не даёт. [s1](#src-s1)

Здесь **target** — та GGUF-модель, чей ответ нужен, **draft** — меньшая модель-кандидат; в n-gram-режиме продолжение берётся из истории текста без второго файла. Эта настройка относится к этапу генерации, а не к выбору лицензии, оценке качества модели или суммарной памяти: второй GGUF и его KV-кеш — дополнительные ресурсы, но размер файла нельзя объявить минимальной RAM/VRAM. [s1](#src-s1) [s2](#src-s2)

Проверяемая задача: на собственном наборе одинаковых промптов сравнить базовый сервер и две настройки — `ngram-simple` и, если найдена совместимая пара весов, `draft-simple`. Для переписывания повторяющегося кода n-gram может иметь более подходящую историю, чем для короткого вопроса без повторов; это **гипотеза для проверки**, не заявленный результат измерений Modelium. Документация проекта приводит переписывание кода как пример n-gram. [s1](#src-s1)

## Что подготовить до запуска?

Нужны компилятор C/C++, CMake, Git и установленный по инструкции проекта `llama-server` **одной закреплённой сборки**. CPU-вариант сборки приведён ниже; для GPU есть отдельные backend-инструкции. Подготовьте выбранный законно полученный target GGUF и, для режима `draft-simple`, совместимый draft GGUF. Авторский пример использует Qwen3-8B-Base-GGUF в роли target и Qwen3-0.6B-Base-GGUF в роли draft; это пример пары, **не** обещание совместимости других двух моделей и не рекомендация по минимальному железу. Для своих весов отдельно проверьте происхождение, лицензию и согласованность токенизатора/формата чата; здесь права на коммерческое применение не установлены. [s4](#src-s4) [s8](#src-s8)

# POSIX shell; соберите одну ревизию для обоих прогонов.git clone https://github.com/ggml-org/llama.cpp.gitcd llama.cppgit checkout 7fe450e19305b828c199d602c23a8337aaa1f03bcmake -B build -DCMAKE_BUILD_TYPE=Releasecmake --build build --config Release -j 4# Путь к бинарнику проверяйте по своей сборке: build/bin/llama-server.

Не выкладывайте коммерческие промпты и веса публично. Сервер ниже привязан к `127.0.0.1`, а не к внешнему адресу; у `/health` нет проверки API-ключа. Если вы целенаправленно открываете сервис в сети, отдельно настройте доступ и TLS. [s2](#src-s2)

## Как получить честную базовую линию?

Запустите **один** сервер, одну модель, один слот и неизменный контекст. `--spec-type none` явно отключает speculative. Убедитесь, что `GET /health` возвращает готовность после загрузки, а запросы обрабатываются. Команды запуска по синтаксису относятся к указанной версии; пути к весам подставляет читатель. [s1](#src-s1) [s2](#src-s2) [s3](#src-s3)

./build/bin/llama-server -m /path/to/target.gguf \  --host 127.0.0.1 --port 8080 -c 8192 --np 1 \  --spec-type none --metrics# В другом терминале: curl -fsS http://127.0.0.1:8080/health

Для одинаковых сравнений фиксируйте target-файл, ревизию llama.cpp, backend, контекст, число слотов, промпты, длину вывода, температуру и параллельность. Сначала прогрейте сервер отдельным запросом и не включайте время загрузки весов в клиентскую задержку. Зафиксируйте версию драйверов, железо и использование памяти собственной системой; не сравнивайте CPU baseline с GPU speculative. Сервер публикует тайминги ответа и при `--metrics` счётчики по draft, но это разные метрики: высокая доля принятия сама по себе не равна малой задержке. [s2](#src-s2) [s3](#src-s3) [s7](#src-s7)

## Как включить n-gram без второй модели?

Остановите baseline-сервер и запустите ту же модель на том же порту, изменив **только** `--spec-type`. `ngram-simple` ищет повторённую последовательность токенов в текущей истории и предлагает её продолжение; на коротком контексте полезных совпадений может не найтись. В отличие от `draft-simple`, здесь `-md` не нужен. Параметры `--spec-ngram-simple-size-n` и `--spec-ngram-simple-size-m` управляют поиском и длиной предлагаемого фрагмента: сначала оставьте defaults, а не подбирайте число по единственному удачному запросу. [s1](#src-s1) [s2](#src-s2)

./build/bin/llama-server -m /path/to/target.gguf \  --host 127.0.0.1 --port 8080 -c 8192 --np 1 \  --spec-type ngram-simple --metrics

Проверьте `GET /metrics` **после** завершения запроса: `llamacpp:spec_decode_num_draft_tokens_total` и `llamacpp:spec_decode_num_accepted_tokens_total` показывают соответственно предложения и принятые токены. Если предложений ноль, не называйте эксперимент успешным ускорением; если принято мало, проверьте подходящесть задания до изменения десятка флагов. В коде сервера счётчик принятых инкрементируется по завершённой проверке, а серверный журнал также печатает статистику draft. [s1](#src-s1) [s2](#src-s2) [s7](#src-s7)

## Как подключить отдельную draft-модель?

Сначала убедитесь, что пара поддерживает одинаковое декодирование токенов и что помещается в вашей конфигурации. Остановите n-gram-сервер. `-md` задаёт второй GGUF, `--spec-type draft-simple` выбирает простой режим, `--spec-draft-n-max` ограничивает число предложений за шаг; пример автора использует иной лимит в демонстрационном CLI, поэтому для первого серверного замера можно взять умеренное значение 3 и потом менять **один** параметр за раз. В коде CLI именно `draft-simple` — поддерживаемое имя режима, а не краткая подпись `draft` в заголовке документации. [s1](#src-s1) [s2](#src-s2) [s4](#src-s4) [s5](#src-s5)

./build/bin/llama-server -m /path/to/target.gguf \  -md /path/to/compatible-draft.gguf \  --host 127.0.0.1 --port 8080 -c 8192 --np 1 \  --spec-type draft-simple --spec-draft-n-max 3 --metrics

Не ставьте рядом случайный маленький GGUF: совпадение формата файла не гарантирует совместимого токенизатора. Если загрузка отвергает пару, сохраните точный текст ошибки и вернитесь к baseline; не маскируйте её нулём принятых токенов. Другая специализированная ветка `draft-eagle3` требует подготовленного для конкретного target вспомогательного checkpoint и конвертации; она **не** заменяется обычным `draft-simple` флагом. [s1](#src-s1) [s2](#src-s2) [s4](#src-s4)

## Как сравнить скорость, принятие и ответы?

Официальный клиент SPEED-Bench обращается к уже работающему серверу, сохраняет результаты baseline и speculative в JSON, измеряет клиентскую задержку, скорость декодирования и долю принятых предложений. Из checkout той же ревизии поставьте зависимости в отдельное окружение; набор и параметры должны быть одинаковыми при обоих прогонах, а сервер между ними перезапущен без смены target/backend. Публичный датасет может не представлять ваши русские или корпоративные задачи; дополните измерение *своими разрешёнными* запросами и ручной проверкой ответа. [s3](#src-s3)

python3 -m venv .venv-bench. .venv-bench/bin/activatepython -m pip install -r tools/server/bench/speed-bench/requirements.txt# При baseline-сервере:python tools/server/bench/speed-bench/speed_bench.py \  --url localhost:8080 --bench qualitative --category coding \  --osl 1024 --concurrency 1 --limit 8 --output baseline.json# Перезапустите сервер с выбранным --spec-type; повторите те же аргументы:python tools/server/bench/speed-bench/speed_bench.py \  --url localhost:8080 --bench qualitative --category coding \  --osl 1024 --concurrency 1 --limit 8 --output spec.jsonpython tools/server/bench/speed-bench/speed_bench_compare.py \  --baseline baseline.json --speculative spec.json

Это **протокол для читателя**, не результат замера Modelium. В выводе клиента `accept_rate = accepted / draft_n`; сравнение считает отношение скорости декодирования и обратное отношение клиентских задержек. Фиксируйте число успешных и неуспешных запросов, различайте prefill и генерацию, проверяйте распределение по нескольким заданиям вместо одного «лучшего» числа. Если speculative снизил latency, но испортил полезность ответа на вашем контрольном наборе, не вводите его в рабочий процесс. [s3](#src-s3)

Для детерминированного smoke-теста можно отправить тот же чат-запрос на `/v1/chat/completions` с `temperature: 0`, фиксированным `seed` и одинаковым `max_tokens`; сервер описывает этот маршрут и параметры. Однако даже фиксированный seed не гарантирует побайтового совпадения при смене sampler/backend из-за численной арифметики. Сравнивайте факты, синтаксис кода и критерии своей задачи вручную; полное равенство строки — полезный диагностический сигнал, но не единственный критерий. **Не используйте** `--spec-synth-rates` или `--spec-synth-len` для проверки правильности: документация предупреждает, что их output не является валидным ответом модели. [s1](#src-s1) [s2](#src-s2)

## Что делать при слабом результате?

При нуле draft-предложений проверьте режим, длину текста и повторения; у n-gram-схемы они важны. При низкой acceptance у пары target/draft перепроверьте их происхождение и совместимость, а не приписывайте всё «медленному железу». При высокой acceptance и плохой end-to-end latency учитывайте стоимость второго прохода и среднюю длину ответа; оставьте baseline как откат: достаточно остановить сервер и запустить исходную команду с `--spec-type none`. Не смешивайте сравнения параллельной нагрузки с single-request тестом. [s1](#src-s1) [s2](#src-s2) [s3](#src-s3)

Смена параметров через HTTP в этой редакции ограничена: схема описывает отдельные поля `speculative.*`, но не полноценную безопасную замену модели и всех настроек в одном запросе. Для воспроизводимого опыта перезапускайте процесс с явными CLI-флагами. Так вы избежите неявно унаследованных настроек предыдущего прогона. [s6](#src-s6)

**Следующий шаг:** откройте [гайд llama.cpp](/zhurnal/llama-cpp/) для базового запуска, сохраните `baseline.json` и `spec.json` на том же target GGUF и вручную проверьте ответы на своих контрольных промптах. Ни время сервера, ни качество ответов для вашей конфигурации заранее не известны.

## Источники и граница проверки

Все восемь первоисточников относятся к закреплённому тегу v0.5.0, коммит `7fe450e19305b828c199d602c23a8337aaa1f03b`, получены 29 сентября 2026 года. Здесь нет собственных запусков модели, доказанной экономии времени, измерений памяти или юридического заключения о весах. [s1](#src-s1) [s2](#src-s2) [s3](#src-s3) [s4](#src-s4) [s5](#src-s5) [s6](#src-s6) [s7](#src-s7) [s8](#src-s8)

## Источники

1. [llama.cpp v0.5.0: документация speculative decoding](https://raw.githubusercontent.com/ggml-org/llama.cpp/7fe450e19305b828c199d602c23a8337aaa1f03b/docs/speculative.md) — получено 2026-09-29
2. [llama.cpp v0.5.0: llama-server README, параметры и метрики](https://raw.githubusercontent.com/ggml-org/llama.cpp/7fe450e19305b828c199d602c23a8337aaa1f03b/tools/server/README.md) — получено 2026-09-29
3. [llama.cpp v0.5.0: SPEED-Bench, клиентский протокол сравнения](https://raw.githubusercontent.com/ggml-org/llama.cpp/7fe450e19305b828c199d602c23a8337aaa1f03b/tools/server/bench/speed-bench/README.md) — получено 2026-09-29
4. [llama.cpp v0.5.0: пример пары Qwen3 target/draft](https://raw.githubusercontent.com/ggml-org/llama.cpp/7fe450e19305b828c199d602c23a8337aaa1f03b/examples/speculative-simple/README.md) — получено 2026-09-29
5. [llama.cpp v0.5.0: исходники параметров CLI](https://raw.githubusercontent.com/ggml-org/llama.cpp/7fe450e19305b828c199d602c23a8337aaa1f03b/common/arg.cpp) — получено 2026-09-29
6. [llama.cpp v0.5.0: схема параметров HTTP-сервера](https://raw.githubusercontent.com/ggml-org/llama.cpp/7fe450e19305b828c199d602c23a8337aaa1f03b/tools/server/server-schema.cpp) — получено 2026-09-29
7. [llama.cpp v0.5.0: счётчики принятия draft в server-context](https://raw.githubusercontent.com/ggml-org/llama.cpp/7fe450e19305b828c199d602c23a8337aaa1f03b/tools/server/server-context.cpp) — получено 2026-09-29
8. [llama.cpp v0.5.0: сборка llama-server из исходников](https://raw.githubusercontent.com/ggml-org/llama.cpp/7fe450e19305b828c199d602c23a8337aaa1f03b/docs/build.md) — получено 2026-09-29
