Compare commits

..

15 Commits

Author SHA1 Message Date
Sigbjørn Skjæret d3a2eb592d disable on windows 2025-05-31 23:17:18 +02:00
Sigbjørn Skjæret 7210ebe230 revert build changes 2025-05-31 23:16:56 +02:00
Sigbjørn Skjæret 05f94a0e90 add arch to matrix 2025-05-31 22:54:37 +02:00
Sigbjørn Skjæret f9a27178e5 download in batches 2025-05-31 22:35:26 +02:00
Sigbjørn Skjæret de8ec1348b Merge branch 'master' into cisc/test-tokenizers-remote 2025-05-31 21:25:34 +02:00
Sigbjørn Skjæret 8e1125a8db copy curl dll for tests 2025-05-31 21:22:37 +02:00
Jiří Podivín b3a89c3d9e docs : Note about necessity of having libcurl installed for standard build. (#13945)
Signed-off-by: Jiri Podivin <jpodivin@gmail.com>
2025-05-31 18:58:35 +02:00
Olivier Chafik e15898d1c7 server: allow unclosed thinking tags (#13931) 2025-05-31 08:26:10 -07:00
Georgi Gerganov 803f8baf4f llama : deprecate explicit kv_self defrag/update calls (#13921)
ggml-ci
2025-05-31 15:58:33 +03:00
Sigbjørn Skjæret 4b4843adf3 windows builds adds build type to runtime output 2025-05-30 11:51:46 +02:00
Sigbjørn Skjæret d97b9ade51 correct working directory for all builds
..and change cache file name as per suggestion.
2025-05-28 12:49:36 +02:00
Sigbjørn Skjæret 0fe7183ae4 fix prototype for non-curl builds 2025-05-28 11:11:02 +02:00
Sigbjørn Skjæret ecbc92acd0 correct working directory 2025-05-28 10:16:34 +02:00
Sigbjørn Skjæret 42ff1867bc add test-tokenizers-remote 2025-05-28 09:51:44 +02:00
Sigbjørn Skjæret 2d2e059f4f make common_download_file_single/multiple public 2025-05-28 09:50:41 +02:00
10 changed files with 200 additions and 23 deletions
+4 -4
View File
@@ -244,7 +244,7 @@ static bool curl_perform_with_retry(const std::string & url, CURL * curl, int ma
}
// download one single file from remote URL to local path
static bool common_download_file_single(const std::string & url, const std::string & path, const std::string & bearer_token, bool offline) {
bool common_download_file_single(const std::string & url, const std::string & path, const std::string & bearer_token, bool offline) {
// Check if the file already exists locally
auto file_exists = std::filesystem::exists(path);
@@ -467,7 +467,7 @@ static bool common_download_file_single(const std::string & url, const std::stri
// download multiple files from remote URLs to local paths
// the input is a vector of pairs <url, path>
static bool common_download_file_multiple(const std::vector<std::pair<std::string, std::string>> & urls, const std::string & bearer_token, bool offline) {
bool common_download_file_multiple(const std::vector<std::pair<std::string, std::string>> & urls, const std::string & bearer_token, bool offline) {
// Prepare download in parallel
std::vector<std::future<bool>> futures_download;
for (auto const & item : urls) {
@@ -711,12 +711,12 @@ bool common_has_curl() {
return false;
}
static bool common_download_file_single(const std::string &, const std::string &, const std::string &, bool) {
bool common_download_file_single(const std::string &, const std::string &, const std::string &, bool) {
LOG_ERR("error: built without CURL, cannot download model from internet\n");
return false;
}
static bool common_download_file_multiple(const std::vector<std::pair<std::string, std::string>> &, const std::string &, bool) {
bool common_download_file_multiple(const std::vector<std::pair<std::string, std::string>> &, const std::string &, bool) {
LOG_ERR("error: built without CURL, cannot download model from the internet\n");
return false;
}
+7
View File
@@ -87,3 +87,10 @@ struct common_remote_params {
};
// get remote file content, returns <http_code, raw_response_body>
std::pair<long, std::vector<char>> common_remote_get_content(const std::string & url, const common_remote_params & params);
// download one single file from remote URL to local path
bool common_download_file_single(const std::string & url, const std::string & path, const std::string & bearer_token, bool offline);
// download multiple files from remote URLs to local paths
// the input is a vector of pairs <url, path>
bool common_download_file_multiple(const std::vector<std::pair<std::string, std::string>> & urls, const std::string & bearer_token, bool offline);
+4 -3
View File
@@ -154,9 +154,10 @@ bool common_chat_msg_parser::try_parse_reasoning(const std::string & start_think
if (!rest.empty()) {
handle_reasoning(rest, /* closed */ !is_partial());
}
if (!syntax_.thinking_forced_open) {
throw common_chat_msg_partial_exception(end_think);
}
// Allow unclosed thinking tags, for now (https://github.com/ggml-org/llama.cpp/issues/13812, https://github.com/ggml-org/llama.cpp/issues/13877)
// if (!syntax_.thinking_forced_open) {
// throw common_chat_msg_partial_exception(end_think);
// }
return true;
}
}
+1
View File
@@ -63,6 +63,7 @@ cmake --build build --config Release
cmake --preset x64-windows-llvm-release
cmake --build build-x64-windows-llvm-release
```
- Curl usage is enabled by default and can be turned off with `-DLLAMA_CURL=OFF`. Otherwise you need to install development libraries for libcurl.
## BLAS Build
+2 -7
View File
@@ -133,9 +133,8 @@ int main(int argc, char ** argv) {
const int ib = i/n_batch - 1;
const int bd = n_batch_grp*(n_grp - 1);
llama_kv_self_seq_add (ctx, 0, n_past - n_batch, n_past, ib*bd);
llama_kv_self_seq_div (ctx, 0, n_past - n_batch + ib*bd, n_past + ib*bd, n_grp);
llama_kv_self_update (ctx);
llama_kv_self_seq_add(ctx, 0, n_past - n_batch, n_past, ib*bd);
llama_kv_self_seq_div(ctx, 0, n_past - n_batch + ib*bd, n_past + ib*bd, n_grp);
n_past = llama_kv_self_seq_pos_max(ctx, 0) + 1;
}
@@ -169,8 +168,6 @@ int main(int argc, char ** argv) {
llama_kv_self_seq_rm (ctx, 0, n_keep , n_keep + n_discard);
llama_kv_self_seq_add(ctx, 0, n_keep + n_discard, n_ctx, -n_discard);
//llama_kv_self_defrag (ctx);
llama_kv_self_update (ctx);
n_past = llama_kv_self_seq_pos_max(ctx, 0) + 1;
@@ -200,8 +197,6 @@ int main(int argc, char ** argv) {
llama_kv_self_seq_rm (ctx, 0, n_keep , n_keep + n_discard);
llama_kv_self_seq_add(ctx, 0, n_keep + n_discard, n_ctx, -n_discard);
//llama_kv_self_defrag (ctx);
llama_kv_self_update (ctx);
n_past = llama_kv_self_seq_pos_max(ctx, 0) + 1;
}
+4 -7
View File
@@ -655,7 +655,6 @@ extern "C" {
// Adds relative position "delta" to all tokens that belong to the specified sequence and have positions in [p0, p1)
// If the KV cache is RoPEd, the KV data is updated accordingly:
// - lazily on next llama_decode()
// - explicitly with llama_kv_self_update()
// p0 < 0 : [0, p1]
// p1 < 0 : [p0, inf)
LLAMA_API void llama_kv_self_seq_add(
@@ -668,7 +667,6 @@ extern "C" {
// Integer division of the positions by factor of `d > 1`
// If the KV cache is RoPEd, the KV data is updated accordingly:
// - lazily on next llama_decode()
// - explicitly with llama_kv_self_update()
// p0 < 0 : [0, p1]
// p1 < 0 : [p0, inf)
LLAMA_API void llama_kv_self_seq_div(
@@ -696,16 +694,15 @@ extern "C" {
// Defragment the KV cache
// This will be applied:
// - lazily on next llama_decode()
// - explicitly with llama_kv_self_update()
// TODO: deprecate and always update the cache lazily [TAG: API_KV_NO_DEFRAG]
LLAMA_API void llama_kv_self_defrag(struct llama_context * ctx);
LLAMA_API DEPRECATED(void llama_kv_self_defrag(struct llama_context * ctx),
"simply remove this call, the context will automatically decide when to do a defragmentation based on 'defrag_thold'");
// Check if the context supports KV cache shifting
LLAMA_API bool llama_kv_self_can_shift(const struct llama_context * ctx);
// Apply the KV cache updates (such as K-shifts, defragmentation, etc.)
// TODO: deprecate and always update the cache lazily [TAG: API_KV_NO_DEFRAG]
LLAMA_API void llama_kv_self_update(struct llama_context * ctx);
LLAMA_API DEPRECATED(void llama_kv_self_update(struct llama_context * ctx),
"simply remove this call, updates are applied lazily on the next llama_decode()");
//
// State / sessions
+2
View File
@@ -2281,6 +2281,7 @@ llama_kv_cache * llama_get_kv_self(llama_context * ctx) {
return ctx->get_kv_self();
}
// deprecated
void llama_kv_self_update(llama_context * ctx) {
ctx->kv_self_update();
}
@@ -2535,6 +2536,7 @@ llama_pos llama_kv_self_seq_pos_max(llama_context * ctx, llama_seq_id seq_id) {
return kv->seq_pos_max(seq_id);
}
// deprecated
void llama_kv_self_defrag(llama_context * ctx) {
auto * kv = ctx->get_kv_self();
if (!kv) {
+3 -2
View File
@@ -97,8 +97,9 @@ llama_test(test-tokenizer-0 NAME test-tokenizer-0-qwen2 ARGS ${CMAKE
llama_test(test-tokenizer-0 NAME test-tokenizer-0-refact ARGS ${CMAKE_CURRENT_SOURCE_DIR}/../models/ggml-vocab-refact.gguf)
llama_test(test-tokenizer-0 NAME test-tokenizer-0-starcoder ARGS ${CMAKE_CURRENT_SOURCE_DIR}/../models/ggml-vocab-starcoder.gguf)
# TODO: missing HF tokenizer for this model in convert_hf_to_gguf_update.py, see https://github.com/ggml-org/llama.cpp/pull/13847
# llama_test(test-tokenizer-0 NAME test-tokenizer-0-nomic-bert-moe ARGS ${CMAKE_CURRENT_SOURCE_DIR}/../models/ggml-vocab-nomic-bert-moe.gguf)
if (LLAMA_CURL AND NOT WIN32)
llama_build_and_test(test-tokenizers-remote.cpp WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
endif()
if (LLAMA_LLGUIDANCE)
llama_build_and_test(test-grammar-llguidance.cpp ARGS ${CMAKE_CURRENT_SOURCE_DIR}/../models/ggml-vocab-llama-bpe.gguf)
+9
View File
@@ -1041,6 +1041,15 @@ static void test_template_output_parsers() {
"<tool_call>\n"
"{\"name\": \"python\", \"arguments\": {\"code\":\"# This is a program:\\nprint('hey')\"}}\n"
"</tool_call>");
assert_msg_equals(
simple_assist_msg("", /* reasoning_content= */ "<tool_call>nah uhg</tool_call>"),
common_chat_parse(
"<think><tool_call>nah uhg</tool_call>",
/* is_partial= */ false,
{
/* .format = */ COMMON_CHAT_FORMAT_HERMES_2_PRO,
/* .reasoning_format = */ COMMON_REASONING_FORMAT_DEEPSEEK,
}));
}
{
auto tmpls = read_templates("models/templates/meta-llama-Llama-3.1-8B-Instruct.jinja");
+164
View File
@@ -0,0 +1,164 @@
#include "arg.h"
#include "common.h"
#include <string>
#include <fstream>
#include <vector>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
#undef NDEBUG
#include <cassert>
std::string endpoint = "https://huggingface.co/";
std::string repo = "ggml-org/vocabs";
static void write_file(const std::string & fname, const std::string & content) {
std::ofstream file(fname);
if (file) {
file << content;
file.close();
}
}
static json get_hf_repo_dir(const std::string & hf_repo_with_branch, bool recursive, const std::string & repo_path, const std::string & bearer_token) {
auto parts = string_split<std::string>(hf_repo_with_branch, ':');
std::string branch = parts.size() > 1 ? parts.back() : "main";
std::string hf_repo = parts[0];
std::string url = endpoint + "api/models/" + hf_repo + "/tree/" + branch;
std::string path = repo_path;
if (!path.empty()) {
// FIXME: path should be properly url-encoded!
string_replace_all(path, "/", "%2F");
url += "/" + path;
}
if (recursive) {
url += "?recursive=true";
}
// headers
std::vector<std::string> headers;
headers.push_back("Accept: application/json");
if (!bearer_token.empty()) {
headers.push_back("Authorization: Bearer " + bearer_token);
}
// we use "=" to avoid clashing with other component, while still being allowed on windows
std::string cached_response_fname = "test_vocab=" + hf_repo + "/" + repo_path + "=" + branch + ".json";
string_replace_all(cached_response_fname, "/", "_");
std::string cached_response_path = fs_get_cache_file(cached_response_fname);
// make the request
common_remote_params params;
params.headers = headers;
json res_data;
try {
// TODO: For pagination links we need response headers, which is not provided by common_remote_get_content()
auto res = common_remote_get_content(url, params);
long res_code = res.first;
std::string res_str = std::string(res.second.data(), res.second.size());
if (res_code == 200) {
write_file(cached_response_path, res_str);
} else if (res_code == 401) {
throw std::runtime_error("error: model is private or does not exist; if you are accessing a gated model, please provide a valid HF token");
} else {
throw std::runtime_error(string_format("error from HF API, response code: %ld, data: %s", res_code, res_str.c_str()));
}
} catch (const std::exception & e) {
fprintf(stderr, "error: failed to get repo tree: %s\n", e.what());
fprintf(stderr, "try reading from cache\n");
}
// try to read from cache
try {
std::ifstream f(cached_response_path);
res_data = json::parse(f);
} catch (const std::exception & e) {
fprintf(stderr, "error: failed to get repo tree (check your internet connection)\n");
}
return res_data;
}
int main(void) {
if (common_has_curl()) {
json tree = get_hf_repo_dir(repo, true, {}, {});
if (!tree.empty()) {
std::vector<std::pair<std::string, std::string>> files;
for (const auto & item : tree) {
if (item.at("type") == "file") {
std::string path = item.at("path");
if (string_ends_with(path, ".gguf") || string_ends_with(path, ".gguf.inp") || string_ends_with(path, ".gguf.out")) {
// this is to avoid different repo having same file name, or same file name in different subdirs
std::string filepath = repo + "_" + path;
// to make sure we don't have any slashes in the filename
string_replace_all(filepath, "/", "_");
// to make sure we don't have any quotes in the filename
string_replace_all(filepath, "'", "_");
filepath = fs_get_cache_file(filepath);
files.push_back({endpoint + repo + "/resolve/main/" + path, filepath});
}
}
}
if (!files.empty()) {
bool downloaded = false;
const size_t batch_size = 6;
size_t batches = (files.size() + batch_size - 1) / batch_size;
for (size_t i = 0; i < batches; i++) {
size_t batch_pos = (i * batch_size);
size_t batch_step = batch_pos + batch_size;
auto batch_begin = files.begin() + batch_pos;
auto batch_end = batch_step >= files.size() ? files.end() : files.begin() + batch_step;
std::vector<std::pair<std::string, std::string>> batch(batch_begin, batch_end);
if (!(downloaded = common_download_file_multiple(batch, {}, false))) {
break;
}
}
if (downloaded) {
std::string dir_sep(1, DIRECTORY_SEPARATOR);
for (auto const & item : files) {
std::string filepath = item.second;
if (string_ends_with(filepath, ".gguf")) {
std::string vocab_inp = filepath + ".inp";
std::string vocab_out = filepath + ".out";
auto matching_inp = std::find_if(files.begin(), files.end(), [&vocab_inp](const auto & p) {
return p.second == vocab_inp;
});
auto matching_out = std::find_if(files.begin(), files.end(), [&vocab_out](const auto & p) {
return p.second == vocab_out;
});
if (matching_inp != files.end() && matching_out != files.end()) {
std::string test_command = "." + dir_sep + "test-tokenizer-0 '" + filepath + "'";
assert(std::system(test_command.c_str()) == 0);
} else {
printf("test-tokenizers-remote: %s found without .inp/out vocab files, skipping...\n", filepath.c_str());
}
}
}
} else {
printf("test-tokenizers-remote: failed to download files, unable to perform tests...\n");
}
}
} else {
printf("test-tokenizers-remote: failed to retrieve repository info, unable to perform tests...\n");
}
} else {
printf("test-tokenizers-remote: no curl, unable to perform tests...\n");
}
}