common : enable default speculative config

Assisted-by: pi:llama.cpp/DeepSeek-V4-Flash-Vision-Exp
This commit is contained in:
Georgi Gerganov
2026-09-04 16:25:14 +03:00
parent d646c9d155
commit 7c2e0dea43
10 changed files with 196 additions and 25 deletions
+50 -17
View File
@@ -355,7 +355,7 @@ static std::string get_default_local_path(const std::string & url) {
}
static bool spec_types_is_default(const common_params & params) {
return params.speculative.types == std::vector<enum common_speculative_type>{COMMON_SPECULATIVE_TYPE_NONE};
return !params.speculative.spec_type_specified;
}
common_models_handler common_models_handler_init(const common_params & params, llama_example curr_ex) {
@@ -1401,8 +1401,11 @@ common_params_context common_params_parser_init(common_params & params, llama_ex
} else if (ex == LLAMA_EXAMPLE_MTMD) {
params.use_jinja = false; // disable jinja by default
params.sampling.temp = 0.2; // lower temp by default for better quality
} else if (ex == LLAMA_EXAMPLE_SERVER) {
params.n_parallel = -1; // auto by default
} else if (ex == LLAMA_EXAMPLE_SERVER || ex == LLAMA_EXAMPLE_CLI) {
params.speculative = common_speculative_default_config();
if (ex == LLAMA_EXAMPLE_SERVER) {
params.n_parallel = -1; // auto by default
}
} else if (ex == LLAMA_EXAMPLE_TOKENIZE) {
params.parse_special = true; // parse special tokens by default, like the old tokenize tool
} else if (ex == LLAMA_EXAMPLE_TTS) {
@@ -4262,9 +4265,48 @@ common_params_context common_params_parser_init(common_params & params, llama_ex
[](common_params & params, const std::string & value) {
const auto types_str = string_split<std::string>(value, ',');
auto types = common_speculative_types_from_names(types_str);
params.speculative.types.insert(params.speculative.types.end(), types.begin(), types.end());
params.speculative.spec_type_specified = true;
if (types.size() == 1 && types.front() == COMMON_SPECULATIVE_TYPE_NONE) {
params.speculative.types = { COMMON_SPECULATIVE_TYPE_NONE };
return;
}
params.speculative.types.erase(
std::remove(params.speculative.types.begin(), params.speculative.types.end(), COMMON_SPECULATIVE_TYPE_NONE),
params.speculative.types.end());
for (const auto & type : types) {
if (std::find(params.speculative.types.begin(), params.speculative.types.end(), type) == params.speculative.types.end()) {
params.speculative.types.push_back(type);
}
}
}
).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_SPEC_TYPE"));
add_opt(common_arg(
{"--no-spec-type"}, common_speculative_all_types_str(),
string_format("comma-separated list of types of speculative decoding to remove\n"),
[](common_params & params, const std::string & value) {
const auto types_str = string_split<std::string>(value, ',');
auto types = common_speculative_types_from_names(types_str);
if (types.size() == 1 && types.front() == COMMON_SPECULATIVE_TYPE_NONE) {
params.speculative.spec_type_specified = true;
params.speculative.types = { COMMON_SPECULATIVE_TYPE_NONE };
return;
}
for (const auto & type : types) {
params.speculative.types.erase(
std::remove(params.speculative.types.begin(), params.speculative.types.end(), type),
params.speculative.types.end());
}
if (params.speculative.types.empty()) {
params.speculative.types = { COMMON_SPECULATIVE_TYPE_NONE };
}
}
).set_spec().set_examples({LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_NO_SPEC_TYPE"));
add_opt(common_arg(
{"--spec-ngram-mod-n-min"}, "N",
string_format("minimum number of ngram tokens to use for ngram-based speculative decoding (default: %d)", params.speculative.ngram_mod.n_min),
@@ -4731,20 +4773,11 @@ common_params_context common_params_parser_init(common_params & params, llama_ex
add_opt(common_arg(
{"--spec-default"},
string_format("enable default speculative decoding config"),
[](common_params & params) {
params.speculative.types.push_back(COMMON_SPECULATIVE_TYPE_NGRAM_MOD);
params.speculative.ngram_mod.n_match = 24;
params.speculative.ngram_mod.n_min = 48;
params.speculative.ngram_mod.n_max = 64;
// TODO: not sure if this is a good config - explore more settings and potentially enable it
//params.speculative.types.push_back(COMMON_SPECULATIVE_TYPE_NGRAM_MAP_K4V);
//params.speculative.ngram_map_k4v.size_n = 8;
//params.speculative.ngram_map_k4v.size_m = 24;
//params.speculative.ngram_map_k4v.min_hits = 2;
string_format("DEPRECATED: default speculative decoding is enabled by default, use --no-spec-type to remove types"),
[](common_params &) {
LOG_WRN("DEPRECATED: --spec-default is no longer needed; default speculative decoding is enabled by default\n");
}
).set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
).set_spec().set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_CLI}));
return ctx_arg;
}
+1
View File
@@ -369,6 +369,7 @@ struct common_params_speculative_ngram_cache {
struct common_params_speculative {
std::vector<enum common_speculative_type> types = { COMMON_SPECULATIVE_TYPE_NONE };
bool spec_type_specified = false; // set when --spec-type is used
double synth_len = -1.0;
std::vector<double> synth_rates;
+9
View File
@@ -44,6 +44,15 @@ const std::map<std::string, common_speculative_type> common_speculative_type_fro
{"ngram-cache", COMMON_SPECULATIVE_TYPE_NGRAM_CACHE}
};
common_params_speculative common_speculative_default_config() {
common_params_speculative result;
result.types = { COMMON_SPECULATIVE_TYPE_NGRAM_MOD };
result.ngram_mod.n_match = 24;
result.ngram_mod.n_min = 48;
result.ngram_mod.n_max = 64;
return result;
}
static std::string common_speculative_get_devices_str(const std::vector<ggml_backend_dev_t> & devices) {
std::string result;
for (size_t i = 0; i < devices.size(); i++) {
+3
View File
@@ -5,6 +5,9 @@
struct common_speculative;
// return the default speculative decoding configuration
common_params_speculative common_speculative_default_config();
// comma separated list the provided types
std::string common_speculative_type_name_str(const std::vector<enum common_speculative_type> & types);
+4 -1
View File
@@ -26,7 +26,7 @@ ctx-size = 0
mmap = 1
kv-unified = 1
parallel = 4
spec-default = 1
no-spec-type = ngram-mod
[Qwen3.5-4B]
hf = unsloth/Qwen3.5-4B-GGUF:Q4_K_M
@@ -52,6 +52,9 @@ chat-template-kwargs = {"reasoning_effort": "high"}
The preset will be loaded similarly to the `--models-preset` option. Therefore, you can also override certain params via CLI arguments:
> [!NOTE]
> A default speculative decoding is enabled by default for the server and CLI.
```sh
# Force temp = 0.1, overriding the preset value
llama-cli -hf username/my-preset --temp 0.1
+5 -3
View File
@@ -226,10 +226,12 @@ Use exactly one of these options:
```
--spec-type [none|draft-simple|draft-eagle3|draft-dflash|draft-dspark|draft-mtp|ngram-cache|ngram-simple|ngram-map-k|ngram-map-k4v|ngram-mod]
comma-separated list of types of speculative decoding to use
(default: none)
(default: server/CLI default config, none for other tools)
(env: LLAMA_ARG_SPEC_TYPE)
--spec-default use default speculative decoding config
(enables ngram-mod)
--no-spec-type [none|draft-simple|draft-eagle3|draft-dflash|draft-dspark|draft-mtp|ngram-cache|ngram-simple|ngram-map-k|ngram-map-k4v|ngram-mod]
comma-separated list of types of speculative decoding to remove
(env: LLAMA_ARG_NO_SPEC_TYPE)
--spec-default DEPRECATED: default speculative decoding is enabled by default
```
### Draft Model Parameters
+111
View File
@@ -254,6 +254,117 @@ static void test(void) {
assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), params, LLAMA_EXAMPLE_SPECULATIVE));
assert(params.speculative.draft.n_max == 123);
{
const auto types_ngram_mod = std::vector<enum common_speculative_type>{ COMMON_SPECULATIVE_TYPE_NGRAM_MOD };
const auto types_draft_mtp = std::vector<enum common_speculative_type>{ COMMON_SPECULATIVE_TYPE_DRAFT_MTP };
const auto types_none = std::vector<enum common_speculative_type>{ COMMON_SPECULATIVE_TYPE_NONE };
{
common_params spec_params;
argv = {"binary_name"};
assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), spec_params, LLAMA_EXAMPLE_SERVER));
assert(spec_params.speculative.types == types_ngram_mod);
}
{
common_params spec_params;
argv = {"binary_name", "--no-spec-type", "ngram-mod"};
assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), spec_params, LLAMA_EXAMPLE_SERVER));
assert(spec_params.speculative.types == types_none);
}
{
common_params spec_params;
argv = {"binary_name", "--spec-type", "draft-mtp"};
assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), spec_params, LLAMA_EXAMPLE_SERVER));
assert(spec_params.speculative.types == std::vector<enum common_speculative_type>({ COMMON_SPECULATIVE_TYPE_NGRAM_MOD, COMMON_SPECULATIVE_TYPE_DRAFT_MTP }));
}
{
common_params spec_params;
argv = {"binary_name", "--spec-type", "ngram-mod"};
assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), spec_params, LLAMA_EXAMPLE_SERVER));
assert(spec_params.speculative.types == types_ngram_mod);
}
{
common_params spec_params;
argv = {"binary_name", "--spec-type", "ngram-mod,draft-mtp"};
assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), spec_params, LLAMA_EXAMPLE_SERVER));
assert(spec_params.speculative.types == std::vector<enum common_speculative_type>({ COMMON_SPECULATIVE_TYPE_NGRAM_MOD, COMMON_SPECULATIVE_TYPE_DRAFT_MTP }));
}
{
common_params spec_params;
argv = {"binary_name", "--no-spec-type", "ngram-mod", "--spec-type", "draft-mtp"};
assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), spec_params, LLAMA_EXAMPLE_SERVER));
assert(spec_params.speculative.types == types_draft_mtp);
}
{
common_params spec_params;
argv = {"binary_name", "--spec-type", "draft-mtp", "--no-spec-type", "ngram-mod"};
assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), spec_params, LLAMA_EXAMPLE_SERVER));
assert(spec_params.speculative.types == types_draft_mtp);
}
{
common_params spec_params;
argv = {"binary_name", "--no-spec-type", "draft-mtp"};
assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), spec_params, LLAMA_EXAMPLE_SERVER));
assert(spec_params.speculative.types == types_ngram_mod);
}
{
common_params spec_params;
argv = {"binary_name", "--no-spec-type", "ngram-mod", "--spec-type", "ngram-mod"};
assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), spec_params, LLAMA_EXAMPLE_SERVER));
assert(spec_params.speculative.types == types_ngram_mod);
}
{
common_params spec_params;
argv = {"binary_name", "--no-spec-type", "ngram-mod", "--spec-type", "ngram-mod,draft-mtp"};
assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), spec_params, LLAMA_EXAMPLE_SERVER));
assert(spec_params.speculative.types == std::vector<enum common_speculative_type>({ COMMON_SPECULATIVE_TYPE_NGRAM_MOD, COMMON_SPECULATIVE_TYPE_DRAFT_MTP }));
}
{
common_params spec_params;
argv = {"binary_name", "--spec-type", "none"};
assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), spec_params, LLAMA_EXAMPLE_SERVER));
assert(spec_params.speculative.types == types_none);
}
{
common_params spec_params;
argv = {"binary_name", "--no-spec-type", "none"};
assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), spec_params, LLAMA_EXAMPLE_SERVER));
assert(spec_params.speculative.types == types_none);
}
{
common_params spec_params;
argv = {"binary_name", "--spec-type", "none", "--spec-type", "draft-mtp"};
assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), spec_params, LLAMA_EXAMPLE_SERVER));
assert(spec_params.speculative.types == types_draft_mtp);
}
{
common_params spec_params;
argv = {"binary_name", "--spec-default"};
assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), spec_params, LLAMA_EXAMPLE_SERVER));
assert(spec_params.speculative.types == types_ngram_mod);
}
{
common_params spec_params;
argv = {"binary_name", "--spec-default", "--no-spec-type", "ngram-mod"};
assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), spec_params, LLAMA_EXAMPLE_SERVER));
assert(spec_params.speculative.types == types_none);
}
}
{
common_params synth_params;
argv = {"binary_name", "--spec-synth-len", "3.4"};
+7
View File
@@ -453,6 +453,13 @@ static void test_task_assembly() {
// -hfd on a repo without sidecars keeps resolving a full model as draft
common_params params;
assemble({"server", "-hf", "test/main:Q8_0", "-hfd", "test/small"}, params);
REQUIRE(params.speculative.types == std::vector<enum common_speculative_type>{COMMON_SPECULATIVE_TYPE_NGRAM_MOD});
REQUIRE_EQ(params.speculative.draft.mparams.path, cached("test/small", "draft-model-Q4_K_M.gguf"));
}
{
// --no-spec-type removes the default speculative type and keeps the fallback draft resolution
common_params params;
assemble({"server", "-hf", "test/main:Q8_0", "-hfd", "test/small", "--no-spec-type", "ngram-mod"}, params);
REQUIRE(params.speculative.types == std::vector<enum common_speculative_type>{COMMON_SPECULATIVE_TYPE_NONE});
REQUIRE_EQ(params.speculative.draft.mparams.path, cached("test/small", "draft-model-Q4_K_M.gguf"));
}
+3 -2
View File
@@ -209,7 +209,8 @@
| `--spec-draft-device, -devd, --device-draft <dev1,dev2,..>` | comma-separated list of devices to use for offloading the draft model (none = don't offload)<br/>use --list-devices to see a list of available devices |
| `--spec-draft-ngl, -ngld, --gpu-layers-draft, --n-gpu-layers-draft N` | max. number of draft model layers to store in VRAM, either an exact number, 'auto', or 'all' (default: auto)<br/>(env: LLAMA_ARG_N_GPU_LAYERS_DRAFT) |
| `--spec-draft-model, -md, --model-draft FNAME` | draft model for speculative decoding (default: unused)<br/>(env: LLAMA_ARG_SPEC_DRAFT_MODEL) |
| `--spec-type none,draft-simple,draft-eagle3,draft-mtp,draft-dflash,draft-dspark,ngram-simple,ngram-map-k,ngram-map-k4v,ngram-mod,ngram-cache` | comma-separated list of types of speculative decoding to use (default: none)<br/><br/>(env: LLAMA_ARG_SPEC_TYPE) |
| `--spec-type none,draft-simple,draft-eagle3,draft-mtp,draft-dflash,draft-dspark,ngram-simple,ngram-map-k,ngram-map-k4v,ngram-mod,ngram-cache` | comma-separated list of types of speculative decoding to use (default: default speculative config)<br/><br/>(env: LLAMA_ARG_SPEC_TYPE) |
| `--no-spec-type none,draft-simple,draft-eagle3,draft-mtp,draft-dflash,draft-dspark,ngram-simple,ngram-map-k,ngram-map-k4v,ngram-mod,ngram-cache` | comma-separated list of types of speculative decoding to remove<br/><br/>(env: LLAMA_ARG_NO_SPEC_TYPE) |
| `--spec-ngram-mod-n-min N` | minimum number of ngram tokens to use for ngram-based speculative decoding (default: 48) |
| `--spec-ngram-mod-n-max N` | maximum number of ngram tokens to use for ngram-based speculative decoding (default: 64) |
| `--spec-ngram-mod-n-match N` | ngram-mod lookup length (default: 24) |
@@ -228,6 +229,6 @@
| `--gpt-oss-120b-default` | use gpt-oss-120b (note: can download weights from the internet) |
| `--vision-gemma-4b-default` | use Gemma 3 4B QAT (note: can download weights from the internet) |
| `--vision-gemma-12b-default` | use Gemma 3 12B QAT (note: can download weights from the internet) |
| `--spec-default` | enable default speculative decoding config |
| `--spec-default` | DEPRECATED: default speculative decoding is enabled by default |
<!-- HELP_END -->
+3 -2
View File
@@ -270,7 +270,8 @@ For the full list of features, please refer to [server's changelog](https://gith
| `--spec-draft-device, -devd, --device-draft <dev1,dev2,..>` | comma-separated list of devices to use for offloading the draft model (none = don't offload)<br/>use --list-devices to see a list of available devices |
| `--spec-draft-ngl, -ngld, --gpu-layers-draft, --n-gpu-layers-draft N` | max. number of draft model layers to store in VRAM, either an exact number, 'auto', or 'all' (default: auto)<br/>(env: LLAMA_ARG_N_GPU_LAYERS_DRAFT) |
| `--spec-draft-model, -md, --model-draft FNAME` | draft model for speculative decoding (default: unused)<br/>(env: LLAMA_ARG_SPEC_DRAFT_MODEL) |
| `--spec-type none,draft-simple,draft-eagle3,draft-mtp,draft-dflash,draft-dspark,ngram-simple,ngram-map-k,ngram-map-k4v,ngram-mod,ngram-cache` | comma-separated list of types of speculative decoding to use (default: none)<br/><br/>(env: LLAMA_ARG_SPEC_TYPE) |
| `--spec-type none,draft-simple,draft-eagle3,draft-mtp,draft-dflash,draft-dspark,ngram-simple,ngram-map-k,ngram-map-k4v,ngram-mod,ngram-cache` | comma-separated list of types of speculative decoding to use (default: default speculative config)<br/><br/>(env: LLAMA_ARG_SPEC_TYPE) |
| `--no-spec-type none,draft-simple,draft-eagle3,draft-mtp,draft-dflash,draft-dspark,ngram-simple,ngram-map-k,ngram-map-k4v,ngram-mod,ngram-cache` | comma-separated list of types of speculative decoding to remove<br/><br/>(env: LLAMA_ARG_NO_SPEC_TYPE) |
| `--spec-ngram-mod-n-min N` | minimum number of ngram tokens to use for ngram-based speculative decoding (default: 48) |
| `--spec-ngram-mod-n-max N` | maximum number of ngram tokens to use for ngram-based speculative decoding (default: 64) |
| `--spec-ngram-mod-n-match N` | ngram-mod lookup length (default: 24) |
@@ -299,7 +300,7 @@ For the full list of features, please refer to [server's changelog](https://gith
| `--gpt-oss-120b-default` | use gpt-oss-120b (note: can download weights from the internet) |
| `--vision-gemma-4b-default` | use Gemma 3 4B QAT (note: can download weights from the internet) |
| `--vision-gemma-12b-default` | use Gemma 3 12B QAT (note: can download weights from the internet) |
| `--spec-default` | enable default speculative decoding config |
| `--spec-default` | DEPRECATED: default speculative decoding is enabled by default |
<!-- HELP_END -->