Commit 4b29d0262 for llama.cpp
commit 4b29d02629b76160350ded907c64b733d98a54d1
Author: Georgi Gerganov <ggerganov@gmail.com>
Date: Wed Nov 4 09:22:54 2026 +0200
common : fix -hf tag matching inside longer quant names (#31620)
* common : fix -hf tag matching inside longer quant names
":F16" picked a BF16 file when the repo had both, since "BF16"
contains "F16". The same applied to ":Q4_XS" vs "IQ4_XS". The tag
now has to start at a token boundary in the path.
Assisted-by: dsh:llama.cpp/ggml-org/GLM-5.3-Flash-GGUF (Mac Studio, M5 Ultra, 256GB)
* common : accept underscore as -hf tag boundary
Some repos separate the quant with an underscore, e.g.
stepfun-ai/Step-3.5-Flash-GGUF-Q4_K_S ships
step3p5_flash_Q4_K_S-00001-of-00012.gguf, which :Q4_K_S no longer
matched. Add _ to the token boundary and pin the tag and default
lookup cases.
---------
Co-authored-by: Pascal <admin@serveurperso.com>
diff --git a/common/download.cpp b/common/download.cpp
index 08531a2d0..4de93f30d 100644
--- a/common/download.cpp
+++ b/common/download.cpp
@@ -748,7 +748,8 @@ static hf_cache::hf_file find_best_model(const hf_cache::hf_files & files,
}
for (const auto & t : tags) {
- std::regex pattern(t + "[.-]", std::regex::icase);
+ // match the tag as a full token, so ":F16" does not match a BF16 file
+ std::regex pattern("(^|[-./_])" + t + "[.-]", std::regex::icase);
for (const auto & f : files) {
if (gguf_filename_is_model(f.path) &&
std::regex_search(f.path, pattern)) {
diff --git a/tests/test-model-resolution.cpp b/tests/test-model-resolution.cpp
index 705fd65fa..73a87482d 100644
--- a/tests/test-model-resolution.cpp
+++ b/tests/test-model-resolution.cpp
@@ -153,6 +153,20 @@ static const std::vector<std::string> vendors = {
"BlackSheep-24B.Q8_0.gguf",
};
+// a tag must match the full token: F16 ends inside BF16, Q4_XS inside IQ4_XS
+static const std::vector<std::string> twins = {
+ "model-BF16.gguf",
+ "model-F16.gguf",
+ "model-IQ4_XS.gguf",
+ "model-Q4_XS.gguf",
+};
+
+// an underscore separates the quant like a dash, as in step3p5_flash_Q4_K_S.gguf
+static const std::vector<std::string> underscore = {
+ "model_Q4_K_S.gguf",
+ "model_Q8_0.gguf",
+};
+
// every speculative sidecar type at the same quant
static const std::vector<std::string> quad = {
"model-Q8_0.gguf",
@@ -270,6 +284,32 @@ static const plan_case plan_cases[] = {
"TheDrummer_Model-24B-v4.1-Q8_0.gguf", {"TheDrummer_Model-24B-v4.1-Q8_0.gguf"},
"", "", "", "", ""},
+ // the tag picks the file carrying it as a full token, never a longer one
+ {"twins f16 tag", twins, "test/repo:F16", "", false, false,
+ "model-F16.gguf", {"model-F16.gguf"},
+ "", "", "", "", ""},
+
+ {"twins bf16 tag", twins, "test/repo:BF16", "", false, false,
+ "model-BF16.gguf", {"model-BF16.gguf"},
+ "", "", "", "", ""},
+
+ {"twins q4_xs tag", twins, "test/repo:Q4_XS", "", false, false,
+ "model-Q4_XS.gguf", {"model-Q4_XS.gguf"},
+ "", "", "", "", ""},
+
+ {"twins iq4_xs tag", twins, "test/repo:IQ4_XS", "", false, false,
+ "model-IQ4_XS.gguf", {"model-IQ4_XS.gguf"},
+ "", "", "", "", ""},
+
+ // the token boundary accepts an underscore, for the tag and the default lookup
+ {"underscore tag", underscore, "test/repo:Q4_K_S", "", false, false,
+ "model_Q4_K_S.gguf", {"model_Q4_K_S.gguf"},
+ "", "", "", "", ""},
+
+ {"underscore default", underscore, "test/repo", "", false, false,
+ "model_Q8_0.gguf", {"model_Q8_0.gguf"},
+ "", "", "", "", ""},
+
// every sidecar type resolves at the tag
{"quad exact tag", quad, "test/repo:Q8_0", "", true, false,
"model-Q8_0.gguf", {"model-Q8_0.gguf"},
@@ -868,7 +908,7 @@ static const real_repo real_repos[] = {
{"Q8_0", "MTP/Qwen3.8-27B-Uncensored-OrcaRouter-MTP-Q8_0.gguf", 1, "", "", "", "", ""},
{"BF16", "BF16/Qwen3.8-27B-Uncensored-OrcaRouter-FP8-derived-BF16-00001-of-00002.gguf", 2, "", "", "", "", ""},
{"Q5_K_M", "Qwen3.8-27B-Uncensored-OrcaRouter-Q5_K_M.gguf", 1, "", "", "", "", ""},
- {"F16", "BF16/Qwen3.8-27B-Uncensored-OrcaRouter-FP8-derived-BF16-00001-of-00002.gguf", 2, "", "", "", "", ""}},
+ {"F16", "", 0, "", "", "", "", ""}},
{"Q8_0", "Q5_K_M", "Q4_K_M", "BF16"}},
{"ChrisColeTech/qwen-image-edit-uncensored-GGUF",
@@ -980,7 +1020,7 @@ static const real_repo real_repos[] = {
{"Q8_0", "Qwen3.5-9B-The-Defiant-Fable-Uncnr-Heretic-NEO-MAX-MTP-Q8_0.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""},
{"IQ2_M", "Qwen3.5-9B-The-Defiant-Fable-Uncnr-Heretic-NEO-MAX-IQ2_M.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""},
{"BF16", "Qwen3.5-9B-The-Defiant-Fable-Uncnr-Heretic-plusIQ-NEO-MAX-MTP-bf16.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""},
- {"F16", "Qwen3.5-9B-The-Defiant-Fable-Uncnr-Heretic-plusIQ-NEO-MAX-MTP-bf16.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""}},
+ {"F16", "", 0, "", "", "", "", ""}},
{"Q8_0", "BF16", "Q4_K_S", "Q4_K_M", "IQ2_M"}},
{"DavidAU/Qwen3.6-27B-Heretic-Uncensored-FINETUNE-NEO-CODE-Di-IMatrix-MAX-GGUF",
@@ -1044,7 +1084,7 @@ static const real_repo real_repos[] = {
{"Q4_K_M", "Qwythos-27B-MTP-Q4_K_M.gguf", 1, "mmproj-Qwythos-27B-F16.gguf", "", "", "", ""},
{"Q8_0", "Qwythos-27B-MTP-Q8_0.gguf", 1, "mmproj-Qwythos-27B-F16.gguf", "", "", "", ""},
{"BF16", "Qwythos-27B-BF16.gguf", 1, "mmproj-Qwythos-27B-F16.gguf", "", "", "", ""},
- {"F16", "Qwythos-27B-BF16.gguf", 1, "mmproj-Qwythos-27B-F16.gguf", "", "", "", ""}},
+ {"F16", "", 0, "", "", "", "", ""}},
{"Q8_0", "Q5_K_M", "Q4_K_M", "BF16"}},
{"empero-ai/Qwythos-9B-v2-GGUF",
@@ -1199,6 +1239,20 @@ static const real_repo real_repos[] = {
{"BF16", "", 0, "", "", "", "eagle3-gpt-oss-120b-BF16.gguf", ""}},
{"MXFP4"}},
+ // F16 and BF16 in one repo, the F16 tag must not pick the BF16 file
+ {"ggml-org/Llama-2-7B-GGUF",
+ {{"Llama-2-7B-BF16.gguf"},
+ {"Llama-2-7B-F16.gguf"},
+ {"Llama-2-7B-Q4_0.gguf"},
+ {"Llama-2-7B-Q8_0.gguf"}},
+ {
+ {"", "Llama-2-7B-Q8_0.gguf", 1, "", "", "", "", ""},
+ {"Q8_0", "Llama-2-7B-Q8_0.gguf", 1, "", "", "", "", ""},
+ {"Q4_0", "Llama-2-7B-Q4_0.gguf", 1, "", "", "", "", ""},
+ {"F16", "Llama-2-7B-F16.gguf", 1, "", "", "", "", ""},
+ {"BF16", "Llama-2-7B-BF16.gguf", 1, "", "", "", "", ""}},
+ {"F16", "Q4_0", "Q8_0", "BF16"}},
+
{"ggml-org/MiMo-V2.6-Distill-Qwen-9B-GGUF",
{{"MiMo-V2.6-Distill-Qwen-9B-Q8_0.gguf"},
{"mmproj-MiMo-V2.6-Distill-Qwen-9B-Q8_0.gguf"}},
@@ -1412,7 +1466,7 @@ static const real_repo real_repos[] = {
{"Q4_K_M", "Qwen3.5-27B-Uncensored-HauhauCS-Aggressive-Q4_K_M.gguf", 1, "mmproj-Qwen3.5-27B-Uncensored-HauhauCS-Aggressive-f16.gguf", "", "", "", ""},
{"Q8_0", "Qwen3.5-27B-Uncensored-HauhauCS-Aggressive-Q8_0.gguf", 1, "mmproj-Qwen3.5-27B-Uncensored-HauhauCS-Aggressive-f16.gguf", "", "", "", ""},
{"BF16", "Qwen3.5-27B-Uncensored-HauhauCS-Aggressive-BF16.gguf", 1, "mmproj-Qwen3.5-27B-Uncensored-HauhauCS-Aggressive-f16.gguf", "", "", "", ""},
- {"F16", "Qwen3.5-27B-Uncensored-HauhauCS-Aggressive-BF16.gguf", 1, "mmproj-Qwen3.5-27B-Uncensored-HauhauCS-Aggressive-f16.gguf", "", "", "", ""}},
+ {"F16", "", 0, "", "", "", "", ""}},
{"Q8_0", "Q4_K_M", "Q3_K_M", "BF16"}},
{"HauhauCS/Qwen3.5-2B-Uncensored-HauhauCS-Aggressive",
@@ -1426,7 +1480,7 @@ static const real_repo real_repos[] = {
{"Q4_K_M", "Qwen3.5-2B-Uncensored-HauhauCS-Aggressive-Q4_K_M.gguf", 1, "mmproj-Qwen3.5-2B-Uncensored-HauhauCS-Aggressive-f16.gguf", "", "", "", ""},
{"Q8_0", "Qwen3.5-2B-Uncensored-HauhauCS-Aggressive-Q8_0.gguf", 1, "mmproj-Qwen3.5-2B-Uncensored-HauhauCS-Aggressive-f16.gguf", "", "", "", ""},
{"BF16", "Qwen3.5-2B-Uncensored-HauhauCS-Aggressive-BF16.gguf", 1, "mmproj-Qwen3.5-2B-Uncensored-HauhauCS-Aggressive-f16.gguf", "", "", "", ""},
- {"F16", "Qwen3.5-2B-Uncensored-HauhauCS-Aggressive-BF16.gguf", 1, "mmproj-Qwen3.5-2B-Uncensored-HauhauCS-Aggressive-f16.gguf", "", "", "", ""}},
+ {"F16", "", 0, "", "", "", "", ""}},
{"Q8_0", "Q6_K", "Q4_K_M", "BF16"}},
{"HauhauCS/Qwen3.5-4B-Uncensored-HauhauCS-Aggressive",
@@ -1622,7 +1676,7 @@ static const real_repo real_repos[] = {
{"IQ2_M", "Qwen3.8-27B-Uncensored-IQ2_M.gguf", 1, "mmproj-Qwen3.8-27B-Uncensored-F16.gguf", "", "", "", ""},
{"Q4_0", "Qwen3.8-27B-Uncensored-draft-Q4_0.gguf", 1, "mmproj-Qwen3.8-27B-Uncensored-F16.gguf", "", "", "", ""},
{"F16", "", 0, "", "", "", "", ""},
- {"mtp", "Qwen3.8-27B-Uncensored-noMTP-IQ2_M.gguf", 1, "mmproj-Qwen3.8-27B-Uncensored-F16.gguf", "", "", "", ""}},
+ {"mtp", "", 0, "", "", "", "", ""}},
{"Q8_0", "Q5_K_M", "Q4_K_M", "IQ2_M", "Q4_0"}},
{"kai-os/Carnice-V2-27b-GGUF",
@@ -1903,7 +1957,7 @@ static const real_repo real_repos[] = {
{"Q4_K_M", "Huihui-Qwen3-VL-4B-Instruct-abliterated-Q4_K_M.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""},
{"Q8_0", "Huihui-Qwen3-VL-4B-Instruct-abliterated-Q8_0.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""},
{"BF16", "Huihui-Qwen3-VL-4B-Instruct-abliterated-BF16.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""},
- {"F16", "Huihui-Qwen3-VL-4B-Instruct-abliterated-BF16.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""}},
+ {"F16", "", 0, "", "", "", "", ""}},
{"Q8_0", "Q4_K_M", "IQ4_XS", "BF16"}},
{"OBLITERATUS/Gemma-4-12B-OBLITERATED",
@@ -2291,7 +2345,7 @@ static const real_repo real_repos[] = {
{"Q8_0", "embeddinggemma-2-Q8_0.gguf", 1, "mmproj-Q8_0.gguf", "", "", "", ""},
{"BF16", "embeddinggemma-2-BF16.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""},
{"UD-Q6_K_XL", "embeddinggemma-2-UD-Q6_K_XL.gguf", 1, "mmproj-Q8_0.gguf", "", "", "", ""},
- {"F16", "embeddinggemma-2-BF16.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""}},
+ {"F16", "", 0, "", "", "", "", ""}},
{"Q6_K_XL", "Q4_K_XL", "Q8_0", "BF16"}},
{"unsloth/GLM-4.7-Flash-GGUF",
@@ -2320,7 +2374,7 @@ static const real_repo real_repos[] = {
{"Q8_0", "Q8_0/GLM-5.3-Flash-Q8_0-00001-of-00008.gguf", 8, "mmproj-BF16.gguf", "", "", "", ""},
{"BF16", "BF16/GLM-5.3-Flash-BF16-00001-of-00014.gguf", 14, "mmproj-BF16.gguf", "", "", "", ""},
{"UD-Q6_K_XL", "UD-Q6_K_XL/GLM-5.3-Flash-UD-Q6_K_XL-00001-of-00007.gguf", 7, "mmproj-BF16.gguf", "", "", "", ""},
- {"F16", "BF16/GLM-5.3-Flash-BF16-00001-of-00014.gguf", 14, "mmproj-BF16.gguf", "", "", "", ""}},
+ {"F16", "", 0, "", "", "", "", ""}},
{"Q6_K_XL", "IQ4_XS", "Q8_0", "BF16"}},
{"unsloth/GLM-5.3-GGUF",
@@ -2359,7 +2413,7 @@ static const real_repo real_repos[] = {
{"", "BF16/Kimi-K2.6-BF16-00001-of-00046.gguf", 46, "mmproj-BF16.gguf", "", "", "", ""},
{"BF16", "BF16/Kimi-K2.6-BF16-00001-of-00046.gguf", 46, "mmproj-BF16.gguf", "", "", "", ""},
{"UD-Q8_K_XL", "UD-Q8_K_XL/Kimi-K2.6-UD-Q8_K_XL-00001-of-00014.gguf", 14, "mmproj-BF16.gguf", "", "", "", ""},
- {"F16", "BF16/Kimi-K2.6-BF16-00001-of-00046.gguf", 46, "mmproj-BF16.gguf", "", "", "", ""}},
+ {"F16", "", 0, "", "", "", "", ""}},
{"Q8_K_XL", "Q4_K_XL", "BF16"}},
{"unsloth/Kimi-K2.7-Code-GGUF",
@@ -2405,7 +2459,7 @@ static const real_repo real_repos[] = {
{"Q8_0", "LFM2.5-VL-3B-Q8_0.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""},
{"BF16", "LFM2.5-VL-3B-BF16.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""},
{"UD-Q8_K_XL", "LFM2.5-VL-3B-UD-Q8_K_XL.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""},
- {"F16", "LFM2.5-VL-3B-BF16.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""}},
+ {"F16", "", 0, "", "", "", "", ""}},
{"Q8_K_XL", "Q8_0", "Q5_K_S", "Q4_K_M", "BF16"}},
{"unsloth/NVIDIA-Nemotron-3.5-Lightning-30B-A3B-GGUF",
@@ -2449,7 +2503,7 @@ static const real_repo real_repos[] = {
{"Q8_0", "Qwen3-VL-30B-A3B-Instruct-Q8_0.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""},
{"BF16", "BF16/Qwen3-VL-30B-A3B-Instruct-BF16-00001-of-00002.gguf", 2, "mmproj-BF16.gguf", "", "", "", ""},
{"UD-TQ1_0", "Qwen3-VL-30B-A3B-Instruct-UD-TQ1_0.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""},
- {"F16", "BF16/Qwen3-VL-30B-A3B-Instruct-BF16-00001-of-00002.gguf", 2, "mmproj-BF16.gguf", "", "", "", ""}},
+ {"F16", "", 0, "", "", "", "", ""}},
{"TQ1_0", "Q8_0", "Q6_K", "Q4_K_M", "BF16"}},
{"unsloth/Qwen3.5-27B-GGUF",
@@ -2467,7 +2521,7 @@ static const real_repo real_repos[] = {
{"Q8_0", "Qwen3.5-27B-Q8_0.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""},
{"BF16", "BF16/Qwen3.5-27B-BF16-00001-of-00002.gguf", 2, "mmproj-BF16.gguf", "", "", "", ""},
{"UD-Q8_K_XL", "Qwen3.5-27B-UD-Q8_K_XL.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""},
- {"F16", "BF16/Qwen3.5-27B-BF16-00001-of-00002.gguf", 2, "mmproj-BF16.gguf", "", "", "", ""}},
+ {"F16", "", 0, "", "", "", "", ""}},
{"Q8_K_XL", "Q8_0", "Q6_K", "Q4_K_M", "BF16"}},
{"unsloth/Qwen3.5-35B-A3B-GGUF",
@@ -2485,7 +2539,7 @@ static const real_repo real_repos[] = {
{"Q8_0", "Qwen3.5-35B-A3B-Q8_0.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""},
{"BF16", "BF16/Qwen3.5-35B-A3B-BF16-00001-of-00002.gguf", 2, "mmproj-BF16.gguf", "", "", "", ""},
{"UD-Q8_K_XL", "Qwen3.5-35B-A3B-UD-Q8_K_XL.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""},
- {"F16", "BF16/Qwen3.5-35B-A3B-BF16-00001-of-00002.gguf", 2, "mmproj-BF16.gguf", "", "", "", ""}},
+ {"F16", "", 0, "", "", "", "", ""}},
{"Q8_K_XL", "IQ3_S", "Q8_0", "Q4_K_M", "BF16"}},
{"unsloth/Qwen3.5-397B-A17B-GGUF",
@@ -2503,7 +2557,7 @@ static const real_repo real_repos[] = {
{"Q8_0", "Q8_0/Qwen3.5-397B-A17B-Q8_0-00001-of-00010.gguf", 10, "mmproj-BF16.gguf", "", "", "", ""},
{"BF16", "BF16/Qwen3.5-397B-A17B-BF16-00001-of-00017.gguf", 17, "mmproj-BF16.gguf", "", "", "", ""},
{"UD-Q8_K_XL", "UD-Q8_K_XL/Qwen3.5-397B-A17B-UD-Q8_K_XL-00001-of-00010.gguf", 10, "mmproj-BF16.gguf", "", "", "", ""},
- {"F16", "BF16/Qwen3.5-397B-A17B-BF16-00001-of-00017.gguf", 17, "mmproj-BF16.gguf", "", "", "", ""}},
+ {"F16", "", 0, "", "", "", "", ""}},
{"Q8_K_XL", "IQ3_XXS", "Q8_0", "Q4_K_M", "BF16"}},
{"unsloth/Qwen3.6-35B-A3B-MTP-GGUF",
@@ -2519,7 +2573,7 @@ static const real_repo real_repos[] = {
{"Q8_0", "Qwen3.6-35B-A3B-Q8_0.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""},
{"BF16", "BF16/Qwen3.6-35B-A3B-BF16-00001-of-00002.gguf", 2, "mmproj-BF16.gguf", "", "", "", ""},
{"UD-Q8_K_XL", "Qwen3.6-35B-A3B-UD-Q8_K_XL.gguf", 1, "mmproj-BF16.gguf", "", "", "", ""},
- {"F16", "BF16/Qwen3.6-35B-A3B-BF16-00001-of-00002.gguf", 2, "mmproj-BF16.gguf", "", "", "", ""}},
+ {"F16", "", 0, "", "", "", "", ""}},
{"Q8_K_XL", "Q3_K_M", "Q8_0", "BF16"}},
{"unsloth/Qwen3.8-Flash-Next-GGUF",
@@ -2557,7 +2611,7 @@ static const real_repo real_repos[] = {
{"Q8_0", "Q8_0/Step-3.7-Flash-Q8_0-00001-of-00006.gguf", 6, "mmproj-BF16.gguf", "", "", "", ""},
{"BF16", "BF16/Step-3.7-Flash-BF16-00001-of-00008.gguf", 8, "mmproj-BF16.gguf", "", "", "", ""},
{"UD-Q8_K_XL", "UD-Q8_K_XL/Step-3.7-Flash-UD-Q8_K_XL-00001-of-00006.gguf", 6, "mmproj-BF16.gguf", "", "", "", ""},
- {"F16", "BF16/Step-3.7-Flash-BF16-00001-of-00008.gguf", 8, "mmproj-BF16.gguf", "", "", "", ""}},
+ {"F16", "", 0, "", "", "", "", ""}},
{"Q8_K_XL", "Q3_K_M", "Q8_0", "BF16"}},
{"vmlinux/Qwen3.8-Flash-Next-Uncensored-Gufo-Q4Mix-GGUF",