From bb2d2496be730e4b1d0cd11cd4152c5a70a7ecd1 Mon Sep 17 00:00:00 2001 From: Mikhail Sotnikov Date: Wed, 4 Mar 2026 18:01:56 +0300 Subject: [PATCH 01/48] (improvement) llamacpp-llm: Qwen3 dynamic tools template --- .../src/utils/Qwen3ToolsDynamicTemplate.cpp | 89 +++++++++++++++++++ .../src/utils/Qwen3ToolsDynamicTemplate.hpp | 15 ++++ 2 files changed, 104 insertions(+) create mode 100644 packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/Qwen3ToolsDynamicTemplate.cpp create mode 100644 packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/Qwen3ToolsDynamicTemplate.hpp diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/Qwen3ToolsDynamicTemplate.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/Qwen3ToolsDynamicTemplate.cpp new file mode 100644 index 0000000000..b086b81b9d --- /dev/null +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/Qwen3ToolsDynamicTemplate.cpp @@ -0,0 +1,89 @@ +#include "QwenTemplate.hpp" + +namespace qvac_lib_inference_addon_llama { +namespace utils { + +const char* getToolsDynamicQwen3Template() { + return R"({%- if messages[0].role == 'system' %} + {{- '<|im_start|>system\n' + messages[0].content + '<|im_end|>\n' }} +{%- endif %} +{%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %} +{%- for message in messages[::-1] %} + {%- set index = (messages|length - 1) - loop.index0 %} + {%- if ns.multi_step_tool and message.role == "user" and not(message.content.startswith('') and message.content.endswith('')) %} + {%- set ns.multi_step_tool = false %} + {%- set ns.last_query_index = index %} + {%- endif %} +{%- endfor %} +{%- for message in messages %} + {%- if (message.role == "user") or (message.role == "system" and not loop.first) %} + {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>' + '\n' }} + {%- elif message.role == "assistant" %} + {%- set content = message.content %} + {%- set reasoning_content = '' %} + {%- if message.reasoning_content is defined and message.reasoning_content is not none %} + {%- set reasoning_content = message.reasoning_content %} + {%- else %} + {%- if '' in message.content %} + {%- set parts = message.content.split('') %} + {%- set content = parts[-1] | trim %} + {%- set think_parts = parts[0].split('') %} + {%- set reasoning_content = think_parts[-1] | trim %} + {%- endif %} + {%- endif %} + {%- if reasoning_content %} + {{- '<|im_start|>' + message.role + '\n\n' + (reasoning_content | trim) + '\n\n\n' + (content | trim) }} + {%- else %} + {{- '<|im_start|>' + message.role + '\n' + content }} + {%- endif %} + {%- if message.tool_calls %} + {%- for tool_call in message.tool_calls %} + {%- if (loop.first and content) or (not loop.first) %} + {{- '\n' }} + {%- endif %} + {%- if tool_call.function %} + {%- set tool_call = tool_call.function %} + {%- endif %} + {{- '\n{"name": "' }} + {{- tool_call.name }} + {{- '", "arguments": ' }} + {%- if tool_call.arguments is string %} + {{- tool_call.arguments }} + {%- else %} + {{- tool_call.arguments | tojson }} + {%- endif %} + {{- '}\n' }} + {%- endfor %} + {%- endif %} + {{- '<|im_end|>\n' }} + {%- elif message.role == "tool" %} + {%- if loop.first or (messages[loop.index0 - 1].role != "tool") %} + {{- '<|im_start|>user' }} + {%- endif %} + {{- '\n\n' }} + {{- message.content }} + {{- '\n' }} + {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %} + {{- '<|im_end|>\n' }} + {%- endif %} + {%- endif %} +{%- endfor %} +{%- if tools %} + {{- '<|im_start|>system\n' }} + {{- "# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within XML tags:\n" }} + {%- for tool in tools %} + {{- "\n" }} + {{- tool | tojson }} + {%- endfor %} + {{- "\n\n\nFor each function call, return a json object with function name and arguments within XML tags:\n\n{\"name\": , \"arguments\": }\n<|im_end|>\n" }} +{%- endif %} +{%- if add_generation_prompt %} + {{- '<|im_start|>assistant\n' }} + {%- if enable_thinking is defined and enable_thinking is false %} + {{- '\n\n\n\n' }} + {%- endif %} +{%- endif %})"; +} + +} // namespace utils +} // namespace qvac_lib_inference_addon_llama diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/Qwen3ToolsDynamicTemplate.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/Qwen3ToolsDynamicTemplate.hpp new file mode 100644 index 0000000000..fb5a9f8b92 --- /dev/null +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/Qwen3ToolsDynamicTemplate.hpp @@ -0,0 +1,15 @@ +#pragma once + +namespace qvac_lib_inference_addon_llama { +namespace utils { + +// Uses fxed Qwen3 chat template as a base +// see QwenTemplate.hpp +// +// Changes: Tools are put in additional system prompt at the end +// in order to apply new (different) tools on each user prompt +const char* getToolsDynamicQwen3Template(); + +} // namespace utils +} // namespace qvac_lib_inference_addon_llama + From b9ed67202189195f4a18f9727a2a4a5dbbcca75a Mon Sep 17 00:00:00 2001 From: Mikhail Sotnikov Date: Wed, 4 Mar 2026 19:28:50 +0300 Subject: [PATCH 02/48] (improvement) llamacpp-llm: add llm config tools flag --- .../addon/src/model-interface/LlamaModel.cpp | 14 +++ .../addon/src/model-interface/LlamaModel.hpp | 1 + .../addon/src/model-interface/LlmContext.hpp | 5 ++ .../src/model-interface/MtmdLlmContext.cpp | 4 + .../src/model-interface/MtmdLlmContext.hpp | 4 + .../src/model-interface/TextLlmContext.cpp | 4 + .../src/model-interface/TextLlmContext.hpp | 4 + .../test/unit/test_llama_model.cpp | 87 +++++++++++++++++++ 8 files changed, 123 insertions(+) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp index 05e8af4e50..de18b1a20e 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp @@ -235,6 +235,11 @@ void LlamaModel::init(bool acquireLock) { params, std::move(llamaInit)); + // Apply tools_at_end flag + if (snap->llmContext_) { + snap->llmContext_->setToolsAtEnd(snap->toolsAtEnd_); + } + if (snap->configuredNDiscarded_ > 0 && snap->llmContext_) { snap->llmContext_->setNDiscarded(snap->configuredNDiscarded_); } @@ -476,6 +481,15 @@ void LlamaModel::commonParamsParse( configFilemap.erase(iter); } + // parse tools_at_end flag from config + if (auto iter = configFilemap.find("tools_at_end"); + iter != configFilemap.end()) { + std::string val = iter->second; + std::transform(val.begin(), val.end(), val.begin(), ::tolower); + state_->toolsAtEnd_ = (val == "true"); + configFilemap.erase(iter); + } + auto deviceIt = configFilemap.find("device"); if (deviceIt == configFilemap.end()) { std::string errorMsg = diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp index 5231360487..aa45dcc59f 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp @@ -181,6 +181,7 @@ class LlamaModel : public IModel, public IModelAsyncLoad, public IModelCancel { // configuration values parsed from configFilemap llama_pos configuredNDiscarded_ = 0; + bool toolsAtEnd_ = false; std::optional cacheManager_; bool lastRunWasPrefill_ = false; }; diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp index 3261d9f8eb..3e85043bc3 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp @@ -181,6 +181,11 @@ class LlmContext { // NOLINT(cppcoreguidelines-special-member-functions) */ virtual void setNDiscarded(llama_pos nDiscarded) = 0; + /** + * Set whether tools should be placed at the end of the prompt. + */ + virtual void setToolsAtEnd(bool toolsAtEnd) = 0; + /** * The load media method. It loads the media from memory buffer. * Default implementation does nothing (for text-only contexts). diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp index 469dcabe79..e39697b608 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp @@ -446,6 +446,10 @@ void MtmdLlmContext::setNDiscarded(llama_pos nDiscarded) { this->nDiscarded_ = nDiscarded; } +void MtmdLlmContext::setToolsAtEnd(bool toolsAtEnd) { + this->toolsAtEnd_ = toolsAtEnd; +} + void MtmdLlmContext::loadMedia(const std::vector& media) { if (media.empty()) { resetMedia(); diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp index f81d099073..f3bc947a5b 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp @@ -112,6 +112,8 @@ class MtmdLlmContext: public LlmContext { */ void setNDiscarded(llama_pos nDiscarded) override; + void setToolsAtEnd(bool toolsAtEnd) override; + /** * The load media method. It loads the media from memory buffer. * @@ -199,6 +201,8 @@ class MtmdLlmContext: public LlmContext { // UTF-8 token buffer for handling incomplete emoji sequences qvac_lib_inference_addon_llama::UTF8TokenBuffer utf8Buffer_; std::atomic stopGeneration_ = false; + + bool toolsAtEnd_ = false; }; diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp index 6d9afe23f7..fe38d33301 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp @@ -534,6 +534,10 @@ void TextLlmContext::setNDiscarded(llama_pos nDiscarded) { this->nDiscarded_ = nDiscarded; } +void TextLlmContext::setToolsAtEnd(bool toolsAtEnd) { + this->toolsAtEnd_ = toolsAtEnd; +} + llama_pos TextLlmContext::removeLastNTokens(llama_pos count) { // Validate input if (count <= 0) { diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp index 9514b2cbce..ef3c290e43 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp @@ -104,6 +104,8 @@ class TextLlmContext: public LlmContext { */ void setNDiscarded(llama_pos nDiscarded) override; + void setToolsAtEnd(bool toolsAtEnd) override; + /** * The reset state method. It resets the context. * @@ -177,6 +179,8 @@ class TextLlmContext: public LlmContext { bool isQwen3Model_ = false; std::atomic stopGeneration_ = false; + + bool toolsAtEnd_ = false; }; diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_llama_model.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_llama_model.cpp index 5bb80420e2..ab3fcd771f 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_llama_model.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_llama_model.cpp @@ -1052,3 +1052,90 @@ TEST_F(LlamaModelTest, ReloadDuringProcessingWaitsAndDoesNotCrash) { EXPECT_GE(output.length(), 0); }); } + +TEST_F(LlamaModelTest, CommonParamsParseToolsAtEndTrue) { + if (!fs::exists(getValidModelPath())) { + FAIL() << "Test model not found at: " << getValidModelPath(); + } + + std::unordered_map config; + config["device"] = test_common::getTestDevice(); + config["ctx_size"] = "2048"; + config["gpu_layers"] = test_common::getTestGpuLayers(); + config["n_predict"] = "10"; + config["tools_at_end"] = "true"; + + fs::path backendDir; +#ifdef TEST_BINARY_DIR + backendDir = fs::path(TEST_BINARY_DIR); +#else + backendDir = fs::current_path() / "build" / "test" / "unit"; +#endif + config["backendsDir"] = backendDir.string(); + + EXPECT_NO_THROW({ + LlamaModel model( + getValidModelPath(), + std::string(test_projection_path), + std::unordered_map(config)); + model.waitForLoadInitialization(); + }); +} + +TEST_F(LlamaModelTest, CommonParamsParseToolsAtEndFalse) { + if (!fs::exists(getValidModelPath())) { + FAIL() << "Test model not found at: " << getValidModelPath(); + } + + std::unordered_map config; + config["device"] = test_common::getTestDevice(); + config["ctx_size"] = "2048"; + config["gpu_layers"] = test_common::getTestGpuLayers(); + config["n_predict"] = "10"; + config["tools_at_end"] = "false"; + + fs::path backendDir; +#ifdef TEST_BINARY_DIR + backendDir = fs::path(TEST_BINARY_DIR); +#else + backendDir = fs::current_path() / "build" / "test" / "unit"; +#endif + config["backendsDir"] = backendDir.string(); + + EXPECT_NO_THROW({ + LlamaModel model( + getValidModelPath(), + std::string(test_projection_path), + std::unordered_map(config)); + model.waitForLoadInitialization(); + }); +} + +TEST_F(LlamaModelTest, CommonParamsParseToolsAtEndUppercase) { + if (!fs::exists(getValidModelPath())) { + FAIL() << "Test model not found at: " << getValidModelPath(); + } + + std::unordered_map config; + config["device"] = test_common::getTestDevice(); + config["ctx_size"] = "2048"; + config["gpu_layers"] = test_common::getTestGpuLayers(); + config["n_predict"] = "10"; + config["tools_at_end"] = "TRUE"; + + fs::path backendDir; +#ifdef TEST_BINARY_DIR + backendDir = fs::path(TEST_BINARY_DIR); +#else + backendDir = fs::current_path() / "build" / "test" / "unit"; +#endif + config["backendsDir"] = backendDir.string(); + + EXPECT_NO_THROW({ + LlamaModel model( + getValidModelPath(), + std::string(test_projection_path), + std::unordered_map(config)); + model.waitForLoadInitialization(); + }); +} From 48cedbde73c1308f4cb3164055f2f7a4cf04b896 Mon Sep 17 00:00:00 2001 From: Mikhail Sotnikov Date: Wed, 4 Mar 2026 21:39:27 +0300 Subject: [PATCH 03/48] (improvement) llamacpp-llm: use template based on tools param --- .../src/model-interface/MtmdLlmContext.cpp | 2 +- .../src/model-interface/TextLlmContext.cpp | 2 +- .../addon/src/utils/ChatTemplateUtils.cpp | 19 +++-- .../addon/src/utils/ChatTemplateUtils.hpp | 13 +++- .../test/unit/CMakeLists.txt | 1 + .../test/unit/test_chat_template_utils.cpp | 73 ++++++++++++++++--- 6 files changed, 85 insertions(+), 25 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp index e39697b608..78fdd49093 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp @@ -40,7 +40,7 @@ MtmdLlmContext::MtmdLlmContext( vocab_ = llama_model_get_vocab(model_); - std::string chatTemplate = getChatTemplate(model_, params_); + std::string chatTemplate = getChatTemplate(model_, params_, toolsAtEnd_); tmpls_ = common_chat_templates_init(model_, chatTemplate); smpl_.reset(common_sampler_init(model_, params_.sampling)); diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp index fe38d33301..b9f153102e 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp @@ -49,7 +49,7 @@ TextLlmContext::TextLlmContext( lctx_, reasoningState_); } - std::string chatTemplate = getChatTemplate(model_, params_); + std::string chatTemplate = getChatTemplate(model_, params_, toolsAtEnd_); tmpls_ = common_chat_templates_init(model_, chatTemplate); smpl_.reset(common_sampler_init(model_, params_.sampling)); diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.cpp index 802c00d4e1..6e4e23116d 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.cpp @@ -5,6 +5,7 @@ #include #include "QwenTemplate.hpp" +#include "Qwen3ToolsDynamicTemplate.hpp" #include "utils/LoggingMacros.hpp" using namespace qvac_lib_inference_addon_cpp::logger; @@ -58,27 +59,29 @@ bool isQwen3Model(const ::llama_model* model) { } std::string getChatTemplateForModel( - const ::llama_model* model, const std::string& manualOverride) { - // If manual override is provided, use it as-is + const ::llama_model* model, + const std::string& manualOverride, + bool toolsAtEnd) { if (!manualOverride.empty()) { return manualOverride; } - // For Qwen3 models, use the fixed template if (isQwen3Model(model)) { - return getFixedQwen3Template(); + return toolsAtEnd ? getToolsDynamicQwen3Template() : getFixedQwen3Template(); } - // For other models, no override needed return ""; } -std::string -getChatTemplate(const ::llama_model* model, const common_params& params) { +std::string getChatTemplate( + const ::llama_model* model, + const common_params& params, + bool toolsAtEnd) { // Use fixed Qwen3 template if model is Qwen3 and Jinja is enabled std::string chatTemplate = params.chat_template; if (params.use_jinja) { - chatTemplate = getChatTemplateForModel(model, params.chat_template); + chatTemplate = getChatTemplateForModel( + model, params.chat_template, toolsAtEnd); if (!chatTemplate.empty() && chatTemplate != params.chat_template) { QLOG_IF( Priority::INFO, "[ChatTemplateUtils] Using fixed Qwen3 template\n"); diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.hpp index 0d73101918..8a22ecea94 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.hpp @@ -17,18 +17,23 @@ bool isQwen3Model(const ::llama_model* model); /** * @brief Gets the appropriate chat template for a model * - * For Qwen3 models, returns the fixed template from QwenTemplate.hpp. + * For Qwen3 models, returns the fixed template or tools-at-end template + * based on the toolsAtEnd flag. * For other models, returns the manual override or empty string. */ std::string getChatTemplateForModel( - const ::llama_model* model, const std::string& manualOverride); + const ::llama_model* model, + const std::string& manualOverride, + bool toolsAtEnd); /** * @brief Gets the chat template for a model, applying Qwen3 fixes if Jinja is * enabled */ -std::string -getChatTemplate(const ::llama_model* model, const common_params& params); +std::string getChatTemplate( + const ::llama_model* model, + const common_params& params, + bool toolsAtEnd); /** * @brief Applies chat templates to generate a prompt, with fallback handling diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/CMakeLists.txt b/packages/qvac-lib-infer-llamacpp-llm/test/unit/CMakeLists.txt index 2c96b5903e..dea6ed2a5e 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/CMakeLists.txt +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/CMakeLists.txt @@ -41,6 +41,7 @@ add_executable( ${CMAKE_SOURCE_DIR}/addon/src/utils/ChatTemplateUtils.cpp ${CMAKE_SOURCE_DIR}/addon/src/utils/Qwen3ReasoningUtils.cpp ${CMAKE_SOURCE_DIR}/addon/src/utils/QwenTemplate.cpp + ${CMAKE_SOURCE_DIR}/addon/src/utils/Qwen3ToolsDynamicTemplate.cpp ) target_compile_options( diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_chat_template_utils.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_chat_template_utils.cpp index 14742e74e2..ef2db48f01 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_chat_template_utils.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_chat_template_utils.cpp @@ -8,6 +8,8 @@ #include "model-interface/LlamaModel.hpp" #include "test_common.hpp" #include "utils/ChatTemplateUtils.hpp" +#include "utils/Qwen3ToolsDynamicTemplate.hpp" +#include "utils/QwenTemplate.hpp" namespace fs = std::filesystem; using namespace qvac_lib_inference_addon_llama::utils; @@ -37,14 +39,25 @@ TEST_F(ChatTemplateUtilsTest, IsQwen3ModelWithNullptr) { EXPECT_FALSE(isQwen3Model(nullptr)); } -TEST_F(ChatTemplateUtilsTest, GetChatTemplateForModelWithManualOverride) { +TEST_F(ChatTemplateUtilsTest, GetChatTemplateForModelWithManualOverrideToolsAtEndFalse) { std::string manual_override = "custom template"; - std::string result = getChatTemplateForModel(nullptr, manual_override); + std::string result = getChatTemplateForModel(nullptr, manual_override, false); EXPECT_EQ(result, manual_override); } -TEST_F(ChatTemplateUtilsTest, GetChatTemplateForModelEmptyOverrideNullptr) { - std::string result = getChatTemplateForModel(nullptr, ""); +TEST_F(ChatTemplateUtilsTest, GetChatTemplateForModelWithManualOverrideToolsAtEndTrue) { + std::string manual_override = "custom template"; + std::string result = getChatTemplateForModel(nullptr, manual_override, true); + EXPECT_EQ(result, manual_override); +} + +TEST_F(ChatTemplateUtilsTest, GetChatTemplateForModelEmptyOverrideNullptrToolsAtEndFalse) { + std::string result = getChatTemplateForModel(nullptr, "", false); + EXPECT_EQ(result, ""); +} + +TEST_F(ChatTemplateUtilsTest, GetChatTemplateForModelEmptyOverrideNullptrToolsAtEndTrue) { + std::string result = getChatTemplateForModel(nullptr, "", true); EXPECT_EQ(result, ""); } @@ -53,7 +66,7 @@ TEST_F(ChatTemplateUtilsTest, GetChatTemplateWithNullptrModel) { params.chat_template = "test template"; params.use_jinja = false; - std::string result = getChatTemplate(nullptr, params); + std::string result = getChatTemplate(nullptr, params, false); EXPECT_EQ(result, params.chat_template); } @@ -62,7 +75,7 @@ TEST_F(ChatTemplateUtilsTest, GetChatTemplateJinjaDisabled) { params.chat_template = "test template"; params.use_jinja = false; - std::string result = getChatTemplate(nullptr, params); + std::string result = getChatTemplate(nullptr, params, false); EXPECT_EQ(result, "test template"); } @@ -71,7 +84,7 @@ TEST_F(ChatTemplateUtilsTest, GetChatTemplateJinjaEnabledWithOverride) { params.chat_template = "custom template"; params.use_jinja = true; - std::string result = getChatTemplate(nullptr, params); + std::string result = getChatTemplate(nullptr, params, false); EXPECT_EQ(result, "custom template"); } @@ -80,7 +93,7 @@ TEST_F(ChatTemplateUtilsTest, GetChatTemplateJinjaEnabledWithoutOverride) { params.chat_template = ""; params.use_jinja = true; - std::string result = getChatTemplate(nullptr, params); + std::string result = getChatTemplate(nullptr, params, false); EXPECT_EQ(result, ""); } @@ -89,7 +102,7 @@ TEST_F(ChatTemplateUtilsTest, GetChatTemplateParamsNotModified) { params.chat_template = "original template"; params.use_jinja = false; - std::string result = getChatTemplate(nullptr, params); + std::string result = getChatTemplate(nullptr, params, false); EXPECT_EQ(params.chat_template, "original template"); EXPECT_FALSE(params.use_jinja); @@ -98,13 +111,51 @@ TEST_F(ChatTemplateUtilsTest, GetChatTemplateParamsNotModified) { TEST_F(ChatTemplateUtilsTest, GetChatTemplateForModelPreservesWhitespace) { std::string overrideWithSpaces = " template with spaces "; - std::string result = getChatTemplateForModel(nullptr, overrideWithSpaces); + std::string result = getChatTemplateForModel(nullptr, overrideWithSpaces, false); EXPECT_EQ(result, overrideWithSpaces); } TEST_F( ChatTemplateUtilsTest, GetChatTemplateForModelPreservesSpecialCharacters) { std::string overrideSpecial = "template\nwith\tspecial\rchars"; - std::string result = getChatTemplateForModel(nullptr, overrideSpecial); + std::string result = getChatTemplateForModel(nullptr, overrideSpecial, false); EXPECT_EQ(result, overrideSpecial); } + +TEST_F(ChatTemplateUtilsTest, GetFixedQwen3TemplateNotNull) { + const char* expectedTemplate = getFixedQwen3Template(); + ASSERT_NE(expectedTemplate, nullptr); + EXPECT_GT(strlen(expectedTemplate), 0u); +} + +TEST_F(ChatTemplateUtilsTest, GetToolsDynamicQwen3TemplateNotNull) { + const char* expectedTemplate = getToolsDynamicQwen3Template(); + ASSERT_NE(expectedTemplate, nullptr); + EXPECT_GT(strlen(expectedTemplate), 0u); +} + +TEST_F(ChatTemplateUtilsTest, TemplatesAreDifferent) { + const char* fixedTemplate = getFixedQwen3Template(); + const char* dynamicTemplate = getToolsDynamicQwen3Template(); + ASSERT_NE(fixedTemplate, nullptr); + ASSERT_NE(dynamicTemplate, nullptr); + EXPECT_STRNE(fixedTemplate, dynamicTemplate); +} + +TEST_F(ChatTemplateUtilsTest, ManualOverrideTakesPrecedenceOverToolsAtEnd) { + common_params params; + params.chat_template = "my_custom_template"; + params.use_jinja = true; + + std::string result = getChatTemplate(nullptr, params, true); + EXPECT_EQ(result, "my_custom_template"); +} + +TEST_F(ChatTemplateUtilsTest, ManualOverrideTakesPrecedenceOverToolsAtEndFalse) { + common_params params; + params.chat_template = "my_custom_template"; + params.use_jinja = true; + + std::string result = getChatTemplate(nullptr, params, false); + EXPECT_EQ(result, "my_custom_template"); +} From 3bf572d48a60b66576e2b8a6aeed34f05d07f7df Mon Sep 17 00:00:00 2001 From: Mikhail Sotnikov Date: Wed, 4 Mar 2026 23:09:18 +0300 Subject: [PATCH 04/48] (improvement) llamacpp-llm: count tools token offset with tokenizer --- .../addon/src/model-interface/LlamaModel.cpp | 7 + .../addon/src/model-interface/LlamaModel.hpp | 6 + .../addon/src/model-interface/LlmContext.hpp | 7 + .../src/model-interface/MtmdLlmContext.cpp | 32 ++ .../src/model-interface/MtmdLlmContext.hpp | 4 + .../src/model-interface/TextLlmContext.cpp | 15 + .../src/model-interface/TextLlmContext.hpp | 4 + .../test/unit/test_text_llm_context.cpp | 403 ++++++++++++++++++ 8 files changed, 478 insertions(+) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp index de18b1a20e..435243055e 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp @@ -264,6 +264,13 @@ bool LlamaModel::isLoaded() { return static_cast(state_->llmContext_); } +llama_pos LlamaModel::getNConversationOnlyTokens() const { + if (llmContext_) { + return llmContext_->getNConversationOnlyTokens(); + } + return 0; +} + void LlamaModel::llamaLogCallback( ggml_log_level level, const char* text, void* userData) { (void)userData; diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp index aa45dcc59f..6d64a2f9e8 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp @@ -126,6 +126,12 @@ class LlamaModel : public IModel, public IModelAsyncLoad, public IModelCancel { */ bool isLoaded(); + /** + * Get the number of conversation-only tokens (without tools). + * This is set when toolsAtEnd is enabled and tools are provided. + */ + llama_pos getNConversationOnlyTokens() const; + /** * Ensure model is initialized */ diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp index 3e85043bc3..738c63fcc8 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp @@ -186,6 +186,13 @@ class LlmContext { // NOLINT(cppcoreguidelines-special-member-functions) */ virtual void setToolsAtEnd(bool toolsAtEnd) = 0; + /** + * Get the number of conversation-only tokens (without tools). + * This is used for double-tokenization to find the boundary between + * conversation tokens and tool tokens. + */ + [[nodiscard]] virtual llama_pos getNConversationOnlyTokens() const = 0; + /** * The load media method. It loads the media from memory buffer. * Default implementation does nothing (for text-only contexts). diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp index 78fdd49093..03ebfcd5da 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp @@ -204,6 +204,34 @@ void MtmdLlmContext::tokenizeChat( throw qvac_errors::StatusError(ADDON_ID, toString(EncoderFailed), errorMsg); } + if (toolsAtEnd_ && !tools.empty()) { + auto savedTools = inputs.tools; + inputs.tools = {}; + auto promptNoTools = getPrompt(tmpls_.get(), inputs); + inputs.tools = savedTools; + + if (!promptNoTools.empty()) { + mtmd_input_text textNoTools; + textNoTools.text = promptNoTools.c_str(); + textNoTools.add_special = addSpecial; + textNoTools.parse_special = true; + + mtmd::input_chunks chunksNoTools(mtmd_input_chunks_init()); + int32_t resNoTools = mtmd_tokenize( + ctxVision_.get(), + chunksNoTools.ptr.get(), + &textNoTools, + bitmapsCPtr.data(), + bitmapsCPtr.size()); + + if (resNoTools == 0) { + nConversationOnlyTokens_ = mtmd_helper_get_n_tokens(chunksNoTools.ptr.get()); + } + } + } else { + nConversationOnlyTokens_ = 0; + } + resetMedia(); } @@ -450,6 +478,10 @@ void MtmdLlmContext::setToolsAtEnd(bool toolsAtEnd) { this->toolsAtEnd_ = toolsAtEnd; } +llama_pos MtmdLlmContext::getNConversationOnlyTokens() const { + return nConversationOnlyTokens_; +} + void MtmdLlmContext::loadMedia(const std::vector& media) { if (media.empty()) { resetMedia(); diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp index f3bc947a5b..7824555fe5 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp @@ -114,6 +114,8 @@ class MtmdLlmContext: public LlmContext { void setToolsAtEnd(bool toolsAtEnd) override; + [[nodiscard]] llama_pos getNConversationOnlyTokens() const override; + /** * The load media method. It loads the media from memory buffer. * @@ -203,6 +205,8 @@ class MtmdLlmContext: public LlmContext { std::atomic stopGeneration_ = false; bool toolsAtEnd_ = false; + + llama_pos nConversationOnlyTokens_ = 0; }; diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp index b9f153102e..065012b162 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp @@ -217,6 +217,17 @@ void TextLlmContext::tokenizeChat( if (!prompt.empty()) { inputTokens = common_tokenize(lctx_, prompt, addSpecial, true); + + if (toolsAtEnd_ && !tools.empty()) { + auto savedTools = inputs.tools; + inputs.tools = {}; + auto promptNoTools = getPrompt(tmpls_.get(), inputs); + auto tokensNoTools = common_tokenize(lctx_, promptNoTools, addSpecial, true); + inputs.tools = savedTools; + nConversationOnlyTokens_ = tokensNoTools.size(); + } else { + nConversationOnlyTokens_ = 0; + } } else { std::string errorMsg = string_format( "[TextLlm] %s: formatted chat prompt is empty\n", __func__); @@ -538,6 +549,10 @@ void TextLlmContext::setToolsAtEnd(bool toolsAtEnd) { this->toolsAtEnd_ = toolsAtEnd; } +llama_pos TextLlmContext::getNConversationOnlyTokens() const { + return nConversationOnlyTokens_; +} + llama_pos TextLlmContext::removeLastNTokens(llama_pos count) { // Validate input if (count <= 0) { diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp index ef3c290e43..491d05b05d 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp @@ -106,6 +106,8 @@ class TextLlmContext: public LlmContext { void setToolsAtEnd(bool toolsAtEnd) override; + [[nodiscard]] llama_pos getNConversationOnlyTokens() const override; + /** * The reset state method. It resets the context. * @@ -181,6 +183,8 @@ class TextLlmContext: public LlmContext { std::atomic stopGeneration_ = false; bool toolsAtEnd_ = false; + + llama_pos nConversationOnlyTokens_ = 0; }; diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context.cpp index 131a3c3c86..d0c880a55a 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -371,3 +372,405 @@ TEST_F(TextLlmContextTest, ProcessWithMultipleTools) { EXPECT_GE(stats.size(), 0); }); } + +TEST_F(TextLlmContextTest, DoubleTokenizeWithToolsAtEnd) { + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + LlamaModel::Prompt prompt; + prompt.input = R"([ + {"role": "user", "content": "What is the weather in Tokyo?"}, + { + "type": "function", + "name": "getWeather", + "description": "Get weather forecast for a city", + "parameters": { + "type": "object", + "properties": { + "city": {"type": "string", "description": "City name"}, + "date": {"type": "string", "description": "Date in YYYY-MM-DD"} + }, + "required": ["city", "date"] + } + } + ])"; + + EXPECT_NO_THROW({ + std::string output = model->processPrompt(prompt); + }); + + llama_pos nConvTokens = model->getNConversationOnlyTokens(); + EXPECT_GT(nConvTokens, 0); +} + +TEST_F(TextLlmContextTest, DoubleTokenizeWithoutToolsAtEnd) { + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "false"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + LlamaModel::Prompt prompt; + prompt.input = R"([ + {"role": "user", "content": "What is the weather in Tokyo?"}, + { + "type": "function", + "name": "getWeather", + "description": "Get weather forecast for a city", + "parameters": { + "type": "object", + "properties": { + "city": {"type": "string", "description": "City name"}, + "date": {"type": "string", "description": "Date in YYYY-MM-DD"} + }, + "required": ["city", "date"] + } + } + ])"; + + EXPECT_NO_THROW({ + std::string output = model->processPrompt(prompt); + }); + + llama_pos nConvTokens = model->getNConversationOnlyTokens(); + EXPECT_EQ(nConvTokens, 0); +} + +TEST_F(TextLlmContextTest, DoubleTokenizeWithToolsAtEndNoTools) { + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + LlamaModel::Prompt prompt; + prompt.input = R"([{"role": "user", "content": "Hello, how are you?"}])"; + + EXPECT_NO_THROW({ + std::string output = model->processPrompt(prompt); + }); + + llama_pos nConvTokens = model->getNConversationOnlyTokens(); + EXPECT_EQ(nConvTokens, 0); +} + +TEST_F(TextLlmContextTest, DoubleTokenizeWithMultipleTools) { + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + LlamaModel::Prompt prompt; + prompt.input = R"([ + {"role": "user", "content": "Search for laptops and add to cart"}, + { + "type": "function", + "name": "searchProducts", + "description": "Search products", + "parameters": { + "type": "object", + "properties": { + "query": {"type": "string", "description": "Search query"} + }, + "required": ["query"] + } + }, + { + "type": "function", + "name": "addToCart", + "description": "Add items to cart", + "parameters": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": {"type": "string"} + } + }, + "required": ["items"] + } + } + ])"; + + EXPECT_NO_THROW({ + std::string output = model->processPrompt(prompt); + }); + + llama_pos nConvTokens = model->getNConversationOnlyTokens(); + EXPECT_GT(nConvTokens, 0); +} + +TEST_F(TextLlmContextTest, DoubleTokenizeBoundaryAccuracy) { + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + LlamaModel::Prompt promptWithTools; + promptWithTools.input = R"([ + {"role": "user", "content": "What is the weather in Tokyo?"}, + { + "type": "function", + "name": "getWeather", + "description": "Get weather forecast for a city", + "parameters": { + "type": "object", + "properties": { + "city": {"type": "string", "description": "City name"}, + "date": {"type": "string", "description": "Date in YYYY-MM-DD"} + }, + "required": ["city", "date"] + } + } + ])"; + + EXPECT_NO_THROW({ + std::string output = model->processPrompt(promptWithTools); + }); + + llama_pos conversationTokens = model->getNConversationOnlyTokens(); + + EXPECT_NO_THROW({ + model->reset(); + }); + + LlamaModel::Prompt promptNoTools; + promptNoTools.input = R"([{"role": "user", "content": "What is the weather in Tokyo?"}])"; + + EXPECT_NO_THROW({ + std::string output = model->processPrompt(promptNoTools); + }); + + llama_pos tokensWithoutTools = model->getNConversationOnlyTokens(); + + EXPECT_EQ(tokensWithoutTools, 0); + EXPECT_GT(conversationTokens, 0); +} + +TEST_F(TextLlmContextTest, DoubleTokenizationTimeOverhead) { + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + const std::string promptWithTools = R"([ + {"role": "user", "content": "What is the weather in Tokyo?"}, + { + "type": "function", + "name": "getWeather", + "description": "Get weather forecast for a city", + "parameters": { + "type": "object", + "properties": { + "city": {"type": "string", "description": "City name"}, + "date": {"type": "string", "description": "Date in YYYY-MM-DD"} + }, + "required": ["city", "date"] + } + } + ])"; + + const int numIterations = 10; + + { + config_files["tools_at_end"] = "false"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + LlamaModel::Prompt prompt; + prompt.input = promptWithTools; + + auto startSingle = std::chrono::high_resolution_clock::now(); + for (int i = 0; i < numIterations; ++i) { + model->reset(); + std::string output = model->processPrompt(prompt); + } + auto endSingle = std::chrono::high_resolution_clock::now(); + auto durationSingle = std::chrono::duration_cast( + endSingle - startSingle) + .count(); + + auto stats = model->runtimeStats(); + int promptTokens = static_cast(getStatValue(stats, "promptTokens")); + + GTEST_LOG_(INFO) << "Single tokenization (no tools_at_end): " + << durationSingle / numIterations << " us per iteration (" + << promptTokens << " prompt tokens)"; + } + + { + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + LlamaModel::Prompt prompt; + prompt.input = promptWithTools; + + auto startDouble = std::chrono::high_resolution_clock::now(); + for (int i = 0; i < numIterations; ++i) { + model->reset(); + std::string output = model->processPrompt(prompt); + } + auto endDouble = std::chrono::high_resolution_clock::now(); + auto durationDouble = std::chrono::duration_cast( + endDouble - startDouble) + .count(); + + auto stats = model->runtimeStats(); + int promptTokens = static_cast(getStatValue(stats, "promptTokens")); + llama_pos convTokens = model->getNConversationOnlyTokens(); + + GTEST_LOG_(INFO) << "Double tokenization (tools_at_end=true): " + << durationDouble / numIterations << " us per iteration (" + << promptTokens << " prompt tokens, " << convTokens + << " conversation-only tokens)"; + } + + { + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + LlamaModel::Prompt promptNoTools; + promptNoTools.input = R"([{"role": "user", "content": "Hello, how are you?"}])"; + + auto startNoTools = std::chrono::high_resolution_clock::now(); + for (int i = 0; i < numIterations; ++i) { + model->reset(); + std::string output = model->processPrompt(promptNoTools); + } + auto endNoTools = std::chrono::high_resolution_clock::now(); + auto durationNoTools = + std::chrono::duration_cast(endNoTools - + startNoTools) + .count(); + + auto stats = model->runtimeStats(); + int promptTokens = static_cast(getStatValue(stats, "promptTokens")); + + GTEST_LOG_(INFO) << "Without tools (tools_at_end=true): " + << durationNoTools / numIterations << " us per iteration (" + << promptTokens << " prompt tokens)"; + } +} + +TEST_F(TextLlmContextTest, DoubleTokenizationTimeOverheadLargePrompt) { + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + std::string longContent; + for (int i = 0; i < 50; ++i) { + longContent += "This is a test message number " + std::to_string(i) + + ". It contains some text that will be tokenized into many " + "tokens. The purpose is to test the performance of " + "tokenization with a large prompt. "; + } + + const std::string promptWithTools = R"([ + {"role": "user", "content": ")" + longContent + R"("}, + { + "type": "function", + "name": "getWeather", + "description": "Get weather forecast for a city", + "parameters": { + "type": "object", + "properties": { + "city": {"type": "string", "description": "City name"}, + "date": {"type": "string", "description": "Date in YYYY-MM-DD"} + }, + "required": ["city", "date"] + } + } + ])"; + + const int numIterations = 3; + + { + config_files["tools_at_end"] = "false"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + LlamaModel::Prompt prompt; + prompt.input = promptWithTools; + + auto startSingle = std::chrono::high_resolution_clock::now(); + for (int i = 0; i < numIterations; ++i) { + model->reset(); + std::string output = model->processPrompt(prompt); + } + auto endSingle = std::chrono::high_resolution_clock::now(); + auto durationSingle = std::chrono::duration_cast( + endSingle - startSingle) + .count(); + + auto stats = model->runtimeStats(); + int promptTokens = static_cast(getStatValue(stats, "promptTokens")); + + GTEST_LOG_(INFO) << "Large prompt - Single tokenization (no tools_at_end): " + << durationSingle / numIterations << " us per iteration (" + << promptTokens << " prompt tokens)"; + } + + { + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + LlamaModel::Prompt prompt; + prompt.input = promptWithTools; + + auto startDouble = std::chrono::high_resolution_clock::now(); + for (int i = 0; i < numIterations; ++i) { + model->reset(); + std::string output = model->processPrompt(prompt); + } + auto endDouble = std::chrono::high_resolution_clock::now(); + auto durationDouble = std::chrono::duration_cast( + endDouble - startDouble) + .count(); + + auto stats = model->runtimeStats(); + int promptTokens = static_cast(getStatValue(stats, "promptTokens")); + llama_pos convTokens = model->getNConversationOnlyTokens(); + + GTEST_LOG_(INFO) << "Large prompt - Double tokenization (tools_at_end=true): " + << durationDouble / numIterations << " us per iteration (" + << promptTokens << " prompt tokens, " << convTokens + << " conversation-only tokens)"; + } +} From d63ad92f1566dcaa87403c9eff98e060b5c3a239 Mon Sep 17 00:00:00 2001 From: Mikhail Sotnikov Date: Thu, 5 Mar 2026 02:33:15 +0300 Subject: [PATCH 05/48] (improvement) llamacpp-llm: track n-past, run Qwen3 tests, fix reset --- .../addon/src/model-interface/LlamaModel.cpp | 7 + .../addon/src/model-interface/LlamaModel.hpp | 8 + .../addon/src/model-interface/LlmContext.hpp | 8 + .../src/model-interface/MtmdLlmContext.cpp | 11 + .../src/model-interface/MtmdLlmContext.hpp | 4 + .../src/model-interface/TextLlmContext.cpp | 17 ++ .../src/model-interface/TextLlmContext.hpp | 5 + .../test/unit/test_common.hpp | 9 +- .../test/unit/test_text_llm_context.cpp | 237 ++++++++++++++++++ 9 files changed, 303 insertions(+), 3 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp index 435243055e..a086ab3f3f 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp @@ -271,6 +271,13 @@ llama_pos LlamaModel::getNConversationOnlyTokens() const { return 0; } +llama_pos LlamaModel::getNPastBeforeTools() const { + if (llmContext_) { + return llmContext_->getNPastBeforeTools(); + } + return -1; +} + void LlamaModel::llamaLogCallback( ggml_log_level level, const char* text, void* userData) { (void)userData; diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp index 6d64a2f9e8..e4c1c86b6e 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp @@ -132,6 +132,14 @@ class LlamaModel : public IModel, public IModelAsyncLoad, public IModelCancel { */ llama_pos getNConversationOnlyTokens() const; + /** + * Get the nPast position before tool evaluation. + * This is used to find the boundary in the KV cache after evaluating + * conversation tokens but before tool tokens. + * @return the nPast position, or -1 if not set. + */ + llama_pos getNPastBeforeTools() const; + /** * Ensure model is initialized */ diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp index 738c63fcc8..38bae3ff28 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp @@ -193,6 +193,14 @@ class LlmContext { // NOLINT(cppcoreguidelines-special-member-functions) */ [[nodiscard]] virtual llama_pos getNConversationOnlyTokens() const = 0; + /** + * Get the nPast position before tool evaluation. + * This is used to find the boundary in the KV cache after evaluating + * conversation tokens but before tool tokens. + * @return the nPast position, or -1 if not set. + */ + [[nodiscard]] virtual llama_pos getNPastBeforeTools() const { return -1; } + /** * The load media method. It loads the media from memory buffer. * Default implementation does nothing (for text-only contexts). diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp index 03ebfcd5da..675af3046b 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp @@ -346,6 +346,9 @@ bool MtmdLlmContext::evalMessageWithTools( nDiscarded_ = ctxSize - firstMsgTokens_ - 1; } } + if (toolsAtEnd_ && !tools.empty()) { + nPastBeforeTools_ = nPast_ - (static_cast(nTokens) - nConversationOnlyTokens_); + } return true; } @@ -482,6 +485,10 @@ llama_pos MtmdLlmContext::getNConversationOnlyTokens() const { return nConversationOnlyTokens_; } +llama_pos MtmdLlmContext::getNPastBeforeTools() const { + return nPastBeforeTools_; +} + void MtmdLlmContext::loadMedia(const std::vector& media) { if (media.empty()) { resetMedia(); @@ -549,6 +556,10 @@ void MtmdLlmContext::loadMedia(const std::string& fname) { } void MtmdLlmContext::resetState(bool resetStats) { + + // Reset conversation-only tokens and nPastBeforeTools + nConversationOnlyTokens_ = 0; + nPastBeforeTools_ = -1; // Reset the n_past nPast_ = 0; diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp index 7824555fe5..2f95ceed5d 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp @@ -116,6 +116,8 @@ class MtmdLlmContext: public LlmContext { [[nodiscard]] llama_pos getNConversationOnlyTokens() const override; + [[nodiscard]] llama_pos getNPastBeforeTools() const override; + /** * The load media method. It loads the media from memory buffer. * @@ -207,6 +209,8 @@ class MtmdLlmContext: public LlmContext { bool toolsAtEnd_ = false; llama_pos nConversationOnlyTokens_ = 0; + + llama_pos nPastBeforeTools_ = -1; }; diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp index 065012b162..ff642a6b01 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp @@ -193,6 +193,11 @@ void TextLlmContext::tokenizeChat( bool isLastMessageFromUser = false; bool addSpecial = false; + if (nPast_ == 0 && !isCacheLoaded) { + nConversationOnlyTokens_ = 0; + nPastBeforeTools_ = -1; + } + if (nPast_ == 0 && !isCacheLoaded) { isLastMessageFromUser = true; addSpecial = true; @@ -376,6 +381,9 @@ bool TextLlmContext::evalMessageWithTools( nDiscarded_ = ctxSize - firstMsgTokens_ - 1; } } + if (toolsAtEnd_ && !tools.empty()) { + nPastBeforeTools_ = nPast_ - (static_cast(inputTokens.size()) - nConversationOnlyTokens_); + } return true; } @@ -506,6 +514,11 @@ void TextLlmContext::stop() { stopGeneration_.store(true); } void TextLlmContext::resetState(bool resetStats) { // Reset the n_past + + // Reset conversation-only tokens and nPastBeforeTools + if (resetStats) { + nPastBeforeTools_ = -1; + } nPast_ = 0; // Reset the first msg token length @@ -553,6 +566,10 @@ llama_pos TextLlmContext::getNConversationOnlyTokens() const { return nConversationOnlyTokens_; } +llama_pos TextLlmContext::getNPastBeforeTools() const { + return nPastBeforeTools_; +} + llama_pos TextLlmContext::removeLastNTokens(llama_pos count) { // Validate input if (count <= 0) { diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp index 491d05b05d..4891b25d77 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp @@ -108,6 +108,8 @@ class TextLlmContext: public LlmContext { [[nodiscard]] llama_pos getNConversationOnlyTokens() const override; + [[nodiscard]] llama_pos getNPastBeforeTools() const override; + /** * The reset state method. It resets the context. * @@ -184,7 +186,10 @@ class TextLlmContext: public LlmContext { bool toolsAtEnd_ = false; + llama_pos nConversationOnlyTokens_ = 0; + + llama_pos nPastBeforeTools_ = -1; }; diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_common.hpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_common.hpp index 1b0a311fae..04ef9b5de4 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_common.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_common.hpp @@ -60,12 +60,15 @@ struct BaseTestModelPath { } /** - * Default model path: Llama-3.2-1B-Instruct-Q4_0.gguf if present, - * else test_model.gguf, else "Llama-3.2-1B-Instruct-Q4_0.gguf". + * Default model path: Qwen3-1.7B-Q4_0.gguf if present (for tools_at_end tests), + * else Llama-3.2-1B-Instruct-Q4_0.gguf, else test_model.gguf. */ static std::string get() { fs::path base = path(); - fs::path p = base / "Llama-3.2-1B-Instruct-Q4_0.gguf"; + fs::path p = base / "Qwen3-1.7B-Q4_0.gguf"; + if (fs::exists(p)) + return p.string(); + p = base / "Llama-3.2-1B-Instruct-Q4_0.gguf"; if (fs::exists(p)) return p.string(); p = base / "test_model.gguf"; diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context.cpp index d0c880a55a..188657f77e 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context.cpp @@ -61,6 +61,14 @@ class TextLlmContextTest : public ::testing::Test { std::string test_projection_path; bool hasValidModel() { return fs::exists(test_model_path); } + bool isQwen3Model() { + std::string lowerPath = test_model_path; + std::transform( + lowerPath.begin(), lowerPath.end(), lowerPath.begin(), + [](unsigned char c) { return std::tolower(c); }); + return lowerPath.find("qwen3") != std::string::npos; + } + std::unique_ptr createModel() { if (!hasValidModel()) { @@ -374,6 +382,11 @@ TEST_F(TextLlmContextTest, ProcessWithMultipleTools) { } TEST_F(TextLlmContextTest, DoubleTokenizeWithToolsAtEnd) { + // tools_at_end feature requires Qwen3 model + if (!isQwen3Model()) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + if (!hasValidModel()) { FAIL() << "Test model not found"; } @@ -470,6 +483,11 @@ TEST_F(TextLlmContextTest, DoubleTokenizeWithToolsAtEndNoTools) { } TEST_F(TextLlmContextTest, DoubleTokenizeWithMultipleTools) { + // tools_at_end feature requires Qwen3 model + if (!isQwen3Model()) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + if (!hasValidModel()) { FAIL() << "Test model not found"; } @@ -521,6 +539,11 @@ TEST_F(TextLlmContextTest, DoubleTokenizeWithMultipleTools) { } TEST_F(TextLlmContextTest, DoubleTokenizeBoundaryAccuracy) { + // tools_at_end feature requires Qwen3 model + if (!isQwen3Model()) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + if (!hasValidModel()) { FAIL() << "Test model not found"; } @@ -774,3 +797,217 @@ TEST_F(TextLlmContextTest, DoubleTokenizationTimeOverheadLargePrompt) { << " conversation-only tokens)"; } } + +TEST_F(TextLlmContextTest, NPastBeforeToolsSetAfterEvalWithTools) { + // tools_at_end feature requires Qwen3 model + if (!isQwen3Model()) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + LlamaModel::Prompt prompt; + prompt.input = R"([ + {"role": "user", "content": "What is the weather in Tokyo?"}, + { + "type": "function", + "name": "getWeather", + "description": "Get weather forecast for a city", + "parameters": { + "type": "object", + "properties": { + "city": {"type": "string", "description": "City name"}, + "date": {"type": "string", "description": "Date in YYYY-MM-DD"} + }, + "required": ["city", "date"] + } + } + ])"; + + EXPECT_NO_THROW({ + std::string output = model->processPrompt(prompt); + }); + + llama_pos nPastBeforeTools = model->getNPastBeforeTools(); + llama_pos nConvTokens = model->getNConversationOnlyTokens(); + + EXPECT_GT(nPastBeforeTools, 0); + EXPECT_GT(nConvTokens, 0); + EXPECT_LE(nPastBeforeTools, nConvTokens); +} + +TEST_F(TextLlmContextTest, NPastBeforeToolsMinusOneWithoutTools) { + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + LlamaModel::Prompt prompt; + prompt.input = R"([{"role": "user", "content": "Hello, how are you?"}])"; + + EXPECT_NO_THROW({ + std::string output = model->processPrompt(prompt); + }); + + llama_pos nPastBeforeTools = model->getNPastBeforeTools(); + EXPECT_EQ(nPastBeforeTools, -1); +} + +TEST_F(TextLlmContextTest, NPastBeforeToolsMinusOneWhenToolsAtEndFalse) { + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "false"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + LlamaModel::Prompt prompt; + prompt.input = R"([ + {"role": "user", "content": "What is the weather in Tokyo?"}, + { + "type": "function", + "name": "getWeather", + "description": "Get weather forecast for a city", + "parameters": { + "type": "object", + "properties": { + "city": {"type": "string", "description": "City name"}, + "date": {"type": "string", "description": "Date in YYYY-MM-DD"} + }, + "required": ["city", "date"] + } + } + ])"; + + EXPECT_NO_THROW({ + std::string output = model->processPrompt(prompt); + }); + + llama_pos nPastBeforeTools = model->getNPastBeforeTools(); + EXPECT_EQ(nPastBeforeTools, -1); +} + +TEST_F(TextLlmContextTest, NPastBeforeToolsResetAfterResetState) { + // tools_at_end feature requires Qwen3 model + if (!isQwen3Model()) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + LlamaModel::Prompt prompt; + prompt.input = R"([ + {"role": "user", "content": "What is the weather in Tokyo?"}, + { + "type": "function", + "name": "getWeather", + "description": "Get weather forecast for a city", + "parameters": { + "type": "object", + "properties": { + "city": {"type": "string", "description": "City name"}, + "date": {"type": "string", "description": "Date in YYYY-MM-DD"} + }, + "required": ["city", "date"] + } + } + ])"; + + EXPECT_NO_THROW({ + std::string output = model->processPrompt(prompt); + }); + + llama_pos nPastBeforeToolsBeforeReset = model->getNPastBeforeTools(); + EXPECT_GT(nPastBeforeToolsBeforeReset, 0); + + model->reset(); + + llama_pos nPastBeforeToolsAfterReset = model->getNPastBeforeTools(); + EXPECT_EQ(nPastBeforeToolsAfterReset, -1); +} + +TEST_F(TextLlmContextTest, NPastBeforeToolsBoundaryAccuracy) { + // tools_at_end feature requires Qwen3 model + if (!isQwen3Model()) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + LlamaModel::Prompt prompt; + prompt.input = R"([ + {"role": "user", "content": "What is the weather in Tokyo?"}, + { + "type": "function", + "name": "getWeather", + "description": "Get weather forecast for a city", + "parameters": { + "type": "object", + "properties": { + "city": {"type": "string", "description": "City name"}, + "date": {"type": "string", "description": "Date in YYYY-MM-DD"} + }, + "required": ["city", "date"] + } + } + ])"; + + EXPECT_NO_THROW({ + std::string output = model->processPrompt(prompt); + }); + + llama_pos nPastBeforeTools = model->getNPastBeforeTools(); + llama_pos nConvTokens = model->getNConversationOnlyTokens(); + + EXPECT_GT(nConvTokens, 0); + EXPECT_GT(nPastBeforeTools, 0); + + EXPECT_NO_THROW({ + model->reset(); + }); + + LlamaModel::Prompt promptNoTools; + promptNoTools.input = R"([{"role": "user", "content": "What is the weather in Tokyo?"}])"; + + EXPECT_NO_THROW({ + std::string output = model->processPrompt(promptNoTools); + }); + + llama_pos nConvTokensNoTools = model->getNConversationOnlyTokens(); + llama_pos nPastBeforeToolsNoTools = model->getNPastBeforeTools(); + + EXPECT_EQ(nConvTokensNoTools, 0); + EXPECT_EQ(nPastBeforeToolsNoTools, -1); +} From 9a75956c8d78d7be1ed59d208df968bfb7e94c42 Mon Sep 17 00:00:00 2001 From: Mikhail Sotnikov Date: Thu, 5 Mar 2026 03:22:49 +0300 Subject: [PATCH 06/48] (improvement) llamacpp-llm: save cache with respect to tools flag --- .../src/model-interface/CacheManager.cpp | 21 +- .../src/model-interface/CacheManager.hpp | 3 +- .../addon/src/model-interface/LlamaModel.cpp | 13 +- .../test/unit/test_cache_management.cpp | 280 ++++++++++++++++++ 4 files changed, 309 insertions(+), 8 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.cpp index d7a56a4713..dcd7e46bae 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.cpp @@ -15,9 +15,10 @@ using namespace qvac_lib_inference_addon_llama::logging; CacheManager::CacheManager( LlmContext* llmContext, llama_pos configuredNDiscarded, - std::function resetStateCallback) + std::function resetStateCallback, bool toolsAtEnd) : llmContext_(llmContext), configuredNDiscarded_(configuredNDiscarded), - resetStateCallback_(std::move(resetStateCallback)) {} + resetStateCallback_(std::move(resetStateCallback)), + toolsAtEnd_(toolsAtEnd) {} bool CacheManager::isFileInitialized(const std::filesystem::path& path) { std::error_code errorCode; @@ -244,6 +245,22 @@ void CacheManager::saveCache() { __func__, sessionPath_.c_str())); + if (toolsAtEnd_) { + llama_pos trimPoint = llmContext_->getNPastBeforeTools(); + if (trimPoint > 0 && trimPoint < llmContext_->getNPast()) { + auto* mem = llama_get_memory(ctx); + llama_memory_seq_rm(mem, -1, trimPoint, -1); + llmContext_->setNPast(trimPoint); + QLOG_IF( + Priority::DEBUG, + string_format( + "%s: trimmed %d tool+response tokens before saving (tools-at-end " + "mode)\n", + __func__, + llmContext_->getNPast() - trimPoint)); + } + } + llama_token sessionTokens[2] = { static_cast(llmContext_->getNPast()), static_cast(llmContext_->getFirstMsgTokens())}; diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.hpp index 359301ef7d..df5c3555f7 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.hpp @@ -14,7 +14,7 @@ class CacheManager { public: CacheManager( LlmContext* llmContext, llama_pos configuredNDiscarded, - std::function resetStateCallback); + std::function resetStateCallback, bool toolsAtEnd); bool handleCache( std::vector& chatMsgs, @@ -39,4 +39,5 @@ class CacheManager { std::string sessionPath_; bool cacheDisabled_ = true; bool cacheUsedInLastPrompt_ = false; + bool toolsAtEnd_ = false; }; diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp index a086ab3f3f..372835e501 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp @@ -248,7 +248,8 @@ void LlamaModel::init(bool acquireLock) { snap->cacheManager_.emplace( snap->llmContext_.get(), snap->configuredNDiscarded_, - [this](bool resetStats) { this->resetState(resetStats); }); + [this](bool resetStats) { this->resetState(resetStats); }, + snap->toolsAtEnd_); } } @@ -265,15 +266,17 @@ bool LlamaModel::isLoaded() { } llama_pos LlamaModel::getNConversationOnlyTokens() const { - if (llmContext_) { - return llmContext_->getNConversationOnlyTokens(); + std::shared_lock lock(stateMtx_); + if (state_->llmContext_) { + return state_->llmContext_->getNConversationOnlyTokens(); } return 0; } llama_pos LlamaModel::getNPastBeforeTools() const { - if (llmContext_) { - return llmContext_->getNPastBeforeTools(); + std::shared_lock lock(stateMtx_); + if (state_->llmContext_) { + return state_->llmContext_->getNPastBeforeTools(); } return -1; } diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management.cpp index 6963d630ea..f6e2184057 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management.cpp @@ -140,6 +140,14 @@ class CacheManagementTest : public ::testing::Test { std::string session1_path; std::string session2_path; std::string temp_session_path; + + bool isQwen3Model() { + std::string lowerPath = test_model_path; + std::transform( + lowerPath.begin(), lowerPath.end(), lowerPath.begin(), + [](unsigned char c) { return std::tolower(c); }); + return lowerPath.find("qwen3") != std::string::npos; + } }; TEST_F(CacheManagementTest, InitialStateNoCache) { @@ -1030,3 +1038,275 @@ TEST_F(CacheManagementTest, CacheTokensExceedContextSize) { { processPromptString(model_small, loadInput); }, qvac_errors::StatusError); } + +TEST_F(CacheManagementTest, CacheWithToolsAtEndFalseSavesFullCache) { + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "false"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + std::string inputWithTools = + R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "What is the weather in Tokyo?"}, {"type": "function", "name": "getWeather", "description": "Get weather forecast", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model, inputWithTools); + EXPECT_GE(output.length(), 0); + auto stats = model->runtimeStats(); + EXPECT_GE(stats.size(), 0); + }); + + auto statsBeforeSave = model->runtimeStats(); + double cacheTokensBeforeSave = getStatValue(statsBeforeSave, "CacheTokens"); + EXPECT_GT(cacheTokensBeforeSave, 0.0); + + llama_pos nPastBeforeTools = model->getNPastBeforeTools(); + EXPECT_EQ(nPastBeforeTools, -1); + + std::string saveInput = + R"([{"role": "session", "content": "test_session1.bin"}, {"role": "session", "content": "save"}])"; + EXPECT_NO_THROW({ + std::string saveOutput = processPromptString(model, saveInput); + EXPECT_EQ(saveOutput.length(), 0); + }); + + EXPECT_TRUE(fs::exists(session1_path)); +} + +TEST_F(CacheManagementTest, CacheWithToolsAtEndTrueTrimsToolTokens) { + if (!isQwen3Model()) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + std::string inputWithTools = + R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "What is the weather in Tokyo?"}, {"type": "function", "name": "getWeather", "description": "Get weather forecast", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model, inputWithTools); + EXPECT_GE(output.length(), 0); + }); + + auto statsBeforeSave = model->runtimeStats(); + double cacheTokensBeforeSave = getStatValue(statsBeforeSave, "CacheTokens"); + EXPECT_GT(cacheTokensBeforeSave, 0.0); + + llama_pos nPastBeforeTools = model->getNPastBeforeTools(); + EXPECT_GT(nPastBeforeTools, 0); + EXPECT_LT(nPastBeforeTools, cacheTokensBeforeSave); + + std::string saveInput = + R"([{"role": "session", "content": "test_session1.bin"}, {"role": "session", "content": "save"}])"; + EXPECT_NO_THROW({ + std::string saveOutput = processPromptString(model, saveInput); + EXPECT_EQ(saveOutput.length(), 0); + }); + + EXPECT_TRUE(fs::exists(session1_path)); +} + +TEST_F(CacheManagementTest, CacheReloadWithToolsAtEndTrue) { + if (!isQwen3Model()) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model1 = createModel(); + if (!model1) { + FAIL() << "Model failed to load"; + } + + std::string inputWithTools = + R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "What is the weather in Tokyo?"}, {"type": "function", "name": "getWeather", "description": "Get weather forecast", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model1, inputWithTools); + EXPECT_GE(output.length(), 0); + }); + + llama_pos nPastBeforeTools1 = model1->getNPastBeforeTools(); + EXPECT_GT(nPastBeforeTools1, 0); + + std::string saveInput = + R"([{"role": "session", "content": "test_session1.bin"}, {"role": "session", "content": "save"}])"; + EXPECT_NO_THROW({ + std::string saveOutput = processPromptString(model1, saveInput); + EXPECT_EQ(saveOutput.length(), 0); + }); + + EXPECT_TRUE(fs::exists(session1_path)); + + model1.reset(); + + auto model2 = createModel(); + if (!model2) { + FAIL() << "Model failed to load"; + } + + EXPECT_NO_THROW({ + std::string output = processPromptString( + model2, + R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "What is the weather in London?"}])"); + EXPECT_GE(output.length(), 0); + }); + + auto statsAfterReload = model2->runtimeStats(); + double cacheTokensAfterReload = getStatValue(statsAfterReload, "CacheTokens"); + EXPECT_GT(cacheTokensAfterReload, 0.0); + + llama_pos nPastBeforeTools2 = model2->getNPastBeforeTools(); + EXPECT_EQ(nPastBeforeTools2, -1); + EXPECT_LE(nPastBeforeTools2, nPastBeforeTools1); +} + +TEST_F(CacheManagementTest, CacheWithoutToolsWithToolsAtEndTrue) { + if (!isQwen3Model()) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + std::string inputNoTools = + R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "What is bitcoin? Answer shortly."}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model, inputNoTools); + EXPECT_GE(output.length(), 0); + }); + + auto statsBeforeSave = model->runtimeStats(); + double cacheTokensBeforeSave = getStatValue(statsBeforeSave, "CacheTokens"); + EXPECT_GT(cacheTokensBeforeSave, 0.0); + + llama_pos nPastBeforeTools = model->getNPastBeforeTools(); + EXPECT_EQ(nPastBeforeTools, -1); + + std::string saveInput = + R"([{"role": "session", "content": "test_session1.bin"}, {"role": "session", "content": "save"}])"; + EXPECT_NO_THROW({ + std::string saveOutput = processPromptString(model, saveInput); + EXPECT_EQ(saveOutput.length(), 0); + }); + + EXPECT_TRUE(fs::exists(session1_path)); +} + +TEST_F(CacheManagementTest, CacheToolsAtEndModeWithMultiplePrompts) { + if (!isQwen3Model()) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + std::string input1 = + R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "What is the weather in Tokyo?"}, {"type": "function", "name": "getWeather", "description": "Get weather forecast", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model, input1); + EXPECT_GE(output.length(), 0); + }); + + auto stats1 = model->runtimeStats(); + double cacheTokens1 = getStatValue(stats1, "CacheTokens"); + EXPECT_GT(cacheTokens1, 0.0); + + std::string input2 = + R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "What about London?"}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model, input2); + EXPECT_GE(output.length(), 0); + }); + + auto stats2 = model->runtimeStats(); + double cacheTokens2 = getStatValue(stats2, "CacheTokens"); + EXPECT_GT(cacheTokens2, 0.0); + + llama_pos nPastBeforeTools = model->getNPastBeforeTools(); + EXPECT_GT(nPastBeforeTools, 0); + EXPECT_LE(nPastBeforeTools, cacheTokens2); + + std::string saveInput = + R"([{"role": "session", "content": "test_session1.bin"}, {"role": "session", "content": "save"}])"; + EXPECT_NO_THROW({ + std::string saveOutput = processPromptString(model, saveInput); + EXPECT_EQ(saveOutput.length(), 0); + }); + + EXPECT_TRUE(fs::exists(session1_path)); +} + +TEST_F(CacheManagementTest, CacheToolsAtEndModeTrimOnlyWhenNPastBeforeToolsPositive) { + if (!isQwen3Model()) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + std::string inputNoTools = + R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "Hello"}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model, inputNoTools); + EXPECT_GE(output.length(), 0); + }); + + llama_pos nPastBeforeTools = model->getNPastBeforeTools(); + EXPECT_EQ(nPastBeforeTools, -1); + + auto statsBeforeSave = model->runtimeStats(); + double cacheTokensBeforeSave = getStatValue(statsBeforeSave, "CacheTokens"); + EXPECT_GT(cacheTokensBeforeSave, 0.0); + + std::string saveInput = + R"([{"role": "session", "content": "test_session1.bin"}, {"role": "session", "content": "save"}])"; + EXPECT_NO_THROW({ + std::string saveOutput = processPromptString(model, saveInput); + EXPECT_EQ(saveOutput.length(), 0); + }); + + auto statsAfterSave = model->runtimeStats(); + double cacheTokensAfterSave = getStatValue(statsAfterSave, "CacheTokens"); + EXPECT_EQ(cacheTokensAfterSave, cacheTokensBeforeSave); +} From 83f2d8ba4a2131a2a984923ef6b0d66683b971a4 Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Mon, 9 Mar 2026 20:28:10 +0300 Subject: [PATCH 07/48] (fix) llamacpp-llm: add Qwen3ToolsDynamicTemplate.cpp to production CMakeLists The new source file was added to the test CMakeLists but missing from the addon and cli_tool targets, causing an undefined symbol linker error on CI win64 builds. Made-with: Cursor --- packages/qvac-lib-infer-llamacpp-llm/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/qvac-lib-infer-llamacpp-llm/CMakeLists.txt b/packages/qvac-lib-infer-llamacpp-llm/CMakeLists.txt index 6756892719..ff679045be 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/CMakeLists.txt +++ b/packages/qvac-lib-infer-llamacpp-llm/CMakeLists.txt @@ -73,6 +73,7 @@ endif() ${PROJECT_SOURCE_DIR}/addon/src/utils/BackendSelection.cpp ${PROJECT_SOURCE_DIR}/addon/src/utils/ChatTemplateUtils.cpp ${PROJECT_SOURCE_DIR}/addon/src/utils/Qwen3ReasoningUtils.cpp + ${PROJECT_SOURCE_DIR}/addon/src/utils/Qwen3ToolsDynamicTemplate.cpp ${PROJECT_SOURCE_DIR}/addon/src/utils/QwenTemplate.cpp ) @@ -117,6 +118,7 @@ if(BUILD_CLI) ${PROJECT_SOURCE_DIR}/addon/src/utils/BackendSelection.cpp ${PROJECT_SOURCE_DIR}/addon/src/utils/ChatTemplateUtils.cpp ${PROJECT_SOURCE_DIR}/addon/src/utils/Qwen3ReasoningUtils.cpp + ${PROJECT_SOURCE_DIR}/addon/src/utils/Qwen3ToolsDynamicTemplate.cpp ${PROJECT_SOURCE_DIR}/addon/src/utils/QwenTemplate.cpp ) From 9f97519d8762b3e639b378cbadc47a94b05d239b Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Mon, 9 Mar 2026 21:48:32 +0300 Subject: [PATCH 08/48] chore: retrigger CI for CMakeLists fix Made-with: Cursor From 0f23162464468b04a12ff9d807123900a7a3aa24 Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Tue, 10 Mar 2026 16:38:07 +0300 Subject: [PATCH 09/48] (fix) llamacpp-llm: fix use-after-free SIGSEGV on process exit (linux) Reorder TextLlmContext members so threadpools are declared before llamaInit_. C++ destroys members in reverse declaration order, so llamaInit_ (which calls llama_free) now runs while threadpools are still alive, preventing use-after-free when llama_free accesses attached threadpool pointers. Made-with: Cursor --- .../addon/src/model-interface/TextLlmContext.hpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp index 4891b25d77..50fde77a84 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp @@ -157,6 +157,13 @@ class TextLlmContext: public LlmContext { void applyContextDiscard(); void handleStopRequestAndAddEot(LlamaBatch& batch); + // threadpools must outlive llamaInit_ because llama_free (called by + // llamaInit_ destructor) may access attached threadpool pointers. + // C++ destroys members in reverse declaration order, so declare + // threadpools before llamaInit_. + ThreadPoolPtr threadpool_; + ThreadPoolPtr threadpoolBatch_; + common_init_result llamaInit_; llama_model* model_; llama_context* lctx_; @@ -170,8 +177,6 @@ class TextLlmContext: public LlmContext { llama_pos nPast_ = 0; llama_pos nDiscarded_ = 0; llama_pos firstMsgTokens_ = 0; - ThreadPoolPtr threadpool_; - ThreadPoolPtr threadpoolBatch_; // UTF-8 token buffer for handling incomplete emoji sequences qvac_lib_inference_addon_llama::UTF8TokenBuffer utf8Buffer_; From f3adb55c6f5d8adab9f0f446d482bc62318487d0 Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Tue, 10 Mar 2026 17:12:44 +0300 Subject: [PATCH 10/48] Revert "(fix) llamacpp-llm: fix use-after-free SIGSEGV on process exit (linux)" This reverts commit 7d9c23784aa1860c93b5d32a2202ba915e6d9f3f. --- .../addon/src/model-interface/TextLlmContext.hpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp index 50fde77a84..4891b25d77 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp @@ -157,13 +157,6 @@ class TextLlmContext: public LlmContext { void applyContextDiscard(); void handleStopRequestAndAddEot(LlamaBatch& batch); - // threadpools must outlive llamaInit_ because llama_free (called by - // llamaInit_ destructor) may access attached threadpool pointers. - // C++ destroys members in reverse declaration order, so declare - // threadpools before llamaInit_. - ThreadPoolPtr threadpool_; - ThreadPoolPtr threadpoolBatch_; - common_init_result llamaInit_; llama_model* model_; llama_context* lctx_; @@ -177,6 +170,8 @@ class TextLlmContext: public LlmContext { llama_pos nPast_ = 0; llama_pos nDiscarded_ = 0; llama_pos firstMsgTokens_ = 0; + ThreadPoolPtr threadpool_; + ThreadPoolPtr threadpoolBatch_; // UTF-8 token buffer for handling incomplete emoji sequences qvac_lib_inference_addon_llama::UTF8TokenBuffer utf8Buffer_; From c1eab4aaa94ad4601953ad3d5fe4c7ede71b42aa Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Tue, 10 Mar 2026 17:27:26 +0300 Subject: [PATCH 11/48] (fix) llamacpp-llm: robust threadpool teardown to prevent SIGSEGV on exit The ThreadPoolDeleter was doing ggml backend registry lookups during destruction, which is fragile during process teardown when the registry may already be torn down. Additionally, threadpools attached to llama_context could be freed before the context itself, causing use-after-free. Fix: cache ggml_threadpool_free fn pointer at construction time, and add explicit destructor that detaches threadpools before freeing them. Made-with: Cursor --- .../addon/src/model-interface/LlmContext.hpp | 29 ++++++----------- .../src/model-interface/TextLlmContext.cpp | 31 +++++++++++++++---- .../src/model-interface/TextLlmContext.hpp | 6 ++-- 3 files changed, 38 insertions(+), 28 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp index 38bae3ff28..5c818c885e 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp @@ -65,27 +65,16 @@ class LlamaBatch { const llama_batch* operator->() const noexcept { return &batch_; } }; -struct ThreadPoolDeleter{ +struct ThreadPoolDeleter { + using FreeFnType = decltype(ggml_threadpool_free)*; + FreeFnType freeFn_ = nullptr; + + ThreadPoolDeleter() = default; + explicit ThreadPoolDeleter(FreeFnType fn) : freeFn_(fn) {} + void operator()(ggml_threadpool* ptr) { - if (ptr != nullptr) { - auto* cpuDev = ggml_backend_dev_by_type(GGML_BACKEND_DEVICE_TYPE_CPU); - if (cpuDev == nullptr) { - throw qvac_errors::StatusError( - ADDON_ID, toString(NoBackendFound), "no CPU backend found"); - } - auto* reg = ggml_backend_dev_backend_reg(cpuDev); - void* procAddr = - ggml_backend_reg_get_proc_address(reg, "ggml_threadpool_free"); - if (procAddr == nullptr) { - throw qvac_errors::StatusError( - ADDON_ID, - toString(UnableToDeleteThreadPool), - "Failed to get ggml_threadpool_free function address"); - } - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) - auto* ggmlThreadpoolFreeFn = - reinterpret_cast(procAddr); - ggmlThreadpoolFreeFn(ptr); + if (ptr != nullptr && freeFn_ != nullptr) { + freeFn_(ptr); } } }; diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp index ff642a6b01..4b8539063a 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp @@ -22,6 +22,14 @@ using namespace qvac_lib_inference_addon_llama::utils; // NOLINTNEXTLINE(readability-function-cognitive-complexity) // NOLINTNEXTLINE(readability-function-cognitive-complexity) +TextLlmContext::~TextLlmContext() { + if (lctx_) { + llama_attach_threadpool(lctx_, nullptr, nullptr); + } + threadpoolBatch_.reset(); + threadpool_.reset(); +} + TextLlmContext::TextLlmContext( common_params& commonParams, common_init_result&& llamaInit) : llamaInit_(std::move(llamaInit)), params_(commonParams) { @@ -103,17 +111,29 @@ TextLlmContext::TextLlmContext( } auto* reg = ggml_backend_dev_backend_reg(cpuDev); - void* procAddr = + void* newProcAddr = ggml_backend_reg_get_proc_address(reg, "ggml_threadpool_new"); - if (procAddr == nullptr) { + if (newProcAddr == nullptr) { throw qvac_errors::StatusError( ADDON_ID, toString(UnableToCreateThreadPool), "Failed to get ggml_threadpool_new function address"); } + void* freeProcAddr = + ggml_backend_reg_get_proc_address(reg, "ggml_threadpool_free"); + if (freeProcAddr == nullptr) { + throw qvac_errors::StatusError( + ADDON_ID, + toString(UnableToCreateThreadPool), + "Failed to get ggml_threadpool_free function address"); + } // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto* ggmlThreadpoolNewFn = - reinterpret_cast(procAddr); + reinterpret_cast(newProcAddr); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + auto* ggmlThreadpoolFreeFn = + reinterpret_cast(freeProcAddr); + ThreadPoolDeleter deleter(ggmlThreadpoolFreeFn); struct ggml_threadpool_params tppBatch = ggml_threadpool_params_from_cpu_params(params_.cpuparams_batch); @@ -123,18 +143,17 @@ TextLlmContext::TextLlmContext( set_process_priority(params_.cpuparams_batch.priority); if (!ggml_threadpool_params_match(&tpp, &tppBatch)) { - threadpoolBatch_.reset(ggmlThreadpoolNewFn(&tppBatch)); + threadpoolBatch_ = ThreadPoolPtr(ggmlThreadpoolNewFn(&tppBatch), deleter); if (!threadpoolBatch_) { throw qvac_errors::StatusError( ADDON_ID, toString(UnableToCreateThreadPool), "batch threadpool create failed"); } - // Start the non-batch threadpool in the paused state tpp.paused = true; } - threadpool_.reset(ggmlThreadpoolNewFn(&tpp)); + threadpool_ = ThreadPoolPtr(ggmlThreadpoolNewFn(&tpp), deleter); if (!threadpool_) { throw qvac_errors::StatusError( ADDON_ID, diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp index 4891b25d77..a6fd8dfc41 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp @@ -19,8 +19,10 @@ class TextLlmContext: public LlmContext { // Constructor TextLlmContext(common_params& commonParams, common_init_result&& llamaInit); - // Destructor - ~TextLlmContext() override = default; + // Explicit destructor: detach threadpools from llama_context before freeing + // them, preventing use-after-free when llamaInit_ destructor later frees the + // context. Also avoids ggml backend registry lookups during process teardown. + ~TextLlmContext() override; /** * The eval message method. It evaluates the message and updates the context. From 7bd6fc2b632fc9d3bd004653be7c80c39daf4ee4 Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Tue, 10 Mar 2026 18:19:31 +0300 Subject: [PATCH 12/48] Revert "(fix) llamacpp-llm: robust threadpool teardown to prevent SIGSEGV on exit" This reverts commit 4e66b38e76303605aa10f423aae3b300184a8253. --- .../addon/src/model-interface/LlmContext.hpp | 29 +++++++++++------ .../src/model-interface/TextLlmContext.cpp | 31 ++++--------------- .../src/model-interface/TextLlmContext.hpp | 6 ++-- 3 files changed, 28 insertions(+), 38 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp index 5c818c885e..38bae3ff28 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp @@ -65,16 +65,27 @@ class LlamaBatch { const llama_batch* operator->() const noexcept { return &batch_; } }; -struct ThreadPoolDeleter { - using FreeFnType = decltype(ggml_threadpool_free)*; - FreeFnType freeFn_ = nullptr; - - ThreadPoolDeleter() = default; - explicit ThreadPoolDeleter(FreeFnType fn) : freeFn_(fn) {} - +struct ThreadPoolDeleter{ void operator()(ggml_threadpool* ptr) { - if (ptr != nullptr && freeFn_ != nullptr) { - freeFn_(ptr); + if (ptr != nullptr) { + auto* cpuDev = ggml_backend_dev_by_type(GGML_BACKEND_DEVICE_TYPE_CPU); + if (cpuDev == nullptr) { + throw qvac_errors::StatusError( + ADDON_ID, toString(NoBackendFound), "no CPU backend found"); + } + auto* reg = ggml_backend_dev_backend_reg(cpuDev); + void* procAddr = + ggml_backend_reg_get_proc_address(reg, "ggml_threadpool_free"); + if (procAddr == nullptr) { + throw qvac_errors::StatusError( + ADDON_ID, + toString(UnableToDeleteThreadPool), + "Failed to get ggml_threadpool_free function address"); + } + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + auto* ggmlThreadpoolFreeFn = + reinterpret_cast(procAddr); + ggmlThreadpoolFreeFn(ptr); } } }; diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp index 4b8539063a..ff642a6b01 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp @@ -22,14 +22,6 @@ using namespace qvac_lib_inference_addon_llama::utils; // NOLINTNEXTLINE(readability-function-cognitive-complexity) // NOLINTNEXTLINE(readability-function-cognitive-complexity) -TextLlmContext::~TextLlmContext() { - if (lctx_) { - llama_attach_threadpool(lctx_, nullptr, nullptr); - } - threadpoolBatch_.reset(); - threadpool_.reset(); -} - TextLlmContext::TextLlmContext( common_params& commonParams, common_init_result&& llamaInit) : llamaInit_(std::move(llamaInit)), params_(commonParams) { @@ -111,29 +103,17 @@ TextLlmContext::TextLlmContext( } auto* reg = ggml_backend_dev_backend_reg(cpuDev); - void* newProcAddr = + void* procAddr = ggml_backend_reg_get_proc_address(reg, "ggml_threadpool_new"); - if (newProcAddr == nullptr) { + if (procAddr == nullptr) { throw qvac_errors::StatusError( ADDON_ID, toString(UnableToCreateThreadPool), "Failed to get ggml_threadpool_new function address"); } - void* freeProcAddr = - ggml_backend_reg_get_proc_address(reg, "ggml_threadpool_free"); - if (freeProcAddr == nullptr) { - throw qvac_errors::StatusError( - ADDON_ID, - toString(UnableToCreateThreadPool), - "Failed to get ggml_threadpool_free function address"); - } // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto* ggmlThreadpoolNewFn = - reinterpret_cast(newProcAddr); - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) - auto* ggmlThreadpoolFreeFn = - reinterpret_cast(freeProcAddr); - ThreadPoolDeleter deleter(ggmlThreadpoolFreeFn); + reinterpret_cast(procAddr); struct ggml_threadpool_params tppBatch = ggml_threadpool_params_from_cpu_params(params_.cpuparams_batch); @@ -143,17 +123,18 @@ TextLlmContext::TextLlmContext( set_process_priority(params_.cpuparams_batch.priority); if (!ggml_threadpool_params_match(&tpp, &tppBatch)) { - threadpoolBatch_ = ThreadPoolPtr(ggmlThreadpoolNewFn(&tppBatch), deleter); + threadpoolBatch_.reset(ggmlThreadpoolNewFn(&tppBatch)); if (!threadpoolBatch_) { throw qvac_errors::StatusError( ADDON_ID, toString(UnableToCreateThreadPool), "batch threadpool create failed"); } + // Start the non-batch threadpool in the paused state tpp.paused = true; } - threadpool_ = ThreadPoolPtr(ggmlThreadpoolNewFn(&tpp), deleter); + threadpool_.reset(ggmlThreadpoolNewFn(&tpp)); if (!threadpool_) { throw qvac_errors::StatusError( ADDON_ID, diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp index a6fd8dfc41..4891b25d77 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp @@ -19,10 +19,8 @@ class TextLlmContext: public LlmContext { // Constructor TextLlmContext(common_params& commonParams, common_init_result&& llamaInit); - // Explicit destructor: detach threadpools from llama_context before freeing - // them, preventing use-after-free when llamaInit_ destructor later frees the - // context. Also avoids ggml backend registry lookups during process teardown. - ~TextLlmContext() override; + // Destructor + ~TextLlmContext() override = default; /** * The eval message method. It evaluates the message and updates the context. From b5fe234ffb37a4f86f168e37532823bbaaeee396 Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Wed, 11 Mar 2026 20:25:36 +0300 Subject: [PATCH 13/48] fix(llm): reset stale state before non-cached run after prefill When a prefill run leaves nPast_ > 0 and the next run is a non-cached single-shot, the stale KV cache and dynamic-tools bookkeeping (nPastBeforeTools_, nConversationOnlyTokens_) caused token duplication and incorrect cache trimming. Clear state eagerly when shouldResetAfterInference is true and nPast_ is non-zero. Made-with: Cursor --- .../addon/src/model-interface/LlamaModel.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp index 372835e501..04bc01cac3 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp @@ -376,6 +376,10 @@ std::string LlamaModel::processPromptImpl(const Prompt& prompt) { std::string out; ResolvedPrompt resolved = resolveChatAndTools(prompt.input); + if (resolved.shouldResetAfterInference && llmContext_->getNPast() > 0) { + resetState(true); + } + if (resolved.chatMsgs.empty() && resolved.tools.empty()) { QLOG_IF( Priority::INFO, From 3cba2d2859336a64d7b3947d0bd9d0070635ef55 Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Wed, 11 Mar 2026 22:37:49 +0300 Subject: [PATCH 14/48] fix(llm): trim stale tool tokens in multi-turn sessions with tools_at_end When tools_at_end is true and a session continues without explicit save between turns, old tool+response tokens remained in the KV cache. New tool tokens were appended, causing conflicting tool definitions. Add a guard in processPrompt() that trims from nPastBeforeTools_ to nPast_ before eval when stale tool tokens are detected. Includes new dynamic-tools integration tests covering changing tools, same tools, and single-shot regression. Made-with: Cursor --- .../addon/src/model-interface/LlamaModel.cpp | 7 + .../test/integration/dynamic-tools.test.js | 220 ++++++++++++++++++ 2 files changed, 227 insertions(+) create mode 100644 packages/qvac-lib-infer-llamacpp-llm/test/integration/dynamic-tools.test.js diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp index 04bc01cac3..8baae768fa 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp @@ -380,6 +380,13 @@ std::string LlamaModel::processPromptImpl(const Prompt& prompt) { resetState(true); } + if (toolsAtEnd_ && !resolved.tools.empty() && + llmContext_->getNPastBeforeTools() > 0 && + llmContext_->getNPast() > llmContext_->getNPastBeforeTools()) { + llmContext_->removeLastNTokens( + llmContext_->getNPast() - llmContext_->getNPastBeforeTools()); + } + if (resolved.chatMsgs.empty() && resolved.tools.empty()) { QLOG_IF( Priority::INFO, diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/integration/dynamic-tools.test.js b/packages/qvac-lib-infer-llamacpp-llm/test/integration/dynamic-tools.test.js new file mode 100644 index 0000000000..f9f0080325 --- /dev/null +++ b/packages/qvac-lib-infer-llamacpp-llm/test/integration/dynamic-tools.test.js @@ -0,0 +1,220 @@ +'use strict' + +const test = require('brittle') +const path = require('bare-path') +const FilesystemDL = require('@qvac/dl-filesystem') +const LlmLlamacpp = require('../../index.js') +const { ensureModel } = require('./utils') +const { attachSpecLogger } = require('./spec-logger') +const os = require('bare-os') + +const isDarwinX64 = os.platform() === 'darwin' && os.arch() === 'x64' +const isLinuxArm64 = os.platform() === 'linux' && os.arch() === 'arm64' +const useCpu = isDarwinX64 || isLinuxArm64 + +const QWEN3_MODEL = { + name: 'Qwen3-0.6B-Q8_0.gguf', + url: 'https://huggingface.co/unsloth/Qwen3-0.6B-GGUF/resolve/main/Qwen3-0.6B-Q8_0.gguf' +} + +const SYSTEM_MESSAGE = { role: 'system', content: 'You are a helpful assistant.' } + +const BASE_CONFIG = { + device: useCpu ? 'cpu' : 'gpu', + gpu_layers: '999', + ctx_size: '4096', + n_predict: '64', + temp: '0.1', + seed: '1', + verbosity: '2', + tools: 'true', + tools_at_end: 'true' +} + +const TOOL_A = { + type: 'function', + name: 'getWeather', + description: 'Get current weather for a city', + parameters: { + type: 'object', + properties: { city: { type: 'string', description: 'City name' } }, + required: ['city'] + } +} + +const TOOL_B = { + type: 'function', + name: 'searchProducts', + description: 'Search for products in catalog', + parameters: { + type: 'object', + properties: { query: { type: 'string', description: 'Search query' } }, + required: ['query'] + } +} + +const TOOL_C = { + type: 'function', + name: 'sendEmail', + description: 'Send an email message', + parameters: { + type: 'object', + properties: { + to: { type: 'string', description: 'Recipient email' }, + body: { type: 'string', description: 'Email body' } + }, + required: ['to', 'body'] + } +} + +const toNumber = value => typeof value === 'number' ? value : Number(value || 0) + +function normalizeStats (rawStats = {}) { + return { + CacheTokens: toNumber(rawStats?.CacheTokens), + promptTokens: toNumber(rawStats?.promptTokens), + generatedTokens: toNumber(rawStats?.generatedTokens) + } +} + +async function setupModel (t, overrides = {}) { + const [modelName, dirPath] = await ensureModel({ + modelName: QWEN3_MODEL.name, + downloadUrl: QWEN3_MODEL.url + }) + + const loader = new FilesystemDL({ dirPath }) + const config = { ...BASE_CONFIG, ...overrides } + const specLogger = attachSpecLogger({ forwardToConsole: true }) + let loggerReleased = false + const releaseLogger = () => { + if (loggerReleased) return + loggerReleased = true + specLogger.release() + } + + const model = new LlmLlamacpp({ + loader, + modelName, + diskPath: dirPath, + logger: console, + opts: { stats: true } + }, config) + + try { + await model.load() + } catch (err) { + releaseLogger() + await loader.close().catch(() => {}) + throw err + } + + t.teardown(async () => { + await model.unload().catch(() => {}) + await loader.close().catch(() => {}) + releaseLogger() + }) + + return { model, dirPath } +} + +async function runAndCollect (model, prompt) { + const response = await model.run(prompt) + const chunks = [] + let chain = response.onUpdate(data => { chunks.push(data) }) + if (typeof response.onError === 'function') { + chain = chain.onError(err => { throw err }) + } + await chain.await() + return { + output: chunks.join(''), + stats: normalizeStats(response.stats) + } +} + +test('[dynamic-tools] multi-turn session with changing tools does not accumulate stale tokens', { timeout: 600_000 }, async t => { + const { model, dirPath } = await setupModel(t) + const sessionName = path.join(dirPath, 'dynamic-tools-changing.bin') + + const prompt1 = [ + { role: 'session', content: sessionName }, + SYSTEM_MESSAGE, + { role: 'user', content: 'Hello, what can you do?' }, + TOOL_A + ] + const r1 = await runAndCollect(model, prompt1) + t.ok(r1.output.length > 0, 'turn 1 produces output') + t.ok(r1.stats.CacheTokens > 0, 'turn 1 has cache tokens') + + const prompt2 = [ + { role: 'session', content: sessionName }, + { role: 'user', content: 'Search for laptops' }, + TOOL_B + ] + const r2 = await runAndCollect(model, prompt2) + t.ok(r2.output.length > 0, 'turn 2 produces output') + t.ok(r2.stats.CacheTokens > 0, 'turn 2 has cache tokens') + + const prompt3 = [ + { role: 'session', content: sessionName }, + { role: 'user', content: 'Send a report' }, + TOOL_C + ] + const r3 = await runAndCollect(model, prompt3) + t.ok(r3.output.length > 0, 'turn 3 produces output') + t.ok(r3.stats.CacheTokens > 0, 'turn 3 has cache tokens') + + const naiveAccumulation = r1.stats.CacheTokens + r2.stats.promptTokens + r2.stats.generatedTokens + r3.stats.promptTokens + r3.stats.generatedTokens + t.ok( + r3.stats.CacheTokens < naiveAccumulation, + `CacheTokens after 3 turns (${r3.stats.CacheTokens}) should be less than naive accumulation (${naiveAccumulation}) — proves old tools are trimmed` + ) + + t.ok( + r3.stats.CacheTokens < 2 * r1.stats.CacheTokens, + `CacheTokens after 3 turns (${r3.stats.CacheTokens}) should be less than 2x turn 1 (${2 * r1.stats.CacheTokens}) — tools are replaced, not accumulated` + ) +}) + +test('[dynamic-tools] multi-turn session with same tools works correctly', { timeout: 600_000 }, async t => { + const { model, dirPath } = await setupModel(t) + const sessionName = path.join(dirPath, 'dynamic-tools-same.bin') + + const prompt1 = [ + { role: 'session', content: sessionName }, + SYSTEM_MESSAGE, + { role: 'user', content: 'What is the weather in Paris?' }, + TOOL_A + ] + const r1 = await runAndCollect(model, prompt1) + t.ok(r1.output.length > 0, 'turn 1 produces output') + t.ok(r1.stats.CacheTokens > 0, 'turn 1 has cache tokens') + + const prompt2 = [ + { role: 'session', content: sessionName }, + { role: 'user', content: 'What about London?' }, + TOOL_A + ] + const r2 = await runAndCollect(model, prompt2) + t.ok(r2.output.length > 0, 'turn 2 produces output') + t.ok(r2.stats.CacheTokens > 0, 'turn 2 has cache tokens') + t.ok( + r2.stats.CacheTokens < 2 * r1.stats.CacheTokens, + `CacheTokens after turn 2 (${r2.stats.CacheTokens}) should be less than 2x turn 1 (${2 * r1.stats.CacheTokens})` + ) +}) + +test('[dynamic-tools] single-shot with tools works without session', { timeout: 600_000 }, async t => { + const { model } = await setupModel(t) + + const prompt = [ + SYSTEM_MESSAGE, + { role: 'user', content: 'What is the weather in Tokyo?' }, + TOOL_A + ] + const r = await runAndCollect(model, prompt) + t.ok(r.output.length > 0, 'produces output') + t.is(r.stats.CacheTokens, 0, 'no cache tokens without session') + t.ok(r.stats.promptTokens > 0, 'prompt tokens tracked') + t.ok(r.stats.generatedTokens > 0, 'generated tokens tracked') +}) From d305c92381f53d756f3cbce88241a28e14a077d3 Mon Sep 17 00:00:00 2001 From: Mikhail Sotnikov Date: Thu, 12 Mar 2026 03:25:47 +0300 Subject: [PATCH 15/48] (fix) llamacpp-llm: dynamic tools cache trim, tmp template, debugs --- .../src/model-interface/CacheManager.cpp | 22 ++++-- .../addon/src/model-interface/LlamaModel.cpp | 15 ++-- .../addon/src/model-interface/LlmContext.hpp | 1 + .../src/model-interface/MtmdLlmContext.cpp | 4 + .../src/model-interface/MtmdLlmContext.hpp | 1 + .../src/model-interface/TextLlmContext.cpp | 9 +++ .../src/model-interface/TextLlmContext.hpp | 1 + .../addon/src/utils/ChatTemplateUtils.cpp | 6 +- .../test/unit/test_cache_management.cpp | 77 +++++++++++++++++-- 9 files changed, 117 insertions(+), 19 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.cpp index dcd7e46bae..fe5c7190ba 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.cpp @@ -64,6 +64,8 @@ bool CacheManager::handleCache( bool cacheLoaded = false; bool cachePathSetInThisArray = false; + printf("CacheManager::handleCache role=%s cmd=%s\n", chatMsgs[0].role.c_str(), chatMsgs[0].content.c_str()); + while (!chatMsgs.empty() && chatMsgs[0].role == "session") { std::string sessionCommand = chatMsgs[0].content; chatMsgs.erase(chatMsgs.begin()); @@ -80,6 +82,8 @@ bool CacheManager::handleCache( resetStateCallback_(true); cacheUsedInLastPrompt_ = false; } else if (sessionCommand == "save") { + printf("CacheManager::handleCache SAVE noPath=%d\n", cachePathSetInThisArray); + // if (sessionPath_.empty()) { if (!cachePathSetInThisArray) { std::string errorMsg = string_format( "%s: save command requires explicit cache file specification in " @@ -114,6 +118,7 @@ bool CacheManager::handleCache( "inference\n", __func__, sessionPath_.c_str())); + printf("CacheManager::handleCache set cache path and continue=\n"); cachePathSetInThisArray = true; cacheUsedInLastPrompt_ = true; continue; @@ -138,6 +143,7 @@ bool CacheManager::handleCache( sessionPath_ = sessionCommand; cachePathSetInThisArray = true; + printf("CacheManager::handleCache set sessionPath_ and cachePathSetInThisArray\n"); if (!sessionPath_.empty()) { cacheDisabled_ = false; @@ -149,6 +155,7 @@ bool CacheManager::handleCache( __func__, sessionPath_.c_str())); + printf("CacheManager::handleCache loadCache, usedInLastPrompt\n"); cacheLoaded = loadCache(); cacheUsedInLastPrompt_ = true; } else { @@ -164,13 +171,14 @@ bool CacheManager::handleCache( } bool CacheManager::loadCache() { + printf("CacheManager::loadCache toolsAtEnd_=%d\n", toolsAtEnd_); if (cacheDisabled_ || sessionPath_.empty()) { return false; } auto* ctx = llmContext_->getCtx(); size_t nTokenCount = 0; - llama_token sessionTokens[2] = {0, 0}; + llama_token sessionTokens[3] = {0, 0, 0}; QLOG_IF( Priority::DEBUG, @@ -187,7 +195,7 @@ bool CacheManager::loadCache() { } if (!llama_state_load_file( - ctx, sessionPath_.c_str(), sessionTokens, 2, &nTokenCount)) { + ctx, sessionPath_.c_str(), sessionTokens, 3, &nTokenCount)) { std::string errorMsg = string_format( "%s: failed to load session file '%s'\n", __func__, @@ -212,6 +220,7 @@ bool CacheManager::loadCache() { } llmContext_->setNPast(sessionTokens[0]); llmContext_->setFirstMsgTokens(sessionTokens[1]); + llmContext_->setNPastBeforeTools(sessionTokens[2]); if (configuredNDiscarded_ > llama_n_ctx(ctx) - llmContext_->getFirstMsgTokens()) { @@ -229,6 +238,7 @@ bool CacheManager::loadCache() { } void CacheManager::saveCache() { + printf("CacheManager::saveCache toolsAtEnd_=%d\n", toolsAtEnd_); if (cacheDisabled_ || sessionPath_.empty()) { std::string errorMsg = string_format( "%s: Cannot save cache - caching disabled or no session path set\n", @@ -247,6 +257,7 @@ void CacheManager::saveCache() { if (toolsAtEnd_) { llama_pos trimPoint = llmContext_->getNPastBeforeTools(); + printf("CacheManager::saveCache trimPoint=%d nPast_=%d\n", trimPoint, llmContext_->getNPast()); if (trimPoint > 0 && trimPoint < llmContext_->getNPast()) { auto* mem = llama_get_memory(ctx); llama_memory_seq_rm(mem, -1, trimPoint, -1); @@ -261,10 +272,11 @@ void CacheManager::saveCache() { } } - llama_token sessionTokens[2] = { + llama_token sessionTokens[3] = { static_cast(llmContext_->getNPast()), - static_cast(llmContext_->getFirstMsgTokens())}; - llama_state_save_file(ctx, sessionPath_.c_str(), sessionTokens, 2); + static_cast(llmContext_->getFirstMsgTokens()), + static_cast(llmContext_->getNPastBeforeTools())}; + llama_state_save_file(ctx, sessionPath_.c_str(), sessionTokens, 3); } bool CacheManager::isCacheDisabled() const { return cacheDisabled_; } diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp index 8baae768fa..d6e190cc68 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp @@ -376,17 +376,10 @@ std::string LlamaModel::processPromptImpl(const Prompt& prompt) { std::string out; ResolvedPrompt resolved = resolveChatAndTools(prompt.input); - if (resolved.shouldResetAfterInference && llmContext_->getNPast() > 0) { + if (resolved.shouldResetAfterInference && state_->llmContext_->getNPast() > 0) { resetState(true); } - if (toolsAtEnd_ && !resolved.tools.empty() && - llmContext_->getNPastBeforeTools() > 0 && - llmContext_->getNPast() > llmContext_->getNPastBeforeTools()) { - llmContext_->removeLastNTokens( - llmContext_->getNPast() - llmContext_->getNPastBeforeTools()); - } - if (resolved.chatMsgs.empty() && resolved.tools.empty()) { QLOG_IF( Priority::INFO, @@ -431,6 +424,12 @@ std::string LlamaModel::processPromptImpl(const Prompt& prompt) { if (!prompt.outputCallback) { out = oss.str(); } + if (state_->toolsAtEnd_ && !resolved.tools.empty() && + state_->llmContext_->getNPastBeforeTools() > 0 && + state_->llmContext_->getNPast() > state_->llmContext_->getNPastBeforeTools()) { + state_->llmContext_->removeLastNTokens( + state_->llmContext_->getNPast() - state_->llmContext_->getNPastBeforeTools()); + } if (resolved.shouldResetAfterInference) { resetState(false); } diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp index 38bae3ff28..e470751c8d 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp @@ -201,6 +201,7 @@ class LlmContext { // NOLINT(cppcoreguidelines-special-member-functions) */ [[nodiscard]] virtual llama_pos getNPastBeforeTools() const { return -1; } + virtual void setNPastBeforeTools(llama_pos nPastBeforeTools) {} /** * The load media method. It loads the media from memory buffer. * Default implementation does nothing (for text-only contexts). diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp index 675af3046b..a18a845925 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp @@ -489,6 +489,10 @@ llama_pos MtmdLlmContext::getNPastBeforeTools() const { return nPastBeforeTools_; } +void MtmdLlmContext::setNPastBeforeTools(llama_pos nPastBeforeTools) { + nPastBeforeTools_ = nPastBeforeTools; +} + void MtmdLlmContext::loadMedia(const std::vector& media) { if (media.empty()) { resetMedia(); diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp index 2f95ceed5d..adee67bebb 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp @@ -117,6 +117,7 @@ class MtmdLlmContext: public LlmContext { [[nodiscard]] llama_pos getNConversationOnlyTokens() const override; [[nodiscard]] llama_pos getNPastBeforeTools() const override; + void setNPastBeforeTools(llama_pos nPastBeforeTools) override; /** * The load media method. It loads the media from memory buffer. diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp index ff642a6b01..ae8095b3f8 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp @@ -220,16 +220,20 @@ void TextLlmContext::tokenizeChat( Priority::DEBUG, string_format("[TextLlm] formatted prompt: %s\n", prompt.c_str())); + printf("TextLlmContext::tokenizeChat prompt=%s\n", prompt.c_str()); if (!prompt.empty()) { inputTokens = common_tokenize(lctx_, prompt, addSpecial, true); + printf("TextLlmContext::tokenizeChat inputTokens.size=%lu\n", inputTokens.size()); if (toolsAtEnd_ && !tools.empty()) { auto savedTools = inputs.tools; inputs.tools = {}; auto promptNoTools = getPrompt(tmpls_.get(), inputs); auto tokensNoTools = common_tokenize(lctx_, promptNoTools, addSpecial, true); + inputs.tools = savedTools; nConversationOnlyTokens_ = tokensNoTools.size(); + printf("TextLlmContext::tokenizeChat nConversationOnlyTokens_=%d\n", nConversationOnlyTokens_); } else { nConversationOnlyTokens_ = 0; } @@ -284,6 +288,7 @@ bool TextLlmContext::evalMessageWithTools( size_t nTokens = inputTokens.size(); const bool isFirstMsg = (nPast_ == 0); + printf("TextLlmContext::evalMessageWithTools nPast_=%d nTokens=%zu\n", nPast_, nTokens); if (nTokens >= llama_n_ctx(lctx_)) { std::string errorMsg = string_format( @@ -566,6 +571,10 @@ llama_pos TextLlmContext::getNConversationOnlyTokens() const { return nConversationOnlyTokens_; } +void TextLlmContext::setNPastBeforeTools(llama_pos nPastBeforeTools) { + nPastBeforeTools_ = nPastBeforeTools; +} + llama_pos TextLlmContext::getNPastBeforeTools() const { return nPastBeforeTools_; } diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp index 4891b25d77..f66afa246a 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp @@ -109,6 +109,7 @@ class TextLlmContext: public LlmContext { [[nodiscard]] llama_pos getNConversationOnlyTokens() const override; [[nodiscard]] llama_pos getNPastBeforeTools() const override; + void setNPastBeforeTools(llama_pos nPastBeforeTools) override; /** * The reset state method. It resets the context. diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.cpp index 6e4e23116d..e6a3e657e1 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.cpp @@ -63,13 +63,17 @@ std::string getChatTemplateForModel( const std::string& manualOverride, bool toolsAtEnd) { if (!manualOverride.empty()) { + printf("ChatTemplateUtils::getChatTemplateForModel - manualOverride\n"); return manualOverride; } if (isQwen3Model(model)) { - return toolsAtEnd ? getToolsDynamicQwen3Template() : getFixedQwen3Template(); + printf("ChatTemplateUtils::getChatTemplateForModel - Qwen3 - toolsAtEnd=%d\n", toolsAtEnd); + return getToolsDynamicQwen3Template(); + // return toolsAtEnd ? getToolsDynamicQwen3Template() : getFixedQwen3Template(); } + printf("ChatTemplateUtils::getChatTemplateForModel - empty\n"); return ""; } diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management.cpp index f6e2184057..41eeedd892 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management.cpp @@ -1172,7 +1172,7 @@ TEST_F(CacheManagementTest, CacheReloadWithToolsAtEndTrue) { EXPECT_GT(cacheTokensAfterReload, 0.0); llama_pos nPastBeforeTools2 = model2->getNPastBeforeTools(); - EXPECT_EQ(nPastBeforeTools2, -1); + EXPECT_EQ(nPastBeforeTools2, nPastBeforeTools1); EXPECT_LE(nPastBeforeTools2, nPastBeforeTools1); } @@ -1232,7 +1232,7 @@ TEST_F(CacheManagementTest, CacheToolsAtEndModeWithMultiplePrompts) { } std::string input1 = - R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "What is the weather in Tokyo?"}, {"type": "function", "name": "getWeather", "description": "Get weather forecast", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}])"; + R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "Hi"}, {"type": "function", "name": "get_weather", "description": "Get detailed weather forecast data with temperature humidity wind speed precipitation UV visibility pressure sunrise sunset alerts", "parameters": {"type": "object", "properties": {"city": {"type": "string", "description": "The name of the city to get weather for"}, "country": {"type": "string", "description": "Country code or name"}, "lat": {"type": "number", "description": "Latitude coordinate"}, "lon": {"type": "number", "description": "Longitude coordinate"}, "zip": {"type": "string", "description": "ZIP postal code"}, "units": {"type": "string", "description": "Temperature units metric imperial or kelvin"}, "lang": {"type": "string", "description": "Language code for localized descriptions"}, "forecast_days": {"type": "integer", "description": "Number of days to forecast from 1 to 7"}, "hourly": {"type": "boolean", "description": "Include hourly forecast data"}, "alerts": {"type": "boolean", "description": "Include weather alerts and warnings"}, "aqi": {"type": "boolean", "description": "Include air quality index data"}, "tides": {"type": "boolean", "description": "Include tide information"}, "solar": {"type": "boolean", "description": "Include solar data like sunrise sunset"}, "tz": {"type": "string", "description": "Timezone identifier"}, "start_dt": {"type": "string", "description": "Start datetime for historical data"}, "end_dt": {"type": "string", "description": "End datetime for historical data"}, "cnt": {"type": "integer", "description": "Number of data points to return"}, "mode": {"type": "string", "description": "Response mode json xml or html"}, "appid": {"type": "string", "description": "API key for authentication"}}, "required": ["city"]}}])"; EXPECT_NO_THROW({ std::string output = processPromptString(model, input1); @@ -1241,8 +1241,19 @@ TEST_F(CacheManagementTest, CacheToolsAtEndModeWithMultiplePrompts) { auto stats1 = model->runtimeStats(); double cacheTokens1 = getStatValue(stats1, "CacheTokens"); + printf("CacheManagementTest::CacheToolsAtEndModeWithMultiplePrompts cacheTokens1=%f\n", cacheTokens1); EXPECT_GT(cacheTokens1, 0.0); + llama_pos nPastBeforeTools = model->getNPastBeforeTools(); + EXPECT_GT(nPastBeforeTools, 0); + EXPECT_LT(nPastBeforeTools, cacheTokens1); + + const int maxExpectedCacheTokens = 50; + EXPECT_GT(cacheTokens1, 0); + EXPECT_LE(cacheTokens1, maxExpectedCacheTokens) + << "Cache tokens (" << cacheTokens1 << ") should not exceed " + << maxExpectedCacheTokens << " - function tokens should be trimmed"; + std::string input2 = R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "What about London?"}])"; @@ -1253,10 +1264,12 @@ TEST_F(CacheManagementTest, CacheToolsAtEndModeWithMultiplePrompts) { auto stats2 = model->runtimeStats(); double cacheTokens2 = getStatValue(stats2, "CacheTokens"); - EXPECT_GT(cacheTokens2, 0.0); + printf("CacheManagementTest::CacheToolsAtEndModeWithMultiplePrompts cacheTokens2=%f\n", cacheTokens2); + EXPECT_GT(cacheTokens2, cacheTokens1); + EXPECT_LE(cacheTokens2, maxExpectedCacheTokens) + << "Cache tokens (" << cacheTokens1 << ") should not exceed " + << maxExpectedCacheTokens << " - function tokens should be trimmed"; - llama_pos nPastBeforeTools = model->getNPastBeforeTools(); - EXPECT_GT(nPastBeforeTools, 0); EXPECT_LE(nPastBeforeTools, cacheTokens2); std::string saveInput = @@ -1310,3 +1323,57 @@ TEST_F(CacheManagementTest, CacheToolsAtEndModeTrimOnlyWhenNPastBeforeToolsPosit double cacheTokensAfterSave = getStatValue(statsAfterSave, "CacheTokens"); EXPECT_EQ(cacheTokensAfterSave, cacheTokensBeforeSave); } + +TEST_F(CacheManagementTest, CacheToolsAtEndModeRestoresNPastBeforeTools) { + if (!isQwen3Model()) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + std::string input1 = + R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "Hi"}, {"type": "function", "name": "get_weather", "description": "Get weather", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model, input1); + EXPECT_GE(output.length(), 0); + }); + + llama_pos nPastBeforeTools1 = model->getNPastBeforeTools(); + EXPECT_GT(nPastBeforeTools1, 0) << "nPastBeforeTools should be set after first prompt with tools"; + + std::string saveInput = + R"([{"role": "session", "content": "test_session1.bin"}, {"role": "session", "content": "save"}])"; + EXPECT_NO_THROW({ + std::string saveOutput = processPromptString(model, saveInput); + EXPECT_EQ(saveOutput.length(), 0); + }); + + EXPECT_TRUE(fs::exists(session1_path)); + + auto model2 = createModel(); + if (!model2) { + FAIL() << "Model2 failed to load"; + } + + std::string input2 = + R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "What about London?"}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model2, input2); + EXPECT_GE(output.length(), 0); + }); + + llama_pos nPastBeforeTools2 = model2->getNPastBeforeTools(); + EXPECT_EQ(nPastBeforeTools2, nPastBeforeTools1) + << "nPastBeforeTools should be restored from session: expected " << nPastBeforeTools1 + << " but got " << nPastBeforeTools2; +} From 2d74bf9b9df7c1c5ac590f67ca8e2b4779791248 Mon Sep 17 00:00:00 2001 From: olyasir Date: Thu, 12 Mar 2026 15:49:52 +0200 Subject: [PATCH 16/48] fix(llm): pass toolsAtEnd flag to context constructors to fix template selection race MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The toolsAtEnd flag was set via setToolsAtEnd() after context creation, but getChatTemplateForModel() was called during construction — always seeing toolsAtEnd=0 and selecting the wrong Qwen3 template. Pass the flag through createContext() into TextLlmContext and MtmdLlmContext constructors so the correct template is selected from the start. Also restore the conditional template selection in ChatTemplateUtils that was previously hardcoded. --- Pitch_tools_at_end_of_prompt.md | 86 +++++ .../addon/src/model-interface/LlamaModel.cpp | 9 +- .../addon/src/model-interface/LlamaModel.hpp | 2 +- .../src/model-interface/MtmdLlmContext.cpp | 4 +- .../src/model-interface/MtmdLlmContext.hpp | 2 +- .../src/model-interface/TextLlmContext.cpp | 4 +- .../src/model-interface/TextLlmContext.hpp | 2 +- .../addon/src/utils/ChatTemplateUtils.cpp | 3 +- .../examples/conv.md | 51 +++ .../examples/testHugeToolCache.js | 312 ++++++++++++++++ prefill_offset_implementation_plan.md | 341 ++++++++++++++++++ 11 files changed, 803 insertions(+), 13 deletions(-) create mode 100644 Pitch_tools_at_end_of_prompt.md create mode 100644 packages/qvac-lib-infer-llamacpp-llm/examples/conv.md create mode 100644 packages/qvac-lib-infer-llamacpp-llm/examples/testHugeToolCache.js create mode 100644 prefill_offset_implementation_plan.md diff --git a/Pitch_tools_at_end_of_prompt.md b/Pitch_tools_at_end_of_prompt.md new file mode 100644 index 0000000000..1db691ae0a --- /dev/null +++ b/Pitch_tools_at_end_of_prompt.md @@ -0,0 +1,86 @@ + + +| Approved by Technical Lead | WIP | +| :---- | :---- | +| Approved by Technical Architect | **WIP** | +| \[optional\] Review from Subash | **WIP** | + +# Tools at End of Prompt for KV-Cache Optimization + +# Pitch + +## Problem + +In the current architecture, tool definitions are placed at the beginning of the prompt (typically inside or right after the system prompt), following default chat templates. This means that whenever tools change between conversation turns — e.g. when an agent selects different tools for a new user query — the KV-cache is invalidated from the point of the tool definitions onward, forcing a full recomputation of the entire conversation history that follows. + +On mobile devices with limited compute, this is especially costly. The conversation history can grow long, and reprocessing it on every turn with changed tools eliminates the benefit of prompt caching. Since we control the KV-cache in our setup, we have an opportunity to optimize: if tools are placed at the **end** of the prompt (after the conversation history, right before generation), we can cache everything up to the tools and only recompute the new query + new tools on each turn. This dramatically reduces per-turn computation. + +**Current layout (tools at the beginning):** +``` +| <-- cache invalidated from tools onward +``` + +**Desired layout (tools at the end):** +``` +| <-- response + new query + tools recomputed as prefill +``` + +Each token in the KV-cache depends on all previous tokens, so tokens can only be removed/changed at the end without invalidating the rest. By placing tools last, we can strip old tools *and* the model's response from the cache tail, then recompute them together with the new query and new tools in a single prefill pass. Since all response tokens are already known, prefill is fully parallel and significantly cheaper than autoregressive generation. The cached system prompt and conversation history up to the last user query is preserved and never recomputed. + +## Solution + +The solution has two parts: + +### 1. Modified Chat Templates + +Model chat templates (Jinja2-based) control where tool definitions appear in the final prompt. We need to modify these templates to extract tool definitions from their default position (usually inside the system prompt) and place them at the end of the prompt, just before the generation token. + +POC results (PR [#232](https://github.com/tetherto/qvac/pull/232)): +- **Qwen3 family**: Successfully tested with modified chat template. Tools placed at the end are picked up correctly — the model calls tools properly with no degradation in quality. Tested on a heavy scenario (1 prompt, 20+ tool calls for code review). +- **LFM (Liquid AI)**: Requires tools in the system prompt — fundamentally different architecture. Would likely need fine-tuning/retraining to support tools at a different position. Out of scope for now. + +### 2. KV-Cache Strategy Update + +The current caching implementation expects an exact prefix match: it caches the full prompt and on the next turn checks if the new prompt starts with the cached prefix. With tools at the end, the conversation turns are inserted *before* the tools, which breaks this assumption. + +We need a new cache strategy: +- After each model response, **trim both the tool tokens and the response tokens from the end of the KV-cache** (we know the exact token counts since we control the prompt construction). +- On the next turn, **recompute the previous response tokens + new user query tokens + new tool tokens as a single prefill pass**. Since all these tokens are already known (the response already happened, the new query and tools are provided), this is a fully parallel operation — no autoregressive generation needed. +- The system prompt + conversation history up to the last user query remains cached and is never recomputed. + +This is possible because we have full control over the KV-cache in our inference stack (llama.cpp / custom server). The key insight is that removing tokens from the end of the cache does not invalidate any preceding tokens, and prefilling known tokens is significantly cheaper than recomputing the full conversation from scratch. + +This approach also avoids any correctness concerns: since the response KV entries are always recomputed alongside the current tool definitions, there is no stale state in the cache. Each turn's response KV is consistent with the tools that were in context when it was generated. + +## Risks + +1. **Model-specific behavior**: Not all models support tools at arbitrary positions. The chat template is model-defined and some models (like LFM) embed tool handling into training. We must test each target model individually. Mitigation: maintain a registry of supported models and fall back to default template for unsupported ones. + +2. **Prefill overhead**: Recomputing response tokens as prefill on each turn adds some per-turn cost compared to keeping them cached. However, prefill is fully parallel and in practice much cheaper than recomputing the full conversation history from scratch, especially for conversations with large payloads (e.g., image tokens in VLM scenarios). Mitigation: benchmark prefill cost vs. full-recompute cost across different conversation lengths to quantify the savings. + +3. **Chat template maintenance**: Modified chat templates need to be kept in sync when models are updated. Mitigation: automate template modification or contribute upstream patches. + +4. **Inference server compatibility**: The current MLX-based server and llama.cpp handle caching differently. The cache trimming strategy needs to work across both. Mitigation: implement the cache strategy at our abstraction layer, not at the server level. + +## Out of scope + +- Fine-tuning or retraining models that don't natively support tools at the end of the prompt (e.g., LFM from Liquid AI). +- Orchestrator/multi-agent architecture for tool management (separate pitch). +- Embedding tool capabilities via fine-tuning (separate pitch). + +## Nice to haves + +- Benchmark suite comparing inference latency with tools-at-beginning vs. tools-at-end across different conversation lengths. +- Automatic chat template modification tool that takes a model's default template and produces the tools-at-end variant. +- Support for partial tool caching (keeping common/unchanged tools in cache, only recomputing added/removed ones). + +## Estimate + +* \[1 dev day\] Implement modified chat templates for Qwen3 family models and validate tool calling accuracy. +* \[2 dev days\] Implement KV-cache trimming strategy — trim tool tokens from cache tail and append new query + tools. +* \[1 dev day\] Integrate cache strategy with llama.cpp inference backend. +* \[1 dev day\] Quality validation — run multi-turn benchmarks comparing full-recompute vs. cache-trimmed responses; measure latency improvements. +* \[0.5 dev days\] Add model compatibility registry and fallback logic for unsupported models. +* \[0.5 dev days\] Documentation and testing. + +**Total: ~6 dev days** diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp index d6e190cc68..e39887303a 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp @@ -233,7 +233,8 @@ void LlamaModel::init(bool acquireLock) { snap->llmContext_ = createContext( std::string(constructionArgs_.projectionPath), params, - std::move(llamaInit)); + std::move(llamaInit), + snap->toolsAtEnd_); // Apply tools_at_end flag if (snap->llmContext_) { @@ -850,12 +851,12 @@ void LlamaModel::resetState(bool resetStats) { std::unique_ptr LlamaModel::createContext( std::string&& projectionPath, common_params& params, - common_init_result&& llamaInit) { + common_init_result&& llamaInit, bool toolsAtEnd) { if (!projectionPath.empty()) { params.mmproj.path = std::move(projectionPath); - return std::make_unique(params, std::move(llamaInit)); + return std::make_unique(params, std::move(llamaInit), toolsAtEnd); } - return std::make_unique(params, std::move(llamaInit)); + return std::make_unique(params, std::move(llamaInit), toolsAtEnd); } bool LlamaModel::loadMedia(const std::vector& input) { diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp index e4c1c86b6e..768ccd2d92 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp @@ -244,7 +244,7 @@ class LlamaModel : public IModel, public IModelAsyncLoad, public IModelCancel { */ std::unique_ptr createContext( std::string&& projectionPath, common_params& params, - common_init_result&& llamaInit); + common_init_result&& llamaInit, bool toolsAtEnd); /** * The Load media method. It loads the media. diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp index a18a845925..40403bb04e 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp @@ -20,9 +20,9 @@ using namespace qvac_lib_inference_addon_llama::utils; // NOLINTNEXTLINE(readability-function-cognitive-complexity) MtmdLlmContext::MtmdLlmContext( - common_params& commonParams, common_init_result&& llamaInit) + common_params& commonParams, common_init_result&& llamaInit, bool toolsAtEnd) : llamaInit_(std::move(llamaInit)), params_(commonParams), - model_(llamaInit_.model.get()), lctx_(llamaInit_.context.get()) { + model_(llamaInit_.model.get()), lctx_(llamaInit_.context.get()), toolsAtEnd_(toolsAtEnd) { if (model_ == nullptr) { throw qvac_errors::StatusError( diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp index adee67bebb..248acd6ac5 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp @@ -18,7 +18,7 @@ class MtmdLlmContext: public LlmContext { * @param _llama_init - The result of initializing/loading the model using * .gguf file(s) */ - MtmdLlmContext(common_params& commonParams, common_init_result&& llamaInit); + MtmdLlmContext(common_params& commonParams, common_init_result&& llamaInit, bool toolsAtEnd = false); /** * The destructor. diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp index ae8095b3f8..b1289f7c45 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp @@ -23,8 +23,8 @@ using namespace qvac_lib_inference_addon_llama::utils; // NOLINTNEXTLINE(readability-function-cognitive-complexity) TextLlmContext::TextLlmContext( - common_params& commonParams, common_init_result&& llamaInit) - : llamaInit_(std::move(llamaInit)), params_(commonParams) { + common_params& commonParams, common_init_result&& llamaInit, bool toolsAtEnd) + : llamaInit_(std::move(llamaInit)), params_(commonParams), toolsAtEnd_(toolsAtEnd) { { model_ = llamaInit_.model.get(); diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp index f66afa246a..3fbd713104 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp @@ -17,7 +17,7 @@ class TextLlmContext: public LlmContext { TextLlmContext(TextLlmContext&&) = delete; TextLlmContext& operator=(TextLlmContext&&) = delete; // Constructor - TextLlmContext(common_params& commonParams, common_init_result&& llamaInit); + TextLlmContext(common_params& commonParams, common_init_result&& llamaInit, bool toolsAtEnd = false); // Destructor ~TextLlmContext() override = default; diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.cpp index e6a3e657e1..f80b01d6cb 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.cpp @@ -69,8 +69,7 @@ std::string getChatTemplateForModel( if (isQwen3Model(model)) { printf("ChatTemplateUtils::getChatTemplateForModel - Qwen3 - toolsAtEnd=%d\n", toolsAtEnd); - return getToolsDynamicQwen3Template(); - // return toolsAtEnd ? getToolsDynamicQwen3Template() : getFixedQwen3Template(); + return toolsAtEnd ? getToolsDynamicQwen3Template() : getFixedQwen3Template(); } printf("ChatTemplateUtils::getChatTemplateForModel - empty\n"); diff --git a/packages/qvac-lib-infer-llamacpp-llm/examples/conv.md b/packages/qvac-lib-infer-llamacpp-llm/examples/conv.md new file mode 100644 index 0000000000..4ecb6b75d7 --- /dev/null +++ b/packages/qvac-lib-infer-llamacpp-llm/examples/conv.md @@ -0,0 +1,51 @@ +# Strip tool_call blocks & benchmark — session notes + +## What was done + +### 1. Strip internal blocks from re-sent assistant responses +Added `stripInternalBlocks()` helper to both example files. It removes `` and `` blocks from assistant responses before they're re-sent in conversation history, preventing the model from pattern-matching on old tool calls and hallucinating removed tools. + +**Files modified:** +- `examples/testToolRemoval.js` — strips `lastResponse` (4 turns) and `history` assistant entries (3 pushes in `mainInSystem()`) +- `examples/benchToolsPlacement.js` — strips `lastAssistantResponse` and `conversationHistory` entries in `runScenario()` + +### 2. testToolRemoval.js — all 8 tests PASS +``` +bare examples/testToolRemoval.js +``` +Both `tools_at_end` and `tools_in_system` sections pass all 4 turns, including turn 4 which previously failed. + +### 3. benchToolsPlacement.js — 20-turn benchmark +Updated `NUM_TURNS` to 20, added 10 more entries to `DYNAMIC_TOOLS_PER_TURN` and `CONVERSATION_TURNS_DYNAMIC`. + +Run with: +``` +bare examples/benchToolsPlacement.js +``` + +**Results (CPU-only, no GPU):** +- tools_at_end (C) is **58.2% faster** — saved 1281s across 20 turns +- All 40 turns PASS — zero stale tool leaks +- D's prompt tokens grow 285→3526, TTFT grows 13s→143s +- C stays relatively flat (15-80s wall time), cache grows 26→1991 tokens +- D gets zero cache hits after turn 1 + +### 4. HTML chart +`examples/benchmark_chart.html` — open in browser, has 4 bar charts (wall time, TTFT, prompt tokens, cache tokens). + +## GPU / Vulkan issue +The benchmark ran on CPU only. The machine has Intel Iris Xe (Raptor Lake-P) but it was booted in **recovery mode with `nomodeset`**, which disables kernel GPU drivers. + +**Fix:** Reboot normally (not recovery mode). The grub config is fine (`quiet splash`). After normal boot: +- `i915` or `xe` module should load automatically +- `/dev/dri/renderD128` should appear +- Vulkan will pick up the Intel GPU +- Benchmark should be significantly faster with bigger gap between C and D + +Verify after reboot: +``` +ls /dev/dri/render* +vulkaninfo --summary 2>&1 | grep deviceName +``` + +Then re-run the 20-turn benchmark to get GPU numbers. diff --git a/packages/qvac-lib-infer-llamacpp-llm/examples/testHugeToolCache.js b/packages/qvac-lib-infer-llamacpp-llm/examples/testHugeToolCache.js new file mode 100644 index 0000000000..87c22b54aa --- /dev/null +++ b/packages/qvac-lib-infer-llamacpp-llm/examples/testHugeToolCache.js @@ -0,0 +1,312 @@ +'use strict' + +const LlmLlamacpp = require('../index') +const FilesystemDL = require('@qvac/dl-filesystem') +const path = require('bare-path') +const fs = require('bare-fs') +const process = require('bare-process') +const os = require('bare-os') +const { downloadModel } = require('./utils') + +const isDarwinX64 = os.platform() === 'darwin' && os.arch() === 'x64' +const isLinuxArm64 = os.platform() === 'linux' && os.arch() === 'arm64' +const useCpu = isDarwinX64 || isLinuxArm64 + +const MODEL = { + name: 'Qwen3-1.7B-Q4_0.gguf', + url: 'https://huggingface.co/unsloth/Qwen3-1.7B-GGUF/resolve/main/Qwen3-1.7B-Q4_0.gguf' +} + +const NUM_TURNS = 10 + +// ─── Generate a massive tool definition (~3000 tokens) ───────────────────── + +function generateHugeTool () { + // ~60 properties with verbose descriptions to hit ~3000 tokens + const properties = {} + const fields = [ + 'user_name', 'user_id', 'user_email', 'user_phone', 'user_address', + 'user_city', 'user_state', 'user_zip', 'user_country', 'user_status', + 'account_id', 'account_type', 'account_tier', 'account_balance', + 'order_id', 'order_status', 'order_total', 'order_currency', 'order_date', + 'product_id', 'product_name', 'product_category', 'product_price', + 'shipping_method', 'shipping_address', 'shipping_tracking', + 'billing_name', 'billing_address', 'billing_card_last4', + 'payment_method', 'payment_status', 'payment_amount', + 'ticket_id', 'ticket_subject', 'ticket_priority', 'ticket_status', + 'subscription_plan', 'subscription_renewal', 'subscription_active', + 'discount_code', 'discount_percent', 'discount_expires', + 'report_type', 'report_start_date', 'report_end_date', 'report_format', + 'notification_type', 'notification_channel', 'notification_message', + 'inventory_sku', 'inventory_quantity', 'inventory_warehouse', + 'analytics_metric', 'analytics_period', 'analytics_segment', + 'webhook_url', 'webhook_event', 'webhook_secret', + 'audit_action', 'audit_timestamp', 'audit_actor' + ] + + for (const field of fields) { + const isNum = field.includes('amount') || field.includes('price') || field.includes('total') || field.includes('quantity') || field.includes('balance') || field.includes('percent') + properties[field] = { + type: isNum ? 'number' : 'string', + description: `The ${field.replace(/_/g, ' ')} field used for enterprise data management operations including filtering, processing, and reporting.` + } + } + + return { + type: 'function', + name: 'enterpriseDataManager', + description: 'A comprehensive enterprise data management tool that handles user management, billing, shipping, orders, payments, inventory, analytics, reporting, notifications, subscriptions, discounts, support tickets, webhooks, and audit logging.', + parameters: { + type: 'object', + properties, + required: ['user_name', 'user_id', 'order_id'] + } + } +} + +const HUGE_TOOL = generateHugeTool() + +const CONVERSATION_TURNS = [ + 'Hello, what can you help me with?', + 'Look up user john@example.com', + 'What is order 12345 status?', + 'Update the shipping address for that order', + 'Show me the billing summary', + 'Create a support ticket for this issue', + 'What analytics do we have for last month?', + 'Generate a report of all active subscriptions', + 'Apply discount code SAVE20 to order 12345', + 'Send a notification to the customer about the update' +] + +function stripInternalBlocks (text) { + return text + .replace(/[\s\S]*?<\/think>/g, '') + .replace(/[\s\S]*?<\/tool_call>/g, '') + .trim() +} + +// ─── Helpers ──────────────────────────────────────────────────────────────── + +async function loadModel (dirPath, modelName, config) { + const loader = new FilesystemDL({ dirPath }) + const model = new LlmLlamacpp({ + loader, + modelName, + diskPath: dirPath, + logger: console, + opts: { stats: true } + }, config) + await model.load() + return { model, loader } +} + +async function runAndCollect (model, prompt) { + const response = await model.run(prompt) + const chunks = [] + await response.onUpdate(data => { chunks.push(data) }).await() + return { output: chunks.join(''), stats: response.stats } +} + +function hrMs (hrtime) { + return (hrtime[0] * 1e3 + hrtime[1] / 1e6).toFixed(2) +} + +// ─── Scenario: tools_at_end ───────────────────────────────────────────────── + +async function runToolsAtEnd (dirPath, modelName) { + console.log('\n' + '='.repeat(70)) + console.log('SCENARIO A: tools_at_end = true (huge tool ~3000 tokens)') + console.log('='.repeat(70)) + + const config = { + device: useCpu ? 'cpu' : 'gpu', + gpu_layers: '999', + ctx_size: '8192', + n_predict: '128', + temp: '0.1', + seed: '1', + verbosity: '0', + tools: 'true', + tools_at_end: 'true' + } + + const { model, loader } = await loadModel(dirPath, modelName, config) + const cachePath = path.join(dirPath, 'huge-tool-at-end.bin') + try { fs.unlinkSync(cachePath) } catch (_) {} + + const stats = [] + let lastResponse = null + + try { + for (let i = 0; i < NUM_TURNS; i++) { + const prompt = [ + { role: 'session', content: cachePath }, + ...(i === 0 + ? [{ role: 'system', content: 'You are a helpful enterprise assistant.' }, { role: 'user', content: CONVERSATION_TURNS[i] }] + : [ + ...(lastResponse ? [{ role: 'assistant', content: lastResponse }] : []), + { role: 'user', content: CONVERSATION_TURNS[i] } + ]), + HUGE_TOOL + ] + + const t0 = process.hrtime() + const result = await runAndCollect(model, prompt) + const elapsed = process.hrtime(t0) + lastResponse = stripInternalBlocks(result.output) + + const s = result.stats || {} + stats.push({ + turn: i + 1, + wallMs: hrMs(elapsed), + promptTokens: s.promptTokens || 0, + cacheTokens: s.CacheTokens || 0, + generatedTokens: s.generatedTokens || 0, + ttft: s.TTFT || 0 + }) + + console.log( + ` Turn ${i + 1}: wall=${hrMs(elapsed)}ms prompt=${stats[i].promptTokens} ` + + `cache=${stats[i].cacheTokens} gen=${stats[i].generatedTokens} TTFT=${stats[i].ttft}ms` + ) + } + } finally { + await model.unload() + await loader.close() + try { fs.unlinkSync(cachePath) } catch (_) {} + } + + return stats +} + +// ─── Scenario: tools_in_system (same tool every turn, no reset needed) ────── + +async function runToolsInSystem (dirPath, modelName) { + console.log('\n' + '='.repeat(70)) + console.log('SCENARIO B: tools_at_end = false (huge tool ~3000 tokens, cached in system)') + console.log('='.repeat(70)) + + const config = { + device: useCpu ? 'cpu' : 'gpu', + gpu_layers: '999', + ctx_size: '8192', + n_predict: '128', + temp: '0.1', + seed: '1', + verbosity: '0', + tools: 'true', + tools_at_end: 'false' + } + + const { model, loader } = await loadModel(dirPath, modelName, config) + const cachePath = path.join(dirPath, 'huge-tool-in-system.bin') + try { fs.unlinkSync(cachePath) } catch (_) {} + + const stats = [] + + try { + for (let i = 0; i < NUM_TURNS; i++) { + // Same tool every turn — no reset needed, tool is cached from turn 1 + const prompt = [ + { role: 'session', content: cachePath }, + ...(i === 0 + ? [{ role: 'system', content: 'You are a helpful enterprise assistant.' }, { role: 'user', content: CONVERSATION_TURNS[i] }] + : [{ role: 'user', content: CONVERSATION_TURNS[i] }]), + ...(i === 0 ? [HUGE_TOOL] : []) + ] + + const t0 = process.hrtime() + const result = await runAndCollect(model, prompt) + const elapsed = process.hrtime(t0) + + const s = result.stats || {} + stats.push({ + turn: i + 1, + wallMs: hrMs(elapsed), + promptTokens: s.promptTokens || 0, + cacheTokens: s.CacheTokens || 0, + generatedTokens: s.generatedTokens || 0, + ttft: s.TTFT || 0 + }) + + console.log( + ` Turn ${i + 1}: wall=${hrMs(elapsed)}ms prompt=${stats[i].promptTokens} ` + + `cache=${stats[i].cacheTokens} gen=${stats[i].generatedTokens} TTFT=${stats[i].ttft}ms` + ) + } + } finally { + await model.unload() + await loader.close() + try { fs.unlinkSync(cachePath) } catch (_) {} + } + + return stats +} + +// ─── Summary ──────────────────────────────────────────────────────────────── + +function printSummary (statsA, statsB) { + console.log('\n' + '='.repeat(80)) + console.log('COMPARISON: tools_at_end (A) vs tools_in_system (B) — SAME huge tool, no tool changes') + console.log('='.repeat(80)) + console.log('') + console.log('Turn | Wall A | Wall B | Cache A | Cache B | Prompt A | Prompt B | TTFT A | TTFT B') + console.log('-----|-----------|-----------|---------|---------|----------|----------|---------|--------') + + for (let i = 0; i < statsA.length; i++) { + const a = statsA[i] + const b = statsB[i] + const ttftA = typeof a.ttft === 'number' ? a.ttft.toFixed(0) : String(a.ttft) + const ttftB = typeof b.ttft === 'number' ? b.ttft.toFixed(0) : String(b.ttft) + + console.log( + ` ${String(a.turn).padStart(2)} ` + + `| ${(a.wallMs + 'ms').padStart(9)} ` + + `| ${(b.wallMs + 'ms').padStart(9)} ` + + `| ${String(a.cacheTokens).padStart(7)} ` + + `| ${String(b.cacheTokens).padStart(7)} ` + + `| ${String(a.promptTokens).padStart(8)} ` + + `| ${String(b.promptTokens).padStart(8)} ` + + `| ${ttftA.padStart(7)} ` + + `| ${ttftB.padStart(7)}` + ) + } + + console.log('') + console.log('Key insight: Cache column shows the difference') + console.log(' - tools_at_end (A): tool tokens are trimmed & re-appended each turn — NOT in cache') + console.log(' - tools_in_system (B): tool tokens are baked into cache from turn 1 — ~3000 extra tokens cached') + console.log('') + + const lastA = statsA[statsA.length - 1] + const lastB = statsB[statsB.length - 1] + const cacheDiff = lastB.cacheTokens - lastA.cacheTokens + console.log(` Final cache: A=${lastA.cacheTokens} tokens, B=${lastB.cacheTokens} tokens`) + console.log(` Difference: B has ${cacheDiff} MORE tokens in cache (the huge tool definition)`) + console.log(` That's ${((cacheDiff / lastB.cacheTokens) * 100).toFixed(1)}% of B's cache wasted on tool tokens`) +} + +// ─── Main ─────────────────────────────────────────────────────────────────── + +async function main () { + console.log('Test: huge tool definition (~3000 tokens) — cache impact') + console.log(`Model: ${MODEL.name}`) + console.log(`Turns: ${NUM_TURNS}`) + console.log('') + + const toolJson = JSON.stringify(HUGE_TOOL) + console.log(`Tool definition size: ${toolJson.length} chars`) + + const [modelName, dirPath] = await downloadModel(MODEL.url, MODEL.name) + + const statsA = await runToolsAtEnd(dirPath, modelName) + const statsB = await runToolsInSystem(dirPath, modelName) + + printSummary(statsA, statsB) +} + +main().catch(err => { + console.error('Fatal:', err.message || err) + process.exit(1) +}) diff --git a/prefill_offset_implementation_plan.md b/prefill_offset_implementation_plan.md new file mode 100644 index 0000000000..ac48469120 --- /dev/null +++ b/prefill_offset_implementation_plan.md @@ -0,0 +1,341 @@ +# Prefill with Offset — Implementation Plan + +## Goal + +Add an `offset` parameter to the eval methods in the LLM addon's C++ layer. When provided, the KV cache is trimmed to `offset` position before evaluating new tokens. Combined with `prefill=true` (from PR #689), this enables the tools-at-end KV cache optimization entirely in C++, with no JS API changes. + +## Context + +The tools-at-end optimization (see `Pitch_tools_at_end_of_prompt.md`) requires: +1. Trimming the KV cache tail (remove old tools + response tokens) +2. Prefilling known tokens (previous response + new query + new tools) from a specific cache position +3. Generating from the warm cache + +PR #689 adds `prefill=true` which evaluates tokens into the KV cache without generating. But it always appends at `nPast_` — there's no way to say "go back to position X and prefill from there." The `offset` parameter fills that gap. + +## How It Works + +``` +offset = -1 (default): current behavior, eval starts from nPast_ +offset >= 0: trim KV cache to that position, then eval new tokens from there +``` + +When `evalMessageWithTools` receives `offset >= 0 && offset < nPast_`: +1. Call `removeLastNTokens(nPast_ - offset)` — this trims the KV cache and sets `nPast_ = offset` +2. Proceed with normal token evaluation starting from the new `nPast_` + +This is atomic — trim + eval in a single call. No need for the caller to manually call `removeLastNTokens` then `evalMessage` separately. + +## End-to-End Flow (tools-at-end optimization) + +This is how `processPrompt()` would use offset + prefill internally: + +### Turn 1 (cold start) +``` +KV cache: empty +Prompt: + +1. evalMessageWithTools(msgs, tools1, ..., prefill=false, offset=-1) + -> tokens evaluated at pos 0..N-1, nPast_ = N +2. generateResponse() -> model generates, nPast_ = N + G +3. Track: toolTokenCount_ = T, responseTokenCount_ = G + Cache state: [system | user-q-1 | tools-1 | response-1] + pos 0 pos N-T pos N pos N+G +``` + +### Turn 2 (tools changed) +``` +KV cache: [system | user-q-1 | tools-1 | response-1] +Want: [system | user-q-1 | response-1 | user-q-2 | tools-2] + +offset = N - T (position just before old tools) + +1. Build full message array: [system, user-q-1, assistant-response-1, user-q-2] + tools-2 +2. evalMessageWithTools(msgs, tools2, ..., prefill=false, offset=N-T) + -> removeLastNTokens(nPast_ - offset) trims tools-1 + response-1 + -> KV cache: [system | user-q-1] + -> tokenizeChat produces full prompt tokens + -> only NEW tokens (after the cached prefix) are evaluated + -> nPast_ updated to include response-1 + user-q-2 + tools-2 +3. generateResponse() -> model generates turn 2 response +``` + +Note: The prefill flag is for when you want to eval without generating (preload context). The offset works with both `prefill=true` and `prefill=false`. + +--- + +## Files to Change + +All files are under `packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/`. + +### 1. LlmContext.hpp (virtual interface) + +**What:** Add `offset` parameter to both virtual method signatures. + +**Current (after PR #689):** +```cpp +virtual bool evalMessage( + const std::vector& chatMsgs, bool isCacheLoaded, + bool prefill) = 0; + +virtual bool evalMessageWithTools( + const std::vector& chatMsgs, + const std::vector& tools, bool isCacheLoaded, + bool prefill) = 0; +``` + +**New:** +```cpp +virtual bool evalMessage( + const std::vector& chatMsgs, bool isCacheLoaded, + bool prefill, llama_pos offset = -1) = 0; + +virtual bool evalMessageWithTools( + const std::vector& chatMsgs, + const std::vector& tools, bool isCacheLoaded, + bool prefill, llama_pos offset = -1) = 0; +``` + +**Lines affected:** ~114-128 (the two virtual declarations and their doc comments) + +**Doc comment addition for both methods:** +```cpp +* @param offset - KV cache position to trim to before evaluation. +* -1 means no trimming (default, eval from current nPast_). +* >= 0 trims cache to this position, then evaluates from there. +``` + +--- + +### 2. TextLlmContext.hpp (override declarations) + +**What:** Update override signatures to match new virtual interface. + +**Current (after PR #689):** +```cpp +bool evalMessage( + const std::vector& chatMsgs, + bool isCacheLoaded, bool prefill) override; + +bool evalMessageWithTools( + const std::vector& chatMsgs, + const std::vector& tools, bool isCacheLoaded, + bool prefill) override; +``` + +**New:** +```cpp +bool evalMessage( + const std::vector& chatMsgs, + bool isCacheLoaded, bool prefill, llama_pos offset = -1) override; + +bool evalMessageWithTools( + const std::vector& chatMsgs, + const std::vector& tools, bool isCacheLoaded, + bool prefill, llama_pos offset = -1) override; +``` + +**Lines affected:** ~30-45 + +--- + +### 3. TextLlmContext.cpp (implementation) + +**What:** Two changes — update signatures + add trim logic. + +#### 3a. evalMessage (forwarding method, ~line 256) + +**Current (after PR #689):** +```cpp +bool TextLlmContext::evalMessage( + const std::vector& chatMsgs, bool isCacheLoaded, + bool prefill) { + return evalMessageWithTools(chatMsgs, {}, isCacheLoaded, prefill); +} +``` + +**New:** +```cpp +bool TextLlmContext::evalMessage( + const std::vector& chatMsgs, bool isCacheLoaded, + bool prefill, llama_pos offset) { + return evalMessageWithTools(chatMsgs, {}, isCacheLoaded, prefill, offset); +} +``` + +#### 3b. evalMessageWithTools (main method, ~line 261) + +**Current (after PR #689):** +```cpp +bool TextLlmContext::evalMessageWithTools( + const std::vector& chatMsgs, + const std::vector& tools, bool isCacheLoaded, + bool prefill) { + std::vector inputTokens; + tokenizeChat(chatMsgs, tools, inputTokens, isCacheLoaded); + // ... rest of method +``` + +**New:** +```cpp +bool TextLlmContext::evalMessageWithTools( + const std::vector& chatMsgs, + const std::vector& tools, bool isCacheLoaded, + bool prefill, llama_pos offset) { + + // Trim KV cache to offset position if specified + if (offset >= 0 && offset < nPast_) { + removeLastNTokens(nPast_ - offset); + } + + std::vector inputTokens; + tokenizeChat(chatMsgs, tools, inputTokens, isCacheLoaded); + // ... rest of method unchanged +``` + +**Why this works:** `removeLastNTokens` calls `llama_memory_seq_rm` to remove entries from the KV cache and decrements `nPast_`. The existing eval loop uses `llama_pos count = nPast_` (line ~319) as its starting position, so new tokens are naturally placed right after the offset. + +--- + +### 4. MtmdLlmContext.hpp (override declarations) + +**What:** Same signature update as TextLlmContext.hpp. + +**Current (after PR #689):** +```cpp +bool evalMessage( + const std::vector& chatMsgs, + bool isCacheLoaded, bool prefill) override; + +bool evalMessageWithTools( + const std::vector& chatMsgs, + const std::vector& tools, bool isCacheLoaded, + bool prefill) override; +``` + +**New:** +```cpp +bool evalMessage( + const std::vector& chatMsgs, + bool isCacheLoaded, bool prefill, llama_pos offset = -1) override; + +bool evalMessageWithTools( + const std::vector& chatMsgs, + const std::vector& tools, bool isCacheLoaded, + bool prefill, llama_pos offset = -1) override; +``` + +**Lines affected:** ~37-52 + +--- + +### 5. MtmdLlmContext.cpp (implementation) + +**What:** Same pattern as TextLlmContext.cpp — update signatures + add trim logic. + +#### 5a. evalMessage (forwarding method, ~line 210) + +**New:** +```cpp +bool MtmdLlmContext::evalMessage( + const std::vector& chatMsgs, bool isCacheLoaded, + bool prefill, llama_pos offset) { + return evalMessageWithTools(chatMsgs, {}, isCacheLoaded, prefill, offset); +} +``` + +#### 5b. evalMessageWithTools (main method, ~line 215) + +**New (add trim block at top):** +```cpp +bool MtmdLlmContext::evalMessageWithTools( + const std::vector& chatMsgs, + const std::vector& tools, bool isCacheLoaded, + bool prefill, llama_pos offset) { + + // Trim KV cache to offset position if specified + if (offset >= 0 && offset < nPast_) { + removeLastNTokens(nPast_ - offset); + } + + mtmd::input_chunks chunks(mtmd_input_chunks_init()); + tokenizeChat(chatMsgs, tools, chunks, isCacheLoaded); + // ... rest unchanged +``` + +--- + +### 6. LlamaModel.cpp — processPrompt() passes offset + +**What:** Thread `offset` from the internal call site into eval methods. For now, always pass `-1` (no trim) to keep existing behavior. The tools-at-end optimization will set a real offset later. + +**Current (after PR #689, ~line 262):** +```cpp +bool evalOk = + resolved.tools.empty() + ? llmContext_->evalMessage( + resolved.chatMsgs, resolved.isCacheLoaded, prompt.prefill) + : llmContext_->evalMessageWithTools( + resolved.chatMsgs, resolved.tools, + resolved.isCacheLoaded, prompt.prefill); +``` + +**No change needed here** — since the default value is `offset = -1` in the virtual declarations, existing call sites don't need to be updated. The offset will only be passed explicitly when the tools-at-end optimization is implemented in `processPrompt()`. + +--- + +## Files NOT Changed + +| File | Why | +|------|-----| +| `LlamaModel.hpp` | `Prompt` struct not touched — offset is internal to C++, not from JS | +| `index.js` | JS API unchanged | +| `index.d.ts` | TypeScript types unchanged | +| `CacheManager.hpp/.cpp` | Cache manager deals with disk sessions, not in-flight cache trimming | + +--- + +## Testing + +### Unit-level validation for offset + +Add to `test/integration/api-behavior.test.js`: + +```js +test('prefill with offset trims cache and re-evaluates', { timeout: 600_000 }, async t => { + const { model } = await setupModel(t) + + // 1. Normal run to populate cache + const r1 = await model.run(BASE_PROMPT) + await collectResponse(r1) + const cacheAfterR1 = toNumber(r1?.stats?.CacheTokens) + t.ok(cacheAfterR1 > 0, 'cache populated after first run') + + // 2. Prefill with offset=0 should trim entire cache, then re-evaluate + const r2 = await model.run(BASE_PROMPT, { prefill: true, offset: 0 }) + await collectResponse(r2) + const cacheAfterR2 = toNumber(r2?.stats?.CacheTokens) + t.ok(cacheAfterR2 > 0, 'cache repopulated after prefill with offset') + + // 3. Normal run after prefill should still work + const r3 = await model.run(BASE_PROMPT) + const output = await collectResponse(r3) + t.ok(output.length > 0, 'generation works after prefill with offset') +}) +``` + +Note: This test requires exposing `offset` via JS (`RunOptions`). If offset stays internal-only in C++, this test would need to be a C++ unit test instead. + +--- + +## Summary + +| Change | Files | Lines of new logic | +|--------|-------|--------------------| +| Add `offset` param to virtual interface | `LlmContext.hpp` | signature only | +| Update TextLlm override signatures | `TextLlmContext.hpp` | signature only | +| Add trim-to-offset logic in TextLlm | `TextLlmContext.cpp` | 3 lines | +| Update MtmdLlm override signatures | `MtmdLlmContext.hpp` | signature only | +| Add trim-to-offset logic in MtmdLlm | `MtmdLlmContext.cpp` | 3 lines | + +Total new logic: ~6 lines across 2 files. The rest is signature propagation. From 22e4c89410e2d83dc94b62fb830437bea1f9845e Mon Sep 17 00:00:00 2001 From: olyasir Date: Thu, 12 Mar 2026 15:50:47 +0200 Subject: [PATCH 17/48] feat(llm): strip tool_call/think blocks from re-sent assistant responses Add stripInternalBlocks() helper to testToolRemoval.js and benchToolsPlacement.js to remove and blocks from assistant responses before including them in conversation history. Prevents model from pattern-matching on old tool calls and hallucinating removed tools. Also extend benchToolsPlacement to 20 turns and add HTML chart. --- .../examples/benchToolsPlacement.js | 552 ++++++++++++++++++ .../examples/benchmark_chart.html | 84 +++ .../examples/testToolRemoval.js | 345 +++++++++++ 3 files changed, 981 insertions(+) create mode 100644 packages/qvac-lib-infer-llamacpp-llm/examples/benchToolsPlacement.js create mode 100644 packages/qvac-lib-infer-llamacpp-llm/examples/benchmark_chart.html create mode 100644 packages/qvac-lib-infer-llamacpp-llm/examples/testToolRemoval.js diff --git a/packages/qvac-lib-infer-llamacpp-llm/examples/benchToolsPlacement.js b/packages/qvac-lib-infer-llamacpp-llm/examples/benchToolsPlacement.js new file mode 100644 index 0000000000..979aae8eaf --- /dev/null +++ b/packages/qvac-lib-infer-llamacpp-llm/examples/benchToolsPlacement.js @@ -0,0 +1,552 @@ +'use strict' + +const LlmLlamacpp = require('../index') +const FilesystemDL = require('@qvac/dl-filesystem') +const path = require('bare-path') +const fs = require('bare-fs') +const process = require('bare-process') +const os = require('bare-os') +const { downloadModel } = require('./utils') + +// ─── Configuration ────────────────────────────────────────────────────────── + +const isDarwinX64 = os.platform() === 'darwin' && os.arch() === 'x64' +const isLinuxArm64 = os.platform() === 'linux' && os.arch() === 'arm64' +const useCpu = isDarwinX64 || isLinuxArm64 + +const MODEL = { + name: 'Qwen3-1.7B-Q4_0.gguf', + url: 'https://huggingface.co/unsloth/Qwen3-1.7B-GGUF/resolve/main/Qwen3-1.7B-Q4_0.gguf' +} + +const NUM_TURNS = 20 + +// ─── Tool definitions ─────────────────────────────────────────────────────── + +const TOOL_WEATHER = { + type: 'function', + name: 'getWeather', + description: 'Get current weather for a city', + parameters: { + type: 'object', + properties: { + city: { type: 'string', description: 'City name' }, + units: { type: 'string', enum: ['celsius', 'fahrenheit'], description: 'Temperature units' } + }, + required: ['city'] + } +} + +const TOOL_SEARCH = { + type: 'function', + name: 'searchWeb', + description: 'Search the web for information', + parameters: { + type: 'object', + properties: { + query: { type: 'string', description: 'Search query' }, + maxResults: { type: 'integer', minimum: 1, maximum: 10, description: 'Max results' } + }, + required: ['query'] + } +} + +const TOOL_CALCULATOR = { + type: 'function', + name: 'calculate', + description: 'Perform a math calculation', + parameters: { + type: 'object', + properties: { + expression: { type: 'string', description: 'Math expression to evaluate' } + }, + required: ['expression'] + } +} + +const TOOL_TRANSLATE = { + type: 'function', + name: 'translateText', + description: 'Translate text to another language', + parameters: { + type: 'object', + properties: { + text: { type: 'string', description: 'Text to translate' }, + targetLang: { type: 'string', description: 'Target language code (e.g. fr, es, de)' } + }, + required: ['text', 'targetLang'] + } +} + +const TOOL_EMAIL = { + type: 'function', + name: 'sendEmail', + description: 'Send an email to a recipient', + parameters: { + type: 'object', + properties: { + to: { type: 'string', description: 'Recipient email address' }, + subject: { type: 'string', description: 'Email subject' }, + body: { type: 'string', description: 'Email body content' } + }, + required: ['to', 'subject', 'body'] + } +} + +const TOOL_REMINDER = { + type: 'function', + name: 'setReminder', + description: 'Set a reminder for a specific time', + parameters: { + type: 'object', + properties: { + message: { type: 'string', description: 'Reminder message' }, + time: { type: 'string', description: 'Time for the reminder (ISO 8601)' } + }, + required: ['message', 'time'] + } +} + +// Same tools every turn (for scenarios A and B) +const FIXED_TOOLS = [TOOL_WEATHER, TOOL_SEARCH] + +// Different tools per turn (for scenario C — dynamic tools) +const DYNAMIC_TOOLS_PER_TURN = [ + [TOOL_WEATHER, TOOL_SEARCH], // Turn 1: weather + search + [TOOL_CALCULATOR], // Turn 2: calculator only + [TOOL_TRANSLATE], // Turn 3: translate only + [TOOL_EMAIL, TOOL_REMINDER], // Turn 4: email + reminder + [TOOL_WEATHER], // Turn 5: weather only + [TOOL_SEARCH, TOOL_CALCULATOR], // Turn 6: search + calculator + [TOOL_TRANSLATE, TOOL_EMAIL], // Turn 7: translate + email + [TOOL_REMINDER, TOOL_WEATHER, TOOL_SEARCH], // Turn 8: reminder + weather + search + [TOOL_CALCULATOR, TOOL_TRANSLATE], // Turn 9: calculator + translate + [TOOL_EMAIL], // Turn 10: email only + [TOOL_WEATHER, TOOL_CALCULATOR], // Turn 11: weather + calculator + [TOOL_SEARCH], // Turn 12: search only + [TOOL_REMINDER, TOOL_TRANSLATE], // Turn 13: reminder + translate + [TOOL_WEATHER, TOOL_EMAIL], // Turn 14: weather + email + [TOOL_CALCULATOR, TOOL_SEARCH], // Turn 15: calculator + search + [TOOL_TRANSLATE], // Turn 16: translate only + [TOOL_REMINDER, TOOL_EMAIL, TOOL_WEATHER], // Turn 17: reminder + email + weather + [TOOL_SEARCH, TOOL_TRANSLATE], // Turn 18: search + translate + [TOOL_CALCULATOR], // Turn 19: calculator only + [TOOL_WEATHER, TOOL_REMINDER] // Turn 20: weather + reminder +] + +// Conversation turns — prompts that match the available tools +const CONVERSATION_TURNS_FIXED = [ + { user: 'Hello, what tools do you have available?' }, + { user: 'What is the weather like in Paris?' }, + { user: 'How about London?' }, + { user: 'Search for the best restaurants in Tokyo' }, + { user: 'What is the weather in New York in fahrenheit?' }, + { user: 'Search for flights from Paris to Tokyo' } +] + +const CONVERSATION_TURNS_DYNAMIC = [ + { user: 'What is the weather in Paris?' }, + { user: 'Calculate 156 * 23' }, + { user: 'Translate "hello world" to French' }, + { user: 'Send an email to bob@example.com about the meeting tomorrow' }, + { user: 'What is the weather in London?' }, + { user: 'Search for AI news and calculate 999 / 3' }, + { user: 'Translate "good morning" to Spanish and email the result to alice@example.com' }, + { user: 'Set a reminder to check the weather in Berlin tomorrow and search for flight deals' }, + { user: 'Calculate 2^10 and translate the result to German' }, + { user: 'Send an email to team@example.com with a summary of today\'s tasks' }, + { user: 'What is the weather in Tokyo and calculate 42 * 17' }, + { user: 'Search for latest Python tutorials' }, + { user: 'Set a reminder for lunch at noon and translate "thank you" to Japanese' }, + { user: 'What is the weather in Sydney and email the forecast to weather@example.com' }, + { user: 'Calculate the square root of 144 and search for math resources' }, + { user: 'Translate "goodbye" to Italian' }, + { user: 'Set a reminder to call the dentist, email jane@example.com about it, and check weather in Rome' }, + { user: 'Search for healthy recipes and translate the top result to Portuguese' }, + { user: 'Calculate 365 * 24' }, + { user: 'What is the weather in Berlin and set a reminder to pack an umbrella' } +] + +// ─── Tool call extraction & validation ────────────────────────────────────── + +function stripInternalBlocks (text) { + return text + .replace(/[\s\S]*?<\/think>/g, '') + .replace(/[\s\S]*?<\/tool_call>/g, '') + .trim() +} + +function extractToolCalls (response) { + const toolCalls = [] + const toolCallRegex = /([\s\S]*?)<\/tool_call>/g + let match + while ((match = toolCallRegex.exec(response)) !== null) { + try { + const parsed = JSON.parse(match[1].trim()) + toolCalls.push(parsed.name || parsed.function?.name || 'unknown') + } catch (_) {} + } + return toolCalls +} + +function validateToolCalls (turnIndex, output, availableTools) { + const calledTools = extractToolCalls(output) + const availableNames = availableTools.map(t => t.name) + const violations = [] + + for (const called of calledTools) { + if (!availableNames.includes(called)) { + violations.push(called) + } + } + + const status = violations.length === 0 ? 'OK' : 'VIOLATION' + return { + status, + calledTools, + availableNames, + violations + } +} + +// ─── Helpers ──────────────────────────────────────────────────────────────── + +function makeBaseConfig (toolsAtEnd) { + return { + device: useCpu ? 'cpu' : 'gpu', + gpu_layers: '999', + ctx_size: '4096', + n_predict: '256', + temp: '0.1', + seed: '1', + verbosity: '0', + tools: 'true', + tools_at_end: toolsAtEnd ? 'true' : 'false' + } +} + +async function loadModel (dirPath, modelName, config) { + const loader = new FilesystemDL({ dirPath }) + const model = new LlmLlamacpp({ + loader, + modelName, + diskPath: dirPath, + logger: console, + opts: { stats: true } + }, config) + await model.load() + return { model, loader } +} + +async function runAndCollect (model, prompt) { + const response = await model.run(prompt) + const chunks = [] + await response + .onUpdate(data => { chunks.push(data) }) + .await() + return { + output: chunks.join(''), + stats: response.stats + } +} + +function hrMs (hrtime) { + return (hrtime[0] * 1e3 + hrtime[1] / 1e6).toFixed(2) +} + +function cleanCache (cachePath) { + try { fs.unlinkSync(cachePath) } catch (_) {} +} + +// ─── Generic scenario runner ──────────────────────────────────────────────── + +async function runScenario (dirPath, modelName, opts) { + const { name, toolsAtEnd, dynamicTools, conversationTurns, getToolsForTurn, cacheName } = opts + + console.log('\n' + '='.repeat(70)) + console.log(name) + console.log('='.repeat(70)) + + const config = makeBaseConfig(toolsAtEnd) + const { model, loader } = await loadModel(dirPath, modelName, config) + const cachePath = path.join(dirPath, cacheName) + cleanCache(cachePath) + + const turnStats = [] + const toolValidations = [] + let lastAssistantResponse = null + // For tools_in_system with dynamic tools: track full conversation history for replay + const conversationHistory = [] + + try { + for (let i = 0; i < NUM_TURNS; i++) { + const turn = conversationTurns[i] + const turnTools = getToolsForTurn(i) + let prompt + + if (toolsAtEnd) { + // tools_at_end: session cache + re-send last assistant response + new user + tools + prompt = [ + { role: 'session', content: cachePath }, + ...(i === 0 + ? [{ role: 'system', content: 'You are a helpful assistant.' }, { role: 'user', content: turn.user }] + : [ + ...(lastAssistantResponse ? [{ role: 'assistant', content: lastAssistantResponse }] : []), + { role: 'user', content: turn.user } + ]), + ...turnTools + ] + } else if (dynamicTools) { + // tools_in_system with changing tools: reset cache and replay full history with new tools + prompt = [ + { role: 'session', content: cachePath }, + ...(i > 0 ? [{ role: 'session', content: 'reset' }] : []), + { role: 'system', content: 'You are a helpful assistant.' }, + ...conversationHistory, + { role: 'user', content: turn.user }, + ...turnTools + ] + } else { + // tools_in_system with same tools: session cache + only new user msg (tools cached from turn 1) + prompt = [ + { role: 'session', content: cachePath }, + ...(i === 0 + ? [{ role: 'system', content: 'You are a helpful assistant.' }, { role: 'user', content: turn.user }] + : [{ role: 'user', content: turn.user }]), + ...(i === 0 ? turnTools : []) + ] + } + + const t0 = process.hrtime() + const result = await runAndCollect(model, prompt) + const elapsed = process.hrtime(t0) + lastAssistantResponse = stripInternalBlocks(result.output) + + // Track history for replay in tools_in_system dynamic mode + conversationHistory.push({ role: 'user', content: turn.user }) + conversationHistory.push({ role: 'assistant', content: stripInternalBlocks(result.output) }) + + const validation = validateToolCalls(i, result.output, turnTools) + toolValidations.push(validation) + + turnStats.push({ + turn: i + 1, + wallMs: hrMs(elapsed), + promptTokens: result.stats?.promptTokens || 0, + generatedTokens: result.stats?.generatedTokens || 0, + cacheTokens: result.stats?.CacheTokens || 0, + ttft: result.stats?.TTFT || 0, + tps: result.stats?.TPS || 0 + }) + + const toolStatus = validation.status === 'OK' ? 'OK' : `VIOLATION: called [${validation.violations.join(', ')}]` + const calledStr = validation.calledTools.length > 0 ? validation.calledTools.join(', ') : 'none' + const availStr = validation.availableNames.join(', ') + + console.log( + ` Turn ${i + 1}: wall=${hrMs(elapsed)}ms prompt=${turnStats[i].promptTokens} ` + + `gen=${turnStats[i].generatedTokens} cache=${turnStats[i].cacheTokens} ` + + `TTFT=${turnStats[i].ttft}ms TPS=${turnStats[i].tps}` + ) + console.log( + ` tools=[${availStr}] called=[${calledStr}] validation=${toolStatus}` + ) + } + } finally { + await model.unload() + await loader.close() + cleanCache(cachePath) + } + + return { turnStats, toolValidations } +} + +// ─── Summary ──────────────────────────────────────────────────────────────── + +function printComparison (labelA, statsA, labelB, statsB) { + console.log('\n' + '='.repeat(80)) + console.log(`COMPARISON: ${labelA} (A) vs ${labelB} (B)`) + console.log('='.repeat(80)) + console.log('') + console.log('Turn | Wall A (ms) | Wall B (ms) | Δ ms | Prompt A | Prompt B | Cache A | Cache B | TTFT A | TTFT B') + console.log('-----|-------------|-------------|----------|----------|----------|---------|---------|---------|--------') + + let totalA = 0 + let totalB = 0 + + for (let i = 0; i < statsA.length; i++) { + const a = statsA[i] + const b = statsB[i] + const delta = (parseFloat(a.wallMs) - parseFloat(b.wallMs)).toFixed(2) + totalA += parseFloat(a.wallMs) + totalB += parseFloat(b.wallMs) + + const ttftA = typeof a.ttft === 'number' ? a.ttft.toFixed(0) : String(a.ttft) + const ttftB = typeof b.ttft === 'number' ? b.ttft.toFixed(0) : String(b.ttft) + + console.log( + ` ${a.turn} ` + + `| ${a.wallMs.padStart(11)} ` + + `| ${b.wallMs.padStart(11)} ` + + `| ${delta.padStart(8)} ` + + `| ${String(a.promptTokens).padStart(8)} ` + + `| ${String(b.promptTokens).padStart(8)} ` + + `| ${String(a.cacheTokens).padStart(7)} ` + + `| ${String(b.cacheTokens).padStart(7)} ` + + `| ${ttftA.padStart(7)} ` + + `| ${ttftB.padStart(7)}` + ) + } + + console.log('-----|-------------|-------------|----------|----------|----------|---------|---------|---------|--------') + console.log( + ` TOT ` + + `| ${totalA.toFixed(2).padStart(11)} ` + + `| ${totalB.toFixed(2).padStart(11)} ` + + `| ${(totalA - totalB).toFixed(2).padStart(8)} |` + ) + console.log('') + + const pctDiff = ((totalA - totalB) / totalB * 100).toFixed(1) + if (totalA > totalB) { + console.log(` → A is ${pctDiff}% SLOWER overall (${(totalA - totalB).toFixed(0)}ms extra across ${NUM_TURNS} turns)`) + } else { + console.log(` → A is ${Math.abs(pctDiff)}% FASTER overall (${(totalB - totalA).toFixed(0)}ms saved across ${NUM_TURNS} turns)`) + } +} + +function printToolValidationSummary (label, validations) { + console.log(`\n─── Tool Call Validation: ${label} ───`) + let allOk = true + for (let i = 0; i < validations.length; i++) { + const v = validations[i] + const icon = v.status === 'OK' ? 'PASS' : 'FAIL' + if (v.status !== 'OK') allOk = false + + if (v.calledTools.length === 0) { + console.log(` Turn ${i + 1} [${icon}]: no tool calls (available: ${v.availableNames.join(', ')})`) + } else if (v.violations.length > 0) { + console.log(` Turn ${i + 1} [${icon}]: called [${v.calledTools.join(', ')}] available [${v.availableNames.join(', ')}] STALE TOOLS USED: [${v.violations.join(', ')}]`) + } else { + console.log(` Turn ${i + 1} [${icon}]: called [${v.calledTools.join(', ')}] (available: ${v.availableNames.join(', ')})`) + } + } + console.log(` Result: ${allOk ? 'ALL PASSED — no stale/trimmed tools were called' : 'FAILURES DETECTED — model called tools that should have been trimmed'}`) +} + +// ─── Main ─────────────────────────────────────────────────────────────────── + +async function main () { + console.log('Benchmark: tools_at_end vs tools_in_system — performance & correctness') + console.log(`Model: ${MODEL.name}`) + console.log(`Turns: ${NUM_TURNS}`) + console.log(`Device: ${useCpu ? 'CPU' : 'GPU'}`) + + const [modelName, dirPath] = await downloadModel(MODEL.url, MODEL.name) + + // // ── Scenario A: tools_at_end, same tools every turn ── + // const resultA = await runScenario(dirPath, modelName, { + // name: 'SCENARIO A: tools_at_end = true, SAME tools every turn', + // toolsAtEnd: true, + // conversationTurns: CONVERSATION_TURNS_FIXED, + // getToolsForTurn: () => FIXED_TOOLS, + // cacheName: 'bench-A-at-end-same.bin' + // }) + + // // ── Scenario B: tools_in_system (standard), same tools every turn ── + // const resultB = await runScenario(dirPath, modelName, { + // name: 'SCENARIO B: tools_at_end = false (standard), SAME tools every turn', + // toolsAtEnd: false, + // conversationTurns: CONVERSATION_TURNS_FIXED, + // getToolsForTurn: () => FIXED_TOOLS, + // cacheName: 'bench-B-in-system-same.bin' + // }) + + // ── Scenario C: tools_at_end with dynamic tools ── + const resultC = await runScenario(dirPath, modelName, { + name: 'SCENARIO C: tools_at_end = true, DIFFERENT tools each turn', + toolsAtEnd: true, + dynamicTools: true, + conversationTurns: CONVERSATION_TURNS_DYNAMIC, + getToolsForTurn: (i) => DYNAMIC_TOOLS_PER_TURN[i], + cacheName: 'bench-C-at-end-dynamic.bin' + }) + + // ── Scenario D: tools_in_system with dynamic tools (must reset+replay each turn) ── + const resultD = await runScenario(dirPath, modelName, { + name: 'SCENARIO D: tools_at_end = false, DIFFERENT tools each turn (reset+replay)', + toolsAtEnd: false, + dynamicTools: true, + conversationTurns: CONVERSATION_TURNS_DYNAMIC, + getToolsForTurn: (i) => DYNAMIC_TOOLS_PER_TURN[i], + cacheName: 'bench-D-in-system-dynamic.bin' + }) + + // ── Comparisons ── + console.log('\n' + '#'.repeat(80)) + console.log('# RESULTS SUMMARY') + console.log('#'.repeat(80)) + + printComparison( + 'tools_at_end (dynamic tools)', + resultC.turnStats, + 'tools_in_system (dynamic tools, reset+replay)', + resultD.turnStats + ) + + // ── Tool validation summary ── + console.log('\n' + '#'.repeat(80)) + console.log('# TOOL CALL CORRECTNESS') + console.log('#'.repeat(80)) + + printToolValidationSummary('Scenario C — tools_at_end, dynamic tools', resultC.toolValidations) + printToolValidationSummary('Scenario D — tools_in_system, dynamic tools (reset+replay)', resultD.toolValidations) + + console.log('\n' + '─'.repeat(80)) + console.log('Key:') + console.log(' Scenario C: tools_at_end=true with dynamic tools — trims & re-sends prev response') + console.log(' Scenario D: tools_at_end=false with dynamic tools — must reset cache & replay full history') + console.log(' PASS = model only called tools available in that turn') + console.log(' FAIL = model called a tool from a previous turn (stale/trimmed tool leak)') + console.log('─'.repeat(80)) + + // ── ASCII Graph: wall time per turn ── + console.log('\n' + '#'.repeat(80)) + console.log('# TIME (ms) vs TURN — tools_at_end (C) vs tools_in_system+replay (D)') + console.log('#'.repeat(80)) + console.log('') + + const BAR_WIDTH = 50 + const allTimes = [ + ...resultC.turnStats.map(s => parseFloat(s.wallMs)), + ...resultD.turnStats.map(s => parseFloat(s.wallMs)) + ] + const maxTime = Math.max(...allTimes) + + function makeBar (value, max, width) { + const filled = Math.round((value / max) * width) + return '\u2588'.repeat(filled) + '\u2591'.repeat(width - filled) + } + + console.log('Turn | C (ms) | D (ms) | Graph') + console.log('-----|----------|----------|' + '-'.repeat(BAR_WIDTH * 2 + 14)) + + for (let i = 0; i < resultC.turnStats.length; i++) { + const cMs = parseFloat(resultC.turnStats[i].wallMs) + const dMs = parseFloat(resultD.turnStats[i].wallMs) + const cBar = makeBar(cMs, maxTime, BAR_WIDTH) + const dBar = makeBar(dMs, maxTime, BAR_WIDTH) + console.log( + ` ${String(i + 1).padStart(2)} ` + + `| ${String(Math.round(cMs)).padStart(8)} ` + + `| ${String(Math.round(dMs)).padStart(8)} ` + + `| C:${cBar} D:${dBar}` + ) + } + console.log('') +} + +main().catch(err => { + console.error('Fatal:', err.message || err) + process.exit(1) +}) diff --git a/packages/qvac-lib-infer-llamacpp-llm/examples/benchmark_chart.html b/packages/qvac-lib-infer-llamacpp-llm/examples/benchmark_chart.html new file mode 100644 index 0000000000..43d558aa96 --- /dev/null +++ b/packages/qvac-lib-infer-llamacpp-llm/examples/benchmark_chart.html @@ -0,0 +1,84 @@ + + + +tools_at_end vs tools_in_system Benchmark (20 turns) + + + + +

Benchmark: tools_at_end vs tools_in_system (reset+replay) — 20 turns

+
tools_at_end is 58.2% faster overall — 1281s saved across 20 turns
+ +
+

Wall Time per Turn (ms)

+ +
+ +
+

TTFT per Turn (ms)

+ +
+ +
+

Prompt Tokens per Turn

+ +
+ +
+

Cache Tokens per Turn

+ +
+ + + + diff --git a/packages/qvac-lib-infer-llamacpp-llm/examples/testToolRemoval.js b/packages/qvac-lib-infer-llamacpp-llm/examples/testToolRemoval.js new file mode 100644 index 0000000000..74a6209cd5 --- /dev/null +++ b/packages/qvac-lib-infer-llamacpp-llm/examples/testToolRemoval.js @@ -0,0 +1,345 @@ +'use strict' + +const LlmLlamacpp = require('../index') +const FilesystemDL = require('@qvac/dl-filesystem') +const path = require('bare-path') +const fs = require('bare-fs') +const process = require('bare-process') +const os = require('bare-os') +const { downloadModel } = require('./utils') + +const isDarwinX64 = os.platform() === 'darwin' && os.arch() === 'x64' +const isLinuxArm64 = os.platform() === 'linux' && os.arch() === 'arm64' +const useCpu = isDarwinX64 || isLinuxArm64 + +const MODEL = { + name: 'Qwen3-1.7B-Q4_0.gguf', + url: 'https://huggingface.co/unsloth/Qwen3-1.7B-GGUF/resolve/main/Qwen3-1.7B-Q4_0.gguf' +} + +const TOOL_WEATHER = { + type: 'function', + name: 'getWeather', + description: 'Get current weather for a city', + parameters: { + type: 'object', + properties: { + city: { type: 'string', description: 'City name' }, + units: { type: 'string', enum: ['celsius', 'fahrenheit'], description: 'Temperature units' } + }, + required: ['city'] + } +} + +const TOOL_CALCULATOR = { + type: 'function', + name: 'calculate', + description: 'Perform a math calculation', + parameters: { + type: 'object', + properties: { + expression: { type: 'string', description: 'Math expression to evaluate' } + }, + required: ['expression'] + } +} + +function stripInternalBlocks (text) { + return text + .replace(/[\s\S]*?<\/think>/g, '') + .replace(/[\s\S]*?<\/tool_call>/g, '') + .trim() +} + +function extractToolCalls (response) { + const toolCalls = [] + const toolCallRegex = /([\s\S]*?)<\/tool_call>/g + let match + while ((match = toolCallRegex.exec(response)) !== null) { + try { + const parsed = JSON.parse(match[1].trim()) + toolCalls.push(parsed.name || parsed.function?.name || 'unknown') + } catch (_) {} + } + return toolCalls +} + +async function loadModel (dirPath, modelName, config) { + const loader = new FilesystemDL({ dirPath }) + const model = new LlmLlamacpp({ + loader, + modelName, + diskPath: dirPath, + logger: console, + opts: { stats: true } + }, config) + await model.load() + return { model, loader } +} + +async function runAndCollect (model, prompt) { + const response = await model.run(prompt) + const chunks = [] + await response.onUpdate(data => { chunks.push(data) }).await() + return { output: chunks.join(''), stats: response.stats } +} + +async function main () { + console.log('Test: tool removal correctness with tools_at_end') + console.log('='.repeat(70)) + console.log('') + + const [modelName, dirPath] = await downloadModel(MODEL.url, MODEL.name) + const config = { + device: useCpu ? 'cpu' : 'gpu', + gpu_layers: '999', + ctx_size: '4096', + n_predict: '256', + temp: '0.1', + seed: '1', + verbosity: '0', + tools: 'true', + tools_at_end: 'true' + } + + const { model, loader } = await loadModel(dirPath, modelName, config) + const cachePath = path.join(dirPath, 'test-tool-removal.bin') + try { fs.unlinkSync(cachePath) } catch (_) {} + + let lastResponse = null + + try { + // ── Turn 1: provide getWeather, ask about weather ── + console.log('── Turn 1: tools=[getWeather], ask about weather ──') + const prompt1 = [ + { role: 'session', content: cachePath }, + { role: 'system', content: 'You are a helpful assistant. You must use tools when available. Do not answer without using a tool.' }, + { role: 'user', content: 'What is the weather in Paris?' }, + TOOL_WEATHER + ] + const r1 = await runAndCollect(model, prompt1) + lastResponse = stripInternalBlocks(r1.output) + const calls1 = extractToolCalls(r1.output) + console.log(` Response tools called: [${calls1.join(', ') || 'none'}]`) + console.log(` Expected: [getWeather]`) + console.log(` ${calls1.includes('getWeather') ? 'PASS ✓' : 'FAIL ✗'}`) + console.log('') + + // ── Turn 2: REMOVE getWeather, provide calculate instead ── + console.log('── Turn 2: tools=[calculate] (getWeather REMOVED), ask to calculate ──') + const prompt2 = [ + { role: 'session', content: cachePath }, + { role: 'assistant', content: lastResponse }, + { role: 'user', content: 'Calculate 256 * 128' }, + TOOL_CALCULATOR + ] + const r2 = await runAndCollect(model, prompt2) + lastResponse = stripInternalBlocks(r2.output) + const calls2 = extractToolCalls(r2.output) + console.log(` Response tools called: [${calls2.join(', ') || 'none'}]`) + console.log(` Expected: [calculate]`) + console.log(` ${calls2.includes('calculate') && !calls2.includes('getWeather') ? 'PASS ✓' : 'FAIL ✗'}`) + console.log('') + + // ── Turn 3: KEEP only calculate, ask about weather (should NOT call getWeather) ── + console.log('── Turn 3: tools=[calculate] (getWeather still removed), ask about weather ──') + console.log(' This is the KEY test: model should NOT call getWeather (it was removed)') + const prompt3 = [ + { role: 'session', content: cachePath }, + { role: 'assistant', content: lastResponse }, + { role: 'user', content: 'What is the weather in London?' }, + TOOL_CALCULATOR + ] + const r3 = await runAndCollect(model, prompt3) + lastResponse = stripInternalBlocks(r3.output) + const calls3 = extractToolCalls(r3.output) + console.log(` Response tools called: [${calls3.join(', ') || 'none'}]`) + console.log(` Expected: NOT getWeather (it's not available)`) + const weatherLeak = calls3.includes('getWeather') + console.log(` ${weatherLeak ? 'FAIL ✗ — stale tool leak! getWeather was called despite being removed' : 'PASS ✓ — model did not call removed tool'}`) + console.log('') + + // ── Turn 4: bring back getWeather, remove calculate, ask to calculate ── + console.log('── Turn 4: tools=[getWeather] (calculate REMOVED), ask to calculate ──') + console.log(' Model should NOT call calculate (it was removed)') + const prompt4 = [ + { role: 'session', content: cachePath }, + { role: 'assistant', content: lastResponse }, + { role: 'user', content: 'Calculate 999 / 3' }, + TOOL_WEATHER + ] + const r4 = await runAndCollect(model, prompt4) + lastResponse = stripInternalBlocks(r4.output) + const calls4 = extractToolCalls(r4.output) + console.log(` Response tools called: [${calls4.join(', ') || 'none'}]`) + console.log(` Expected: NOT calculate (it's not available)`) + const calcLeak = calls4.includes('calculate') + console.log(` ${calcLeak ? 'FAIL ✗ — stale tool leak! calculate was called despite being removed' : 'PASS ✓ — model did not call removed tool'}`) + console.log('') + + // ── Summary ── + console.log('='.repeat(70)) + console.log('SUMMARY') + console.log('='.repeat(70)) + const results = [ + { turn: 1, pass: calls1.includes('getWeather'), desc: 'getWeather available → called it' }, + { turn: 2, pass: calls2.includes('calculate') && !calls2.includes('getWeather'), desc: 'calculate available, getWeather removed → called calculate' }, + { turn: 3, pass: !weatherLeak, desc: 'getWeather removed → did NOT call it' }, + { turn: 4, pass: !calcLeak, desc: 'calculate removed → did NOT call it' } + ] + for (const r of results) { + console.log(` Turn ${r.turn}: ${r.pass ? 'PASS ✓' : 'FAIL ✗'} — ${r.desc}`) + } + const allPass = results.every(r => r.pass) + console.log('') + console.log(allPass + ? ' ALL PASSED — tool trimming correctly prevents stale tool usage' + : ' FAILURES DETECTED — removed tools leaked through the cache') + + } finally { + await model.unload() + await loader.close() + try { fs.unlinkSync(cachePath) } catch (_) {} + } +} + +// ─── Same test but with tools_in_system (reset+replay) ───────────────────── + +async function mainInSystem () { + console.log('\n\n') + console.log('Test: tool removal correctness with tools_in_system (reset+replay)') + console.log('='.repeat(70)) + console.log('') + + const [modelName, dirPath] = await downloadModel(MODEL.url, MODEL.name) + const config = { + device: useCpu ? 'cpu' : 'gpu', + gpu_layers: '999', + ctx_size: '4096', + n_predict: '256', + temp: '0.1', + seed: '1', + verbosity: '0', + tools: 'true', + tools_at_end: 'false' + } + + const { model, loader } = await loadModel(dirPath, modelName, config) + const cachePath = path.join(dirPath, 'test-tool-removal-insystem.bin') + try { fs.unlinkSync(cachePath) } catch (_) {} + + const SYSTEM = 'You are a helpful assistant. You must use tools when available. Do not answer without using a tool.' + const history = [] // accumulate {role, content} for replay + + try { + // ── Turn 1: provide getWeather, ask about weather ── + console.log('── Turn 1: tools=[getWeather], ask about weather ──') + const prompt1 = [ + { role: 'session', content: cachePath }, + { role: 'system', content: SYSTEM }, + { role: 'user', content: 'What is the weather in Paris?' }, + TOOL_WEATHER + ] + const r1 = await runAndCollect(model, prompt1) + history.push({ role: 'user', content: 'What is the weather in Paris?' }) + history.push({ role: 'assistant', content: stripInternalBlocks(r1.output) }) + const calls1 = extractToolCalls(r1.output) + console.log(` Response tools called: [${calls1.join(', ') || 'none'}]`) + console.log(` Expected: [getWeather]`) + console.log(` ${calls1.includes('getWeather') ? 'PASS ✓' : 'FAIL ✗'}`) + console.log('') + + // ── Turn 2: REMOVE getWeather, provide calculate — reset+replay ── + console.log('── Turn 2: tools=[calculate] (getWeather REMOVED), ask to calculate ──') + const prompt2 = [ + { role: 'session', content: cachePath }, + { role: 'session', content: 'reset' }, + { role: 'system', content: SYSTEM }, + ...history, + { role: 'user', content: 'Calculate 256 * 128' }, + TOOL_CALCULATOR + ] + const r2 = await runAndCollect(model, prompt2) + history.push({ role: 'user', content: 'Calculate 256 * 128' }) + history.push({ role: 'assistant', content: stripInternalBlocks(r2.output) }) + const calls2 = extractToolCalls(r2.output) + console.log(` Response tools called: [${calls2.join(', ') || 'none'}]`) + console.log(` Expected: [calculate]`) + console.log(` ${calls2.includes('calculate') && !calls2.includes('getWeather') ? 'PASS ✓' : 'FAIL ✗'}`) + console.log('') + + // ── Turn 3: KEEP only calculate, ask about weather ── + console.log('── Turn 3: tools=[calculate] (getWeather still removed), ask about weather ──') + console.log(' This is the KEY test: model should NOT call getWeather (it was removed)') + const prompt3 = [ + { role: 'session', content: cachePath }, + { role: 'session', content: 'reset' }, + { role: 'system', content: SYSTEM }, + ...history, + { role: 'user', content: 'What is the weather in London?' }, + TOOL_CALCULATOR + ] + const r3 = await runAndCollect(model, prompt3) + history.push({ role: 'user', content: 'What is the weather in London?' }) + history.push({ role: 'assistant', content: stripInternalBlocks(r3.output) }) + const calls3 = extractToolCalls(r3.output) + console.log(` Response tools called: [${calls3.join(', ') || 'none'}]`) + console.log(` Expected: NOT getWeather (it's not available)`) + const weatherLeak = calls3.includes('getWeather') + console.log(` ${weatherLeak ? 'FAIL ✗ — stale tool leak! getWeather was called despite being removed' : 'PASS ✓ — model did not call removed tool'}`) + console.log('') + + // ── Turn 4: bring back getWeather, remove calculate, ask to calculate ── + console.log('── Turn 4: tools=[getWeather] (calculate REMOVED), ask to calculate ──') + console.log(' Model should NOT call calculate (it was removed)') + const prompt4 = [ + { role: 'session', content: cachePath }, + { role: 'session', content: 'reset' }, + { role: 'system', content: SYSTEM }, + ...history, + { role: 'user', content: 'Calculate 999 / 3' }, + TOOL_WEATHER + ] + const r4 = await runAndCollect(model, prompt4) + const calls4 = extractToolCalls(r4.output) + console.log(` Response tools called: [${calls4.join(', ') || 'none'}]`) + console.log(` Expected: NOT calculate (it's not available)`) + const calcLeak = calls4.includes('calculate') + console.log(` ${calcLeak ? 'FAIL ✗ — stale tool leak! calculate was called despite being removed' : 'PASS ✓ — model did not call removed tool'}`) + console.log('') + + // ── Summary ── + console.log('='.repeat(70)) + console.log('SUMMARY (tools_in_system, reset+replay)') + console.log('='.repeat(70)) + const results = [ + { turn: 1, pass: calls1.includes('getWeather'), desc: 'getWeather available → called it' }, + { turn: 2, pass: calls2.includes('calculate') && !calls2.includes('getWeather'), desc: 'calculate available, getWeather removed → called calculate' }, + { turn: 3, pass: !weatherLeak, desc: 'getWeather removed → did NOT call it' }, + { turn: 4, pass: !calcLeak, desc: 'calculate removed → did NOT call it' } + ] + for (const r of results) { + console.log(` Turn ${r.turn}: ${r.pass ? 'PASS ✓' : 'FAIL ✗'} — ${r.desc}`) + } + const allPass = results.every(r => r.pass) + console.log('') + console.log(allPass + ? ' ALL PASSED — tool switching correctly prevents stale tool usage' + : ' FAILURES DETECTED — removed tools leaked from conversation history') + + } finally { + await model.unload() + await loader.close() + try { fs.unlinkSync(cachePath) } catch (_) {} + } +} + +async function runAll () { + await main() + await mainInSystem() +} + +runAll().catch(err => { + console.error('Fatal:', err.message || err) + process.exit(1) +}) From b6dae3a26e5ad9f0f5b7deae4fb236e63ee0c694 Mon Sep 17 00:00:00 2001 From: Mikhail Sotnikov Date: Thu, 12 Mar 2026 23:36:22 +0300 Subject: [PATCH 18/48] (fix) llamacpp-llm: use correct template in tests --- .../test/unit/test_cache_management.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management.cpp index 41eeedd892..ac8e6cfc2c 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management.cpp @@ -52,6 +52,7 @@ class CacheManagementTest : public ::testing::Test { config_files["ctx_size"] = "2048"; config_files["gpu_layers"] = test_common::getTestGpuLayers(); config_files["n_predict"] = "10"; + config_files["tools"] = "true"; test_model_path = test_common::BaseTestModelPath::get(); test_projection_path = ""; From 31b2069b8407b8069faee129dfa9b27488a0235d Mon Sep 17 00:00:00 2001 From: Mikhail Sotnikov Date: Fri, 13 Mar 2026 00:35:39 +0300 Subject: [PATCH 19/48] (chore) llamacpp-llm: move qwen3 cache tests to own file --- .../test/unit/CMakeLists.txt | 1 + .../test/unit/test_cache_management.cpp | 308 ------------- .../test/unit/test_cache_management_qwen3.cpp | 412 ++++++++++++++++++ .../test/unit/test_common.hpp | 9 +- 4 files changed, 416 insertions(+), 314 deletions(-) create mode 100644 packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/CMakeLists.txt b/packages/qvac-lib-infer-llamacpp-llm/test/unit/CMakeLists.txt index dea6ed2a5e..fc38141b51 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/CMakeLists.txt +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/CMakeLists.txt @@ -12,6 +12,7 @@ add_executable( addon-test test_llama_model.cpp test_cache_management.cpp + test_cache_management_qwen3.cpp test_text_llm_context.cpp test_addon_cpp.cpp test_backend_selection.cpp diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management.cpp index ac8e6cfc2c..6250ebc2dc 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management.cpp @@ -52,7 +52,6 @@ class CacheManagementTest : public ::testing::Test { config_files["ctx_size"] = "2048"; config_files["gpu_layers"] = test_common::getTestGpuLayers(); config_files["n_predict"] = "10"; - config_files["tools"] = "true"; test_model_path = test_common::BaseTestModelPath::get(); test_projection_path = ""; @@ -142,13 +141,6 @@ class CacheManagementTest : public ::testing::Test { std::string session2_path; std::string temp_session_path; - bool isQwen3Model() { - std::string lowerPath = test_model_path; - std::transform( - lowerPath.begin(), lowerPath.end(), lowerPath.begin(), - [](unsigned char c) { return std::tolower(c); }); - return lowerPath.find("qwen3") != std::string::npos; - } }; TEST_F(CacheManagementTest, InitialStateNoCache) { @@ -1078,303 +1070,3 @@ TEST_F(CacheManagementTest, CacheWithToolsAtEndFalseSavesFullCache) { EXPECT_TRUE(fs::exists(session1_path)); } -TEST_F(CacheManagementTest, CacheWithToolsAtEndTrueTrimsToolTokens) { - if (!isQwen3Model()) { - GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; - } - - if (!hasValidModel()) { - FAIL() << "Test model not found"; - } - - config_files["tools_at_end"] = "true"; - auto model = createModel(); - if (!model) { - FAIL() << "Model failed to load"; - } - - std::string inputWithTools = - R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "What is the weather in Tokyo?"}, {"type": "function", "name": "getWeather", "description": "Get weather forecast", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}])"; - - EXPECT_NO_THROW({ - std::string output = processPromptString(model, inputWithTools); - EXPECT_GE(output.length(), 0); - }); - - auto statsBeforeSave = model->runtimeStats(); - double cacheTokensBeforeSave = getStatValue(statsBeforeSave, "CacheTokens"); - EXPECT_GT(cacheTokensBeforeSave, 0.0); - - llama_pos nPastBeforeTools = model->getNPastBeforeTools(); - EXPECT_GT(nPastBeforeTools, 0); - EXPECT_LT(nPastBeforeTools, cacheTokensBeforeSave); - - std::string saveInput = - R"([{"role": "session", "content": "test_session1.bin"}, {"role": "session", "content": "save"}])"; - EXPECT_NO_THROW({ - std::string saveOutput = processPromptString(model, saveInput); - EXPECT_EQ(saveOutput.length(), 0); - }); - - EXPECT_TRUE(fs::exists(session1_path)); -} - -TEST_F(CacheManagementTest, CacheReloadWithToolsAtEndTrue) { - if (!isQwen3Model()) { - GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; - } - - if (!hasValidModel()) { - FAIL() << "Test model not found"; - } - - config_files["tools_at_end"] = "true"; - auto model1 = createModel(); - if (!model1) { - FAIL() << "Model failed to load"; - } - - std::string inputWithTools = - R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "What is the weather in Tokyo?"}, {"type": "function", "name": "getWeather", "description": "Get weather forecast", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}])"; - - EXPECT_NO_THROW({ - std::string output = processPromptString(model1, inputWithTools); - EXPECT_GE(output.length(), 0); - }); - - llama_pos nPastBeforeTools1 = model1->getNPastBeforeTools(); - EXPECT_GT(nPastBeforeTools1, 0); - - std::string saveInput = - R"([{"role": "session", "content": "test_session1.bin"}, {"role": "session", "content": "save"}])"; - EXPECT_NO_THROW({ - std::string saveOutput = processPromptString(model1, saveInput); - EXPECT_EQ(saveOutput.length(), 0); - }); - - EXPECT_TRUE(fs::exists(session1_path)); - - model1.reset(); - - auto model2 = createModel(); - if (!model2) { - FAIL() << "Model failed to load"; - } - - EXPECT_NO_THROW({ - std::string output = processPromptString( - model2, - R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "What is the weather in London?"}])"); - EXPECT_GE(output.length(), 0); - }); - - auto statsAfterReload = model2->runtimeStats(); - double cacheTokensAfterReload = getStatValue(statsAfterReload, "CacheTokens"); - EXPECT_GT(cacheTokensAfterReload, 0.0); - - llama_pos nPastBeforeTools2 = model2->getNPastBeforeTools(); - EXPECT_EQ(nPastBeforeTools2, nPastBeforeTools1); - EXPECT_LE(nPastBeforeTools2, nPastBeforeTools1); -} - -TEST_F(CacheManagementTest, CacheWithoutToolsWithToolsAtEndTrue) { - if (!isQwen3Model()) { - GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; - } - - if (!hasValidModel()) { - FAIL() << "Test model not found"; - } - - config_files["tools_at_end"] = "true"; - auto model = createModel(); - if (!model) { - FAIL() << "Model failed to load"; - } - - std::string inputNoTools = - R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "What is bitcoin? Answer shortly."}])"; - - EXPECT_NO_THROW({ - std::string output = processPromptString(model, inputNoTools); - EXPECT_GE(output.length(), 0); - }); - - auto statsBeforeSave = model->runtimeStats(); - double cacheTokensBeforeSave = getStatValue(statsBeforeSave, "CacheTokens"); - EXPECT_GT(cacheTokensBeforeSave, 0.0); - - llama_pos nPastBeforeTools = model->getNPastBeforeTools(); - EXPECT_EQ(nPastBeforeTools, -1); - - std::string saveInput = - R"([{"role": "session", "content": "test_session1.bin"}, {"role": "session", "content": "save"}])"; - EXPECT_NO_THROW({ - std::string saveOutput = processPromptString(model, saveInput); - EXPECT_EQ(saveOutput.length(), 0); - }); - - EXPECT_TRUE(fs::exists(session1_path)); -} - -TEST_F(CacheManagementTest, CacheToolsAtEndModeWithMultiplePrompts) { - if (!isQwen3Model()) { - GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; - } - - if (!hasValidModel()) { - FAIL() << "Test model not found"; - } - - config_files["tools_at_end"] = "true"; - auto model = createModel(); - if (!model) { - FAIL() << "Model failed to load"; - } - - std::string input1 = - R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "Hi"}, {"type": "function", "name": "get_weather", "description": "Get detailed weather forecast data with temperature humidity wind speed precipitation UV visibility pressure sunrise sunset alerts", "parameters": {"type": "object", "properties": {"city": {"type": "string", "description": "The name of the city to get weather for"}, "country": {"type": "string", "description": "Country code or name"}, "lat": {"type": "number", "description": "Latitude coordinate"}, "lon": {"type": "number", "description": "Longitude coordinate"}, "zip": {"type": "string", "description": "ZIP postal code"}, "units": {"type": "string", "description": "Temperature units metric imperial or kelvin"}, "lang": {"type": "string", "description": "Language code for localized descriptions"}, "forecast_days": {"type": "integer", "description": "Number of days to forecast from 1 to 7"}, "hourly": {"type": "boolean", "description": "Include hourly forecast data"}, "alerts": {"type": "boolean", "description": "Include weather alerts and warnings"}, "aqi": {"type": "boolean", "description": "Include air quality index data"}, "tides": {"type": "boolean", "description": "Include tide information"}, "solar": {"type": "boolean", "description": "Include solar data like sunrise sunset"}, "tz": {"type": "string", "description": "Timezone identifier"}, "start_dt": {"type": "string", "description": "Start datetime for historical data"}, "end_dt": {"type": "string", "description": "End datetime for historical data"}, "cnt": {"type": "integer", "description": "Number of data points to return"}, "mode": {"type": "string", "description": "Response mode json xml or html"}, "appid": {"type": "string", "description": "API key for authentication"}}, "required": ["city"]}}])"; - - EXPECT_NO_THROW({ - std::string output = processPromptString(model, input1); - EXPECT_GE(output.length(), 0); - }); - - auto stats1 = model->runtimeStats(); - double cacheTokens1 = getStatValue(stats1, "CacheTokens"); - printf("CacheManagementTest::CacheToolsAtEndModeWithMultiplePrompts cacheTokens1=%f\n", cacheTokens1); - EXPECT_GT(cacheTokens1, 0.0); - - llama_pos nPastBeforeTools = model->getNPastBeforeTools(); - EXPECT_GT(nPastBeforeTools, 0); - EXPECT_LT(nPastBeforeTools, cacheTokens1); - - const int maxExpectedCacheTokens = 50; - EXPECT_GT(cacheTokens1, 0); - EXPECT_LE(cacheTokens1, maxExpectedCacheTokens) - << "Cache tokens (" << cacheTokens1 << ") should not exceed " - << maxExpectedCacheTokens << " - function tokens should be trimmed"; - - std::string input2 = - R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "What about London?"}])"; - - EXPECT_NO_THROW({ - std::string output = processPromptString(model, input2); - EXPECT_GE(output.length(), 0); - }); - - auto stats2 = model->runtimeStats(); - double cacheTokens2 = getStatValue(stats2, "CacheTokens"); - printf("CacheManagementTest::CacheToolsAtEndModeWithMultiplePrompts cacheTokens2=%f\n", cacheTokens2); - EXPECT_GT(cacheTokens2, cacheTokens1); - EXPECT_LE(cacheTokens2, maxExpectedCacheTokens) - << "Cache tokens (" << cacheTokens1 << ") should not exceed " - << maxExpectedCacheTokens << " - function tokens should be trimmed"; - - EXPECT_LE(nPastBeforeTools, cacheTokens2); - - std::string saveInput = - R"([{"role": "session", "content": "test_session1.bin"}, {"role": "session", "content": "save"}])"; - EXPECT_NO_THROW({ - std::string saveOutput = processPromptString(model, saveInput); - EXPECT_EQ(saveOutput.length(), 0); - }); - - EXPECT_TRUE(fs::exists(session1_path)); -} - -TEST_F(CacheManagementTest, CacheToolsAtEndModeTrimOnlyWhenNPastBeforeToolsPositive) { - if (!isQwen3Model()) { - GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; - } - - if (!hasValidModel()) { - FAIL() << "Test model not found"; - } - - config_files["tools_at_end"] = "true"; - auto model = createModel(); - if (!model) { - FAIL() << "Model failed to load"; - } - - std::string inputNoTools = - R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "Hello"}])"; - - EXPECT_NO_THROW({ - std::string output = processPromptString(model, inputNoTools); - EXPECT_GE(output.length(), 0); - }); - - llama_pos nPastBeforeTools = model->getNPastBeforeTools(); - EXPECT_EQ(nPastBeforeTools, -1); - - auto statsBeforeSave = model->runtimeStats(); - double cacheTokensBeforeSave = getStatValue(statsBeforeSave, "CacheTokens"); - EXPECT_GT(cacheTokensBeforeSave, 0.0); - - std::string saveInput = - R"([{"role": "session", "content": "test_session1.bin"}, {"role": "session", "content": "save"}])"; - EXPECT_NO_THROW({ - std::string saveOutput = processPromptString(model, saveInput); - EXPECT_EQ(saveOutput.length(), 0); - }); - - auto statsAfterSave = model->runtimeStats(); - double cacheTokensAfterSave = getStatValue(statsAfterSave, "CacheTokens"); - EXPECT_EQ(cacheTokensAfterSave, cacheTokensBeforeSave); -} - -TEST_F(CacheManagementTest, CacheToolsAtEndModeRestoresNPastBeforeTools) { - if (!isQwen3Model()) { - GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; - } - - if (!hasValidModel()) { - FAIL() << "Test model not found"; - } - - config_files["tools_at_end"] = "true"; - auto model = createModel(); - if (!model) { - FAIL() << "Model failed to load"; - } - - std::string input1 = - R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "Hi"}, {"type": "function", "name": "get_weather", "description": "Get weather", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}])"; - - EXPECT_NO_THROW({ - std::string output = processPromptString(model, input1); - EXPECT_GE(output.length(), 0); - }); - - llama_pos nPastBeforeTools1 = model->getNPastBeforeTools(); - EXPECT_GT(nPastBeforeTools1, 0) << "nPastBeforeTools should be set after first prompt with tools"; - - std::string saveInput = - R"([{"role": "session", "content": "test_session1.bin"}, {"role": "session", "content": "save"}])"; - EXPECT_NO_THROW({ - std::string saveOutput = processPromptString(model, saveInput); - EXPECT_EQ(saveOutput.length(), 0); - }); - - EXPECT_TRUE(fs::exists(session1_path)); - - auto model2 = createModel(); - if (!model2) { - FAIL() << "Model2 failed to load"; - } - - std::string input2 = - R"([{"role": "session", "content": "test_session1.bin"}, {"role": "user", "content": "What about London?"}])"; - - EXPECT_NO_THROW({ - std::string output = processPromptString(model2, input2); - EXPECT_GE(output.length(), 0); - }); - - llama_pos nPastBeforeTools2 = model2->getNPastBeforeTools(); - EXPECT_EQ(nPastBeforeTools2, nPastBeforeTools1) - << "nPastBeforeTools should be restored from session: expected " << nPastBeforeTools1 - << " but got " << nPastBeforeTools2; -} diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp new file mode 100644 index 0000000000..2d672b184a --- /dev/null +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp @@ -0,0 +1,412 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "model-interface/LlamaModel.hpp" +#include "test_common.hpp" + +namespace fs = std::filesystem; + +namespace { +double getStatValue( + const qvac_lib_inference_addon_cpp::RuntimeStats& stats, + const std::string& key) { + for (const auto& stat : stats) { + if (stat.first == key) { + return std::visit( + [](const auto& value) -> double { + if constexpr (std::is_same_v< + std::decay_t, + double>) { + return value; + } else { + return static_cast(value); + } + }, + stat.second); + } + } + return 0.0; +} + +std::string processPromptString( + const std::unique_ptr& model, const std::string& input) { + LlamaModel::Prompt prompt; + prompt.input = input; + return model->processPrompt(prompt); +} + +bool isQwen3ModelPath(const std::string& path) { + std::string lowerPath = path; + std::transform( + lowerPath.begin(), lowerPath.end(), lowerPath.begin(), + [](unsigned char c) { return std::tolower(c); }); + return lowerPath.find("qwen3") != std::string::npos; +} +} // namespace + +class CacheManagementQwen3Test : public ::testing::Test { +protected: + void SetUp() override { + config_files["device"] = test_common::getTestDevice(); + config_files["ctx_size"] = "2048"; + config_files["gpu_layers"] = test_common::getTestGpuLayers(); + config_files["n_predict"] = "10"; + config_files["tools"] = "true"; + + test_model_path = test_common::BaseTestModelPath::get("Qwen3-1.7B-Q4_0.gguf", "Llama-3.2-1B-Instruct-Q4_0.gguf"); + test_projection_path = ""; + + config_files["backendsDir"] = test_common::getTestBackendsDir().string(); + + session1_path = "test_session1_qwen3.bin"; + session2_path = "test_session2_qwen3.bin"; + temp_session_path = "temp_session_qwen3.bin"; + } + + void TearDown() override { + for (const auto& session_file : + {session1_path, + session2_path, + temp_session_path, + std::string("test_large_cache_qwen3.bin")}) { + if (fs::exists(session_file)) { + fs::remove(session_file); + } + } + } + + bool hasValidModel() { return fs::exists(test_model_path); } + + std::unique_ptr createModel() { + if (!hasValidModel()) { + return nullptr; + } + std::string modelPath = test_model_path; + std::string projectionPath = test_projection_path; + auto configCopy = config_files; + auto model = std::make_unique( + std::move(modelPath), std::move(projectionPath), std::move(configCopy)); + model->waitForLoadInitialization(); + if (!model->isLoaded()) { + return nullptr; + } + return model; + } + + std::unordered_map config_files; + std::string test_model_path; + std::string test_projection_path; + std::string session1_path; + std::string session2_path; + std::string temp_session_path; +}; + +TEST_F(CacheManagementQwen3Test, CacheWithToolsAtEndTrueTrimsToolTokens) { + if (!isQwen3ModelPath(test_model_path)) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + std::string inputWithTools = + R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "user", "content": "What is the weather in Tokyo?"}, {"type": "function", "name": "getWeather", "description": "Get weather forecast", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model, inputWithTools); + EXPECT_GE(output.length(), 0); + }); + + auto statsBeforeSave = model->runtimeStats(); + double cacheTokensBeforeSave = getStatValue(statsBeforeSave, "CacheTokens"); + EXPECT_GT(cacheTokensBeforeSave, 0.0); + + llama_pos nPastBeforeTools = model->getNPastBeforeTools(); + EXPECT_GT(nPastBeforeTools, 0); + EXPECT_LT(nPastBeforeTools, cacheTokensBeforeSave); + + std::string saveInput = + R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "session", "content": "save"}])"; + EXPECT_NO_THROW({ + std::string saveOutput = processPromptString(model, saveInput); + EXPECT_EQ(saveOutput.length(), 0); + }); + + EXPECT_TRUE(fs::exists(session1_path)); +} + +TEST_F(CacheManagementQwen3Test, CacheReloadWithToolsAtEndTrue) { + if (!isQwen3ModelPath(test_model_path)) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model1 = createModel(); + if (!model1) { + FAIL() << "Model failed to load"; + } + + std::string inputWithTools = + R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "user", "content": "What is the weather in Tokyo?"}, {"type": "function", "name": "getWeather", "description": "Get weather forecast", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model1, inputWithTools); + EXPECT_GE(output.length(), 0); + }); + + llama_pos nPastBeforeTools1 = model1->getNPastBeforeTools(); + EXPECT_GT(nPastBeforeTools1, 0); + + std::string saveInput = + R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "session", "content": "save"}])"; + EXPECT_NO_THROW({ + std::string saveOutput = processPromptString(model1, saveInput); + EXPECT_EQ(saveOutput.length(), 0); + }); + + EXPECT_TRUE(fs::exists(session1_path)); + + model1.reset(); + + auto model2 = createModel(); + if (!model2) { + FAIL() << "Model failed to load"; + } + + EXPECT_NO_THROW({ + std::string output = processPromptString( + model2, + R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "user", "content": "What is the weather in London?"}])"); + EXPECT_GE(output.length(), 0); + }); + + auto statsAfterReload = model2->runtimeStats(); + double cacheTokensAfterReload = getStatValue(statsAfterReload, "CacheTokens"); + EXPECT_GT(cacheTokensAfterReload, 0.0); + + llama_pos nPastBeforeTools2 = model2->getNPastBeforeTools(); + EXPECT_EQ(nPastBeforeTools2, nPastBeforeTools1); + EXPECT_LE(nPastBeforeTools2, nPastBeforeTools1); +} + +TEST_F(CacheManagementQwen3Test, CacheWithoutToolsWithToolsAtEndTrue) { + if (!isQwen3ModelPath(test_model_path)) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + std::string inputNoTools = + R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "user", "content": "What is bitcoin? Answer shortly."}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model, inputNoTools); + EXPECT_GE(output.length(), 0); + }); + + auto statsBeforeSave = model->runtimeStats(); + double cacheTokensBeforeSave = getStatValue(statsBeforeSave, "CacheTokens"); + EXPECT_GT(cacheTokensBeforeSave, 0.0); + + llama_pos nPastBeforeTools = model->getNPastBeforeTools(); + EXPECT_EQ(nPastBeforeTools, -1); + + std::string saveInput = + R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "session", "content": "save"}])"; + EXPECT_NO_THROW({ + std::string saveOutput = processPromptString(model, saveInput); + EXPECT_EQ(saveOutput.length(), 0); + }); + + EXPECT_TRUE(fs::exists(session1_path)); +} + +TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeWithMultiplePrompts) { + if (!isQwen3ModelPath(test_model_path)) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + std::string input1 = + R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "user", "content": "Hi"}, {"type": "function", "name": "get_weather", "description": "Get detailed weather forecast data with temperature humidity wind speed precipitation UV visibility pressure sunrise sunset alerts", "parameters": {"type": "object", "properties": {"city": {"type": "string", "description": "The name of the city to get weather for"}, "country": {"type": "string", "description": "Country code or name"}, "lat": {"type": "number", "description": "Latitude coordinate"}, "lon": {"type": "number", "description": "Longitude coordinate"}, "zip": {"type": "string", "description": "ZIP postal code"}, "units": {"type": "string", "description": "Temperature units metric imperial or kelvin"}, "lang": {"type": "string", "description": "Language code for localized descriptions"}, "forecast_days": {"type": "integer", "description": "Number of days to forecast from 1 to 7"}, "hourly": {"type": "boolean", "description": "Include hourly forecast data"}, "alerts": {"type": "boolean", "description": "Include weather alerts and warnings"}, "aqi": {"type": "boolean", "description": "Include air quality index data"}, "tides": {"type": "boolean", "description": "Include tide information"}, "solar": {"type": "boolean", "description": "Include solar data like sunrise sunset"}, "tz": {"type": "string", "description": "Timezone identifier"}, "start_dt": {"type": "string", "description": "Start datetime for historical data"}, "end_dt": {"type": "string", "description": "End datetime for historical data"}, "cnt": {"type": "integer", "description": "Number of data points to return"}, "mode": {"type": "string", "description": "Response mode json xml or html"}, "appid": {"type": "string", "description": "API key for authentication"}}, "required": ["city"]}}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model, input1); + EXPECT_GE(output.length(), 0); + }); + + auto stats1 = model->runtimeStats(); + double cacheTokens1 = getStatValue(stats1, "CacheTokens"); + printf("CacheManagementQwen3Test::CacheToolsAtEndModeWithMultiplePrompts cacheTokens1=%f\n", cacheTokens1); + EXPECT_GT(cacheTokens1, 0.0); + + llama_pos nPastBeforeTools = model->getNPastBeforeTools(); + EXPECT_GT(nPastBeforeTools, 0); + EXPECT_LT(nPastBeforeTools, cacheTokens1); + + const int maxExpectedCacheTokens = 50; + EXPECT_GT(cacheTokens1, 0); + EXPECT_LE(cacheTokens1, maxExpectedCacheTokens) + << "Cache tokens (" << cacheTokens1 << ") should not exceed " + << maxExpectedCacheTokens << " - function tokens should be trimmed"; + + std::string input2 = + R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "user", "content": "What about London?"}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model, input2); + EXPECT_GE(output.length(), 0); + }); + + auto stats2 = model->runtimeStats(); + double cacheTokens2 = getStatValue(stats2, "CacheTokens"); + printf("CacheManagementQwen3Test::CacheToolsAtEndModeWithMultiplePrompts cacheTokens2=%f\n", cacheTokens2); + EXPECT_GT(cacheTokens2, cacheTokens1); + EXPECT_LE(cacheTokens2, maxExpectedCacheTokens) + << "Cache tokens (" << cacheTokens1 << ") should not exceed " + << maxExpectedCacheTokens << " - function tokens should be trimmed"; + + EXPECT_LE(nPastBeforeTools, cacheTokens2); + + std::string saveInput = + R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "session", "content": "save"}])"; + EXPECT_NO_THROW({ + std::string saveOutput = processPromptString(model, saveInput); + EXPECT_EQ(saveOutput.length(), 0); + }); + + EXPECT_TRUE(fs::exists(session1_path)); +} + +TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeTrimOnlyWhenNPastBeforeToolsPositive) { + if (!isQwen3ModelPath(test_model_path)) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + std::string inputNoTools = + R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "user", "content": "Hello"}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model, inputNoTools); + EXPECT_GE(output.length(), 0); + }); + + llama_pos nPastBeforeTools = model->getNPastBeforeTools(); + EXPECT_EQ(nPastBeforeTools, -1); + + auto statsBeforeSave = model->runtimeStats(); + double cacheTokensBeforeSave = getStatValue(statsBeforeSave, "CacheTokens"); + EXPECT_GT(cacheTokensBeforeSave, 0.0); + + std::string saveInput = + R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "session", "content": "save"}])"; + EXPECT_NO_THROW({ + std::string saveOutput = processPromptString(model, saveInput); + EXPECT_EQ(saveOutput.length(), 0); + }); + + auto statsAfterSave = model->runtimeStats(); + double cacheTokensAfterSave = getStatValue(statsAfterSave, "CacheTokens"); + EXPECT_EQ(cacheTokensAfterSave, cacheTokensBeforeSave); +} + +TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeRestoresNPastBeforeTools) { + if (!isQwen3ModelPath(test_model_path)) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + std::string input1 = + R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "user", "content": "Hi"}, {"type": "function", "name": "get_weather", "description": "Get weather", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model, input1); + EXPECT_GE(output.length(), 0); + }); + + llama_pos nPastBeforeTools1 = model->getNPastBeforeTools(); + EXPECT_GT(nPastBeforeTools1, 0) << "nPastBeforeTools should be set after first prompt with tools"; + + std::string saveInput = + R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "session", "content": "save"}])"; + EXPECT_NO_THROW({ + std::string saveOutput = processPromptString(model, saveInput); + EXPECT_EQ(saveOutput.length(), 0); + }); + + EXPECT_TRUE(fs::exists(session1_path)); + + auto model2 = createModel(); + if (!model2) { + FAIL() << "Model2 failed to load"; + } + + std::string input2 = + R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "user", "content": "What about London?"}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model2, input2); + EXPECT_GE(output.length(), 0); + }); + + llama_pos nPastBeforeTools2 = model2->getNPastBeforeTools(); + EXPECT_EQ(nPastBeforeTools2, nPastBeforeTools1) + << "nPastBeforeTools should be restored from session: expected " << nPastBeforeTools1 + << " but got " << nPastBeforeTools2; +} diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_common.hpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_common.hpp index 04ef9b5de4..1b0a311fae 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_common.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_common.hpp @@ -60,15 +60,12 @@ struct BaseTestModelPath { } /** - * Default model path: Qwen3-1.7B-Q4_0.gguf if present (for tools_at_end tests), - * else Llama-3.2-1B-Instruct-Q4_0.gguf, else test_model.gguf. + * Default model path: Llama-3.2-1B-Instruct-Q4_0.gguf if present, + * else test_model.gguf, else "Llama-3.2-1B-Instruct-Q4_0.gguf". */ static std::string get() { fs::path base = path(); - fs::path p = base / "Qwen3-1.7B-Q4_0.gguf"; - if (fs::exists(p)) - return p.string(); - p = base / "Llama-3.2-1B-Instruct-Q4_0.gguf"; + fs::path p = base / "Llama-3.2-1B-Instruct-Q4_0.gguf"; if (fs::exists(p)) return p.string(); p = base / "test_model.gguf"; From e2b660ba117d1b0447a1e9018e8417d6c1a938c2 Mon Sep 17 00:00:00 2001 From: Mikhail Sotnikov Date: Fri, 13 Mar 2026 01:34:35 +0300 Subject: [PATCH 20/48] (improvement) llamacpp-llm: simplify nPastBeforeTools reset, multi-turn cache tests --- .../addon/src/model-interface/LlamaModel.cpp | 1 + .../src/model-interface/TextLlmContext.cpp | 1 + .../qvac-lib-infer-llamacpp-llm/test/model | 1 + .../test/unit/test_cache_management_qwen3.cpp | 54 ++++++++++++++++--- 4 files changed, 49 insertions(+), 8 deletions(-) create mode 120000 packages/qvac-lib-infer-llamacpp-llm/test/model diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp index e39887303a..9d18f34ecf 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp @@ -430,6 +430,7 @@ std::string LlamaModel::processPromptImpl(const Prompt& prompt) { state_->llmContext_->getNPast() > state_->llmContext_->getNPastBeforeTools()) { state_->llmContext_->removeLastNTokens( state_->llmContext_->getNPast() - state_->llmContext_->getNPastBeforeTools()); + state_->llmContext_->setNPastBeforeTools(-1); } if (resolved.shouldResetAfterInference) { resetState(false); diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp index b1289f7c45..8d91b645c8 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp @@ -518,6 +518,7 @@ bool TextLlmContext::generateResponse( void TextLlmContext::stop() { stopGeneration_.store(true); } void TextLlmContext::resetState(bool resetStats) { + printf("TextLlmContext::resetState resetStats=%d\n", resetStats); // Reset the n_past // Reset conversation-only tokens and nPastBeforeTools diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/model b/packages/qvac-lib-infer-llamacpp-llm/test/model new file mode 120000 index 0000000000..9fbb2fffd2 --- /dev/null +++ b/packages/qvac-lib-infer-llamacpp-llm/test/model @@ -0,0 +1 @@ +/home/mialso/.qvac/models/ \ No newline at end of file diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp index 2d672b184a..77221c60fe 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp @@ -274,12 +274,10 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeWithMultiplePrompts) { auto stats1 = model->runtimeStats(); double cacheTokens1 = getStatValue(stats1, "CacheTokens"); - printf("CacheManagementQwen3Test::CacheToolsAtEndModeWithMultiplePrompts cacheTokens1=%f\n", cacheTokens1); + double promptTokens1 = getStatValue(stats1, "promptTokens"); + printf("CacheManagementQwen3Test::CacheToolsAtEndModeWithMultiplePrompts cacheTokens1=%f promptTokens1=%f\n", cacheTokens1, promptTokens1); EXPECT_GT(cacheTokens1, 0.0); - - llama_pos nPastBeforeTools = model->getNPastBeforeTools(); - EXPECT_GT(nPastBeforeTools, 0); - EXPECT_LT(nPastBeforeTools, cacheTokens1); + EXPECT_GT(promptTokens1, 500.0); const int maxExpectedCacheTokens = 50; EXPECT_GT(cacheTokens1, 0); @@ -297,14 +295,14 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeWithMultiplePrompts) { auto stats2 = model->runtimeStats(); double cacheTokens2 = getStatValue(stats2, "CacheTokens"); - printf("CacheManagementQwen3Test::CacheToolsAtEndModeWithMultiplePrompts cacheTokens2=%f\n", cacheTokens2); + double promptTokens2 = getStatValue(stats2, "promptTokens"); + printf("CacheManagementQwen3Test::CacheToolsAtEndModeWithMultiplePrompts cacheTokens2=%f, promptTokens2=%f\n", cacheTokens2, promptTokens2); EXPECT_GT(cacheTokens2, cacheTokens1); + EXPECT_LT(promptTokens2, 500.0); EXPECT_LE(cacheTokens2, maxExpectedCacheTokens) << "Cache tokens (" << cacheTokens1 << ") should not exceed " << maxExpectedCacheTokens << " - function tokens should be trimmed"; - EXPECT_LE(nPastBeforeTools, cacheTokens2); - std::string saveInput = R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "session", "content": "save"}])"; EXPECT_NO_THROW({ @@ -313,6 +311,46 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeWithMultiplePrompts) { }); EXPECT_TRUE(fs::exists(session1_path)); + + model.reset(); + + auto model2 = createModel(); + if (!model2) { + FAIL() << "Model2 failed to load"; + } + + std::string input3 = + R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "user", "content": "What about Paris?"}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model2, input3); + EXPECT_GE(output.length(), 0); + }); + + auto stats3 = model2->runtimeStats(); + double cacheTokens3 = getStatValue(stats3, "CacheTokens"); + double promptTokens3 = getStatValue(stats3, "promptTokens"); + printf("CacheManagementQwen3Test::CacheToolsAtEndModeWithMultiplePrompts cacheTokens3=%f, promptTokens3=%f\n", cacheTokens3, promptTokens3); + + EXPECT_GT(cacheTokens3, cacheTokens2); + EXPECT_LT(promptTokens3, 100.0); + + auto model3 = createModel(); + if (!model3) { + FAIL() << "Model3 failed to load"; + } + + std::string getTokensInput = + R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "session", "content": "getTokens"}])"; + EXPECT_NO_THROW({ + std::string output = processPromptString(model3, getTokensInput); + EXPECT_EQ(output.length(), 0); + }); + + auto stats4 = model3->runtimeStats(); + double cacheTokens4 = getStatValue(stats4, "CacheTokens"); + printf("CacheManagementQwen3Test::CacheToolsAtEndModeWithMultiplePrompts cacheTokens4=%f\n", cacheTokens4); + EXPECT_EQ(cacheTokens4, cacheTokens2); } TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeTrimOnlyWhenNPastBeforeToolsPositive) { From 47292a509f4a329e14e56d73b67efe6c238fdc75 Mon Sep 17 00:00:00 2001 From: Mikhail Sotnikov Date: Fri, 13 Mar 2026 03:45:54 +0300 Subject: [PATCH 21/48] (improvement) llamacpp-llm: simply nPastBeforeTools tracking, no trim on save --- .../src/model-interface/CacheManager.cpp | 43 +++---------------- .../src/model-interface/CacheManager.hpp | 3 +- .../addon/src/model-interface/LlamaModel.cpp | 3 +- .../test/unit/test_cache_management_qwen3.cpp | 14 +++--- 4 files changed, 14 insertions(+), 49 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.cpp index fe5c7190ba..d7a56a4713 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.cpp @@ -15,10 +15,9 @@ using namespace qvac_lib_inference_addon_llama::logging; CacheManager::CacheManager( LlmContext* llmContext, llama_pos configuredNDiscarded, - std::function resetStateCallback, bool toolsAtEnd) + std::function resetStateCallback) : llmContext_(llmContext), configuredNDiscarded_(configuredNDiscarded), - resetStateCallback_(std::move(resetStateCallback)), - toolsAtEnd_(toolsAtEnd) {} + resetStateCallback_(std::move(resetStateCallback)) {} bool CacheManager::isFileInitialized(const std::filesystem::path& path) { std::error_code errorCode; @@ -64,8 +63,6 @@ bool CacheManager::handleCache( bool cacheLoaded = false; bool cachePathSetInThisArray = false; - printf("CacheManager::handleCache role=%s cmd=%s\n", chatMsgs[0].role.c_str(), chatMsgs[0].content.c_str()); - while (!chatMsgs.empty() && chatMsgs[0].role == "session") { std::string sessionCommand = chatMsgs[0].content; chatMsgs.erase(chatMsgs.begin()); @@ -82,8 +79,6 @@ bool CacheManager::handleCache( resetStateCallback_(true); cacheUsedInLastPrompt_ = false; } else if (sessionCommand == "save") { - printf("CacheManager::handleCache SAVE noPath=%d\n", cachePathSetInThisArray); - // if (sessionPath_.empty()) { if (!cachePathSetInThisArray) { std::string errorMsg = string_format( "%s: save command requires explicit cache file specification in " @@ -118,7 +113,6 @@ bool CacheManager::handleCache( "inference\n", __func__, sessionPath_.c_str())); - printf("CacheManager::handleCache set cache path and continue=\n"); cachePathSetInThisArray = true; cacheUsedInLastPrompt_ = true; continue; @@ -143,7 +137,6 @@ bool CacheManager::handleCache( sessionPath_ = sessionCommand; cachePathSetInThisArray = true; - printf("CacheManager::handleCache set sessionPath_ and cachePathSetInThisArray\n"); if (!sessionPath_.empty()) { cacheDisabled_ = false; @@ -155,7 +148,6 @@ bool CacheManager::handleCache( __func__, sessionPath_.c_str())); - printf("CacheManager::handleCache loadCache, usedInLastPrompt\n"); cacheLoaded = loadCache(); cacheUsedInLastPrompt_ = true; } else { @@ -171,14 +163,13 @@ bool CacheManager::handleCache( } bool CacheManager::loadCache() { - printf("CacheManager::loadCache toolsAtEnd_=%d\n", toolsAtEnd_); if (cacheDisabled_ || sessionPath_.empty()) { return false; } auto* ctx = llmContext_->getCtx(); size_t nTokenCount = 0; - llama_token sessionTokens[3] = {0, 0, 0}; + llama_token sessionTokens[2] = {0, 0}; QLOG_IF( Priority::DEBUG, @@ -195,7 +186,7 @@ bool CacheManager::loadCache() { } if (!llama_state_load_file( - ctx, sessionPath_.c_str(), sessionTokens, 3, &nTokenCount)) { + ctx, sessionPath_.c_str(), sessionTokens, 2, &nTokenCount)) { std::string errorMsg = string_format( "%s: failed to load session file '%s'\n", __func__, @@ -220,7 +211,6 @@ bool CacheManager::loadCache() { } llmContext_->setNPast(sessionTokens[0]); llmContext_->setFirstMsgTokens(sessionTokens[1]); - llmContext_->setNPastBeforeTools(sessionTokens[2]); if (configuredNDiscarded_ > llama_n_ctx(ctx) - llmContext_->getFirstMsgTokens()) { @@ -238,7 +228,6 @@ bool CacheManager::loadCache() { } void CacheManager::saveCache() { - printf("CacheManager::saveCache toolsAtEnd_=%d\n", toolsAtEnd_); if (cacheDisabled_ || sessionPath_.empty()) { std::string errorMsg = string_format( "%s: Cannot save cache - caching disabled or no session path set\n", @@ -255,28 +244,10 @@ void CacheManager::saveCache() { __func__, sessionPath_.c_str())); - if (toolsAtEnd_) { - llama_pos trimPoint = llmContext_->getNPastBeforeTools(); - printf("CacheManager::saveCache trimPoint=%d nPast_=%d\n", trimPoint, llmContext_->getNPast()); - if (trimPoint > 0 && trimPoint < llmContext_->getNPast()) { - auto* mem = llama_get_memory(ctx); - llama_memory_seq_rm(mem, -1, trimPoint, -1); - llmContext_->setNPast(trimPoint); - QLOG_IF( - Priority::DEBUG, - string_format( - "%s: trimmed %d tool+response tokens before saving (tools-at-end " - "mode)\n", - __func__, - llmContext_->getNPast() - trimPoint)); - } - } - - llama_token sessionTokens[3] = { + llama_token sessionTokens[2] = { static_cast(llmContext_->getNPast()), - static_cast(llmContext_->getFirstMsgTokens()), - static_cast(llmContext_->getNPastBeforeTools())}; - llama_state_save_file(ctx, sessionPath_.c_str(), sessionTokens, 3); + static_cast(llmContext_->getFirstMsgTokens())}; + llama_state_save_file(ctx, sessionPath_.c_str(), sessionTokens, 2); } bool CacheManager::isCacheDisabled() const { return cacheDisabled_; } diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.hpp index df5c3555f7..359301ef7d 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.hpp @@ -14,7 +14,7 @@ class CacheManager { public: CacheManager( LlmContext* llmContext, llama_pos configuredNDiscarded, - std::function resetStateCallback, bool toolsAtEnd); + std::function resetStateCallback); bool handleCache( std::vector& chatMsgs, @@ -39,5 +39,4 @@ class CacheManager { std::string sessionPath_; bool cacheDisabled_ = true; bool cacheUsedInLastPrompt_ = false; - bool toolsAtEnd_ = false; }; diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp index 9d18f34ecf..f32145fb93 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp @@ -249,8 +249,7 @@ void LlamaModel::init(bool acquireLock) { snap->cacheManager_.emplace( snap->llmContext_.get(), snap->configuredNDiscarded_, - [this](bool resetStats) { this->resetState(resetStats); }, - snap->toolsAtEnd_); + [this](bool resetStats) { this->resetState(resetStats); }); } } diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp index 77221c60fe..83734a77ad 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp @@ -138,8 +138,7 @@ TEST_F(CacheManagementQwen3Test, CacheWithToolsAtEndTrueTrimsToolTokens) { EXPECT_GT(cacheTokensBeforeSave, 0.0); llama_pos nPastBeforeTools = model->getNPastBeforeTools(); - EXPECT_GT(nPastBeforeTools, 0); - EXPECT_LT(nPastBeforeTools, cacheTokensBeforeSave); + EXPECT_EQ(nPastBeforeTools, -1); std::string saveInput = R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "session", "content": "save"}])"; @@ -175,7 +174,7 @@ TEST_F(CacheManagementQwen3Test, CacheReloadWithToolsAtEndTrue) { }); llama_pos nPastBeforeTools1 = model1->getNPastBeforeTools(); - EXPECT_GT(nPastBeforeTools1, 0); + EXPECT_EQ(nPastBeforeTools1, -1); std::string saveInput = R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "session", "content": "save"}])"; @@ -205,8 +204,7 @@ TEST_F(CacheManagementQwen3Test, CacheReloadWithToolsAtEndTrue) { EXPECT_GT(cacheTokensAfterReload, 0.0); llama_pos nPastBeforeTools2 = model2->getNPastBeforeTools(); - EXPECT_EQ(nPastBeforeTools2, nPastBeforeTools1); - EXPECT_LE(nPastBeforeTools2, nPastBeforeTools1); + EXPECT_EQ(nPastBeforeTools2, -1); } TEST_F(CacheManagementQwen3Test, CacheWithoutToolsWithToolsAtEndTrue) { @@ -419,7 +417,7 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeRestoresNPastBeforeTools) { }); llama_pos nPastBeforeTools1 = model->getNPastBeforeTools(); - EXPECT_GT(nPastBeforeTools1, 0) << "nPastBeforeTools should be set after first prompt with tools"; + EXPECT_EQ(nPastBeforeTools1, -1); std::string saveInput = R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "session", "content": "save"}])"; @@ -444,7 +442,5 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeRestoresNPastBeforeTools) { }); llama_pos nPastBeforeTools2 = model2->getNPastBeforeTools(); - EXPECT_EQ(nPastBeforeTools2, nPastBeforeTools1) - << "nPastBeforeTools should be restored from session: expected " << nPastBeforeTools1 - << " but got " << nPastBeforeTools2; + EXPECT_EQ(nPastBeforeTools2, -1); } From aedaddac738c410c339c6fcaeb808fdb042aab28 Mon Sep 17 00:00:00 2001 From: Mikhail Sotnikov Date: Fri, 13 Mar 2026 04:46:35 +0300 Subject: [PATCH 22/48] (chore) llamacpp-llm: remove redundant getters and cleanup --- .../addon/src/model-interface/LlamaModel.cpp | 8 -------- .../addon/src/model-interface/LlamaModel.hpp | 6 ------ .../addon/src/model-interface/LlmContext.hpp | 7 ------- .../addon/src/model-interface/MtmdLlmContext.cpp | 4 ---- .../addon/src/model-interface/MtmdLlmContext.hpp | 2 -- .../addon/src/model-interface/TextLlmContext.cpp | 9 --------- .../addon/src/model-interface/TextLlmContext.hpp | 2 -- .../addon/src/utils/ChatTemplateUtils.cpp | 3 --- 8 files changed, 41 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp index f32145fb93..f286c2c20a 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp @@ -265,14 +265,6 @@ bool LlamaModel::isLoaded() { return static_cast(state_->llmContext_); } -llama_pos LlamaModel::getNConversationOnlyTokens() const { - std::shared_lock lock(stateMtx_); - if (state_->llmContext_) { - return state_->llmContext_->getNConversationOnlyTokens(); - } - return 0; -} - llama_pos LlamaModel::getNPastBeforeTools() const { std::shared_lock lock(stateMtx_); if (state_->llmContext_) { diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp index 768ccd2d92..59ac4f98c7 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp @@ -126,12 +126,6 @@ class LlamaModel : public IModel, public IModelAsyncLoad, public IModelCancel { */ bool isLoaded(); - /** - * Get the number of conversation-only tokens (without tools). - * This is set when toolsAtEnd is enabled and tools are provided. - */ - llama_pos getNConversationOnlyTokens() const; - /** * Get the nPast position before tool evaluation. * This is used to find the boundary in the KV cache after evaluating diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp index e470751c8d..660f11cff5 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp @@ -186,13 +186,6 @@ class LlmContext { // NOLINT(cppcoreguidelines-special-member-functions) */ virtual void setToolsAtEnd(bool toolsAtEnd) = 0; - /** - * Get the number of conversation-only tokens (without tools). - * This is used for double-tokenization to find the boundary between - * conversation tokens and tool tokens. - */ - [[nodiscard]] virtual llama_pos getNConversationOnlyTokens() const = 0; - /** * Get the nPast position before tool evaluation. * This is used to find the boundary in the KV cache after evaluating diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp index 40403bb04e..996d542a07 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp @@ -481,10 +481,6 @@ void MtmdLlmContext::setToolsAtEnd(bool toolsAtEnd) { this->toolsAtEnd_ = toolsAtEnd; } -llama_pos MtmdLlmContext::getNConversationOnlyTokens() const { - return nConversationOnlyTokens_; -} - llama_pos MtmdLlmContext::getNPastBeforeTools() const { return nPastBeforeTools_; } diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp index 248acd6ac5..8f9b117c76 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp @@ -114,8 +114,6 @@ class MtmdLlmContext: public LlmContext { void setToolsAtEnd(bool toolsAtEnd) override; - [[nodiscard]] llama_pos getNConversationOnlyTokens() const override; - [[nodiscard]] llama_pos getNPastBeforeTools() const override; void setNPastBeforeTools(llama_pos nPastBeforeTools) override; diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp index 8d91b645c8..ef5a3e6229 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp @@ -220,10 +220,8 @@ void TextLlmContext::tokenizeChat( Priority::DEBUG, string_format("[TextLlm] formatted prompt: %s\n", prompt.c_str())); - printf("TextLlmContext::tokenizeChat prompt=%s\n", prompt.c_str()); if (!prompt.empty()) { inputTokens = common_tokenize(lctx_, prompt, addSpecial, true); - printf("TextLlmContext::tokenizeChat inputTokens.size=%lu\n", inputTokens.size()); if (toolsAtEnd_ && !tools.empty()) { auto savedTools = inputs.tools; @@ -233,7 +231,6 @@ void TextLlmContext::tokenizeChat( inputs.tools = savedTools; nConversationOnlyTokens_ = tokensNoTools.size(); - printf("TextLlmContext::tokenizeChat nConversationOnlyTokens_=%d\n", nConversationOnlyTokens_); } else { nConversationOnlyTokens_ = 0; } @@ -288,7 +285,6 @@ bool TextLlmContext::evalMessageWithTools( size_t nTokens = inputTokens.size(); const bool isFirstMsg = (nPast_ == 0); - printf("TextLlmContext::evalMessageWithTools nPast_=%d nTokens=%zu\n", nPast_, nTokens); if (nTokens >= llama_n_ctx(lctx_)) { std::string errorMsg = string_format( @@ -518,7 +514,6 @@ bool TextLlmContext::generateResponse( void TextLlmContext::stop() { stopGeneration_.store(true); } void TextLlmContext::resetState(bool resetStats) { - printf("TextLlmContext::resetState resetStats=%d\n", resetStats); // Reset the n_past // Reset conversation-only tokens and nPastBeforeTools @@ -568,10 +563,6 @@ void TextLlmContext::setToolsAtEnd(bool toolsAtEnd) { this->toolsAtEnd_ = toolsAtEnd; } -llama_pos TextLlmContext::getNConversationOnlyTokens() const { - return nConversationOnlyTokens_; -} - void TextLlmContext::setNPastBeforeTools(llama_pos nPastBeforeTools) { nPastBeforeTools_ = nPastBeforeTools; } diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp index 3fbd713104..602a65309a 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp @@ -106,8 +106,6 @@ class TextLlmContext: public LlmContext { void setToolsAtEnd(bool toolsAtEnd) override; - [[nodiscard]] llama_pos getNConversationOnlyTokens() const override; - [[nodiscard]] llama_pos getNPastBeforeTools() const override; void setNPastBeforeTools(llama_pos nPastBeforeTools) override; diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.cpp index f80b01d6cb..6e4e23116d 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.cpp @@ -63,16 +63,13 @@ std::string getChatTemplateForModel( const std::string& manualOverride, bool toolsAtEnd) { if (!manualOverride.empty()) { - printf("ChatTemplateUtils::getChatTemplateForModel - manualOverride\n"); return manualOverride; } if (isQwen3Model(model)) { - printf("ChatTemplateUtils::getChatTemplateForModel - Qwen3 - toolsAtEnd=%d\n", toolsAtEnd); return toolsAtEnd ? getToolsDynamicQwen3Template() : getFixedQwen3Template(); } - printf("ChatTemplateUtils::getChatTemplateForModel - empty\n"); return ""; } From f13b1aa7533dc7ad6e12284af1421b3ebd1d293a Mon Sep 17 00:00:00 2001 From: Mikhail Sotnikov Date: Fri, 13 Mar 2026 05:14:30 +0300 Subject: [PATCH 23/48] (internal) llamacpp-llm: run Qwen3 context tests --- .../test/unit/CMakeLists.txt | 1 + .../test/unit/test_cache_management_qwen3.cpp | 4 - .../test/unit/test_text_llm_context.cpp | 344 ++---------------- .../test/unit/test_text_llm_context_qwen3.cpp | 342 +++++++++++++++++ 4 files changed, 369 insertions(+), 322 deletions(-) create mode 100644 packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context_qwen3.cpp diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/CMakeLists.txt b/packages/qvac-lib-infer-llamacpp-llm/test/unit/CMakeLists.txt index fc38141b51..4cd5906d7a 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/CMakeLists.txt +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/CMakeLists.txt @@ -14,6 +14,7 @@ add_executable( test_cache_management.cpp test_cache_management_qwen3.cpp test_text_llm_context.cpp + test_text_llm_context_qwen3.cpp test_addon_cpp.cpp test_backend_selection.cpp test_tune_config_map.cpp diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp index 83734a77ad..4117497ac2 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp @@ -273,7 +273,6 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeWithMultiplePrompts) { auto stats1 = model->runtimeStats(); double cacheTokens1 = getStatValue(stats1, "CacheTokens"); double promptTokens1 = getStatValue(stats1, "promptTokens"); - printf("CacheManagementQwen3Test::CacheToolsAtEndModeWithMultiplePrompts cacheTokens1=%f promptTokens1=%f\n", cacheTokens1, promptTokens1); EXPECT_GT(cacheTokens1, 0.0); EXPECT_GT(promptTokens1, 500.0); @@ -294,7 +293,6 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeWithMultiplePrompts) { auto stats2 = model->runtimeStats(); double cacheTokens2 = getStatValue(stats2, "CacheTokens"); double promptTokens2 = getStatValue(stats2, "promptTokens"); - printf("CacheManagementQwen3Test::CacheToolsAtEndModeWithMultiplePrompts cacheTokens2=%f, promptTokens2=%f\n", cacheTokens2, promptTokens2); EXPECT_GT(cacheTokens2, cacheTokens1); EXPECT_LT(promptTokens2, 500.0); EXPECT_LE(cacheTokens2, maxExpectedCacheTokens) @@ -328,7 +326,6 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeWithMultiplePrompts) { auto stats3 = model2->runtimeStats(); double cacheTokens3 = getStatValue(stats3, "CacheTokens"); double promptTokens3 = getStatValue(stats3, "promptTokens"); - printf("CacheManagementQwen3Test::CacheToolsAtEndModeWithMultiplePrompts cacheTokens3=%f, promptTokens3=%f\n", cacheTokens3, promptTokens3); EXPECT_GT(cacheTokens3, cacheTokens2); EXPECT_LT(promptTokens3, 100.0); @@ -347,7 +344,6 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeWithMultiplePrompts) { auto stats4 = model3->runtimeStats(); double cacheTokens4 = getStatValue(stats4, "CacheTokens"); - printf("CacheManagementQwen3Test::CacheToolsAtEndModeWithMultiplePrompts cacheTokens4=%f\n", cacheTokens4); EXPECT_EQ(cacheTokens4, cacheTokens2); } diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context.cpp index 188657f77e..2f57cbf539 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context.cpp @@ -61,14 +61,6 @@ class TextLlmContextTest : public ::testing::Test { std::string test_projection_path; bool hasValidModel() { return fs::exists(test_model_path); } - bool isQwen3Model() { - std::string lowerPath = test_model_path; - std::transform( - lowerPath.begin(), lowerPath.end(), lowerPath.begin(), - [](unsigned char c) { return std::tolower(c); }); - return lowerPath.find("qwen3") != std::string::npos; - } - std::unique_ptr createModel() { if (!hasValidModel()) { @@ -381,47 +373,7 @@ TEST_F(TextLlmContextTest, ProcessWithMultipleTools) { }); } -TEST_F(TextLlmContextTest, DoubleTokenizeWithToolsAtEnd) { - // tools_at_end feature requires Qwen3 model - if (!isQwen3Model()) { - GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; - } - - if (!hasValidModel()) { - FAIL() << "Test model not found"; - } - - config_files["tools_at_end"] = "true"; - auto model = createModel(); - if (!model) { - FAIL() << "Model failed to load"; - } - - LlamaModel::Prompt prompt; - prompt.input = R"([ - {"role": "user", "content": "What is the weather in Tokyo?"}, - { - "type": "function", - "name": "getWeather", - "description": "Get weather forecast for a city", - "parameters": { - "type": "object", - "properties": { - "city": {"type": "string", "description": "City name"}, - "date": {"type": "string", "description": "Date in YYYY-MM-DD"} - }, - "required": ["city", "date"] - } - } - ])"; - - EXPECT_NO_THROW({ - std::string output = model->processPrompt(prompt); - }); - llama_pos nConvTokens = model->getNConversationOnlyTokens(); - EXPECT_GT(nConvTokens, 0); -} TEST_F(TextLlmContextTest, DoubleTokenizeWithoutToolsAtEnd) { if (!hasValidModel()) { @@ -429,6 +381,7 @@ TEST_F(TextLlmContextTest, DoubleTokenizeWithoutToolsAtEnd) { } config_files["tools_at_end"] = "false"; + config_files["tools"] = "true"; auto model = createModel(); if (!model) { FAIL() << "Model failed to load"; @@ -456,8 +409,12 @@ TEST_F(TextLlmContextTest, DoubleTokenizeWithoutToolsAtEnd) { std::string output = model->processPrompt(prompt); }); - llama_pos nConvTokens = model->getNConversationOnlyTokens(); - EXPECT_EQ(nConvTokens, 0); + auto stats = model->runtimeStats(); + int cacheTokens = static_cast(getStatValue(stats, "CacheTokens")); + int promptTokens = static_cast(getStatValue(stats, "promptTokens")); + EXPECT_EQ(cacheTokens, 0); + // prompt tokens with tools + EXPECT_GT(promptTokens, 200); } TEST_F(TextLlmContextTest, DoubleTokenizeWithToolsAtEndNoTools) { @@ -466,6 +423,7 @@ TEST_F(TextLlmContextTest, DoubleTokenizeWithToolsAtEndNoTools) { } config_files["tools_at_end"] = "true"; + config_files["tools"] = "true"; auto model = createModel(); if (!model) { FAIL() << "Model failed to load"; @@ -478,122 +436,15 @@ TEST_F(TextLlmContextTest, DoubleTokenizeWithToolsAtEndNoTools) { std::string output = model->processPrompt(prompt); }); - llama_pos nConvTokens = model->getNConversationOnlyTokens(); - EXPECT_EQ(nConvTokens, 0); + // Without tools, CacheTokens should equal promptTokens (no cached conversation tokens) + auto stats = model->runtimeStats(); + int promptTokens = static_cast(getStatValue(stats, "promptTokens")); + EXPECT_LT(promptTokens, 50); } -TEST_F(TextLlmContextTest, DoubleTokenizeWithMultipleTools) { - // tools_at_end feature requires Qwen3 model - if (!isQwen3Model()) { - GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; - } - - if (!hasValidModel()) { - FAIL() << "Test model not found"; - } - config_files["tools_at_end"] = "true"; - auto model = createModel(); - if (!model) { - FAIL() << "Model failed to load"; - } - LlamaModel::Prompt prompt; - prompt.input = R"([ - {"role": "user", "content": "Search for laptops and add to cart"}, - { - "type": "function", - "name": "searchProducts", - "description": "Search products", - "parameters": { - "type": "object", - "properties": { - "query": {"type": "string", "description": "Search query"} - }, - "required": ["query"] - } - }, - { - "type": "function", - "name": "addToCart", - "description": "Add items to cart", - "parameters": { - "type": "object", - "properties": { - "items": { - "type": "array", - "items": {"type": "string"} - } - }, - "required": ["items"] - } - } - ])"; - - EXPECT_NO_THROW({ - std::string output = model->processPrompt(prompt); - }); - - llama_pos nConvTokens = model->getNConversationOnlyTokens(); - EXPECT_GT(nConvTokens, 0); -} - -TEST_F(TextLlmContextTest, DoubleTokenizeBoundaryAccuracy) { - // tools_at_end feature requires Qwen3 model - if (!isQwen3Model()) { - GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; - } - - if (!hasValidModel()) { - FAIL() << "Test model not found"; - } - - config_files["tools_at_end"] = "true"; - auto model = createModel(); - if (!model) { - FAIL() << "Model failed to load"; - } - - LlamaModel::Prompt promptWithTools; - promptWithTools.input = R"([ - {"role": "user", "content": "What is the weather in Tokyo?"}, - { - "type": "function", - "name": "getWeather", - "description": "Get weather forecast for a city", - "parameters": { - "type": "object", - "properties": { - "city": {"type": "string", "description": "City name"}, - "date": {"type": "string", "description": "Date in YYYY-MM-DD"} - }, - "required": ["city", "date"] - } - } - ])"; - - EXPECT_NO_THROW({ - std::string output = model->processPrompt(promptWithTools); - }); - - llama_pos conversationTokens = model->getNConversationOnlyTokens(); - - EXPECT_NO_THROW({ - model->reset(); - }); - - LlamaModel::Prompt promptNoTools; - promptNoTools.input = R"([{"role": "user", "content": "What is the weather in Tokyo?"}])"; - - EXPECT_NO_THROW({ - std::string output = model->processPrompt(promptNoTools); - }); - llama_pos tokensWithoutTools = model->getNConversationOnlyTokens(); - - EXPECT_EQ(tokensWithoutTools, 0); - EXPECT_GT(conversationTokens, 0); -} TEST_F(TextLlmContextTest, DoubleTokenizationTimeOverhead) { if (!hasValidModel()) { @@ -621,6 +472,7 @@ TEST_F(TextLlmContextTest, DoubleTokenizationTimeOverhead) { { config_files["tools_at_end"] = "false"; + config_files["tools"] = "true"; auto model = createModel(); if (!model) { FAIL() << "Model failed to load"; @@ -649,6 +501,7 @@ TEST_F(TextLlmContextTest, DoubleTokenizationTimeOverhead) { { config_files["tools_at_end"] = "true"; + config_files["tools"] = "true"; auto model = createModel(); if (!model) { FAIL() << "Model failed to load"; @@ -669,16 +522,17 @@ TEST_F(TextLlmContextTest, DoubleTokenizationTimeOverhead) { auto stats = model->runtimeStats(); int promptTokens = static_cast(getStatValue(stats, "promptTokens")); - llama_pos convTokens = model->getNConversationOnlyTokens(); + int cacheTokens = static_cast(getStatValue(stats, "CacheTokens")); GTEST_LOG_(INFO) << "Double tokenization (tools_at_end=true): " << durationDouble / numIterations << " us per iteration (" - << promptTokens << " prompt tokens, " << convTokens - << " conversation-only tokens)"; + << promptTokens << " prompt tokens, " << cacheTokens + << " cached tokens)"; } { config_files["tools_at_end"] = "true"; + config_files["tools"] = "true"; auto model = createModel(); if (!model) { FAIL() << "Model failed to load"; @@ -741,6 +595,8 @@ TEST_F(TextLlmContextTest, DoubleTokenizationTimeOverheadLargePrompt) { { config_files["tools_at_end"] = "false"; + config_files["tools"] = "true"; + config_files["ctx_size"] = "4096"; auto model = createModel(); if (!model) { FAIL() << "Model failed to load"; @@ -769,6 +625,7 @@ TEST_F(TextLlmContextTest, DoubleTokenizationTimeOverheadLargePrompt) { { config_files["tools_at_end"] = "true"; + config_files["tools"] = "true"; auto model = createModel(); if (!model) { FAIL() << "Model failed to load"; @@ -789,67 +646,22 @@ TEST_F(TextLlmContextTest, DoubleTokenizationTimeOverheadLargePrompt) { auto stats = model->runtimeStats(); int promptTokens = static_cast(getStatValue(stats, "promptTokens")); - llama_pos convTokens = model->getNConversationOnlyTokens(); + int cacheTokens = static_cast(getStatValue(stats, "CacheTokens")); GTEST_LOG_(INFO) << "Large prompt - Double tokenization (tools_at_end=true): " << durationDouble / numIterations << " us per iteration (" - << promptTokens << " prompt tokens, " << convTokens - << " conversation-only tokens)"; + << promptTokens << " prompt tokens, " << cacheTokens + << " cached tokens)"; } } -TEST_F(TextLlmContextTest, NPastBeforeToolsSetAfterEvalWithTools) { - // tools_at_end feature requires Qwen3 model - if (!isQwen3Model()) { - GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; - } - - if (!hasValidModel()) { - FAIL() << "Test model not found"; - } - - config_files["tools_at_end"] = "true"; - auto model = createModel(); - if (!model) { - FAIL() << "Model failed to load"; - } - - LlamaModel::Prompt prompt; - prompt.input = R"([ - {"role": "user", "content": "What is the weather in Tokyo?"}, - { - "type": "function", - "name": "getWeather", - "description": "Get weather forecast for a city", - "parameters": { - "type": "object", - "properties": { - "city": {"type": "string", "description": "City name"}, - "date": {"type": "string", "description": "Date in YYYY-MM-DD"} - }, - "required": ["city", "date"] - } - } - ])"; - - EXPECT_NO_THROW({ - std::string output = model->processPrompt(prompt); - }); - - llama_pos nPastBeforeTools = model->getNPastBeforeTools(); - llama_pos nConvTokens = model->getNConversationOnlyTokens(); - - EXPECT_GT(nPastBeforeTools, 0); - EXPECT_GT(nConvTokens, 0); - EXPECT_LE(nPastBeforeTools, nConvTokens); -} - TEST_F(TextLlmContextTest, NPastBeforeToolsMinusOneWithoutTools) { if (!hasValidModel()) { FAIL() << "Test model not found"; } config_files["tools_at_end"] = "true"; + config_files["tools"] = "true"; auto model = createModel(); if (!model) { FAIL() << "Model failed to load"; @@ -872,6 +684,7 @@ TEST_F(TextLlmContextTest, NPastBeforeToolsMinusOneWhenToolsAtEndFalse) { } config_files["tools_at_end"] = "false"; + config_files["tools"] = "true"; auto model = createModel(); if (!model) { FAIL() << "Model failed to load"; @@ -903,111 +716,6 @@ TEST_F(TextLlmContextTest, NPastBeforeToolsMinusOneWhenToolsAtEndFalse) { EXPECT_EQ(nPastBeforeTools, -1); } -TEST_F(TextLlmContextTest, NPastBeforeToolsResetAfterResetState) { - // tools_at_end feature requires Qwen3 model - if (!isQwen3Model()) { - GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; - } - - if (!hasValidModel()) { - FAIL() << "Test model not found"; - } - - config_files["tools_at_end"] = "true"; - auto model = createModel(); - if (!model) { - FAIL() << "Model failed to load"; - } - - LlamaModel::Prompt prompt; - prompt.input = R"([ - {"role": "user", "content": "What is the weather in Tokyo?"}, - { - "type": "function", - "name": "getWeather", - "description": "Get weather forecast for a city", - "parameters": { - "type": "object", - "properties": { - "city": {"type": "string", "description": "City name"}, - "date": {"type": "string", "description": "Date in YYYY-MM-DD"} - }, - "required": ["city", "date"] - } - } - ])"; - - EXPECT_NO_THROW({ - std::string output = model->processPrompt(prompt); - }); - - llama_pos nPastBeforeToolsBeforeReset = model->getNPastBeforeTools(); - EXPECT_GT(nPastBeforeToolsBeforeReset, 0); - - model->reset(); - - llama_pos nPastBeforeToolsAfterReset = model->getNPastBeforeTools(); - EXPECT_EQ(nPastBeforeToolsAfterReset, -1); -} - -TEST_F(TextLlmContextTest, NPastBeforeToolsBoundaryAccuracy) { - // tools_at_end feature requires Qwen3 model - if (!isQwen3Model()) { - GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; - } - if (!hasValidModel()) { - FAIL() << "Test model not found"; - } - config_files["tools_at_end"] = "true"; - auto model = createModel(); - if (!model) { - FAIL() << "Model failed to load"; - } - LlamaModel::Prompt prompt; - prompt.input = R"([ - {"role": "user", "content": "What is the weather in Tokyo?"}, - { - "type": "function", - "name": "getWeather", - "description": "Get weather forecast for a city", - "parameters": { - "type": "object", - "properties": { - "city": {"type": "string", "description": "City name"}, - "date": {"type": "string", "description": "Date in YYYY-MM-DD"} - }, - "required": ["city", "date"] - } - } - ])"; - - EXPECT_NO_THROW({ - std::string output = model->processPrompt(prompt); - }); - - llama_pos nPastBeforeTools = model->getNPastBeforeTools(); - llama_pos nConvTokens = model->getNConversationOnlyTokens(); - - EXPECT_GT(nConvTokens, 0); - EXPECT_GT(nPastBeforeTools, 0); - - EXPECT_NO_THROW({ - model->reset(); - }); - - LlamaModel::Prompt promptNoTools; - promptNoTools.input = R"([{"role": "user", "content": "What is the weather in Tokyo?"}])"; - - EXPECT_NO_THROW({ - std::string output = model->processPrompt(promptNoTools); - }); - - llama_pos nConvTokensNoTools = model->getNConversationOnlyTokens(); - llama_pos nPastBeforeToolsNoTools = model->getNPastBeforeTools(); - - EXPECT_EQ(nConvTokensNoTools, 0); - EXPECT_EQ(nPastBeforeToolsNoTools, -1); -} diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context_qwen3.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context_qwen3.cpp new file mode 100644 index 0000000000..a8c71e2a1a --- /dev/null +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context_qwen3.cpp @@ -0,0 +1,342 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "common/chat.h" +#include "model-interface/LlamaModel.hpp" +#include "model-interface/TextLlmContext.hpp" +#include "test_common.hpp" + +namespace { +double getStatValue( + const qvac_lib_inference_addon_cpp::RuntimeStats& stats, + const std::string& key) { + for (const auto& stat : stats) { + if (stat.first == key) { + return std::visit( + [](const auto& value) -> double { + if constexpr (std::is_same_v< + std::decay_t, + double>) { + return value; + } else { + return static_cast(value); + } + }, + stat.second); + } + } + return 0.0; +} + +bool isQwen3ModelPath(const std::string& path) { + std::string lowerPath = path; + std::transform( + lowerPath.begin(), lowerPath.end(), lowerPath.begin(), + [](unsigned char c) { return std::tolower(c); }); + return lowerPath.find("qwen3") != std::string::npos; +} +} // namespace + +namespace fs = std::filesystem; + +class TextLlmContextQwen3Test : public ::testing::Test { +protected: + void SetUp() override { + config_files["device"] = test_common::getTestDevice(); + config_files["ctx_size"] = "2048"; + config_files["gpu_layers"] = test_common::getTestGpuLayers(); + config_files["n_predict"] = "10"; + + // Use Qwen3 model if available, skip if not + test_model_path = test_common::BaseTestModelPath::get( + "Qwen3-1.7B-Q4_0.gguf", "Llama-3.2-1B-Instruct-Q4_0.gguf"); + test_projection_path = ""; + + config_files["backendsDir"] = test_common::getTestBackendsDir().string(); + } + + std::unordered_map config_files; + std::string test_model_path; + std::string test_projection_path; + + bool hasValidModel() { return fs::exists(test_model_path); } + bool isQwen3Model() { return isQwen3ModelPath(test_model_path); } + + std::unique_ptr createModel() { + if (!hasValidModel()) { + return nullptr; + } + std::string modelPath = test_model_path; + std::string projectionPath = test_projection_path; + auto configCopy = config_files; + auto model = std::make_unique( + std::move(modelPath), std::move(projectionPath), std::move(configCopy)); + model->waitForLoadInitialization(); + if (!model->isLoaded()) { + return nullptr; + } + return model; + } +}; + +TEST_F(TextLlmContextQwen3Test, DoubleTokenizeWithToolsAtEnd) { + if (!isQwen3Model()) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + LlamaModel::Prompt prompt; + prompt.input = R"([ + {"role": "user", "content": "What is the weather in Tokyo?"}, + { + "type": "function", + "name": "getWeather", + "description": "Get weather forecast for a city", + "parameters": { + "type": "object", + "properties": { + "city": {"type": "string", "description": "City name"}, + "date": {"type": "string", "description": "Date in YYYY-MM-DD"} + }, + "required": ["city", "date"] + } + } + ])"; + + EXPECT_NO_THROW({ + std::string output = model->processPrompt(prompt); + }); + + auto stats = model->runtimeStats(); + int promptTokens = static_cast(getStatValue(stats, "promptTokens")); + EXPECT_GT(promptTokens, 0); +} + +TEST_F(TextLlmContextQwen3Test, DoubleTokenizeWithMultipleTools) { + if (!isQwen3Model()) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + config_files["tools"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + LlamaModel::Prompt prompt; + prompt.input = R"([ + {"role": "user", "content": "Search for laptops and add to cart"}, + { + "type": "function", + "name": "searchProducts", + "description": "Search products", + "parameters": { + "type": "object", + "properties": { + "query": {"type": "string", "description": "Search query"} + }, + "required": ["query"] + } + }, + { + "type": "function", + "name": "addToCart", + "description": "Add items to cart", + "parameters": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": {"type": "string"} + } + }, + "required": ["items"] + } + } + ])"; + + EXPECT_NO_THROW({ + std::string output = model->processPrompt(prompt); + }); + + auto stats = model->runtimeStats(); + int promptTokens = static_cast(getStatValue(stats, "promptTokens")); + EXPECT_GT(promptTokens, 0); +} + +TEST_F(TextLlmContextQwen3Test, DoubleTokenizeBoundaryAccuracy) { + if (!isQwen3Model()) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + config_files["tools"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + LlamaModel::Prompt promptWithTools; + promptWithTools.input = R"([ + {"role": "user", "content": "What is the weather in Tokyo?"}, + { + "type": "function", + "name": "getWeather", + "description": "Get weather forecast for a city", + "parameters": { + "type": "object", + "properties": { + "city": {"type": "string", "description": "City name"}, + "date": {"type": "string", "description": "Date in YYYY-MM-DD"} + }, + "required": ["city", "date"] + } + } + ])"; + + EXPECT_NO_THROW({ + std::string output = model->processPrompt(promptWithTools); + }); + + auto statsWithTools = model->runtimeStats(); + int promptTokensWithTools = static_cast(getStatValue(statsWithTools, "promptTokens")); + EXPECT_GT(promptTokensWithTools, 150); + + EXPECT_NO_THROW({ + model->reset(); + }); + + LlamaModel::Prompt promptNoTools; + promptNoTools.input = R"([{"role": "user", "content": "What is the weather in Tokyo?"}])"; + + EXPECT_NO_THROW({ + std::string output = model->processPrompt(promptNoTools); + }); + + auto statsNoTools = model->runtimeStats(); + int promptTokensNoTools = static_cast(getStatValue(statsNoTools, "promptTokens")); + + EXPECT_LT(promptTokensNoTools, 30); +} + +TEST_F(TextLlmContextQwen3Test, NPastBeforeToolsSetAfterEvalWithTools) { + if (!isQwen3Model()) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + config_files["tools"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + LlamaModel::Prompt prompt; + prompt.input = R"([ + {"role": "user", "content": "What is the weather in Tokyo?"}, + { + "type": "function", + "name": "getWeather", + "description": "Get weather forecast for a city", + "parameters": { + "type": "object", + "properties": { + "city": {"type": "string", "description": "City name"}, + "date": {"type": "string", "description": "Date in YYYY-MM-DD"} + }, + "required": ["city", "date"] + } + } + ])"; + + EXPECT_NO_THROW({ + std::string output = model->processPrompt(prompt); + }); + + llama_pos nPastBeforeTools = model->getNPastBeforeTools(); + auto stats = model->runtimeStats(); + int promptTokens = static_cast(getStatValue(stats, "promptTokens")); + + EXPECT_EQ(nPastBeforeTools, -1); + EXPECT_GT(promptTokens, 0); +} + +TEST_F(TextLlmContextQwen3Test, NPastBeforeToolsResetAfterResetState) { + if (!isQwen3Model()) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + config_files["tools"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + LlamaModel::Prompt prompt; + prompt.input = R"([ + {"role": "user", "content": "What is the weather in Tokyo?"}, + { + "type": "function", + "name": "getWeather", + "description": "Get weather forecast for a city", + "parameters": { + "type": "object", + "properties": { + "city": {"type": "string", "description": "City name"}, + "date": {"type": "string", "description": "Date in YYYY-MM-DD"} + }, + "required": ["city", "date"] + } + } + ])"; + + EXPECT_NO_THROW({ + std::string output = model->processPrompt(prompt); + }); + + llama_pos nPastBeforeToolsBeforeReset = model->getNPastBeforeTools(); + EXPECT_EQ(nPastBeforeToolsBeforeReset, -1); + + model->reset(); + + llama_pos nPastBeforeToolsAfterReset = model->getNPastBeforeTools(); + EXPECT_EQ(nPastBeforeToolsAfterReset, -1); +} From c1e85c2eff5afb1760de239b7ea233fde1513f07 Mon Sep 17 00:00:00 2001 From: Mikhail Sotnikov Date: Fri, 13 Mar 2026 05:15:49 +0300 Subject: [PATCH 24/48] (chore) cleanup --- packages/qvac-lib-infer-llamacpp-llm/test/model | 1 - 1 file changed, 1 deletion(-) delete mode 120000 packages/qvac-lib-infer-llamacpp-llm/test/model diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/model b/packages/qvac-lib-infer-llamacpp-llm/test/model deleted file mode 120000 index 9fbb2fffd2..0000000000 --- a/packages/qvac-lib-infer-llamacpp-llm/test/model +++ /dev/null @@ -1 +0,0 @@ -/home/mialso/.qvac/models/ \ No newline at end of file From f2fe2a55696f9438b5d7e23b222b0324c4cc8985 Mon Sep 17 00:00:00 2001 From: olyasir Date: Fri, 13 Mar 2026 13:00:28 +0200 Subject: [PATCH 25/48] (chore) fix lint errors in examples --- .../src/model-interface/TextLlmContext.cpp | 4 +- .../examples/benchToolsPlacement.js | 6 +- .../examples/benchmark_chart.html | 14 +- .../examples/testHugeToolCache.js | 312 ------------------ .../examples/testToolRemoval.js | 18 +- .../test/mobile/integration.auto.cjs | 4 + 6 files changed, 23 insertions(+), 335 deletions(-) delete mode 100644 packages/qvac-lib-infer-llamacpp-llm/examples/testHugeToolCache.js diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp index ef5a3e6229..1c5799ac74 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp @@ -517,9 +517,7 @@ void TextLlmContext::resetState(bool resetStats) { // Reset the n_past // Reset conversation-only tokens and nPastBeforeTools - if (resetStats) { - nPastBeforeTools_ = -1; - } + nPastBeforeTools_ = -1; nPast_ = 0; // Reset the first msg token length diff --git a/packages/qvac-lib-infer-llamacpp-llm/examples/benchToolsPlacement.js b/packages/qvac-lib-infer-llamacpp-llm/examples/benchToolsPlacement.js index 979aae8eaf..297c24b1a4 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/examples/benchToolsPlacement.js +++ b/packages/qvac-lib-infer-llamacpp-llm/examples/benchToolsPlacement.js @@ -292,8 +292,8 @@ async function runScenario (dirPath, modelName, opts) { ? [{ role: 'system', content: 'You are a helpful assistant.' }, { role: 'user', content: turn.user }] : [ ...(lastAssistantResponse ? [{ role: 'assistant', content: lastAssistantResponse }] : []), - { role: 'user', content: turn.user } - ]), + { role: 'user', content: turn.user } + ]), ...turnTools ] } else if (dynamicTools) { @@ -400,7 +400,7 @@ function printComparison (labelA, statsA, labelB, statsB) { console.log('-----|-------------|-------------|----------|----------|----------|---------|---------|---------|--------') console.log( - ` TOT ` + + ' TOT ' + `| ${totalA.toFixed(2).padStart(11)} ` + `| ${totalB.toFixed(2).padStart(11)} ` + `| ${(totalA - totalB).toFixed(2).padStart(8)} |` diff --git a/packages/qvac-lib-infer-llamacpp-llm/examples/benchmark_chart.html b/packages/qvac-lib-infer-llamacpp-llm/examples/benchmark_chart.html index 43d558aa96..60bb2b7609 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/examples/benchmark_chart.html +++ b/packages/qvac-lib-infer-llamacpp-llm/examples/benchmark_chart.html @@ -13,7 +13,7 @@

Benchmark: tools_at_end vs tools_in_system (reset+replay) — 20 turns

-
tools_at_end is 58.2% faster overall — 1281s saved across 20 turns
+
tools_at_end is 60.3% faster overall — 896s saved across 20 turns (CPU-only, correct templates)

Wall Time per Turn (ms)

@@ -38,16 +38,16 @@

Cache Tokens per Turn

- - - -

Benchmark: tools_at_end vs tools_in_system (reset+replay) — 20 turns

-
tools_at_end is 60.3% faster overall — 896s saved across 20 turns (CPU-only, correct templates)
- -
-

Wall Time per Turn (ms)

- -
- -
-

TTFT per Turn (ms)

- -
- -
-

Prompt Tokens per Turn

- -
- -
-

Cache Tokens per Turn

- -
- - - - diff --git a/packages/qvac-lib-infer-llamacpp-llm/examples/conv.md b/packages/qvac-lib-infer-llamacpp-llm/examples/conv.md deleted file mode 100644 index 4ecb6b75d7..0000000000 --- a/packages/qvac-lib-infer-llamacpp-llm/examples/conv.md +++ /dev/null @@ -1,51 +0,0 @@ -# Strip tool_call blocks & benchmark — session notes - -## What was done - -### 1. Strip internal blocks from re-sent assistant responses -Added `stripInternalBlocks()` helper to both example files. It removes `` and `` blocks from assistant responses before they're re-sent in conversation history, preventing the model from pattern-matching on old tool calls and hallucinating removed tools. - -**Files modified:** -- `examples/testToolRemoval.js` — strips `lastResponse` (4 turns) and `history` assistant entries (3 pushes in `mainInSystem()`) -- `examples/benchToolsPlacement.js` — strips `lastAssistantResponse` and `conversationHistory` entries in `runScenario()` - -### 2. testToolRemoval.js — all 8 tests PASS -``` -bare examples/testToolRemoval.js -``` -Both `tools_at_end` and `tools_in_system` sections pass all 4 turns, including turn 4 which previously failed. - -### 3. benchToolsPlacement.js — 20-turn benchmark -Updated `NUM_TURNS` to 20, added 10 more entries to `DYNAMIC_TOOLS_PER_TURN` and `CONVERSATION_TURNS_DYNAMIC`. - -Run with: -``` -bare examples/benchToolsPlacement.js -``` - -**Results (CPU-only, no GPU):** -- tools_at_end (C) is **58.2% faster** — saved 1281s across 20 turns -- All 40 turns PASS — zero stale tool leaks -- D's prompt tokens grow 285→3526, TTFT grows 13s→143s -- C stays relatively flat (15-80s wall time), cache grows 26→1991 tokens -- D gets zero cache hits after turn 1 - -### 4. HTML chart -`examples/benchmark_chart.html` — open in browser, has 4 bar charts (wall time, TTFT, prompt tokens, cache tokens). - -## GPU / Vulkan issue -The benchmark ran on CPU only. The machine has Intel Iris Xe (Raptor Lake-P) but it was booted in **recovery mode with `nomodeset`**, which disables kernel GPU drivers. - -**Fix:** Reboot normally (not recovery mode). The grub config is fine (`quiet splash`). After normal boot: -- `i915` or `xe` module should load automatically -- `/dev/dri/renderD128` should appear -- Vulkan will pick up the Intel GPU -- Benchmark should be significantly faster with bigger gap between C and D - -Verify after reboot: -``` -ls /dev/dri/render* -vulkaninfo --summary 2>&1 | grep deviceName -``` - -Then re-run the 20-turn benchmark to get GPU numbers. From 05674f0c9953a91addd79b82f4aa82fdbb29d570 Mon Sep 17 00:00:00 2001 From: olyasir Date: Fri, 13 Mar 2026 15:23:18 +0200 Subject: [PATCH 29/48] (chore) remove scratch planning docs --- Pitch_tools_at_end_of_prompt.md | 86 ------- prefill_offset_implementation_plan.md | 341 -------------------------- 2 files changed, 427 deletions(-) delete mode 100644 Pitch_tools_at_end_of_prompt.md delete mode 100644 prefill_offset_implementation_plan.md diff --git a/Pitch_tools_at_end_of_prompt.md b/Pitch_tools_at_end_of_prompt.md deleted file mode 100644 index 1db691ae0a..0000000000 --- a/Pitch_tools_at_end_of_prompt.md +++ /dev/null @@ -1,86 +0,0 @@ - - -| Approved by Technical Lead | WIP | -| :---- | :---- | -| Approved by Technical Architect | **WIP** | -| \[optional\] Review from Subash | **WIP** | - -# Tools at End of Prompt for KV-Cache Optimization - -# Pitch - -## Problem - -In the current architecture, tool definitions are placed at the beginning of the prompt (typically inside or right after the system prompt), following default chat templates. This means that whenever tools change between conversation turns — e.g. when an agent selects different tools for a new user query — the KV-cache is invalidated from the point of the tool definitions onward, forcing a full recomputation of the entire conversation history that follows. - -On mobile devices with limited compute, this is especially costly. The conversation history can grow long, and reprocessing it on every turn with changed tools eliminates the benefit of prompt caching. Since we control the KV-cache in our setup, we have an opportunity to optimize: if tools are placed at the **end** of the prompt (after the conversation history, right before generation), we can cache everything up to the tools and only recompute the new query + new tools on each turn. This dramatically reduces per-turn computation. - -**Current layout (tools at the beginning):** -``` -| <-- cache invalidated from tools onward -``` - -**Desired layout (tools at the end):** -``` -| <-- response + new query + tools recomputed as prefill -``` - -Each token in the KV-cache depends on all previous tokens, so tokens can only be removed/changed at the end without invalidating the rest. By placing tools last, we can strip old tools *and* the model's response from the cache tail, then recompute them together with the new query and new tools in a single prefill pass. Since all response tokens are already known, prefill is fully parallel and significantly cheaper than autoregressive generation. The cached system prompt and conversation history up to the last user query is preserved and never recomputed. - -## Solution - -The solution has two parts: - -### 1. Modified Chat Templates - -Model chat templates (Jinja2-based) control where tool definitions appear in the final prompt. We need to modify these templates to extract tool definitions from their default position (usually inside the system prompt) and place them at the end of the prompt, just before the generation token. - -POC results (PR [#232](https://github.com/tetherto/qvac/pull/232)): -- **Qwen3 family**: Successfully tested with modified chat template. Tools placed at the end are picked up correctly — the model calls tools properly with no degradation in quality. Tested on a heavy scenario (1 prompt, 20+ tool calls for code review). -- **LFM (Liquid AI)**: Requires tools in the system prompt — fundamentally different architecture. Would likely need fine-tuning/retraining to support tools at a different position. Out of scope for now. - -### 2. KV-Cache Strategy Update - -The current caching implementation expects an exact prefix match: it caches the full prompt and on the next turn checks if the new prompt starts with the cached prefix. With tools at the end, the conversation turns are inserted *before* the tools, which breaks this assumption. - -We need a new cache strategy: -- After each model response, **trim both the tool tokens and the response tokens from the end of the KV-cache** (we know the exact token counts since we control the prompt construction). -- On the next turn, **recompute the previous response tokens + new user query tokens + new tool tokens as a single prefill pass**. Since all these tokens are already known (the response already happened, the new query and tools are provided), this is a fully parallel operation — no autoregressive generation needed. -- The system prompt + conversation history up to the last user query remains cached and is never recomputed. - -This is possible because we have full control over the KV-cache in our inference stack (llama.cpp / custom server). The key insight is that removing tokens from the end of the cache does not invalidate any preceding tokens, and prefilling known tokens is significantly cheaper than recomputing the full conversation from scratch. - -This approach also avoids any correctness concerns: since the response KV entries are always recomputed alongside the current tool definitions, there is no stale state in the cache. Each turn's response KV is consistent with the tools that were in context when it was generated. - -## Risks - -1. **Model-specific behavior**: Not all models support tools at arbitrary positions. The chat template is model-defined and some models (like LFM) embed tool handling into training. We must test each target model individually. Mitigation: maintain a registry of supported models and fall back to default template for unsupported ones. - -2. **Prefill overhead**: Recomputing response tokens as prefill on each turn adds some per-turn cost compared to keeping them cached. However, prefill is fully parallel and in practice much cheaper than recomputing the full conversation history from scratch, especially for conversations with large payloads (e.g., image tokens in VLM scenarios). Mitigation: benchmark prefill cost vs. full-recompute cost across different conversation lengths to quantify the savings. - -3. **Chat template maintenance**: Modified chat templates need to be kept in sync when models are updated. Mitigation: automate template modification or contribute upstream patches. - -4. **Inference server compatibility**: The current MLX-based server and llama.cpp handle caching differently. The cache trimming strategy needs to work across both. Mitigation: implement the cache strategy at our abstraction layer, not at the server level. - -## Out of scope - -- Fine-tuning or retraining models that don't natively support tools at the end of the prompt (e.g., LFM from Liquid AI). -- Orchestrator/multi-agent architecture for tool management (separate pitch). -- Embedding tool capabilities via fine-tuning (separate pitch). - -## Nice to haves - -- Benchmark suite comparing inference latency with tools-at-beginning vs. tools-at-end across different conversation lengths. -- Automatic chat template modification tool that takes a model's default template and produces the tools-at-end variant. -- Support for partial tool caching (keeping common/unchanged tools in cache, only recomputing added/removed ones). - -## Estimate - -* \[1 dev day\] Implement modified chat templates for Qwen3 family models and validate tool calling accuracy. -* \[2 dev days\] Implement KV-cache trimming strategy — trim tool tokens from cache tail and append new query + tools. -* \[1 dev day\] Integrate cache strategy with llama.cpp inference backend. -* \[1 dev day\] Quality validation — run multi-turn benchmarks comparing full-recompute vs. cache-trimmed responses; measure latency improvements. -* \[0.5 dev days\] Add model compatibility registry and fallback logic for unsupported models. -* \[0.5 dev days\] Documentation and testing. - -**Total: ~6 dev days** diff --git a/prefill_offset_implementation_plan.md b/prefill_offset_implementation_plan.md deleted file mode 100644 index ac48469120..0000000000 --- a/prefill_offset_implementation_plan.md +++ /dev/null @@ -1,341 +0,0 @@ -# Prefill with Offset — Implementation Plan - -## Goal - -Add an `offset` parameter to the eval methods in the LLM addon's C++ layer. When provided, the KV cache is trimmed to `offset` position before evaluating new tokens. Combined with `prefill=true` (from PR #689), this enables the tools-at-end KV cache optimization entirely in C++, with no JS API changes. - -## Context - -The tools-at-end optimization (see `Pitch_tools_at_end_of_prompt.md`) requires: -1. Trimming the KV cache tail (remove old tools + response tokens) -2. Prefilling known tokens (previous response + new query + new tools) from a specific cache position -3. Generating from the warm cache - -PR #689 adds `prefill=true` which evaluates tokens into the KV cache without generating. But it always appends at `nPast_` — there's no way to say "go back to position X and prefill from there." The `offset` parameter fills that gap. - -## How It Works - -``` -offset = -1 (default): current behavior, eval starts from nPast_ -offset >= 0: trim KV cache to that position, then eval new tokens from there -``` - -When `evalMessageWithTools` receives `offset >= 0 && offset < nPast_`: -1. Call `removeLastNTokens(nPast_ - offset)` — this trims the KV cache and sets `nPast_ = offset` -2. Proceed with normal token evaluation starting from the new `nPast_` - -This is atomic — trim + eval in a single call. No need for the caller to manually call `removeLastNTokens` then `evalMessage` separately. - -## End-to-End Flow (tools-at-end optimization) - -This is how `processPrompt()` would use offset + prefill internally: - -### Turn 1 (cold start) -``` -KV cache: empty -Prompt: - -1. evalMessageWithTools(msgs, tools1, ..., prefill=false, offset=-1) - -> tokens evaluated at pos 0..N-1, nPast_ = N -2. generateResponse() -> model generates, nPast_ = N + G -3. Track: toolTokenCount_ = T, responseTokenCount_ = G - Cache state: [system | user-q-1 | tools-1 | response-1] - pos 0 pos N-T pos N pos N+G -``` - -### Turn 2 (tools changed) -``` -KV cache: [system | user-q-1 | tools-1 | response-1] -Want: [system | user-q-1 | response-1 | user-q-2 | tools-2] - -offset = N - T (position just before old tools) - -1. Build full message array: [system, user-q-1, assistant-response-1, user-q-2] + tools-2 -2. evalMessageWithTools(msgs, tools2, ..., prefill=false, offset=N-T) - -> removeLastNTokens(nPast_ - offset) trims tools-1 + response-1 - -> KV cache: [system | user-q-1] - -> tokenizeChat produces full prompt tokens - -> only NEW tokens (after the cached prefix) are evaluated - -> nPast_ updated to include response-1 + user-q-2 + tools-2 -3. generateResponse() -> model generates turn 2 response -``` - -Note: The prefill flag is for when you want to eval without generating (preload context). The offset works with both `prefill=true` and `prefill=false`. - ---- - -## Files to Change - -All files are under `packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/`. - -### 1. LlmContext.hpp (virtual interface) - -**What:** Add `offset` parameter to both virtual method signatures. - -**Current (after PR #689):** -```cpp -virtual bool evalMessage( - const std::vector& chatMsgs, bool isCacheLoaded, - bool prefill) = 0; - -virtual bool evalMessageWithTools( - const std::vector& chatMsgs, - const std::vector& tools, bool isCacheLoaded, - bool prefill) = 0; -``` - -**New:** -```cpp -virtual bool evalMessage( - const std::vector& chatMsgs, bool isCacheLoaded, - bool prefill, llama_pos offset = -1) = 0; - -virtual bool evalMessageWithTools( - const std::vector& chatMsgs, - const std::vector& tools, bool isCacheLoaded, - bool prefill, llama_pos offset = -1) = 0; -``` - -**Lines affected:** ~114-128 (the two virtual declarations and their doc comments) - -**Doc comment addition for both methods:** -```cpp -* @param offset - KV cache position to trim to before evaluation. -* -1 means no trimming (default, eval from current nPast_). -* >= 0 trims cache to this position, then evaluates from there. -``` - ---- - -### 2. TextLlmContext.hpp (override declarations) - -**What:** Update override signatures to match new virtual interface. - -**Current (after PR #689):** -```cpp -bool evalMessage( - const std::vector& chatMsgs, - bool isCacheLoaded, bool prefill) override; - -bool evalMessageWithTools( - const std::vector& chatMsgs, - const std::vector& tools, bool isCacheLoaded, - bool prefill) override; -``` - -**New:** -```cpp -bool evalMessage( - const std::vector& chatMsgs, - bool isCacheLoaded, bool prefill, llama_pos offset = -1) override; - -bool evalMessageWithTools( - const std::vector& chatMsgs, - const std::vector& tools, bool isCacheLoaded, - bool prefill, llama_pos offset = -1) override; -``` - -**Lines affected:** ~30-45 - ---- - -### 3. TextLlmContext.cpp (implementation) - -**What:** Two changes — update signatures + add trim logic. - -#### 3a. evalMessage (forwarding method, ~line 256) - -**Current (after PR #689):** -```cpp -bool TextLlmContext::evalMessage( - const std::vector& chatMsgs, bool isCacheLoaded, - bool prefill) { - return evalMessageWithTools(chatMsgs, {}, isCacheLoaded, prefill); -} -``` - -**New:** -```cpp -bool TextLlmContext::evalMessage( - const std::vector& chatMsgs, bool isCacheLoaded, - bool prefill, llama_pos offset) { - return evalMessageWithTools(chatMsgs, {}, isCacheLoaded, prefill, offset); -} -``` - -#### 3b. evalMessageWithTools (main method, ~line 261) - -**Current (after PR #689):** -```cpp -bool TextLlmContext::evalMessageWithTools( - const std::vector& chatMsgs, - const std::vector& tools, bool isCacheLoaded, - bool prefill) { - std::vector inputTokens; - tokenizeChat(chatMsgs, tools, inputTokens, isCacheLoaded); - // ... rest of method -``` - -**New:** -```cpp -bool TextLlmContext::evalMessageWithTools( - const std::vector& chatMsgs, - const std::vector& tools, bool isCacheLoaded, - bool prefill, llama_pos offset) { - - // Trim KV cache to offset position if specified - if (offset >= 0 && offset < nPast_) { - removeLastNTokens(nPast_ - offset); - } - - std::vector inputTokens; - tokenizeChat(chatMsgs, tools, inputTokens, isCacheLoaded); - // ... rest of method unchanged -``` - -**Why this works:** `removeLastNTokens` calls `llama_memory_seq_rm` to remove entries from the KV cache and decrements `nPast_`. The existing eval loop uses `llama_pos count = nPast_` (line ~319) as its starting position, so new tokens are naturally placed right after the offset. - ---- - -### 4. MtmdLlmContext.hpp (override declarations) - -**What:** Same signature update as TextLlmContext.hpp. - -**Current (after PR #689):** -```cpp -bool evalMessage( - const std::vector& chatMsgs, - bool isCacheLoaded, bool prefill) override; - -bool evalMessageWithTools( - const std::vector& chatMsgs, - const std::vector& tools, bool isCacheLoaded, - bool prefill) override; -``` - -**New:** -```cpp -bool evalMessage( - const std::vector& chatMsgs, - bool isCacheLoaded, bool prefill, llama_pos offset = -1) override; - -bool evalMessageWithTools( - const std::vector& chatMsgs, - const std::vector& tools, bool isCacheLoaded, - bool prefill, llama_pos offset = -1) override; -``` - -**Lines affected:** ~37-52 - ---- - -### 5. MtmdLlmContext.cpp (implementation) - -**What:** Same pattern as TextLlmContext.cpp — update signatures + add trim logic. - -#### 5a. evalMessage (forwarding method, ~line 210) - -**New:** -```cpp -bool MtmdLlmContext::evalMessage( - const std::vector& chatMsgs, bool isCacheLoaded, - bool prefill, llama_pos offset) { - return evalMessageWithTools(chatMsgs, {}, isCacheLoaded, prefill, offset); -} -``` - -#### 5b. evalMessageWithTools (main method, ~line 215) - -**New (add trim block at top):** -```cpp -bool MtmdLlmContext::evalMessageWithTools( - const std::vector& chatMsgs, - const std::vector& tools, bool isCacheLoaded, - bool prefill, llama_pos offset) { - - // Trim KV cache to offset position if specified - if (offset >= 0 && offset < nPast_) { - removeLastNTokens(nPast_ - offset); - } - - mtmd::input_chunks chunks(mtmd_input_chunks_init()); - tokenizeChat(chatMsgs, tools, chunks, isCacheLoaded); - // ... rest unchanged -``` - ---- - -### 6. LlamaModel.cpp — processPrompt() passes offset - -**What:** Thread `offset` from the internal call site into eval methods. For now, always pass `-1` (no trim) to keep existing behavior. The tools-at-end optimization will set a real offset later. - -**Current (after PR #689, ~line 262):** -```cpp -bool evalOk = - resolved.tools.empty() - ? llmContext_->evalMessage( - resolved.chatMsgs, resolved.isCacheLoaded, prompt.prefill) - : llmContext_->evalMessageWithTools( - resolved.chatMsgs, resolved.tools, - resolved.isCacheLoaded, prompt.prefill); -``` - -**No change needed here** — since the default value is `offset = -1` in the virtual declarations, existing call sites don't need to be updated. The offset will only be passed explicitly when the tools-at-end optimization is implemented in `processPrompt()`. - ---- - -## Files NOT Changed - -| File | Why | -|------|-----| -| `LlamaModel.hpp` | `Prompt` struct not touched — offset is internal to C++, not from JS | -| `index.js` | JS API unchanged | -| `index.d.ts` | TypeScript types unchanged | -| `CacheManager.hpp/.cpp` | Cache manager deals with disk sessions, not in-flight cache trimming | - ---- - -## Testing - -### Unit-level validation for offset - -Add to `test/integration/api-behavior.test.js`: - -```js -test('prefill with offset trims cache and re-evaluates', { timeout: 600_000 }, async t => { - const { model } = await setupModel(t) - - // 1. Normal run to populate cache - const r1 = await model.run(BASE_PROMPT) - await collectResponse(r1) - const cacheAfterR1 = toNumber(r1?.stats?.CacheTokens) - t.ok(cacheAfterR1 > 0, 'cache populated after first run') - - // 2. Prefill with offset=0 should trim entire cache, then re-evaluate - const r2 = await model.run(BASE_PROMPT, { prefill: true, offset: 0 }) - await collectResponse(r2) - const cacheAfterR2 = toNumber(r2?.stats?.CacheTokens) - t.ok(cacheAfterR2 > 0, 'cache repopulated after prefill with offset') - - // 3. Normal run after prefill should still work - const r3 = await model.run(BASE_PROMPT) - const output = await collectResponse(r3) - t.ok(output.length > 0, 'generation works after prefill with offset') -}) -``` - -Note: This test requires exposing `offset` via JS (`RunOptions`). If offset stays internal-only in C++, this test would need to be a C++ unit test instead. - ---- - -## Summary - -| Change | Files | Lines of new logic | -|--------|-------|--------------------| -| Add `offset` param to virtual interface | `LlmContext.hpp` | signature only | -| Update TextLlm override signatures | `TextLlmContext.hpp` | signature only | -| Add trim-to-offset logic in TextLlm | `TextLlmContext.cpp` | 3 lines | -| Update MtmdLlm override signatures | `MtmdLlmContext.hpp` | signature only | -| Add trim-to-offset logic in MtmdLlm | `MtmdLlmContext.cpp` | 3 lines | - -Total new logic: ~6 lines across 2 files. The rest is signature propagation. From 71c3f19a65bf8f855eb8908630d6e179cedd0fe3 Mon Sep 17 00:00:00 2001 From: Mikhail Sotnikov Date: Fri, 13 Mar 2026 17:22:04 +0300 Subject: [PATCH 30/48] (doc) llamacpp-llm: tools_at_end param description --- .../qvac-lib-infer-llamacpp-llm/README.md | 1 + .../docs/tools-at-end.md | 51 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 packages/qvac-lib-infer-llamacpp-llm/docs/tools-at-end.md diff --git a/packages/qvac-lib-infer-llamacpp-llm/README.md b/packages/qvac-lib-infer-llamacpp-llm/README.md index 29cb26f1f1..cdab3498cc 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/README.md +++ b/packages/qvac-lib-infer-llamacpp-llm/README.md @@ -158,6 +158,7 @@ const config = { | presence_penalty | float | 0 | Presence penalty for sampling | | frequency_penalty | float | 0 | Frequency penalty for sampling | | tools | `"true"` or `"false"` | `"false"` | Enable tool calling with jinja templating | +| tools_at_end | `"true"` or `"false"` | `"false"` | Place tools at end of prompt ([details](./docs/tools-at-end.md)) | | verbosity | 0 – 3 (0=ERROR, 1=WARNING, 2=INFO, 3=DEBUG) | 0 | Logging verbosity level | | n_discarded | integer | 0 | Tokens to discard in sliding window context | | main-gpu | integer, `"integrated"`, or `"dedicated"` | — | GPU selection for multi-GPU systems | diff --git a/packages/qvac-lib-infer-llamacpp-llm/docs/tools-at-end.md b/packages/qvac-lib-infer-llamacpp-llm/docs/tools-at-end.md new file mode 100644 index 0000000000..9f98e6ca9e --- /dev/null +++ b/packages/qvac-lib-infer-llamacpp-llm/docs/tools-at-end.md @@ -0,0 +1,51 @@ +# Tools at End of Prompt + +## Overview + +The `tools_at_end` configuration option places tool definitions at the end of the prompt (after the conversation history) instead of the default position (typically inside the system prompt). This enables KV cache optimization for multi-turn conversations with dynamic tool sets. + +## Configuration + +```js +const config = { + tools: 'true', + tools_at_end: 'true' +} +``` + +## Usage Requirements + +### Multi-turn Conversation Pattern + +When using `tools_at_end`, consumers must follow a specific pattern: + +1. **Include prior response**: Pass the assistant's previous response (including any `` or `` blocks) back alongside the new user message. + +2. **Full history each turn**: Since the KV cache is trimmed after each turn, the full conversation history must be re-provided. + +``` +Turn 1: [user-q-1] + [tools-1] → [response-1] +Turn 2: [response-1] + [user-q-2] + [tools-2] → [response-2] + (tools-1 is automatically trimmed from cache) +``` + +3. **Strip stale tool blocks**: Remove `` blocks from prior responses when tools have changed to prevent model from pattern-matching on removed tools. + +## Performance Characteristics + +| Overhead Type | Impact | Note | +|---------------|--------|------| +| Double tokenization | ~2% | Required to calculate tool token boundary | +| Tools prefill | Up to 100% | Tools re-evaluated every turn regardless of change | + +## When to Use + +**Use `tools_at_end` when:** +- Long conversations with many turns (cache hit on history saves significant compute) +- Frequent tool replacement between turns (e.g., tools A → tools B → tools A) + +**Use standard `tools` config when:** +- Short conversations or single-turn tool calls +- Tools remain the same across many turns + +The feature provides net benefit when conversation history cache savings outweigh the tools prefill overhead. \ No newline at end of file From c52e076c296ffd33332cfda81249ab03724ca782 Mon Sep 17 00:00:00 2001 From: Mikhail Sotnikov Date: Mon, 16 Mar 2026 18:35:07 +0300 Subject: [PATCH 31/48] (chore) llamacpp-llm: changelog and version bump --- packages/qvac-lib-infer-llamacpp-llm/CHANGELOG.md | 13 +++++++++++++ packages/qvac-lib-infer-llamacpp-llm/package.json | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/CHANGELOG.md b/packages/qvac-lib-infer-llamacpp-llm/CHANGELOG.md index 1f28214b36..fdb5b370e3 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/CHANGELOG.md +++ b/packages/qvac-lib-infer-llamacpp-llm/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [0.12.3] - 2026-03-16 + +### Dynamic tool management feature + +#### `tools_at_end` configuration for dynamic tool management in multi-turn conversations + +New `tools_at_end` configuration option (`"true"` or `"false"`, default: `"false"`) places tool definitions at the end of the prompt (after conversation history) instead of in the system prompt. This enables KV cache optimization for multi-turn conversations with dynamic tool sets, where tools change between turns. Currently supports Qwen3 models only. + +- **KV cache trimming**: After each turn, tools are automatically removed from the KV cache, preventing stale tool definitions from accumulating +- **Conversation history reuse**: History tokens are preserved in cache, saving recomputation on long conversations +- **Dynamic tool replacement**: Different tool sets can be used per turn without cache bloat from unused tools + + ## [0.12.2] - 2026-03-13 This release fixes antiprompt (reverse-prompt) detection for short stop sequences like `\n`, which is critical for translation workloads that rely on newline-based early stopping. diff --git a/packages/qvac-lib-infer-llamacpp-llm/package.json b/packages/qvac-lib-infer-llamacpp-llm/package.json index 7cad5d0327..d5178ef04b 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/package.json +++ b/packages/qvac-lib-infer-llamacpp-llm/package.json @@ -1,6 +1,6 @@ { "name": "@qvac/llm-llamacpp", - "version": "0.12.2", + "version": "0.12.3", "description": "llama addon for qvac", "addon": true, "scripts": { From cc18a150fca3e5dde387bfee9680a329dcb09a3e Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Tue, 17 Mar 2026 15:16:27 +0300 Subject: [PATCH 32/48] refactor(llamacpp-llm): address PR #706 review comments Implement all 10 reviewer requests from PR #706 (jesusmb1995, gianni-cor). | # | Reviewer | Request | Result | |---|---------|---------|--------| | R1 | @jesusmb1995 | Extract DynamicToolsState class | Done - new class in LlmContext.hpp with toolsAtEnd_, nConversationOnlyTokens_, nPastBeforeTools_, recordToolBoundary(), reset() | | R2 | @jesusmb1995 | Collapse 3 virtual methods into single dynamicToolsState() accessor | Done - removed setToolsAtEnd, getNPastBeforeTools, setNPastBeforeTools virtuals; added dynamicToolsState() non-virtual accessor on base class | | R3 | @gianni-cor | Remove redundant setToolsAtEnd() after createContext() | Done - removed the 4-line block in LlamaModel::init() | | R4 | @gianni-cor | Add assert: nConversationOnlyTokens_ <= inputTokens.size() | Done - added in TextLlmContext::tokenizeChat | | R5 | @gianni-cor | Reset nConversationOnlyTokens_ in TextLlmContext::resetState | Done - both contexts now call dynamicToolsState().reset() which resets both values | | R6 | @gianni-cor | Guard tools_at_end for non-Qwen3 models | Done - architecture check after config parsing, logs warning and disables flag | | R7 | @gianni-cor | Fix off-by-A trim error (disable add_generation_prompt) | Done - both TextLlmContext and MtmdLlmContext save/restore add_generation_prompt=false during no-tools tokenization | | R8 | @gianni-cor | Add cold-start reset in MtmdLlmContext::tokenizeChat | Done - dynamicToolsState().reset() added at cold-start path | | R9 | @gianni-cor | Cap firstMsgTokens_ after post-eval trim | Done - setFirstMsgTokens(getNPast()) if inflated after trim | | R10 | @gianni-cor | Remove duplicate toolsAtEnd_ from LlamaModel | Done - runtime code in processPromptImpl queries dynamicToolsState().toolsAtEnd() instead of state_->toolsAtEnd_ | Made-with: Cursor --- .../addon/src/model-interface/LlamaModel.cpp | 32 +++++++++----- .../addon/src/model-interface/LlmContext.hpp | 42 +++++++++++++------ .../src/model-interface/MtmdLlmContext.cpp | 36 ++++++---------- .../src/model-interface/MtmdLlmContext.hpp | 11 ----- .../src/model-interface/TextLlmContext.cpp | 39 +++++++---------- .../src/model-interface/TextLlmContext.hpp | 12 ------ 6 files changed, 78 insertions(+), 94 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp index 5c99bce02d..70c44dec10 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp @@ -237,11 +237,6 @@ void LlamaModel::init(bool acquireLock) { std::move(llamaInit), snap->toolsAtEnd_); - // Apply tools_at_end flag - if (snap->llmContext_) { - snap->llmContext_->setToolsAtEnd(snap->toolsAtEnd_); - } - if (snap->configuredNDiscarded_ > 0 && snap->llmContext_) { snap->llmContext_->setNDiscarded(snap->configuredNDiscarded_); } @@ -269,7 +264,7 @@ bool LlamaModel::isLoaded() { llama_pos LlamaModel::getNPastBeforeTools() const { std::shared_lock lock(stateMtx_); if (state_->llmContext_) { - return state_->llmContext_->getNPastBeforeTools(); + return state_->llmContext_->dynamicToolsState().nPastBeforeTools(); } return -1; } @@ -421,12 +416,16 @@ std::string LlamaModel::processPromptImpl(const Prompt& prompt) { if (!prompt.outputCallback) { out = oss.str(); } - if (state_->toolsAtEnd_ && !resolved.tools.empty() && - state_->llmContext_->getNPastBeforeTools() > 0 && - state_->llmContext_->getNPast() > state_->llmContext_->getNPastBeforeTools()) { + auto& dts = state_->llmContext_->dynamicToolsState(); + if (dts.toolsAtEnd() && !resolved.tools.empty() && + dts.nPastBeforeTools() > 0 && + state_->llmContext_->getNPast() > dts.nPastBeforeTools()) { state_->llmContext_->removeLastNTokens( - state_->llmContext_->getNPast() - state_->llmContext_->getNPastBeforeTools()); - state_->llmContext_->setNPastBeforeTools(-1); + state_->llmContext_->getNPast() - dts.nPastBeforeTools()); + dts.setNPastBeforeTools(-1); + if (state_->llmContext_->getFirstMsgTokens() > state_->llmContext_->getNPast()) { + state_->llmContext_->setFirstMsgTokens(state_->llmContext_->getNPast()); + } } if (resolved.shouldResetAfterInference) { resetState(false); @@ -515,6 +514,17 @@ void LlamaModel::commonParamsParse( configFilemap.erase(iter); } + if (state_->toolsAtEnd_) { + auto arch = metadata_.tryGetString("general.architecture"); + if (!arch.has_value() || arch.value() != "qwen3") { + QLOG_IF( + Priority::WARNING, + "[LlamaModel] tools_at_end is only supported for Qwen3 models, " + "ignoring\n"); + state_->toolsAtEnd_ = false; + } + } + auto deviceIt = configFilemap.find("device"); if (deviceIt == configFilemap.end()) { std::string errorMsg = diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp index 2057ead5cc..de4f09ec68 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp @@ -110,6 +110,30 @@ struct ThreadPoolDeleter{ }; using ThreadPoolPtr = std::unique_ptr; +class DynamicToolsState { +public: + void setToolsAtEnd(bool v) { toolsAtEnd_ = v; } + [[nodiscard]] bool toolsAtEnd() const { return toolsAtEnd_; } + [[nodiscard]] llama_pos nPastBeforeTools() const { return nPastBeforeTools_; } + void setNPastBeforeTools(llama_pos pos) { nPastBeforeTools_ = pos; } + void recordToolBoundary(llama_pos nPast, llama_pos totalTokens) { + if (toolsAtEnd_ && nConversationOnlyTokens_ > 0) { + nPastBeforeTools_ = nPast - (totalTokens - nConversationOnlyTokens_); + } + } + void setConversationOnlyTokens(llama_pos n) { nConversationOnlyTokens_ = n; } + [[nodiscard]] llama_pos conversationOnlyTokens() const { return nConversationOnlyTokens_; } + void reset() { + nConversationOnlyTokens_ = 0; + nPastBeforeTools_ = -1; + } + +private: + bool toolsAtEnd_ = false; + llama_pos nConversationOnlyTokens_ = 0; + llama_pos nPastBeforeTools_ = -1; +}; + class LlmContext { // NOLINT(cppcoreguidelines-special-member-functions) public: LlmContext() = default; @@ -200,20 +224,9 @@ class LlmContext { // NOLINT(cppcoreguidelines-special-member-functions) */ virtual void setNDiscarded(llama_pos nDiscarded) = 0; - /** - * Set whether tools should be placed at the end of the prompt. - */ - virtual void setToolsAtEnd(bool toolsAtEnd) = 0; - - /** - * Get the nPast position before tool evaluation. - * This is used to find the boundary in the KV cache after evaluating - * conversation tokens but before tool tokens. - * @return the nPast position, or -1 if not set. - */ - [[nodiscard]] virtual llama_pos getNPastBeforeTools() const { return -1; } + DynamicToolsState& dynamicToolsState() { return dynamicToolsState_; } + [[nodiscard]] const DynamicToolsState& dynamicToolsState() const { return dynamicToolsState_; } - virtual void setNPastBeforeTools(llama_pos nPastBeforeTools) {} /** * The load media method. It loads the media from memory buffer. * Default implementation does nothing (for text-only contexts). @@ -269,6 +282,9 @@ class LlmContext { // NOLINT(cppcoreguidelines-special-member-functions) * */ virtual void resetMedia() {}; + +private: + DynamicToolsState dynamicToolsState_; }; diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp index d2b3168cbd..7a64ec8d18 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp @@ -22,7 +22,8 @@ using namespace qvac_lib_inference_addon_llama::utils; MtmdLlmContext::MtmdLlmContext( common_params& commonParams, common_init_result&& llamaInit, bool toolsAtEnd) : llamaInit_(std::move(llamaInit)), params_(commonParams), - model_(llamaInit_.model.get()), lctx_(llamaInit_.context.get()), toolsAtEnd_(toolsAtEnd) { + model_(llamaInit_.model.get()), lctx_(llamaInit_.context.get()) { + dynamicToolsState().setToolsAtEnd(toolsAtEnd); if (model_ == nullptr) { throw qvac_errors::StatusError( @@ -40,7 +41,7 @@ MtmdLlmContext::MtmdLlmContext( vocab_ = llama_model_get_vocab(model_); - std::string chatTemplate = getChatTemplate(model_, params_, toolsAtEnd_); + std::string chatTemplate = getChatTemplate(model_, params_, dynamicToolsState().toolsAtEnd()); tmpls_ = common_chat_templates_init(model_, chatTemplate); smpl_.reset(common_sampler_init(model_, params_.sampling)); @@ -153,6 +154,7 @@ void MtmdLlmContext::tokenizeChat( bool addSpecial = false; if (nPast_ == 0 && !isCacheLoaded) { + dynamicToolsState().reset(); isLastMessageFromUser = true; addSpecial = true; } else if (nPast_ > 0) { @@ -199,11 +201,14 @@ void MtmdLlmContext::tokenizeChat( throw qvac_errors::StatusError(ADDON_ID, toString(EncoderFailed), errorMsg); } - if (toolsAtEnd_ && !tools.empty()) { + if (dynamicToolsState().toolsAtEnd() && !tools.empty()) { auto savedTools = inputs.tools; + auto savedGenPrompt = inputs.add_generation_prompt; inputs.tools = {}; + inputs.add_generation_prompt = false; auto promptNoTools = getPrompt(tmpls_.get(), inputs); inputs.tools = savedTools; + inputs.add_generation_prompt = savedGenPrompt; if (!promptNoTools.empty()) { mtmd_input_text textNoTools; @@ -220,11 +225,12 @@ void MtmdLlmContext::tokenizeChat( bitmapsCPtr.size()); if (resNoTools == 0) { - nConversationOnlyTokens_ = mtmd_helper_get_n_tokens(chunksNoTools.ptr.get()); + dynamicToolsState().setConversationOnlyTokens( + mtmd_helper_get_n_tokens(chunksNoTools.ptr.get())); } } } else { - nConversationOnlyTokens_ = 0; + dynamicToolsState().setConversationOnlyTokens(0); } resetMedia(); @@ -341,9 +347,7 @@ bool MtmdLlmContext::evalMessageWithTools( nDiscarded_ = ctxSize - firstMsgTokens_ - 1; } } - if (toolsAtEnd_ && !tools.empty()) { - nPastBeforeTools_ = nPast_ - (static_cast(nTokens) - nConversationOnlyTokens_); - } + dynamicToolsState().recordToolBoundary(nPast_, static_cast(nTokens)); return true; } @@ -507,18 +511,6 @@ void MtmdLlmContext::setNDiscarded(llama_pos nDiscarded) { this->nDiscarded_ = nDiscarded; } -void MtmdLlmContext::setToolsAtEnd(bool toolsAtEnd) { - this->toolsAtEnd_ = toolsAtEnd; -} - -llama_pos MtmdLlmContext::getNPastBeforeTools() const { - return nPastBeforeTools_; -} - -void MtmdLlmContext::setNPastBeforeTools(llama_pos nPastBeforeTools) { - nPastBeforeTools_ = nPastBeforeTools; -} - void MtmdLlmContext::loadMedia(const std::vector& media) { if (media.empty()) { resetMedia(); @@ -587,9 +579,7 @@ void MtmdLlmContext::loadMedia(const std::string& fname) { void MtmdLlmContext::resetState(bool resetStats) { - // Reset conversation-only tokens and nPastBeforeTools - nConversationOnlyTokens_ = 0; - nPastBeforeTools_ = -1; + dynamicToolsState().reset(); // Reset the n_past nPast_ = 0; diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp index 51113557fa..3b6b10639d 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp @@ -115,11 +115,6 @@ class MtmdLlmContext: public LlmContext { */ void setNDiscarded(llama_pos nDiscarded) override; - void setToolsAtEnd(bool toolsAtEnd) override; - - [[nodiscard]] llama_pos getNPastBeforeTools() const override; - void setNPastBeforeTools(llama_pos nPastBeforeTools) override; - /** * The load media method. It loads the media from memory buffer. * @@ -207,12 +202,6 @@ class MtmdLlmContext: public LlmContext { // UTF-8 token buffer for handling incomplete emoji sequences qvac_lib_inference_addon_llama::UTF8TokenBuffer utf8Buffer_; std::atomic stopGeneration_ = false; - - bool toolsAtEnd_ = false; - - llama_pos nConversationOnlyTokens_ = 0; - - llama_pos nPastBeforeTools_ = -1; }; diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp index f7ad2aeaba..a7e4efdb43 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp @@ -1,6 +1,7 @@ #include "TextLlmContext.hpp" #include +#include #include #include @@ -24,7 +25,8 @@ using namespace qvac_lib_inference_addon_llama::utils; // NOLINTNEXTLINE(readability-function-cognitive-complexity) TextLlmContext::TextLlmContext( common_params& commonParams, common_init_result&& llamaInit, bool toolsAtEnd) - : llamaInit_(std::move(llamaInit)), params_(commonParams), toolsAtEnd_(toolsAtEnd) { + : llamaInit_(std::move(llamaInit)), params_(commonParams) { + dynamicToolsState().setToolsAtEnd(toolsAtEnd); { model_ = llamaInit_.model.get(); @@ -49,7 +51,7 @@ TextLlmContext::TextLlmContext( lctx_, reasoningState_); } - std::string chatTemplate = getChatTemplate(model_, params_, toolsAtEnd_); + std::string chatTemplate = getChatTemplate(model_, params_, dynamicToolsState().toolsAtEnd()); tmpls_ = common_chat_templates_init(model_, chatTemplate); smpl_.reset(common_sampler_init(model_, params_.sampling)); @@ -189,8 +191,7 @@ void TextLlmContext::tokenizeChat( bool addSpecial = false; if (nPast_ == 0 && !isCacheLoaded) { - nConversationOnlyTokens_ = 0; - nPastBeforeTools_ = -1; + dynamicToolsState().reset(); } if (nPast_ == 0 && !isCacheLoaded) { @@ -218,16 +219,21 @@ void TextLlmContext::tokenizeChat( if (!prompt.empty()) { inputTokens = common_tokenize(lctx_, prompt, addSpecial, true); - if (toolsAtEnd_ && !tools.empty()) { + if (dynamicToolsState().toolsAtEnd() && !tools.empty()) { auto savedTools = inputs.tools; + auto savedGenPrompt = inputs.add_generation_prompt; inputs.tools = {}; + inputs.add_generation_prompt = false; auto promptNoTools = getPrompt(tmpls_.get(), inputs); auto tokensNoTools = common_tokenize(lctx_, promptNoTools, addSpecial, true); inputs.tools = savedTools; - nConversationOnlyTokens_ = tokensNoTools.size(); + inputs.add_generation_prompt = savedGenPrompt; + dynamicToolsState().setConversationOnlyTokens(tokensNoTools.size()); + assert(dynamicToolsState().conversationOnlyTokens() <= static_cast(inputTokens.size()) && + "conversation-only tokens exceeds total tokens"); } else { - nConversationOnlyTokens_ = 0; + dynamicToolsState().setConversationOnlyTokens(0); } } else { std::string errorMsg = string_format( @@ -377,9 +383,7 @@ bool TextLlmContext::evalMessageWithTools( nDiscarded_ = ctxSize - firstMsgTokens_ - 1; } } - if (toolsAtEnd_ && !tools.empty()) { - nPastBeforeTools_ = nPast_ - (static_cast(inputTokens.size()) - nConversationOnlyTokens_); - } + dynamicToolsState().recordToolBoundary(nPast_, static_cast(inputTokens.size())); return true; } @@ -546,8 +550,7 @@ void TextLlmContext::stop() { stopGeneration_.store(true); } void TextLlmContext::resetState(bool resetStats) { // Reset the n_past - // Reset conversation-only tokens and nPastBeforeTools - nPastBeforeTools_ = -1; + dynamicToolsState().reset(); nPast_ = 0; // Reset the first msg token length @@ -587,18 +590,6 @@ void TextLlmContext::setNDiscarded(llama_pos nDiscarded) { this->nDiscarded_ = nDiscarded; } -void TextLlmContext::setToolsAtEnd(bool toolsAtEnd) { - this->toolsAtEnd_ = toolsAtEnd; -} - -void TextLlmContext::setNPastBeforeTools(llama_pos nPastBeforeTools) { - nPastBeforeTools_ = nPastBeforeTools; -} - -llama_pos TextLlmContext::getNPastBeforeTools() const { - return nPastBeforeTools_; -} - llama_pos TextLlmContext::removeLastNTokens(llama_pos count) { // Validate input if (count <= 0) { diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp index 4dc7a7b167..9cb6e93247 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp @@ -108,11 +108,6 @@ class TextLlmContext: public LlmContext { */ void setNDiscarded(llama_pos nDiscarded) override; - void setToolsAtEnd(bool toolsAtEnd) override; - - [[nodiscard]] llama_pos getNPastBeforeTools() const override; - void setNPastBeforeTools(llama_pos nPastBeforeTools) override; - /** * The reset state method. It resets the context. * @@ -186,13 +181,6 @@ class TextLlmContext: public LlmContext { bool isQwen3Model_ = false; std::atomic stopGeneration_ = false; - - bool toolsAtEnd_ = false; - - - llama_pos nConversationOnlyTokens_ = 0; - - llama_pos nPastBeforeTools_ = -1; }; From 44da74e266b06c84bf65d6066e8ff97329ac065c Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Tue, 17 Mar 2026 15:36:29 +0300 Subject: [PATCH 33/48] refactor(llamacpp-llm): remove toolsAtEnd_ from ReloadableState, single source of truth in DynamicToolsState Made-with: Cursor --- .../addon/src/model-interface/LlamaModel.cpp | 14 ++++++++------ .../addon/src/model-interface/LlamaModel.hpp | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp index 70c44dec10..de9efc5587 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp @@ -208,7 +208,8 @@ void LlamaModel::init(bool acquireLock) { common_params params; std::optional adrenoVersion; - commonParamsParse(modelPath, configFilemap, params, adrenoVersion); + bool toolsAtEnd = false; + commonParamsParse(modelPath, configFilemap, params, adrenoVersion, toolsAtEnd); const std::string errorWhenFailed = toString(UnableToLoadModel); auto streamedFiles = @@ -235,7 +236,7 @@ void LlamaModel::init(bool acquireLock) { std::string(constructionArgs_.projectionPath), params, std::move(llamaInit), - snap->toolsAtEnd_); + toolsAtEnd); if (snap->configuredNDiscarded_ > 0 && snap->llmContext_) { snap->llmContext_->setNDiscarded(snap->configuredNDiscarded_); @@ -462,7 +463,8 @@ qvac_lib_inference_addon_cpp::RuntimeStats LlamaModel::runtimeStats() const { void LlamaModel::commonParamsParse( const std::string& modelPath, std::unordered_map& configFilemap, - common_params& params, std::optional& outAdrenoVersion) { + common_params& params, std::optional& outAdrenoVersion, + bool& outToolsAtEnd) { std::vector configVector; @@ -510,18 +512,18 @@ void LlamaModel::commonParamsParse( iter != configFilemap.end()) { std::string val = iter->second; std::transform(val.begin(), val.end(), val.begin(), ::tolower); - state_->toolsAtEnd_ = (val == "true"); + outToolsAtEnd = (val == "true"); configFilemap.erase(iter); } - if (state_->toolsAtEnd_) { + if (outToolsAtEnd) { auto arch = metadata_.tryGetString("general.architecture"); if (!arch.has_value() || arch.value() != "qwen3") { QLOG_IF( Priority::WARNING, "[LlamaModel] tools_at_end is only supported for Qwen3 models, " "ignoring\n"); - state_->toolsAtEnd_ = false; + outToolsAtEnd = false; } } diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp index 3c9c337c1e..00e3a207d6 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp @@ -190,7 +190,6 @@ class LlamaModel : public IModel, public IModelAsyncLoad, public IModelCancel { // configuration values parsed from configFilemap llama_pos configuredNDiscarded_ = 0; - bool toolsAtEnd_ = false; std::optional cacheManager_; bool lastRunWasPrefill_ = false; }; @@ -213,7 +212,8 @@ class LlamaModel : public IModel, public IModelAsyncLoad, public IModelCancel { void commonParamsParse( const std::string& modelPath, std::unordered_map& configFilemap, - common_params& params, std::optional& outAdrenoVersion); + common_params& params, std::optional& outAdrenoVersion, + bool& outToolsAtEnd); /** * The Format prompt method. It formats the prompt json to chat messages. From 4161c774e8c471d7c626cdfd282454cb365951f8 Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Tue, 17 Mar 2026 16:18:18 +0300 Subject: [PATCH 34/48] fix(llamacpp-llm): use dts.reset() after post-eval trim for full state cleanup Made-with: Cursor --- .../addon/src/model-interface/LlamaModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp index de9efc5587..98d80d98c2 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp @@ -423,7 +423,7 @@ std::string LlamaModel::processPromptImpl(const Prompt& prompt) { state_->llmContext_->getNPast() > dts.nPastBeforeTools()) { state_->llmContext_->removeLastNTokens( state_->llmContext_->getNPast() - dts.nPastBeforeTools()); - dts.setNPastBeforeTools(-1); + dts.reset(); if (state_->llmContext_->getFirstMsgTokens() > state_->llmContext_->getNPast()) { state_->llmContext_->setFirstMsgTokens(state_->llmContext_->getNPast()); } From 27e6a5c50d6c9db368c917f5f9a4dd5d732a43a1 Mon Sep 17 00:00:00 2001 From: Mikhail Sotnikov Date: Wed, 18 Mar 2026 07:33:54 +0300 Subject: [PATCH 35/48] (draft) llamacpp-llm: dynamic tools cache tokens test debug --- .../addon/src/model-interface/LlamaModel.hpp | 13 ++ .../addon/src/model-interface/LlmContext.hpp | 7 + .../src/model-interface/MtmdLlmContext.hpp | 7 + .../src/model-interface/TextLlmContext.cpp | 3 + .../src/model-interface/TextLlmContext.hpp | 7 + .../test/unit/test_cache_management_qwen3.cpp | 184 +++++++++++++++++- 6 files changed, 219 insertions(+), 2 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp index 00e3a207d6..558debc776 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp @@ -154,6 +154,19 @@ class LlamaModel : public IModel, public IModelAsyncLoad, public IModelCancel { */ qvac_lib_inference_addon_cpp::RuntimeStats runtimeStats() const final; + /** + * Get the underlying llama_model pointer. + * + * @return pointer to llama_model, or nullptr if not loaded + */ + const struct llama_model* getLlamaModel() const { + std::shared_lock lock(stateMtx_); + if (state_ && state_->llmContext_) { + return state_->llmContext_->getModel(); + } + return nullptr; + } + /** * Static callback function for llama.cpp logging */ diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp index de4f09ec68..e94ebde9c8 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp @@ -195,6 +195,13 @@ class LlmContext { // NOLINT(cppcoreguidelines-special-member-functions) */ virtual llama_context* getCtx() = 0; + /** + * The get model method. It returns the underlying llama model. + * + * @return - the model. + */ + virtual const struct llama_model* getModel() const = 0; + /** * The get nPast method. It returns the nPast. * diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp index 3b6b10639d..e1d5ca6fc7 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp @@ -80,6 +80,13 @@ class MtmdLlmContext: public LlmContext { */ llama_context* getCtx() override; + /** + * The get model method. It returns the underlying llama model. + * + * @return - the model. + */ + const struct llama_model* getModel() const override { return model_; } + /** * The get n_past method. It returns the n_past. * diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp index a7e4efdb43..13a205e6a2 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp @@ -211,6 +211,9 @@ void TextLlmContext::tokenizeChat( inputs.tools = tools; } prompt = getPrompt(tmpls_.get(), inputs); + std::cout << "=== DEBUG-REAL: Actual model prompt (after session removal) ===" << std::endl; + std::cout << prompt << std::endl; + std::cout << "=== END DEBUG-REAL ===\n" << std::endl; QLOG_IF( Priority::DEBUG, diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp index 9cb6e93247..7de43f791a 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp @@ -74,6 +74,13 @@ class TextLlmContext: public LlmContext { */ llama_context* getCtx() override; + /** + * The get model method. It returns the underlying llama model. + * + * @return - the model. + */ + const struct llama_model* getModel() const override { return model_; } + /** * The get n_past method. It returns the n_past. * diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp index 4117497ac2..423601ccf5 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp @@ -8,7 +8,11 @@ #include #include +#include #include +#include +#include "utils/Qwen3ToolsDynamicTemplate.hpp" +#include "utils/ChatTemplateUtils.hpp" #include "model-interface/LlamaModel.hpp" #include "test_common.hpp" @@ -51,6 +55,34 @@ bool isQwen3ModelPath(const std::string& path) { [](unsigned char c) { return std::tolower(c); }); return lowerPath.find("qwen3") != std::string::npos; } + +std::vector parseChatMessages(const std::string& input) { + picojson::value chatJson; + std::string err = picojson::parse(chatJson, input); + if (!err.empty()) { + throw std::runtime_error("Failed to parse JSON: " + err); + } + if (!chatJson.is()) { + throw std::runtime_error("Expected JSON array"); + } + std::vector messages; + auto& obj = chatJson.get(); + for (const auto& subObj : obj) { + if (subObj.is()) { + picojson::object jsonObj = subObj.get(); + // Skip function type (tools) + auto it = jsonObj.find("type"); + if (it != jsonObj.end() && it->second.get() == "function") { + continue; + } + common_chat_msg msg; + msg.role = jsonObj["role"].get(); + msg.content = jsonObj["content"].get(); + messages.push_back(msg); + } + } + return messages; +} } // namespace class CacheManagementQwen3Test : public ::testing::Test { @@ -230,9 +262,67 @@ TEST_F(CacheManagementQwen3Test, CacheWithoutToolsWithToolsAtEndTrue) { EXPECT_GE(output.length(), 0); }); + // Compute expected token count for the no-tools prompt + std::string chatTemplate = qvac_lib_inference_addon_llama::utils::getToolsDynamicQwen3Template(); + common_chat_templates_ptr tmpls_ = common_chat_templates_init(model->getLlamaModel(), chatTemplate); + + // Parse input into chat messages + auto messages = parseChatMessages(inputNoTools); + std::cout << "\n=== DEBUG: Parsed messages (before session removal) ===" << std::endl; + std::cout << "Number of messages: " << messages.size() << std::endl; + for (size_t i = 0; i < messages.size(); i++) { + std::cout << " [" << i << "] role='" << messages[i].role << "' content='" << messages[i].content << "'" << std::endl; + } + std::cout << "=== END DEBUG ===\n" << std::endl; + + // Build inputs for template + common_chat_templates_inputs inputs; + inputs.use_jinja = true; // tools=true sets use_jinja=true in commonParamsParse + inputs.add_generation_prompt = true; // first message, nPast==0 => add generation prompt + inputs.messages = messages; + + auto promptNoTools = qvac_lib_inference_addon_llama::utils::getPrompt(tmpls_.get(), inputs); + + std::cout << "\n=== DEBUG: Test expected prompt ===" << std::endl; + std::cout << promptNoTools << std::endl; + std::cout << "=== END DEBUG ===\n" << std::endl; + + // For first prefill, addSpecial = true + auto tokensNoTools = common_tokenize(llama_model_get_vocab(model->getLlamaModel()), promptNoTools, true, true); + + std::cout << "=== DEBUG: tokensNoTools.size() = " << tokensNoTools.size() << " ===" << std::endl; + + // Also get the actual prompt from the model by parsing messages like the model does + auto modelMessages = parseChatMessages(inputNoTools); + // Simulate what CacheManager does: remove session messages + auto it = modelMessages.begin(); + while (it != modelMessages.end()) { + if (it->role == "session") { + it = modelMessages.erase(it); + } else { + ++it; + } + } + + common_chat_templates_inputs modelInputs; + modelInputs.use_jinja = true; + modelInputs.add_generation_prompt = true; + modelInputs.messages = modelMessages; + + auto actualPrompt = qvac_lib_inference_addon_llama::utils::getPrompt(tmpls_.get(), modelInputs); + std::cout << "=== DEBUG: Actual model prompt (after session removal) ===" << std::endl; + std::cout << actualPrompt << std::endl; + std::cout << "=== END DEBUG ===\n" << std::endl; + + auto actualTokens = common_tokenize(llama_model_get_vocab(model->getLlamaModel()), actualPrompt, true, true); + std::cout << "=== DEBUG: actualTokens.size() = " << actualTokens.size() << " ===" << std::endl; + auto statsBeforeSave = model->runtimeStats(); double cacheTokensBeforeSave = getStatValue(statsBeforeSave, "CacheTokens"); - EXPECT_GT(cacheTokensBeforeSave, 0.0); + std::cout << "=== DEBUG: cacheTokensBeforeSave = " << cacheTokensBeforeSave << " ===" << std::endl; + + // The test should compare with the model's actual behavior (after session removal) + EXPECT_EQ(cacheTokensBeforeSave, static_cast(actualTokens.size())); llama_pos nPastBeforeTools = model->getNPastBeforeTools(); EXPECT_EQ(nPastBeforeTools, -1); @@ -270,10 +360,71 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeWithMultiplePrompts) { EXPECT_GE(output.length(), 0); }); + // START + + // Compute expected token count for the no-tools prompt + std::string chatTemplate = qvac_lib_inference_addon_llama::utils::getToolsDynamicQwen3Template(); + common_chat_templates_ptr tmpls_ = common_chat_templates_init(model->getLlamaModel(), chatTemplate); + + // Parse input into chat messages + auto messages = parseChatMessages(input1); + std::cout << "\n=== DEBUG: Parsed messages (before session removal) ===" << std::endl; + std::cout << "Number of messages: " << messages.size() << std::endl; + for (size_t i = 0; i < messages.size(); i++) { + std::cout << " [" << i << "] role='" << messages[i].role << "' content='" << messages[i].content << "'" << std::endl; + } + std::cout << "=== END DEBUG ===\n" << std::endl; + + // Build inputs for template + common_chat_templates_inputs inputs; + inputs.use_jinja = true; // tools=true sets use_jinja=true in commonParamsParse + inputs.add_generation_prompt = false; // first message, nPast==0 => add generation prompt + inputs.messages = messages; + + auto promptWithTools = qvac_lib_inference_addon_llama::utils::getPrompt(tmpls_.get(), inputs); + + std::cout << "\n=== DEBUG: Test expected prompt ===" << std::endl; + std::cout << promptWithTools << std::endl; + std::cout << "=== END DEBUG ===\n" << std::endl; + + // For first prefill, addSpecial = true + auto tokensNoTools = common_tokenize(llama_model_get_vocab(model->getLlamaModel()), promptWithTools, true, true); + + std::cout << "=== DEBUG: tokensNoTools.size() = " << tokensNoTools.size() << " ===" << std::endl; + + // Also get the actual prompt from the model by parsing messages like the model does + auto modelMessages = parseChatMessages(input1); + // Simulate what CacheManager does: remove session messages + auto it = modelMessages.begin(); + while (it != modelMessages.end()) { + if (it->role == "session") { + it = modelMessages.erase(it); + } else { + ++it; + } + } + + common_chat_templates_inputs modelInputs; + modelInputs.use_jinja = true; + modelInputs.add_generation_prompt = false; + modelInputs.messages = modelMessages; + + auto actualPrompt = qvac_lib_inference_addon_llama::utils::getPrompt(tmpls_.get(), modelInputs); + std::cout << "=== DEBUG: Actual model prompt (after session removal) ===" << std::endl; + std::cout << actualPrompt << std::endl; + std::cout << "=== END DEBUG ===\n" << std::endl; + + auto actualTokens = common_tokenize(llama_model_get_vocab(model->getLlamaModel()), actualPrompt, true, true); + std::cout << "=== DEBUG: actualTokens.size() = " << actualTokens.size() << " ===" << std::endl; + auto stats1 = model->runtimeStats(); double cacheTokens1 = getStatValue(stats1, "CacheTokens"); + std::cout << "=== DEBUG: cacheTokens1 = " << cacheTokens1 << " ===" << std::endl; double promptTokens1 = getStatValue(stats1, "promptTokens"); - EXPECT_GT(cacheTokens1, 0.0); + // The test should compare with the model's actual behavior (after session removal) + EXPECT_EQ(cacheTokens1, static_cast(tokensNoTools.size())); + EXPECT_EQ(cacheTokens1, static_cast(actualTokens.size())); + // EXPECT_GT(cacheTokens1, 0.0); EXPECT_GT(promptTokens1, 500.0); const int maxExpectedCacheTokens = 50; @@ -285,6 +436,34 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeWithMultiplePrompts) { std::string input2 = R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "user", "content": "What about London?"}])"; + // START + std::string inputFull2 = + R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "user", "content": "Hi"}, {"role": "user", "content": "What about London?"}])"; + // Parse input into chat messages + auto messages2 = parseChatMessages(inputFull2); + std::cout << "\n=== DEBUG: Parsed messages (before session removal) ===" << std::endl; + std::cout << "Number of messages: " << messages2.size() << std::endl; + for (size_t i = 0; i < messages2.size(); i++) { + std::cout << " [" << i << "] role='" << messages2[i].role << "' content='" << messages2[i].content << "'" << std::endl; + } + std::cout << "=== END DEBUG ===\n" << std::endl; + + // Build inputs for template + common_chat_templates_inputs inputs2; + inputs2.use_jinja = true; // tools=true sets use_jinja=true in commonParamsParse + inputs2.add_generation_prompt = true; // first message, nPast==0 => add generation prompt + inputs2.messages = messages2; + + auto promptWithoutTools = qvac_lib_inference_addon_llama::utils::getPrompt(tmpls_.get(), inputs2); + + std::cout << "\n=== DEBUG: Test expected prompt ===" << std::endl; + std::cout << promptWithoutTools << std::endl; + std::cout << "=== END DEBUG ===\n" << std::endl; + + // For first prefill, addSpecial = true + auto tokensFinal = common_tokenize(llama_model_get_vocab(model->getLlamaModel()), promptWithoutTools, false, true); + // END + EXPECT_NO_THROW({ std::string output = processPromptString(model, input2); EXPECT_GE(output.length(), 0); @@ -293,6 +472,7 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeWithMultiplePrompts) { auto stats2 = model->runtimeStats(); double cacheTokens2 = getStatValue(stats2, "CacheTokens"); double promptTokens2 = getStatValue(stats2, "promptTokens"); + EXPECT_EQ(cacheTokens2, static_cast(tokensFinal.size())); EXPECT_GT(cacheTokens2, cacheTokens1); EXPECT_LT(promptTokens2, 500.0); EXPECT_LE(cacheTokens2, maxExpectedCacheTokens) From 181b98a530633cf17899f1fcae70322a0d86a5fe Mon Sep 17 00:00:00 2001 From: Mikhail Sotnikov Date: Thu, 19 Mar 2026 02:34:26 +0300 Subject: [PATCH 36/48] (internal) llamacpp-llm: dynamic tools token count and cache match test --- .../src/model-interface/CacheManager.cpp | 87 ++++- .../src/model-interface/TextLlmContext.cpp | 24 ++ .../src/model-interface/TextLlmContext.hpp | 15 + .../test/unit/test_cache_management_qwen3.cpp | 301 +++++++++++++++++- 4 files changed, 405 insertions(+), 22 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.cpp index d7a56a4713..caab2a2303 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.cpp @@ -6,6 +6,7 @@ #include #include +#include "TextLlmContext.hpp" #include "addon/LlmErrors.hpp" #include "utils/LoggingMacros.hpp" @@ -169,7 +170,6 @@ bool CacheManager::loadCache() { auto* ctx = llmContext_->getCtx(); size_t nTokenCount = 0; - llama_token sessionTokens[2] = {0, 0}; QLOG_IF( Priority::DEBUG, @@ -185,8 +185,22 @@ bool CacheManager::loadCache() { return false; } - if (!llama_state_load_file( - ctx, sessionPath_.c_str(), sessionTokens, 2, &nTokenCount)) { + // First, get the token count to allocate the buffer + // We use a larger buffer to accommodate all tokens + std::vector loadedTokens(llama_n_ctx(ctx)); + size_t maxTokens = loadedTokens.size(); + + // Use llama_state_seq_load_file which returns actual token IDs + // seq_id 0 is the default sequence + size_t bytesRead = llama_state_seq_load_file( + ctx, + sessionPath_.c_str(), + 0, // dest_seq_id + loadedTokens.data(), // tokens_out + maxTokens, // n_token_capacity + &nTokenCount); // n_token_count_out + + if (bytesRead == 0) { std::string errorMsg = string_format( "%s: failed to load session file '%s'\n", __func__, @@ -195,22 +209,42 @@ bool CacheManager::loadCache() { ADDON_ID, toString(UnableToLoadSessionFile), errorMsg); } - QLOG_IF(Priority::DEBUG, string_format("%s: loaded a session\n", __func__)); + // Resize to actual token count + loadedTokens.resize(nTokenCount); - if (nTokenCount > 1) { - if (sessionTokens[0] > llama_n_ctx(ctx)) { + QLOG_IF(Priority::DEBUG, string_format("%s: loaded a session with %zu tokens\n", __func__, nTokenCount)); + + if (nTokenCount > 0) { + if (nTokenCount > static_cast(llama_n_ctx(ctx))) { std::string errorMsg = string_format( "%s: cache file '%s' contains %zu tokens, which exceeds the current " "context size of %d tokens\n", __func__, sessionPath_.c_str(), - static_cast(sessionTokens[0]), + nTokenCount, + llama_n_ctx(ctx)); + throw qvac_errors::StatusError( + ADDON_ID, toString(ContextLengthExeeded), errorMsg); + } + + // Extract metadata from the beginning of the token array + // Format: [nPast, firstMsgTokens, token0, token1, ...] + llama_pos savedNPast = loadedTokens[0]; + llama_pos savedFirstMsgTokens = loadedTokens[1]; + + if (savedNPast > llama_n_ctx(ctx)) { + std::string errorMsg = string_format( + "%s: cache file '%s' has nPast=%lld which exceeds context size of %d\n", + __func__, + sessionPath_.c_str(), + static_cast(savedNPast), llama_n_ctx(ctx)); throw qvac_errors::StatusError( ADDON_ID, toString(ContextLengthExeeded), errorMsg); } - llmContext_->setNPast(sessionTokens[0]); - llmContext_->setFirstMsgTokens(sessionTokens[1]); + + llmContext_->setNPast(savedNPast); + llmContext_->setFirstMsgTokens(savedFirstMsgTokens); if (configuredNDiscarded_ > llama_n_ctx(ctx) - llmContext_->getFirstMsgTokens()) { @@ -220,8 +254,16 @@ bool CacheManager::loadCache() { llmContext_->setNDiscarded(configuredNDiscarded_); } + // Restore token tracking buffer in TextLlmContext (skip metadata) + auto* textCtx = dynamic_cast(llmContext_); + if (textCtx && nTokenCount > 2) { + std::vector actualTokens(loadedTokens.begin() + 2, loadedTokens.end()); + textCtx->setAllTokens(actualTokens); + } + + // Remove tokens beyond nPast from the KV cache auto* mem = llama_get_memory(ctx); - llama_memory_seq_rm(mem, -1, sessionTokens[0], -1); + llama_memory_seq_rm(mem, -1, savedNPast, -1); return true; } return false; @@ -244,10 +286,27 @@ void CacheManager::saveCache() { __func__, sessionPath_.c_str())); - llama_token sessionTokens[2] = { - static_cast(llmContext_->getNPast()), - static_cast(llmContext_->getFirstMsgTokens())}; - llama_state_save_file(ctx, sessionPath_.c_str(), sessionTokens, 2); + // Get all tracked tokens from the context + // The TextLlmContext maintains a buffer of all processed tokens + const auto* textCtx = dynamic_cast(llmContext_); + std::vector tokens; + if (textCtx) { + tokens = textCtx->getAllTokens(); + } else { + // Fallback: create minimal token info + tokens.clear(); + } + + // Prepend metadata: [nPast, firstMsgTokens] at the start of the token array + // This allows us to restore firstMsgTokens on load + std::vector tokensWithMetadata; + tokensWithMetadata.reserve(tokens.size() + 2); + tokensWithMetadata.push_back(static_cast(llmContext_->getNPast())); + tokensWithMetadata.push_back(static_cast(llmContext_->getFirstMsgTokens())); + tokensWithMetadata.insert(tokensWithMetadata.end(), tokens.begin(), tokens.end()); + + // Use llama_state_seq_save_file which saves tokens along with KV cache + llama_state_seq_save_file(ctx, sessionPath_.c_str(), 0, tokensWithMetadata.data(), tokensWithMetadata.size()); } bool CacheManager::isCacheDisabled() const { return cacheDisabled_; } diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp index 13a205e6a2..6302679cdf 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp @@ -379,6 +379,9 @@ bool TextLlmContext::evalMessageWithTools( // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic,bugprone-narrowing-conversions,readability-implicit-bool-conversion,readability-identifier-naming) } + // Track input tokens for cache saving + allTokens_.insert(allTokens_.end(), inputTokens.begin(), inputTokens.end()); + if (isFirstMsg) { firstMsgTokens_ = nPast_; const auto ctxSize = static_cast(llama_n_ctx(lctx_)); @@ -410,6 +413,16 @@ void TextLlmContext::applyContextDiscard() { llama_memory_seq_rm(mem, 0, firstMsgTokens_, firstMsgTokens_ + nDiscarded_); llama_memory_seq_add( mem, 0, firstMsgTokens_ + nDiscarded_, nPast_, -nDiscarded_); + + // Remove discarded tokens from tracking buffer + if (firstMsgTokens_ < static_cast(allTokens_.size())) { + auto eraseStart = allTokens_.begin() + firstMsgTokens_; + auto eraseEnd = eraseStart + nDiscarded_; + if (eraseEnd <= allTokens_.end()) { + allTokens_.erase(eraseStart, eraseEnd); + } + } + nPast_ -= nDiscarded_; QLOG_IF( Priority::DEBUG, @@ -465,6 +478,9 @@ bool TextLlmContext::generateResponse( common_sampler_accept(smpl_.get(), tokenId, true); --nRemain; + // Track generated token for cache saving + allTokens_.push_back(tokenId); + std::string tokenStr = common_token_to_piece(lctx_, tokenId, params_.special); if (outputCallback) { @@ -559,6 +575,9 @@ void TextLlmContext::resetState(bool resetStats) { // Reset the first msg token length firstMsgTokens_ = 0; + // Clear token tracking buffer + allTokens_.clear(); + // Clear UTF-8 buffer when resetting state utf8Buffer_.clear(); @@ -606,6 +625,11 @@ llama_pos TextLlmContext::removeLastNTokens(llama_pos count) { return 0; } + // Remove from token tracking buffer + if (tokensToRemove <= static_cast(allTokens_.size())) { + allTokens_.resize(allTokens_.size() - tokensToRemove); + } + // Get the memory for KV cache manipulation auto* mem = llama_get_memory(lctx_); diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp index 7de43f791a..c3f01257b7 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp @@ -132,6 +132,18 @@ class TextLlmContext: public LlmContext { */ llama_pos removeLastNTokens(llama_pos count) override; + /** + * Get all tracked tokens for cache saving. + * @return vector of all token IDs that have been processed + */ + const std::vector& getAllTokens() const { return allTokens_; } + + /** + * Set tracked tokens for cache loading. + * @param tokens vector of token IDs to restore + */ + void setAllTokens(const std::vector& tokens) { allTokens_ = tokens; } + private: /** * The check antiprompt method. It checks the antiprompt. @@ -188,6 +200,9 @@ class TextLlmContext: public LlmContext { bool isQwen3Model_ = false; std::atomic stopGeneration_ = false; + + // Track all processed tokens for cache saving/loading + std::vector allTokens_; }; diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp index 423601ccf5..4ad60e74bd 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp @@ -1,5 +1,7 @@ #include +#include #include +#include #include #include #include @@ -83,6 +85,67 @@ std::vector parseChatMessages(const std::string& input) { } return messages; } + +std::string tokensToPromptString(const llama_vocab* vocab, const std::vector& tokens) { + std::string result; + for (llama_token tok : tokens) { + char buf[256]; + int n = llama_token_to_piece(vocab, tok, buf, sizeof(buf), 0, true); + if (n > 0) { + result.append(buf, n); + } + } + return result; +} + +struct CachedPromptResult { + size_t nPast; + size_t nTokenCount; + std::vector tokens; + std::string promptString; +}; + +CachedPromptResult loadCachedPromptFromFile( + const llama_model* modelPtr, + const std::string& sessionFilename) { + CachedPromptResult result; + + llama_context_params ctx_params = llama_context_default_params(); + ctx_params.n_ctx = 2048; + + llama_context* tempCtx = llama_init_from_model( + const_cast(modelPtr), ctx_params); + + // Allocate a buffer for tokens - use a reasonable maximum + const size_t maxTokens = 2048; + std::vector tokensBuffer(maxTokens); + size_t nTokenCount = 0; + + // Use llama_state_seq_load_file to get actual token IDs from the session file + // This loads the KV cache state AND returns the token IDs that were cached + size_t bytesRead = llama_state_seq_load_file( + tempCtx, + sessionFilename.c_str(), + 0, // dest_seq_id + tokensBuffer.data(), // tokens_out + maxTokens, // n_token_capacity + &nTokenCount); // n_token_count_out + + if (bytesRead == 0) { + throw std::runtime_error("Failed to load session file: " + sessionFilename); + } + + result.nPast = nTokenCount; + result.nTokenCount = nTokenCount; + result.tokens = std::vector(tokensBuffer.begin(), tokensBuffer.begin() + nTokenCount); + + const llama_vocab* vocab = llama_model_get_vocab(modelPtr); + result.promptString = tokensToPromptString(vocab, result.tokens); + + llama_free(tempCtx); + + return result; +} } // namespace class CacheManagementQwen3Test : public ::testing::Test { @@ -321,8 +384,9 @@ TEST_F(CacheManagementQwen3Test, CacheWithoutToolsWithToolsAtEndTrue) { double cacheTokensBeforeSave = getStatValue(statsBeforeSave, "CacheTokens"); std::cout << "=== DEBUG: cacheTokensBeforeSave = " << cacheTokensBeforeSave << " ===" << std::endl; - // The test should compare with the model's actual behavior (after session removal) - EXPECT_EQ(cacheTokensBeforeSave, static_cast(actualTokens.size())); + // The cache includes prompt + response tokens. We expect at least the prompt tokens. + EXPECT_GE(cacheTokensBeforeSave, static_cast(actualTokens.size())); + EXPECT_GT(cacheTokensBeforeSave, 0.0); llama_pos nPastBeforeTools = model->getNPastBeforeTools(); EXPECT_EQ(nPastBeforeTools, -1); @@ -472,7 +536,8 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeWithMultiplePrompts) { auto stats2 = model->runtimeStats(); double cacheTokens2 = getStatValue(stats2, "CacheTokens"); double promptTokens2 = getStatValue(stats2, "promptTokens"); - EXPECT_EQ(cacheTokens2, static_cast(tokensFinal.size())); + // Cache includes prompt + response tokens, so expect at least the prompt tokens + EXPECT_GE(cacheTokens2, static_cast(tokensFinal.size())); EXPECT_GT(cacheTokens2, cacheTokens1); EXPECT_LT(promptTokens2, 500.0); EXPECT_LE(cacheTokens2, maxExpectedCacheTokens) @@ -550,9 +615,6 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeTrimOnlyWhenNPastBeforeTools EXPECT_GE(output.length(), 0); }); - llama_pos nPastBeforeTools = model->getNPastBeforeTools(); - EXPECT_EQ(nPastBeforeTools, -1); - auto statsBeforeSave = model->runtimeStats(); double cacheTokensBeforeSave = getStatValue(statsBeforeSave, "CacheTokens"); EXPECT_GT(cacheTokensBeforeSave, 0.0); @@ -589,7 +651,9 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeRestoresNPastBeforeTools) { EXPECT_NO_THROW({ std::string output = processPromptString(model, input1); - EXPECT_GE(output.length(), 0); + EXPECT_GT(output.length(), 1); + std::cout << "\n=== THE DDDD Output: Cached User Prompt String ===" << std::endl; + std::cout << output << std::endl; }); llama_pos nPastBeforeTools1 = model->getNPastBeforeTools(); @@ -614,9 +678,230 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeRestoresNPastBeforeTools) { EXPECT_NO_THROW({ std::string output = processPromptString(model2, input2); - EXPECT_GE(output.length(), 0); + EXPECT_GT(output.length(), 0); }); llama_pos nPastBeforeTools2 = model2->getNPastBeforeTools(); EXPECT_EQ(nPastBeforeTools2, -1); } + +TEST_F(CacheManagementQwen3Test, CacheExportToTokensAndString) { + if (!isQwen3ModelPath(test_model_path)) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + // Step 1: Send user message with tools + std::string inputWithTools = + // R"([{"role": "session", "content": "test_cache_export_qwen3.bin"}, {"role": "user", "content": "Hi"}])"; + R"([{"role": "session", "content": "test_cache_export_qwen3.bin"}, {"role": "user", "content": "Hi"}, {"type": "function", "name": "get_weather", "description": "Get weather forecast", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model, inputWithTools); + EXPECT_GT(output.length(), 0); + }); + + // Verify that we have tokens in cache + auto statsBeforeSave = model->runtimeStats(); + double cacheTokensBeforeSave = getStatValue(statsBeforeSave, "CacheTokens"); + EXPECT_GT(cacheTokensBeforeSave, 0.0); + + // Step 2: Save the session to a .bin file + std::string saveInput = + R"([{"role": "session", "content": "test_cache_export_qwen3.bin"}, {"role": "session", "content": "save"}])"; + EXPECT_NO_THROW({ + std::string saveOutput = processPromptString(model, saveInput); + EXPECT_EQ(saveOutput.length(), 0); + }); + + EXPECT_TRUE(fs::exists("test_cache_export_qwen3.bin")); + + // Step 3: Create a new model instance to load the session + model.reset(); + + auto model2 = createModel(); + if (!model2) { + FAIL() << "Model2 failed to load"; + } + + // Step 4: Load the session and extract cached prompt using helper function + const llama_model* modelPtr = model2->getLlamaModel(); + EXPECT_NE(modelPtr, nullptr) << "Model pointer is null"; + + CachedPromptResult cacheResult = loadCachedPromptFromFile( + modelPtr, + "test_cache_export_qwen3.bin"); + + const llama_vocab* vocab = llama_model_get_vocab(modelPtr); + + std::cout << "\n=== Cached Tokens from Session File ===" << std::endl; + std::cout << "nTokenCount from load: " << cacheResult.nTokenCount << std::endl; + std::cout << "nPast (total processed tokens): " << cacheResult.nPast << std::endl; + std::cout << "Token count for prompt: " << cacheResult.tokens.size() << std::endl; + std::cout << "\nToken breakdown:" << std::endl; + + // Convert each token ID to string and output + for (size_t i = 0; i < cacheResult.tokens.size(); ++i) { + llama_token tok = cacheResult.tokens[i]; + char buf[256]; + int n = llama_token_to_piece(vocab, tok, buf, sizeof(buf), 0, true); + + // Mark special tokens + std::string markers; + if (tok == llama_vocab_bos(vocab)) markers += " [BOS]"; + if (tok == llama_vocab_eos(vocab)) markers += " [EOS]"; + if (tok == llama_vocab_eot(vocab)) markers += " [EOT]"; + if (llama_vocab_is_control(vocab, tok)) markers += " [CONTROL]"; + + std::cout << " [" << std::setw(3) << i << "] " + << std::setw(6) << tok << markers << " -> \""; + + // Escape special characters for display + for (int j = 0; j < n; ++j) { + char c = buf[j]; + if (c == '\n') std::cout << "\\n"; + else if (c == '\t') std::cout << "\\t"; + else if (c == '\r') std::cout << "\\r"; + else if (c == '"') std::cout << "\\\""; + else if (c < 32) std::cout << "\\x" << std::hex << (int)(unsigned char)c << std::dec; + else std::cout << c; + } + std::cout << "\"" << std::endl; + } + + std::cout << "\n=== Final Output: Cached User Prompt String ===" << std::endl; + std::cout << cacheResult.promptString << std::endl; + + // Cleanup session file + if (fs::exists("test_cache_export_qwen3.bin")) { + fs::remove("test_cache_export_qwen3.bin"); + } +} + +TEST_F(CacheManagementQwen3Test, CacheExportToTokensAndStringMultiturn) { + if (!isQwen3ModelPath(test_model_path)) { + GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; + } + + if (!hasValidModel()) { + FAIL() << "Test model not found"; + } + + config_files["tools_at_end"] = "true"; + auto model = createModel(); + if (!model) { + FAIL() << "Model failed to load"; + } + + // Step 1: Send user message without tools + std::string inputWithoutTools = + R"([{"role": "session", "content": "test_cache_export_qwen3.bin"}, {"role": "user", "content": "Hi"}])"; + // R"([{"role": "session", "content": "test_cache_export_qwen3.bin"}, {"role": "user", "content": "Hi"}, {"type": "function", "name": "get_weather", "description": "Get weather forecast", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model, inputWithoutTools); + EXPECT_GT(output.length(), 0); + std::cout << "\n=== Output: LLM response ===" << std::endl; + std::cout << output << std::endl; + }); + + // Verify that we have tokens in cache + auto statsInitial = model->runtimeStats(); + double cacheInitial = getStatValue(statsInitial, "CacheTokens"); + EXPECT_GT(cacheInitial, 0.0); + + // Step 2: Send user message with tools + std::string inputWithTools = + R"([{"role": "session", "content": "test_cache_export_qwen3.bin"}, {"role": "user", "content": "Hi"}, {"role": "assistant", "content": "Hello"}, {"role": "user", "content": "What's the weather"}, {"type": "function", "name": "get_weather", "description": "Get weather forecast", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}])"; + + EXPECT_NO_THROW({ + std::string output = processPromptString(model, inputWithTools); + EXPECT_GT(output.length(), 0); + std::cout << "\n=== Output: LLM response ===" << std::endl; + std::cout << output << std::endl; + }); + // Verify that we have tokens in cache + auto statsBeforeSave = model->runtimeStats(); + double cacheTokensBeforeSave = getStatValue(statsBeforeSave, "CacheTokens"); + EXPECT_GT(cacheTokensBeforeSave, cacheInitial); + + // Step 3: Save the session to a .bin file + std::string saveInput = + R"([{"role": "session", "content": "test_cache_export_qwen3.bin"}, {"role": "session", "content": "save"}])"; + EXPECT_NO_THROW({ + std::string saveOutput = processPromptString(model, saveInput); + EXPECT_EQ(saveOutput.length(), 0); + }); + + EXPECT_TRUE(fs::exists("test_cache_export_qwen3.bin")); + + // Step 3: Create a new model instance to load the session + model.reset(); + + auto model2 = createModel(); + if (!model2) { + FAIL() << "Model2 failed to load"; + } + + // Step 4: Load the session and extract cached prompt using helper function + const llama_model* modelPtr = model2->getLlamaModel(); + EXPECT_NE(modelPtr, nullptr) << "Model pointer is null"; + + CachedPromptResult cacheResult = loadCachedPromptFromFile( + modelPtr, + "test_cache_export_qwen3.bin"); + + const llama_vocab* vocab = llama_model_get_vocab(modelPtr); + + std::cout << "\n=== Cached Tokens from Session File ===" << std::endl; + std::cout << "nTokenCount from load: " << cacheResult.nTokenCount << std::endl; + std::cout << "nPast (total processed tokens): " << cacheResult.nPast << std::endl; + std::cout << "Token count for prompt: " << cacheResult.tokens.size() << std::endl; + std::cout << "\nToken breakdown:" << std::endl; + + // Convert each token ID to string and output + for (size_t i = 0; i < cacheResult.tokens.size(); ++i) { + llama_token tok = cacheResult.tokens[i]; + char buf[256]; + int n = llama_token_to_piece(vocab, tok, buf, sizeof(buf), 0, true); + + // Mark special tokens + std::string markers; + if (tok == llama_vocab_bos(vocab)) markers += " [BOS]"; + if (tok == llama_vocab_eos(vocab)) markers += " [EOS]"; + if (tok == llama_vocab_eot(vocab)) markers += " [EOT]"; + if (llama_vocab_is_control(vocab, tok)) markers += " [CONTROL]"; + + std::cout << " [" << std::setw(3) << i << "] " + << std::setw(6) << tok << markers << " -> \""; + + // Escape special characters for display + for (int j = 0; j < n; ++j) { + char c = buf[j]; + if (c == '\n') std::cout << "\\n"; + else if (c == '\t') std::cout << "\\t"; + else if (c == '\r') std::cout << "\\r"; + else if (c == '"') std::cout << "\\\""; + else if (c < 32) std::cout << "\\x" << std::hex << (int)(unsigned char)c << std::dec; + else std::cout << c; + } + std::cout << "\"" << std::endl; + } + + std::cout << "\n=== Final Output: Cached User Prompt String ===" << std::endl; + std::cout << cacheResult.promptString << std::endl; + + // Cleanup session file + if (fs::exists("test_cache_export_qwen3.bin")) { + fs::remove("test_cache_export_qwen3.bin"); + } +} From a03ad4948afbd0de303305a93f413b1f8e452a20 Mon Sep 17 00:00:00 2001 From: Mikhail Sotnikov Date: Thu, 19 Mar 2026 02:34:40 +0300 Subject: [PATCH 37/48] Revert "(internal) llamacpp-llm: dynamic tools token count and cache match test" This reverts commit 181b98a530633cf17899f1fcae70322a0d86a5fe. --- .../src/model-interface/CacheManager.cpp | 87 +---- .../src/model-interface/TextLlmContext.cpp | 24 -- .../src/model-interface/TextLlmContext.hpp | 15 - .../test/unit/test_cache_management_qwen3.cpp | 301 +----------------- 4 files changed, 22 insertions(+), 405 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.cpp index caab2a2303..d7a56a4713 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/CacheManager.cpp @@ -6,7 +6,6 @@ #include #include -#include "TextLlmContext.hpp" #include "addon/LlmErrors.hpp" #include "utils/LoggingMacros.hpp" @@ -170,6 +169,7 @@ bool CacheManager::loadCache() { auto* ctx = llmContext_->getCtx(); size_t nTokenCount = 0; + llama_token sessionTokens[2] = {0, 0}; QLOG_IF( Priority::DEBUG, @@ -185,22 +185,8 @@ bool CacheManager::loadCache() { return false; } - // First, get the token count to allocate the buffer - // We use a larger buffer to accommodate all tokens - std::vector loadedTokens(llama_n_ctx(ctx)); - size_t maxTokens = loadedTokens.size(); - - // Use llama_state_seq_load_file which returns actual token IDs - // seq_id 0 is the default sequence - size_t bytesRead = llama_state_seq_load_file( - ctx, - sessionPath_.c_str(), - 0, // dest_seq_id - loadedTokens.data(), // tokens_out - maxTokens, // n_token_capacity - &nTokenCount); // n_token_count_out - - if (bytesRead == 0) { + if (!llama_state_load_file( + ctx, sessionPath_.c_str(), sessionTokens, 2, &nTokenCount)) { std::string errorMsg = string_format( "%s: failed to load session file '%s'\n", __func__, @@ -209,42 +195,22 @@ bool CacheManager::loadCache() { ADDON_ID, toString(UnableToLoadSessionFile), errorMsg); } - // Resize to actual token count - loadedTokens.resize(nTokenCount); + QLOG_IF(Priority::DEBUG, string_format("%s: loaded a session\n", __func__)); - QLOG_IF(Priority::DEBUG, string_format("%s: loaded a session with %zu tokens\n", __func__, nTokenCount)); - - if (nTokenCount > 0) { - if (nTokenCount > static_cast(llama_n_ctx(ctx))) { + if (nTokenCount > 1) { + if (sessionTokens[0] > llama_n_ctx(ctx)) { std::string errorMsg = string_format( "%s: cache file '%s' contains %zu tokens, which exceeds the current " "context size of %d tokens\n", __func__, sessionPath_.c_str(), - nTokenCount, - llama_n_ctx(ctx)); - throw qvac_errors::StatusError( - ADDON_ID, toString(ContextLengthExeeded), errorMsg); - } - - // Extract metadata from the beginning of the token array - // Format: [nPast, firstMsgTokens, token0, token1, ...] - llama_pos savedNPast = loadedTokens[0]; - llama_pos savedFirstMsgTokens = loadedTokens[1]; - - if (savedNPast > llama_n_ctx(ctx)) { - std::string errorMsg = string_format( - "%s: cache file '%s' has nPast=%lld which exceeds context size of %d\n", - __func__, - sessionPath_.c_str(), - static_cast(savedNPast), + static_cast(sessionTokens[0]), llama_n_ctx(ctx)); throw qvac_errors::StatusError( ADDON_ID, toString(ContextLengthExeeded), errorMsg); } - - llmContext_->setNPast(savedNPast); - llmContext_->setFirstMsgTokens(savedFirstMsgTokens); + llmContext_->setNPast(sessionTokens[0]); + llmContext_->setFirstMsgTokens(sessionTokens[1]); if (configuredNDiscarded_ > llama_n_ctx(ctx) - llmContext_->getFirstMsgTokens()) { @@ -254,16 +220,8 @@ bool CacheManager::loadCache() { llmContext_->setNDiscarded(configuredNDiscarded_); } - // Restore token tracking buffer in TextLlmContext (skip metadata) - auto* textCtx = dynamic_cast(llmContext_); - if (textCtx && nTokenCount > 2) { - std::vector actualTokens(loadedTokens.begin() + 2, loadedTokens.end()); - textCtx->setAllTokens(actualTokens); - } - - // Remove tokens beyond nPast from the KV cache auto* mem = llama_get_memory(ctx); - llama_memory_seq_rm(mem, -1, savedNPast, -1); + llama_memory_seq_rm(mem, -1, sessionTokens[0], -1); return true; } return false; @@ -286,27 +244,10 @@ void CacheManager::saveCache() { __func__, sessionPath_.c_str())); - // Get all tracked tokens from the context - // The TextLlmContext maintains a buffer of all processed tokens - const auto* textCtx = dynamic_cast(llmContext_); - std::vector tokens; - if (textCtx) { - tokens = textCtx->getAllTokens(); - } else { - // Fallback: create minimal token info - tokens.clear(); - } - - // Prepend metadata: [nPast, firstMsgTokens] at the start of the token array - // This allows us to restore firstMsgTokens on load - std::vector tokensWithMetadata; - tokensWithMetadata.reserve(tokens.size() + 2); - tokensWithMetadata.push_back(static_cast(llmContext_->getNPast())); - tokensWithMetadata.push_back(static_cast(llmContext_->getFirstMsgTokens())); - tokensWithMetadata.insert(tokensWithMetadata.end(), tokens.begin(), tokens.end()); - - // Use llama_state_seq_save_file which saves tokens along with KV cache - llama_state_seq_save_file(ctx, sessionPath_.c_str(), 0, tokensWithMetadata.data(), tokensWithMetadata.size()); + llama_token sessionTokens[2] = { + static_cast(llmContext_->getNPast()), + static_cast(llmContext_->getFirstMsgTokens())}; + llama_state_save_file(ctx, sessionPath_.c_str(), sessionTokens, 2); } bool CacheManager::isCacheDisabled() const { return cacheDisabled_; } diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp index 6302679cdf..13a205e6a2 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp @@ -379,9 +379,6 @@ bool TextLlmContext::evalMessageWithTools( // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic,bugprone-narrowing-conversions,readability-implicit-bool-conversion,readability-identifier-naming) } - // Track input tokens for cache saving - allTokens_.insert(allTokens_.end(), inputTokens.begin(), inputTokens.end()); - if (isFirstMsg) { firstMsgTokens_ = nPast_; const auto ctxSize = static_cast(llama_n_ctx(lctx_)); @@ -413,16 +410,6 @@ void TextLlmContext::applyContextDiscard() { llama_memory_seq_rm(mem, 0, firstMsgTokens_, firstMsgTokens_ + nDiscarded_); llama_memory_seq_add( mem, 0, firstMsgTokens_ + nDiscarded_, nPast_, -nDiscarded_); - - // Remove discarded tokens from tracking buffer - if (firstMsgTokens_ < static_cast(allTokens_.size())) { - auto eraseStart = allTokens_.begin() + firstMsgTokens_; - auto eraseEnd = eraseStart + nDiscarded_; - if (eraseEnd <= allTokens_.end()) { - allTokens_.erase(eraseStart, eraseEnd); - } - } - nPast_ -= nDiscarded_; QLOG_IF( Priority::DEBUG, @@ -478,9 +465,6 @@ bool TextLlmContext::generateResponse( common_sampler_accept(smpl_.get(), tokenId, true); --nRemain; - // Track generated token for cache saving - allTokens_.push_back(tokenId); - std::string tokenStr = common_token_to_piece(lctx_, tokenId, params_.special); if (outputCallback) { @@ -575,9 +559,6 @@ void TextLlmContext::resetState(bool resetStats) { // Reset the first msg token length firstMsgTokens_ = 0; - // Clear token tracking buffer - allTokens_.clear(); - // Clear UTF-8 buffer when resetting state utf8Buffer_.clear(); @@ -625,11 +606,6 @@ llama_pos TextLlmContext::removeLastNTokens(llama_pos count) { return 0; } - // Remove from token tracking buffer - if (tokensToRemove <= static_cast(allTokens_.size())) { - allTokens_.resize(allTokens_.size() - tokensToRemove); - } - // Get the memory for KV cache manipulation auto* mem = llama_get_memory(lctx_); diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp index c3f01257b7..7de43f791a 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp @@ -132,18 +132,6 @@ class TextLlmContext: public LlmContext { */ llama_pos removeLastNTokens(llama_pos count) override; - /** - * Get all tracked tokens for cache saving. - * @return vector of all token IDs that have been processed - */ - const std::vector& getAllTokens() const { return allTokens_; } - - /** - * Set tracked tokens for cache loading. - * @param tokens vector of token IDs to restore - */ - void setAllTokens(const std::vector& tokens) { allTokens_ = tokens; } - private: /** * The check antiprompt method. It checks the antiprompt. @@ -200,9 +188,6 @@ class TextLlmContext: public LlmContext { bool isQwen3Model_ = false; std::atomic stopGeneration_ = false; - - // Track all processed tokens for cache saving/loading - std::vector allTokens_; }; diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp index 4ad60e74bd..423601ccf5 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp @@ -1,7 +1,5 @@ #include -#include #include -#include #include #include #include @@ -85,67 +83,6 @@ std::vector parseChatMessages(const std::string& input) { } return messages; } - -std::string tokensToPromptString(const llama_vocab* vocab, const std::vector& tokens) { - std::string result; - for (llama_token tok : tokens) { - char buf[256]; - int n = llama_token_to_piece(vocab, tok, buf, sizeof(buf), 0, true); - if (n > 0) { - result.append(buf, n); - } - } - return result; -} - -struct CachedPromptResult { - size_t nPast; - size_t nTokenCount; - std::vector tokens; - std::string promptString; -}; - -CachedPromptResult loadCachedPromptFromFile( - const llama_model* modelPtr, - const std::string& sessionFilename) { - CachedPromptResult result; - - llama_context_params ctx_params = llama_context_default_params(); - ctx_params.n_ctx = 2048; - - llama_context* tempCtx = llama_init_from_model( - const_cast(modelPtr), ctx_params); - - // Allocate a buffer for tokens - use a reasonable maximum - const size_t maxTokens = 2048; - std::vector tokensBuffer(maxTokens); - size_t nTokenCount = 0; - - // Use llama_state_seq_load_file to get actual token IDs from the session file - // This loads the KV cache state AND returns the token IDs that were cached - size_t bytesRead = llama_state_seq_load_file( - tempCtx, - sessionFilename.c_str(), - 0, // dest_seq_id - tokensBuffer.data(), // tokens_out - maxTokens, // n_token_capacity - &nTokenCount); // n_token_count_out - - if (bytesRead == 0) { - throw std::runtime_error("Failed to load session file: " + sessionFilename); - } - - result.nPast = nTokenCount; - result.nTokenCount = nTokenCount; - result.tokens = std::vector(tokensBuffer.begin(), tokensBuffer.begin() + nTokenCount); - - const llama_vocab* vocab = llama_model_get_vocab(modelPtr); - result.promptString = tokensToPromptString(vocab, result.tokens); - - llama_free(tempCtx); - - return result; -} } // namespace class CacheManagementQwen3Test : public ::testing::Test { @@ -384,9 +321,8 @@ TEST_F(CacheManagementQwen3Test, CacheWithoutToolsWithToolsAtEndTrue) { double cacheTokensBeforeSave = getStatValue(statsBeforeSave, "CacheTokens"); std::cout << "=== DEBUG: cacheTokensBeforeSave = " << cacheTokensBeforeSave << " ===" << std::endl; - // The cache includes prompt + response tokens. We expect at least the prompt tokens. - EXPECT_GE(cacheTokensBeforeSave, static_cast(actualTokens.size())); - EXPECT_GT(cacheTokensBeforeSave, 0.0); + // The test should compare with the model's actual behavior (after session removal) + EXPECT_EQ(cacheTokensBeforeSave, static_cast(actualTokens.size())); llama_pos nPastBeforeTools = model->getNPastBeforeTools(); EXPECT_EQ(nPastBeforeTools, -1); @@ -536,8 +472,7 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeWithMultiplePrompts) { auto stats2 = model->runtimeStats(); double cacheTokens2 = getStatValue(stats2, "CacheTokens"); double promptTokens2 = getStatValue(stats2, "promptTokens"); - // Cache includes prompt + response tokens, so expect at least the prompt tokens - EXPECT_GE(cacheTokens2, static_cast(tokensFinal.size())); + EXPECT_EQ(cacheTokens2, static_cast(tokensFinal.size())); EXPECT_GT(cacheTokens2, cacheTokens1); EXPECT_LT(promptTokens2, 500.0); EXPECT_LE(cacheTokens2, maxExpectedCacheTokens) @@ -615,6 +550,9 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeTrimOnlyWhenNPastBeforeTools EXPECT_GE(output.length(), 0); }); + llama_pos nPastBeforeTools = model->getNPastBeforeTools(); + EXPECT_EQ(nPastBeforeTools, -1); + auto statsBeforeSave = model->runtimeStats(); double cacheTokensBeforeSave = getStatValue(statsBeforeSave, "CacheTokens"); EXPECT_GT(cacheTokensBeforeSave, 0.0); @@ -651,9 +589,7 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeRestoresNPastBeforeTools) { EXPECT_NO_THROW({ std::string output = processPromptString(model, input1); - EXPECT_GT(output.length(), 1); - std::cout << "\n=== THE DDDD Output: Cached User Prompt String ===" << std::endl; - std::cout << output << std::endl; + EXPECT_GE(output.length(), 0); }); llama_pos nPastBeforeTools1 = model->getNPastBeforeTools(); @@ -678,230 +614,9 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeRestoresNPastBeforeTools) { EXPECT_NO_THROW({ std::string output = processPromptString(model2, input2); - EXPECT_GT(output.length(), 0); + EXPECT_GE(output.length(), 0); }); llama_pos nPastBeforeTools2 = model2->getNPastBeforeTools(); EXPECT_EQ(nPastBeforeTools2, -1); } - -TEST_F(CacheManagementQwen3Test, CacheExportToTokensAndString) { - if (!isQwen3ModelPath(test_model_path)) { - GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; - } - - if (!hasValidModel()) { - FAIL() << "Test model not found"; - } - - config_files["tools_at_end"] = "true"; - auto model = createModel(); - if (!model) { - FAIL() << "Model failed to load"; - } - - // Step 1: Send user message with tools - std::string inputWithTools = - // R"([{"role": "session", "content": "test_cache_export_qwen3.bin"}, {"role": "user", "content": "Hi"}])"; - R"([{"role": "session", "content": "test_cache_export_qwen3.bin"}, {"role": "user", "content": "Hi"}, {"type": "function", "name": "get_weather", "description": "Get weather forecast", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}])"; - - EXPECT_NO_THROW({ - std::string output = processPromptString(model, inputWithTools); - EXPECT_GT(output.length(), 0); - }); - - // Verify that we have tokens in cache - auto statsBeforeSave = model->runtimeStats(); - double cacheTokensBeforeSave = getStatValue(statsBeforeSave, "CacheTokens"); - EXPECT_GT(cacheTokensBeforeSave, 0.0); - - // Step 2: Save the session to a .bin file - std::string saveInput = - R"([{"role": "session", "content": "test_cache_export_qwen3.bin"}, {"role": "session", "content": "save"}])"; - EXPECT_NO_THROW({ - std::string saveOutput = processPromptString(model, saveInput); - EXPECT_EQ(saveOutput.length(), 0); - }); - - EXPECT_TRUE(fs::exists("test_cache_export_qwen3.bin")); - - // Step 3: Create a new model instance to load the session - model.reset(); - - auto model2 = createModel(); - if (!model2) { - FAIL() << "Model2 failed to load"; - } - - // Step 4: Load the session and extract cached prompt using helper function - const llama_model* modelPtr = model2->getLlamaModel(); - EXPECT_NE(modelPtr, nullptr) << "Model pointer is null"; - - CachedPromptResult cacheResult = loadCachedPromptFromFile( - modelPtr, - "test_cache_export_qwen3.bin"); - - const llama_vocab* vocab = llama_model_get_vocab(modelPtr); - - std::cout << "\n=== Cached Tokens from Session File ===" << std::endl; - std::cout << "nTokenCount from load: " << cacheResult.nTokenCount << std::endl; - std::cout << "nPast (total processed tokens): " << cacheResult.nPast << std::endl; - std::cout << "Token count for prompt: " << cacheResult.tokens.size() << std::endl; - std::cout << "\nToken breakdown:" << std::endl; - - // Convert each token ID to string and output - for (size_t i = 0; i < cacheResult.tokens.size(); ++i) { - llama_token tok = cacheResult.tokens[i]; - char buf[256]; - int n = llama_token_to_piece(vocab, tok, buf, sizeof(buf), 0, true); - - // Mark special tokens - std::string markers; - if (tok == llama_vocab_bos(vocab)) markers += " [BOS]"; - if (tok == llama_vocab_eos(vocab)) markers += " [EOS]"; - if (tok == llama_vocab_eot(vocab)) markers += " [EOT]"; - if (llama_vocab_is_control(vocab, tok)) markers += " [CONTROL]"; - - std::cout << " [" << std::setw(3) << i << "] " - << std::setw(6) << tok << markers << " -> \""; - - // Escape special characters for display - for (int j = 0; j < n; ++j) { - char c = buf[j]; - if (c == '\n') std::cout << "\\n"; - else if (c == '\t') std::cout << "\\t"; - else if (c == '\r') std::cout << "\\r"; - else if (c == '"') std::cout << "\\\""; - else if (c < 32) std::cout << "\\x" << std::hex << (int)(unsigned char)c << std::dec; - else std::cout << c; - } - std::cout << "\"" << std::endl; - } - - std::cout << "\n=== Final Output: Cached User Prompt String ===" << std::endl; - std::cout << cacheResult.promptString << std::endl; - - // Cleanup session file - if (fs::exists("test_cache_export_qwen3.bin")) { - fs::remove("test_cache_export_qwen3.bin"); - } -} - -TEST_F(CacheManagementQwen3Test, CacheExportToTokensAndStringMultiturn) { - if (!isQwen3ModelPath(test_model_path)) { - GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; - } - - if (!hasValidModel()) { - FAIL() << "Test model not found"; - } - - config_files["tools_at_end"] = "true"; - auto model = createModel(); - if (!model) { - FAIL() << "Model failed to load"; - } - - // Step 1: Send user message without tools - std::string inputWithoutTools = - R"([{"role": "session", "content": "test_cache_export_qwen3.bin"}, {"role": "user", "content": "Hi"}])"; - // R"([{"role": "session", "content": "test_cache_export_qwen3.bin"}, {"role": "user", "content": "Hi"}, {"type": "function", "name": "get_weather", "description": "Get weather forecast", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}])"; - - EXPECT_NO_THROW({ - std::string output = processPromptString(model, inputWithoutTools); - EXPECT_GT(output.length(), 0); - std::cout << "\n=== Output: LLM response ===" << std::endl; - std::cout << output << std::endl; - }); - - // Verify that we have tokens in cache - auto statsInitial = model->runtimeStats(); - double cacheInitial = getStatValue(statsInitial, "CacheTokens"); - EXPECT_GT(cacheInitial, 0.0); - - // Step 2: Send user message with tools - std::string inputWithTools = - R"([{"role": "session", "content": "test_cache_export_qwen3.bin"}, {"role": "user", "content": "Hi"}, {"role": "assistant", "content": "Hello"}, {"role": "user", "content": "What's the weather"}, {"type": "function", "name": "get_weather", "description": "Get weather forecast", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}])"; - - EXPECT_NO_THROW({ - std::string output = processPromptString(model, inputWithTools); - EXPECT_GT(output.length(), 0); - std::cout << "\n=== Output: LLM response ===" << std::endl; - std::cout << output << std::endl; - }); - // Verify that we have tokens in cache - auto statsBeforeSave = model->runtimeStats(); - double cacheTokensBeforeSave = getStatValue(statsBeforeSave, "CacheTokens"); - EXPECT_GT(cacheTokensBeforeSave, cacheInitial); - - // Step 3: Save the session to a .bin file - std::string saveInput = - R"([{"role": "session", "content": "test_cache_export_qwen3.bin"}, {"role": "session", "content": "save"}])"; - EXPECT_NO_THROW({ - std::string saveOutput = processPromptString(model, saveInput); - EXPECT_EQ(saveOutput.length(), 0); - }); - - EXPECT_TRUE(fs::exists("test_cache_export_qwen3.bin")); - - // Step 3: Create a new model instance to load the session - model.reset(); - - auto model2 = createModel(); - if (!model2) { - FAIL() << "Model2 failed to load"; - } - - // Step 4: Load the session and extract cached prompt using helper function - const llama_model* modelPtr = model2->getLlamaModel(); - EXPECT_NE(modelPtr, nullptr) << "Model pointer is null"; - - CachedPromptResult cacheResult = loadCachedPromptFromFile( - modelPtr, - "test_cache_export_qwen3.bin"); - - const llama_vocab* vocab = llama_model_get_vocab(modelPtr); - - std::cout << "\n=== Cached Tokens from Session File ===" << std::endl; - std::cout << "nTokenCount from load: " << cacheResult.nTokenCount << std::endl; - std::cout << "nPast (total processed tokens): " << cacheResult.nPast << std::endl; - std::cout << "Token count for prompt: " << cacheResult.tokens.size() << std::endl; - std::cout << "\nToken breakdown:" << std::endl; - - // Convert each token ID to string and output - for (size_t i = 0; i < cacheResult.tokens.size(); ++i) { - llama_token tok = cacheResult.tokens[i]; - char buf[256]; - int n = llama_token_to_piece(vocab, tok, buf, sizeof(buf), 0, true); - - // Mark special tokens - std::string markers; - if (tok == llama_vocab_bos(vocab)) markers += " [BOS]"; - if (tok == llama_vocab_eos(vocab)) markers += " [EOS]"; - if (tok == llama_vocab_eot(vocab)) markers += " [EOT]"; - if (llama_vocab_is_control(vocab, tok)) markers += " [CONTROL]"; - - std::cout << " [" << std::setw(3) << i << "] " - << std::setw(6) << tok << markers << " -> \""; - - // Escape special characters for display - for (int j = 0; j < n; ++j) { - char c = buf[j]; - if (c == '\n') std::cout << "\\n"; - else if (c == '\t') std::cout << "\\t"; - else if (c == '\r') std::cout << "\\r"; - else if (c == '"') std::cout << "\\\""; - else if (c < 32) std::cout << "\\x" << std::hex << (int)(unsigned char)c << std::dec; - else std::cout << c; - } - std::cout << "\"" << std::endl; - } - - std::cout << "\n=== Final Output: Cached User Prompt String ===" << std::endl; - std::cout << cacheResult.promptString << std::endl; - - // Cleanup session file - if (fs::exists("test_cache_export_qwen3.bin")) { - fs::remove("test_cache_export_qwen3.bin"); - } -} From a58893be36f71f49aef21d7463c1931e6d359b40 Mon Sep 17 00:00:00 2001 From: Mikhail Sotnikov Date: Thu, 19 Mar 2026 02:34:49 +0300 Subject: [PATCH 38/48] Revert "(draft) llamacpp-llm: dynamic tools cache tokens test debug" This reverts commit 27e6a5c50d6c9db368c917f5f9a4dd5d732a43a1. --- .../addon/src/model-interface/LlamaModel.hpp | 13 -- .../addon/src/model-interface/LlmContext.hpp | 7 - .../src/model-interface/MtmdLlmContext.hpp | 7 - .../src/model-interface/TextLlmContext.cpp | 3 - .../src/model-interface/TextLlmContext.hpp | 7 - .../test/unit/test_cache_management_qwen3.cpp | 184 +----------------- 6 files changed, 2 insertions(+), 219 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp index 558debc776..00e3a207d6 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.hpp @@ -154,19 +154,6 @@ class LlamaModel : public IModel, public IModelAsyncLoad, public IModelCancel { */ qvac_lib_inference_addon_cpp::RuntimeStats runtimeStats() const final; - /** - * Get the underlying llama_model pointer. - * - * @return pointer to llama_model, or nullptr if not loaded - */ - const struct llama_model* getLlamaModel() const { - std::shared_lock lock(stateMtx_); - if (state_ && state_->llmContext_) { - return state_->llmContext_->getModel(); - } - return nullptr; - } - /** * Static callback function for llama.cpp logging */ diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp index e94ebde9c8..de4f09ec68 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp @@ -195,13 +195,6 @@ class LlmContext { // NOLINT(cppcoreguidelines-special-member-functions) */ virtual llama_context* getCtx() = 0; - /** - * The get model method. It returns the underlying llama model. - * - * @return - the model. - */ - virtual const struct llama_model* getModel() const = 0; - /** * The get nPast method. It returns the nPast. * diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp index e1d5ca6fc7..3b6b10639d 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp @@ -80,13 +80,6 @@ class MtmdLlmContext: public LlmContext { */ llama_context* getCtx() override; - /** - * The get model method. It returns the underlying llama model. - * - * @return - the model. - */ - const struct llama_model* getModel() const override { return model_; } - /** * The get n_past method. It returns the n_past. * diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp index 13a205e6a2..a7e4efdb43 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp @@ -211,9 +211,6 @@ void TextLlmContext::tokenizeChat( inputs.tools = tools; } prompt = getPrompt(tmpls_.get(), inputs); - std::cout << "=== DEBUG-REAL: Actual model prompt (after session removal) ===" << std::endl; - std::cout << prompt << std::endl; - std::cout << "=== END DEBUG-REAL ===\n" << std::endl; QLOG_IF( Priority::DEBUG, diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp index 7de43f791a..9cb6e93247 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp @@ -74,13 +74,6 @@ class TextLlmContext: public LlmContext { */ llama_context* getCtx() override; - /** - * The get model method. It returns the underlying llama model. - * - * @return - the model. - */ - const struct llama_model* getModel() const override { return model_; } - /** * The get n_past method. It returns the n_past. * diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp index 423601ccf5..4117497ac2 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp @@ -8,11 +8,7 @@ #include #include -#include #include -#include -#include "utils/Qwen3ToolsDynamicTemplate.hpp" -#include "utils/ChatTemplateUtils.hpp" #include "model-interface/LlamaModel.hpp" #include "test_common.hpp" @@ -55,34 +51,6 @@ bool isQwen3ModelPath(const std::string& path) { [](unsigned char c) { return std::tolower(c); }); return lowerPath.find("qwen3") != std::string::npos; } - -std::vector parseChatMessages(const std::string& input) { - picojson::value chatJson; - std::string err = picojson::parse(chatJson, input); - if (!err.empty()) { - throw std::runtime_error("Failed to parse JSON: " + err); - } - if (!chatJson.is()) { - throw std::runtime_error("Expected JSON array"); - } - std::vector messages; - auto& obj = chatJson.get(); - for (const auto& subObj : obj) { - if (subObj.is()) { - picojson::object jsonObj = subObj.get(); - // Skip function type (tools) - auto it = jsonObj.find("type"); - if (it != jsonObj.end() && it->second.get() == "function") { - continue; - } - common_chat_msg msg; - msg.role = jsonObj["role"].get(); - msg.content = jsonObj["content"].get(); - messages.push_back(msg); - } - } - return messages; -} } // namespace class CacheManagementQwen3Test : public ::testing::Test { @@ -262,67 +230,9 @@ TEST_F(CacheManagementQwen3Test, CacheWithoutToolsWithToolsAtEndTrue) { EXPECT_GE(output.length(), 0); }); - // Compute expected token count for the no-tools prompt - std::string chatTemplate = qvac_lib_inference_addon_llama::utils::getToolsDynamicQwen3Template(); - common_chat_templates_ptr tmpls_ = common_chat_templates_init(model->getLlamaModel(), chatTemplate); - - // Parse input into chat messages - auto messages = parseChatMessages(inputNoTools); - std::cout << "\n=== DEBUG: Parsed messages (before session removal) ===" << std::endl; - std::cout << "Number of messages: " << messages.size() << std::endl; - for (size_t i = 0; i < messages.size(); i++) { - std::cout << " [" << i << "] role='" << messages[i].role << "' content='" << messages[i].content << "'" << std::endl; - } - std::cout << "=== END DEBUG ===\n" << std::endl; - - // Build inputs for template - common_chat_templates_inputs inputs; - inputs.use_jinja = true; // tools=true sets use_jinja=true in commonParamsParse - inputs.add_generation_prompt = true; // first message, nPast==0 => add generation prompt - inputs.messages = messages; - - auto promptNoTools = qvac_lib_inference_addon_llama::utils::getPrompt(tmpls_.get(), inputs); - - std::cout << "\n=== DEBUG: Test expected prompt ===" << std::endl; - std::cout << promptNoTools << std::endl; - std::cout << "=== END DEBUG ===\n" << std::endl; - - // For first prefill, addSpecial = true - auto tokensNoTools = common_tokenize(llama_model_get_vocab(model->getLlamaModel()), promptNoTools, true, true); - - std::cout << "=== DEBUG: tokensNoTools.size() = " << tokensNoTools.size() << " ===" << std::endl; - - // Also get the actual prompt from the model by parsing messages like the model does - auto modelMessages = parseChatMessages(inputNoTools); - // Simulate what CacheManager does: remove session messages - auto it = modelMessages.begin(); - while (it != modelMessages.end()) { - if (it->role == "session") { - it = modelMessages.erase(it); - } else { - ++it; - } - } - - common_chat_templates_inputs modelInputs; - modelInputs.use_jinja = true; - modelInputs.add_generation_prompt = true; - modelInputs.messages = modelMessages; - - auto actualPrompt = qvac_lib_inference_addon_llama::utils::getPrompt(tmpls_.get(), modelInputs); - std::cout << "=== DEBUG: Actual model prompt (after session removal) ===" << std::endl; - std::cout << actualPrompt << std::endl; - std::cout << "=== END DEBUG ===\n" << std::endl; - - auto actualTokens = common_tokenize(llama_model_get_vocab(model->getLlamaModel()), actualPrompt, true, true); - std::cout << "=== DEBUG: actualTokens.size() = " << actualTokens.size() << " ===" << std::endl; - auto statsBeforeSave = model->runtimeStats(); double cacheTokensBeforeSave = getStatValue(statsBeforeSave, "CacheTokens"); - std::cout << "=== DEBUG: cacheTokensBeforeSave = " << cacheTokensBeforeSave << " ===" << std::endl; - - // The test should compare with the model's actual behavior (after session removal) - EXPECT_EQ(cacheTokensBeforeSave, static_cast(actualTokens.size())); + EXPECT_GT(cacheTokensBeforeSave, 0.0); llama_pos nPastBeforeTools = model->getNPastBeforeTools(); EXPECT_EQ(nPastBeforeTools, -1); @@ -360,71 +270,10 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeWithMultiplePrompts) { EXPECT_GE(output.length(), 0); }); - // START - - // Compute expected token count for the no-tools prompt - std::string chatTemplate = qvac_lib_inference_addon_llama::utils::getToolsDynamicQwen3Template(); - common_chat_templates_ptr tmpls_ = common_chat_templates_init(model->getLlamaModel(), chatTemplate); - - // Parse input into chat messages - auto messages = parseChatMessages(input1); - std::cout << "\n=== DEBUG: Parsed messages (before session removal) ===" << std::endl; - std::cout << "Number of messages: " << messages.size() << std::endl; - for (size_t i = 0; i < messages.size(); i++) { - std::cout << " [" << i << "] role='" << messages[i].role << "' content='" << messages[i].content << "'" << std::endl; - } - std::cout << "=== END DEBUG ===\n" << std::endl; - - // Build inputs for template - common_chat_templates_inputs inputs; - inputs.use_jinja = true; // tools=true sets use_jinja=true in commonParamsParse - inputs.add_generation_prompt = false; // first message, nPast==0 => add generation prompt - inputs.messages = messages; - - auto promptWithTools = qvac_lib_inference_addon_llama::utils::getPrompt(tmpls_.get(), inputs); - - std::cout << "\n=== DEBUG: Test expected prompt ===" << std::endl; - std::cout << promptWithTools << std::endl; - std::cout << "=== END DEBUG ===\n" << std::endl; - - // For first prefill, addSpecial = true - auto tokensNoTools = common_tokenize(llama_model_get_vocab(model->getLlamaModel()), promptWithTools, true, true); - - std::cout << "=== DEBUG: tokensNoTools.size() = " << tokensNoTools.size() << " ===" << std::endl; - - // Also get the actual prompt from the model by parsing messages like the model does - auto modelMessages = parseChatMessages(input1); - // Simulate what CacheManager does: remove session messages - auto it = modelMessages.begin(); - while (it != modelMessages.end()) { - if (it->role == "session") { - it = modelMessages.erase(it); - } else { - ++it; - } - } - - common_chat_templates_inputs modelInputs; - modelInputs.use_jinja = true; - modelInputs.add_generation_prompt = false; - modelInputs.messages = modelMessages; - - auto actualPrompt = qvac_lib_inference_addon_llama::utils::getPrompt(tmpls_.get(), modelInputs); - std::cout << "=== DEBUG: Actual model prompt (after session removal) ===" << std::endl; - std::cout << actualPrompt << std::endl; - std::cout << "=== END DEBUG ===\n" << std::endl; - - auto actualTokens = common_tokenize(llama_model_get_vocab(model->getLlamaModel()), actualPrompt, true, true); - std::cout << "=== DEBUG: actualTokens.size() = " << actualTokens.size() << " ===" << std::endl; - auto stats1 = model->runtimeStats(); double cacheTokens1 = getStatValue(stats1, "CacheTokens"); - std::cout << "=== DEBUG: cacheTokens1 = " << cacheTokens1 << " ===" << std::endl; double promptTokens1 = getStatValue(stats1, "promptTokens"); - // The test should compare with the model's actual behavior (after session removal) - EXPECT_EQ(cacheTokens1, static_cast(tokensNoTools.size())); - EXPECT_EQ(cacheTokens1, static_cast(actualTokens.size())); - // EXPECT_GT(cacheTokens1, 0.0); + EXPECT_GT(cacheTokens1, 0.0); EXPECT_GT(promptTokens1, 500.0); const int maxExpectedCacheTokens = 50; @@ -436,34 +285,6 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeWithMultiplePrompts) { std::string input2 = R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "user", "content": "What about London?"}])"; - // START - std::string inputFull2 = - R"([{"role": "session", "content": "test_session1_qwen3.bin"}, {"role": "user", "content": "Hi"}, {"role": "user", "content": "What about London?"}])"; - // Parse input into chat messages - auto messages2 = parseChatMessages(inputFull2); - std::cout << "\n=== DEBUG: Parsed messages (before session removal) ===" << std::endl; - std::cout << "Number of messages: " << messages2.size() << std::endl; - for (size_t i = 0; i < messages2.size(); i++) { - std::cout << " [" << i << "] role='" << messages2[i].role << "' content='" << messages2[i].content << "'" << std::endl; - } - std::cout << "=== END DEBUG ===\n" << std::endl; - - // Build inputs for template - common_chat_templates_inputs inputs2; - inputs2.use_jinja = true; // tools=true sets use_jinja=true in commonParamsParse - inputs2.add_generation_prompt = true; // first message, nPast==0 => add generation prompt - inputs2.messages = messages2; - - auto promptWithoutTools = qvac_lib_inference_addon_llama::utils::getPrompt(tmpls_.get(), inputs2); - - std::cout << "\n=== DEBUG: Test expected prompt ===" << std::endl; - std::cout << promptWithoutTools << std::endl; - std::cout << "=== END DEBUG ===\n" << std::endl; - - // For first prefill, addSpecial = true - auto tokensFinal = common_tokenize(llama_model_get_vocab(model->getLlamaModel()), promptWithoutTools, false, true); - // END - EXPECT_NO_THROW({ std::string output = processPromptString(model, input2); EXPECT_GE(output.length(), 0); @@ -472,7 +293,6 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeWithMultiplePrompts) { auto stats2 = model->runtimeStats(); double cacheTokens2 = getStatValue(stats2, "CacheTokens"); double promptTokens2 = getStatValue(stats2, "promptTokens"); - EXPECT_EQ(cacheTokens2, static_cast(tokensFinal.size())); EXPECT_GT(cacheTokens2, cacheTokens1); EXPECT_LT(promptTokens2, 500.0); EXPECT_LE(cacheTokens2, maxExpectedCacheTokens) From afea85e726dfc8d5235a4a064f8432c7eaca8c50 Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Thu, 19 Mar 2026 16:15:22 +0300 Subject: [PATCH 39/48] fix(llamacpp-llm): address PR review comments N3-N8, merge main N3: Save/restore inputs.use_jinja around no-tools tokenization to prevent getPrompt() Jinja fallback from corrupting the flag. N4: Remove dead Jinja template variables (ns.multi_step_tool, ns.last_query_index) from Qwen3ToolsDynamicTemplate. N5: Add missing assert(conversationOnlyTokens <= totalTokens) in MtmdLlmContext::tokenizeChat, matching TextLlmContext. N6: Document Qwen3-only model support in tools-at-end.md. N7: Merge duplicate if(nPast_==0 && !isCacheLoaded) blocks in TextLlmContext::tokenizeChat. N8: Remove unnecessary save/restore of inputs.tools and inputs.add_generation_prompt (locals not read after). Also: merge main into feature branch, move dynamic-tools changelog to separate 0.13.1 entry. Made-with: Cursor --- .../qvac-lib-infer-llamacpp-llm/CHANGELOG.md | 22 ++++++++++--------- .../src/model-interface/MtmdLlmContext.cpp | 10 +++++---- .../src/model-interface/TextLlmContext.cpp | 9 ++------ .../src/utils/Qwen3ToolsDynamicTemplate.cpp | 8 ------- .../docs/tools-at-end.md | 4 ++++ 5 files changed, 24 insertions(+), 29 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/CHANGELOG.md b/packages/qvac-lib-infer-llamacpp-llm/CHANGELOG.md index 437de31158..cd875f11fb 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/CHANGELOG.md +++ b/packages/qvac-lib-infer-llamacpp-llm/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [0.13.1] - 2026-03-19 + +### Added + +#### `tools_at_end` configuration for dynamic tool management in multi-turn conversations + +New `tools_at_end` configuration option (`"true"` or `"false"`, default: `"false"`) places tool definitions at the end of the prompt (after conversation history) instead of in the system prompt. This enables KV cache optimization for multi-turn conversations with dynamic tool sets, where tools change between turns. Currently supports Qwen3 models only. + +- **KV cache trimming**: After each turn, tools are automatically removed from the KV cache, preventing stale tool definitions from accumulating +- **Conversation history reuse**: History tokens are preserved in cache, saving recomputation on long conversations +- **Dynamic tool replacement**: Different tool sets can be used per turn without cache bloat from unused tools + ## [0.13.0] - 2026-03-18 ### Added @@ -15,16 +27,6 @@ - Added typed `FinetuneOptions`, `FinetuneValidation`, `FinetuneProgressStats`, `FinetuneStats`, `FinetuneResult`, and `FinetuneHandle` interfaces to `index.d.ts` - Added finetuning guide at `docs/finetuning.md` -#### Dynamic tool management feature - -##### `tools_at_end` configuration for dynamic tool management in multi-turn conversations - -New `tools_at_end` configuration option (`"true"` or `"false"`, default: `"false"`) places tool definitions at the end of the prompt (after conversation history) instead of in the system prompt. This enables KV cache optimization for multi-turn conversations with dynamic tool sets, where tools change between turns. Currently supports Qwen3 models only. - -- **KV cache trimming**: After each turn, tools are automatically removed from the KV cache, preventing stale tool definitions from accumulating -- **Conversation history reuse**: History tokens are preserved in cache, saving recomputation on long conversations -- **Dynamic tool replacement**: Different tool sets can be used per turn without cache bloat from unused tools - ### Changed - `model.cancel()` now also clears pause checkpoints (`pause_checkpoint_step_*`) from the checkpoint directory, so the next `finetune()` call starts fresh instead of resuming. diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp index 45668fc29e..938a5fdb57 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp @@ -1,6 +1,7 @@ #include "MtmdLlmContext.hpp" #include +#include #include #include @@ -202,13 +203,11 @@ void MtmdLlmContext::tokenizeChat( } if (dynamicToolsState().toolsAtEnd() && !tools.empty()) { - auto savedTools = inputs.tools; - auto savedGenPrompt = inputs.add_generation_prompt; + auto savedUseJinja = inputs.use_jinja; inputs.tools = {}; inputs.add_generation_prompt = false; auto promptNoTools = getPrompt(tmpls_.get(), inputs); - inputs.tools = savedTools; - inputs.add_generation_prompt = savedGenPrompt; + inputs.use_jinja = savedUseJinja; if (!promptNoTools.empty()) { mtmd_input_text textNoTools; @@ -227,6 +226,9 @@ void MtmdLlmContext::tokenizeChat( if (resNoTools == 0) { dynamicToolsState().setConversationOnlyTokens( mtmd_helper_get_n_tokens(chunksNoTools.ptr.get())); + assert(dynamicToolsState().conversationOnlyTokens() <= + static_cast(mtmd_helper_get_n_tokens(chunks.ptr.get())) && + "conversation-only tokens exceeds total tokens"); } } } else { diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp index 0184e692d6..d51aab5334 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp @@ -192,9 +192,6 @@ void TextLlmContext::tokenizeChat( if (nPast_ == 0 && !isCacheLoaded) { dynamicToolsState().reset(); - } - - if (nPast_ == 0 && !isCacheLoaded) { isLastMessageFromUser = true; addSpecial = true; } else if (nPast_ > 0) { @@ -220,15 +217,13 @@ void TextLlmContext::tokenizeChat( inputTokens = common_tokenize(lctx_, prompt, addSpecial, true); if (dynamicToolsState().toolsAtEnd() && !tools.empty()) { - auto savedTools = inputs.tools; - auto savedGenPrompt = inputs.add_generation_prompt; + auto savedUseJinja = inputs.use_jinja; inputs.tools = {}; inputs.add_generation_prompt = false; auto promptNoTools = getPrompt(tmpls_.get(), inputs); auto tokensNoTools = common_tokenize(lctx_, promptNoTools, addSpecial, true); - inputs.tools = savedTools; - inputs.add_generation_prompt = savedGenPrompt; + inputs.use_jinja = savedUseJinja; dynamicToolsState().setConversationOnlyTokens(tokensNoTools.size()); assert(dynamicToolsState().conversationOnlyTokens() <= static_cast(inputTokens.size()) && "conversation-only tokens exceeds total tokens"); diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/Qwen3ToolsDynamicTemplate.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/Qwen3ToolsDynamicTemplate.cpp index b086b81b9d..435d236a20 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/Qwen3ToolsDynamicTemplate.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/Qwen3ToolsDynamicTemplate.cpp @@ -7,14 +7,6 @@ const char* getToolsDynamicQwen3Template() { return R"({%- if messages[0].role == 'system' %} {{- '<|im_start|>system\n' + messages[0].content + '<|im_end|>\n' }} {%- endif %} -{%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %} -{%- for message in messages[::-1] %} - {%- set index = (messages|length - 1) - loop.index0 %} - {%- if ns.multi_step_tool and message.role == "user" and not(message.content.startswith('') and message.content.endswith('')) %} - {%- set ns.multi_step_tool = false %} - {%- set ns.last_query_index = index %} - {%- endif %} -{%- endfor %} {%- for message in messages %} {%- if (message.role == "user") or (message.role == "system" and not loop.first) %} {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>' + '\n' }} diff --git a/packages/qvac-lib-infer-llamacpp-llm/docs/tools-at-end.md b/packages/qvac-lib-infer-llamacpp-llm/docs/tools-at-end.md index 9f98e6ca9e..9831eabee9 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/docs/tools-at-end.md +++ b/packages/qvac-lib-infer-llamacpp-llm/docs/tools-at-end.md @@ -13,6 +13,10 @@ const config = { } ``` +## Model Support + +Currently `tools_at_end` is only supported for **Qwen3** models. If enabled on a non-Qwen3 model, the flag is silently ignored and a warning is logged. + ## Usage Requirements ### Multi-turn Conversation Pattern From a4086e8ac68e8b7c0155ac04a3bb4bb98db1535f Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Thu, 19 Mar 2026 17:08:20 +0300 Subject: [PATCH 40/48] style(llamacpp-llm): apply clang-format to all PR-touched C++ files Made-with: Cursor --- .../addon/src/model-interface/LlamaModel.cpp | 30 ++++++----- .../addon/src/model-interface/LlmContext.hpp | 52 ++++++++++--------- .../src/model-interface/MtmdLlmContext.cpp | 17 +++--- .../src/model-interface/MtmdLlmContext.hpp | 22 ++++---- .../src/model-interface/TextLlmContext.cpp | 21 +++++--- .../src/model-interface/TextLlmContext.hpp | 8 +-- .../addon/src/utils/ChatTemplateUtils.cpp | 16 +++--- .../addon/src/utils/ChatTemplateUtils.hpp | 7 +-- .../src/utils/Qwen3ToolsDynamicTemplate.hpp | 1 - .../test/unit/test_cache_management.cpp | 2 - .../test/unit/test_cache_management_qwen3.cpp | 11 ++-- .../test/unit/test_chat_template_utils.cpp | 22 +++++--- .../test/unit/test_text_llm_context.cpp | 48 ++++++----------- .../test/unit/test_text_llm_context_qwen3.cpp | 43 +++++++-------- 14 files changed, 154 insertions(+), 146 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp index a1bbb5f5d0..5324423d7e 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp @@ -309,7 +309,8 @@ void LlamaModel::init(bool acquireLock) { common_params params; std::optional adrenoVersion; bool toolsAtEnd = false; - commonParamsParse(modelPath, configFilemap, params, adrenoVersion, toolsAtEnd); + commonParamsParse( + modelPath, configFilemap, params, adrenoVersion, toolsAtEnd); const std::string errorWhenFailed = toString(UnableToLoadModel); auto streamedFiles = @@ -514,7 +515,8 @@ std::string LlamaModel::processPromptImpl(const Prompt& prompt) { std::string out; ResolvedPrompt resolved = resolveChatAndTools(prompt.input); - if (resolved.shouldResetAfterInference && state_->llmContext_->getNPast() > 0) { + if (resolved.shouldResetAfterInference && + state_->llmContext_->getNPast() > 0) { resetState(true); } @@ -573,7 +575,8 @@ std::string LlamaModel::processPromptImpl(const Prompt& prompt) { state_->llmContext_->removeLastNTokens( state_->llmContext_->getNPast() - dts.nPastBeforeTools()); dts.reset(); - if (state_->llmContext_->getFirstMsgTokens() > state_->llmContext_->getNPast()) { + if (state_->llmContext_->getFirstMsgTokens() > + state_->llmContext_->getNPast()) { state_->llmContext_->setFirstMsgTokens(state_->llmContext_->getNPast()); } } @@ -1017,9 +1020,11 @@ std::unique_ptr LlamaModel::createContext( common_init_result&& llamaInit, bool toolsAtEnd) { if (!projectionPath.empty()) { params.mmproj.path = std::move(projectionPath); - return std::make_unique(params, std::move(llamaInit), toolsAtEnd); + return std::make_unique( + params, std::move(llamaInit), toolsAtEnd); } - return std::make_unique(params, std::move(llamaInit), toolsAtEnd); + return std::make_unique( + params, std::move(llamaInit), toolsAtEnd); } bool LlamaModel::loadMedia(const std::vector& input) { @@ -1141,13 +1146,14 @@ std::string LlamaModel::finetune( // (e.g. flash-attn off, ubatch sizing) and gives a clean llama_context. // TODO: investigate recreating the context without a full weights reload // to reduce latency when the backend itself does not change. - reload(FinetuneConfigOverrides{ - .active = true, - .batchSize = params.batchSize, - .microBatchSize = params.microBatchSize, - .contextLength = params.contextLength, - .gpuSupportsF16OutProd = gpuSupportsOutProdF16(), - .flashAttn = params.flashAttn}); + reload( + FinetuneConfigOverrides{ + .active = true, + .batchSize = params.batchSize, + .microBatchSize = params.microBatchSize, + .contextLength = params.contextLength, + .gpuSupportsF16OutProd = gpuSupportsOutProdF16(), + .flashAttn = params.flashAttn}); llama_context* ctx = getContext(); llama_model* mdl = getModel(); diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp index 0623081dd8..dc8e8578c5 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlmContext.hpp @@ -84,29 +84,29 @@ class LlamaBatch { const llama_batch* operator->() const noexcept { return &batch_; } }; -struct ThreadPoolDeleter{ - void operator()(ggml_threadpool* ptr) { - if (ptr != nullptr) { - auto* cpuDev = ggml_backend_dev_by_type(GGML_BACKEND_DEVICE_TYPE_CPU); - if (cpuDev == nullptr) { - throw qvac_errors::StatusError( - ADDON_ID, toString(NoBackendFound), "no CPU backend found"); - } - auto* reg = ggml_backend_dev_backend_reg(cpuDev); - void* procAddr = - ggml_backend_reg_get_proc_address(reg, "ggml_threadpool_free"); - if (procAddr == nullptr) { - throw qvac_errors::StatusError( - ADDON_ID, - toString(UnableToDeleteThreadPool), - "Failed to get ggml_threadpool_free function address"); - } - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) - auto* ggmlThreadpoolFreeFn = - reinterpret_cast(procAddr); - ggmlThreadpoolFreeFn(ptr); +struct ThreadPoolDeleter { + void operator()(ggml_threadpool* ptr) { + if (ptr != nullptr) { + auto* cpuDev = ggml_backend_dev_by_type(GGML_BACKEND_DEVICE_TYPE_CPU); + if (cpuDev == nullptr) { + throw qvac_errors::StatusError( + ADDON_ID, toString(NoBackendFound), "no CPU backend found"); + } + auto* reg = ggml_backend_dev_backend_reg(cpuDev); + void* procAddr = + ggml_backend_reg_get_proc_address(reg, "ggml_threadpool_free"); + if (procAddr == nullptr) { + throw qvac_errors::StatusError( + ADDON_ID, + toString(UnableToDeleteThreadPool), + "Failed to get ggml_threadpool_free function address"); } + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + auto* ggmlThreadpoolFreeFn = + reinterpret_cast(procAddr); + ggmlThreadpoolFreeFn(ptr); } + } }; using ThreadPoolPtr = std::unique_ptr; @@ -122,7 +122,9 @@ class DynamicToolsState { } } void setConversationOnlyTokens(llama_pos n) { nConversationOnlyTokens_ = n; } - [[nodiscard]] llama_pos conversationOnlyTokens() const { return nConversationOnlyTokens_; } + [[nodiscard]] llama_pos conversationOnlyTokens() const { + return nConversationOnlyTokens_; + } void reset() { nConversationOnlyTokens_ = 0; nPastBeforeTools_ = -1; @@ -236,7 +238,9 @@ class LlmContext { // NOLINT(cppcoreguidelines-special-member-functions) virtual void setNDiscarded(llama_pos nDiscarded) = 0; DynamicToolsState& dynamicToolsState() { return dynamicToolsState_; } - [[nodiscard]] const DynamicToolsState& dynamicToolsState() const { return dynamicToolsState_; } + [[nodiscard]] const DynamicToolsState& dynamicToolsState() const { + return dynamicToolsState_; + } /** * Get the number of context slides (discards) that have occurred. @@ -307,5 +311,3 @@ class LlmContext { // NOLINT(cppcoreguidelines-special-member-functions) private: DynamicToolsState dynamicToolsState_; }; - - diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp index 938a5fdb57..6573d054d8 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp @@ -21,7 +21,8 @@ using namespace qvac_lib_inference_addon_llama::utils; // NOLINTNEXTLINE(readability-function-cognitive-complexity) MtmdLlmContext::MtmdLlmContext( - common_params& commonParams, common_init_result&& llamaInit, bool toolsAtEnd) + common_params& commonParams, common_init_result&& llamaInit, + bool toolsAtEnd) : llamaInit_(std::move(llamaInit)), params_(commonParams), model_(llamaInit_.model.get()), lctx_(llamaInit_.context.get()) { dynamicToolsState().setToolsAtEnd(toolsAtEnd); @@ -42,7 +43,8 @@ MtmdLlmContext::MtmdLlmContext( vocab_ = llama_model_get_vocab(model_); - std::string chatTemplate = getChatTemplate(model_, params_, dynamicToolsState().toolsAtEnd()); + std::string chatTemplate = + getChatTemplate(model_, params_, dynamicToolsState().toolsAtEnd()); tmpls_ = common_chat_templates_init(model_, chatTemplate); smpl_.reset(common_sampler_init(model_, params_.sampling)); @@ -226,9 +228,11 @@ void MtmdLlmContext::tokenizeChat( if (resNoTools == 0) { dynamicToolsState().setConversationOnlyTokens( mtmd_helper_get_n_tokens(chunksNoTools.ptr.get())); - assert(dynamicToolsState().conversationOnlyTokens() <= - static_cast(mtmd_helper_get_n_tokens(chunks.ptr.get())) && - "conversation-only tokens exceeds total tokens"); + assert( + dynamicToolsState().conversationOnlyTokens() <= + static_cast( + mtmd_helper_get_n_tokens(chunks.ptr.get())) && + "conversation-only tokens exceeds total tokens"); } } } else { @@ -351,7 +355,8 @@ bool MtmdLlmContext::evalMessageWithTools( nDiscarded_ = ctxSize - firstMsgTokens_ - 1; } } - dynamicToolsState().recordToolBoundary(nPast_, static_cast(nTokens)); + dynamicToolsState().recordToolBoundary( + nPast_, static_cast(nTokens)); return true; } diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp index aec22514e4..2f25120df8 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.hpp @@ -9,7 +9,7 @@ #include "LlmContext.hpp" #include "qvac-lib-inference-addon-cpp/Logger.hpp" -class MtmdLlmContext: public LlmContext { +class MtmdLlmContext : public LlmContext { public: /** * The constructor. @@ -18,7 +18,9 @@ class MtmdLlmContext: public LlmContext { * @param _llama_init - The result of initializing/loading the model using * .gguf file(s) */ - MtmdLlmContext(common_params& commonParams, common_init_result&& llamaInit, bool toolsAtEnd = false); + MtmdLlmContext( + common_params& commonParams, common_init_result&& llamaInit, + bool toolsAtEnd = false); /** * The destructor. @@ -38,8 +40,8 @@ class MtmdLlmContext: public LlmContext { * @return - true if successful, false if inference is stopped. */ bool evalMessage( - const std::vector& chatMsgs, - bool isCacheLoaded, bool prefill) override; + const std::vector& chatMsgs, bool isCacheLoaded, + bool prefill) override; /** * The eval message with tools method. It evaluates the message with tools and @@ -165,11 +167,11 @@ class MtmdLlmContext: public LlmContext { void resetMedia() override; private: - /** - * The check antiprompt method. It checks the antiprompt. - * - * @return - true if the antiprompt is found, false otherwise. - */ + /** + * The check antiprompt method. It checks the antiprompt. + * + * @return - true if the antiprompt is found, false otherwise. + */ bool checkAntiprompt(); /** @@ -217,5 +219,3 @@ class MtmdLlmContext: public LlmContext { qvac_lib_inference_addon_llama::UTF8TokenBuffer utf8Buffer_; std::atomic stopGeneration_ = false; }; - - diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp index d51aab5334..62ca039fb5 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp @@ -24,7 +24,8 @@ using namespace qvac_lib_inference_addon_llama::utils; // NOLINTNEXTLINE(readability-function-cognitive-complexity) TextLlmContext::TextLlmContext( - common_params& commonParams, common_init_result&& llamaInit, bool toolsAtEnd) + common_params& commonParams, common_init_result&& llamaInit, + bool toolsAtEnd) : llamaInit_(std::move(llamaInit)), params_(commonParams) { dynamicToolsState().setToolsAtEnd(toolsAtEnd); { @@ -51,7 +52,8 @@ TextLlmContext::TextLlmContext( lctx_, reasoningState_); } - std::string chatTemplate = getChatTemplate(model_, params_, dynamicToolsState().toolsAtEnd()); + std::string chatTemplate = + getChatTemplate(model_, params_, dynamicToolsState().toolsAtEnd()); tmpls_ = common_chat_templates_init(model_, chatTemplate); smpl_.reset(common_sampler_init(model_, params_.sampling)); @@ -221,12 +223,15 @@ void TextLlmContext::tokenizeChat( inputs.tools = {}; inputs.add_generation_prompt = false; auto promptNoTools = getPrompt(tmpls_.get(), inputs); - auto tokensNoTools = common_tokenize(lctx_, promptNoTools, addSpecial, true); + auto tokensNoTools = + common_tokenize(lctx_, promptNoTools, addSpecial, true); inputs.use_jinja = savedUseJinja; dynamicToolsState().setConversationOnlyTokens(tokensNoTools.size()); - assert(dynamicToolsState().conversationOnlyTokens() <= static_cast(inputTokens.size()) && - "conversation-only tokens exceeds total tokens"); + assert( + dynamicToolsState().conversationOnlyTokens() <= + static_cast(inputTokens.size()) && + "conversation-only tokens exceeds total tokens"); } else { dynamicToolsState().setConversationOnlyTokens(0); } @@ -284,7 +289,8 @@ bool TextLlmContext::evalMessageWithTools( if (nTokens >= llama_n_ctx(lctx_)) { std::string errorMsg = string_format( - "[TextLlm] context overflow at prefill step: prompt tokens %ld, max context tokens %d\n", + "[TextLlm] context overflow at prefill step: prompt tokens %ld, max " + "context tokens %d\n", nTokens, llama_n_ctx(lctx_)); throw qvac_errors::StatusError( @@ -380,7 +386,8 @@ bool TextLlmContext::evalMessageWithTools( nDiscarded_ = ctxSize - firstMsgTokens_ - 1; } } - dynamicToolsState().recordToolBoundary(nPast_, static_cast(inputTokens.size())); + dynamicToolsState().recordToolBoundary( + nPast_, static_cast(inputTokens.size())); return true; } diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp index 4f16539ac2..37294cd073 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.hpp @@ -18,7 +18,9 @@ class TextLlmContext : public LlmContext { TextLlmContext(TextLlmContext&&) = delete; TextLlmContext& operator=(TextLlmContext&&) = delete; // Constructor - TextLlmContext(common_params& commonParams, common_init_result&& llamaInit, bool toolsAtEnd = false); + TextLlmContext( + common_params& commonParams, common_init_result&& llamaInit, + bool toolsAtEnd = false); // Destructor ~TextLlmContext() override = default; @@ -32,8 +34,8 @@ class TextLlmContext : public LlmContext { * @return - true if successful, false if inference is stopped. */ bool evalMessage( - const std::vector& chatMsgs, - bool isCacheLoaded, bool prefill) override; + const std::vector& chatMsgs, bool isCacheLoaded, + bool prefill) override; /** * The eval message with tools method. It evaluates the message with tools and diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.cpp index 6e4e23116d..9f462fc60f 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.cpp @@ -4,8 +4,8 @@ #include -#include "QwenTemplate.hpp" #include "Qwen3ToolsDynamicTemplate.hpp" +#include "QwenTemplate.hpp" #include "utils/LoggingMacros.hpp" using namespace qvac_lib_inference_addon_cpp::logger; @@ -59,29 +59,27 @@ bool isQwen3Model(const ::llama_model* model) { } std::string getChatTemplateForModel( - const ::llama_model* model, - const std::string& manualOverride, + const ::llama_model* model, const std::string& manualOverride, bool toolsAtEnd) { if (!manualOverride.empty()) { return manualOverride; } if (isQwen3Model(model)) { - return toolsAtEnd ? getToolsDynamicQwen3Template() : getFixedQwen3Template(); + return toolsAtEnd ? getToolsDynamicQwen3Template() + : getFixedQwen3Template(); } return ""; } std::string getChatTemplate( - const ::llama_model* model, - const common_params& params, - bool toolsAtEnd) { + const ::llama_model* model, const common_params& params, bool toolsAtEnd) { // Use fixed Qwen3 template if model is Qwen3 and Jinja is enabled std::string chatTemplate = params.chat_template; if (params.use_jinja) { - chatTemplate = getChatTemplateForModel( - model, params.chat_template, toolsAtEnd); + chatTemplate = + getChatTemplateForModel(model, params.chat_template, toolsAtEnd); if (!chatTemplate.empty() && chatTemplate != params.chat_template) { QLOG_IF( Priority::INFO, "[ChatTemplateUtils] Using fixed Qwen3 template\n"); diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.hpp index 8a22ecea94..1b376faf27 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/ChatTemplateUtils.hpp @@ -22,8 +22,7 @@ bool isQwen3Model(const ::llama_model* model); * For other models, returns the manual override or empty string. */ std::string getChatTemplateForModel( - const ::llama_model* model, - const std::string& manualOverride, + const ::llama_model* model, const std::string& manualOverride, bool toolsAtEnd); /** @@ -31,9 +30,7 @@ std::string getChatTemplateForModel( * enabled */ std::string getChatTemplate( - const ::llama_model* model, - const common_params& params, - bool toolsAtEnd); + const ::llama_model* model, const common_params& params, bool toolsAtEnd); /** * @brief Applies chat templates to generate a prompt, with fallback handling diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/Qwen3ToolsDynamicTemplate.hpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/Qwen3ToolsDynamicTemplate.hpp index fb5a9f8b92..024e0416bf 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/Qwen3ToolsDynamicTemplate.hpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/utils/Qwen3ToolsDynamicTemplate.hpp @@ -12,4 +12,3 @@ const char* getToolsDynamicQwen3Template(); } // namespace utils } // namespace qvac_lib_inference_addon_llama - diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management.cpp index 6250ebc2dc..4510671747 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management.cpp @@ -140,7 +140,6 @@ class CacheManagementTest : public ::testing::Test { std::string session1_path; std::string session2_path; std::string temp_session_path; - }; TEST_F(CacheManagementTest, InitialStateNoCache) { @@ -1069,4 +1068,3 @@ TEST_F(CacheManagementTest, CacheWithToolsAtEndFalseSavesFullCache) { EXPECT_TRUE(fs::exists(session1_path)); } - diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp index 4117497ac2..63f4ddf602 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_cache_management_qwen3.cpp @@ -47,7 +47,9 @@ std::string processPromptString( bool isQwen3ModelPath(const std::string& path) { std::string lowerPath = path; std::transform( - lowerPath.begin(), lowerPath.end(), lowerPath.begin(), + lowerPath.begin(), + lowerPath.end(), + lowerPath.begin(), [](unsigned char c) { return std::tolower(c); }); return lowerPath.find("qwen3") != std::string::npos; } @@ -62,7 +64,8 @@ class CacheManagementQwen3Test : public ::testing::Test { config_files["n_predict"] = "10"; config_files["tools"] = "true"; - test_model_path = test_common::BaseTestModelPath::get("Qwen3-1.7B-Q4_0.gguf", "Llama-3.2-1B-Instruct-Q4_0.gguf"); + test_model_path = test_common::BaseTestModelPath::get( + "Qwen3-1.7B-Q4_0.gguf", "Llama-3.2-1B-Instruct-Q4_0.gguf"); test_projection_path = ""; config_files["backendsDir"] = test_common::getTestBackendsDir().string(); @@ -347,7 +350,9 @@ TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeWithMultiplePrompts) { EXPECT_EQ(cacheTokens4, cacheTokens2); } -TEST_F(CacheManagementQwen3Test, CacheToolsAtEndModeTrimOnlyWhenNPastBeforeToolsPositive) { +TEST_F( + CacheManagementQwen3Test, + CacheToolsAtEndModeTrimOnlyWhenNPastBeforeToolsPositive) { if (!isQwen3ModelPath(test_model_path)) { GTEST_SKIP() << "Test requires Qwen3 model for tools_at_end feature"; } diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_chat_template_utils.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_chat_template_utils.cpp index ef2db48f01..82c089e39a 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_chat_template_utils.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_chat_template_utils.cpp @@ -39,24 +39,32 @@ TEST_F(ChatTemplateUtilsTest, IsQwen3ModelWithNullptr) { EXPECT_FALSE(isQwen3Model(nullptr)); } -TEST_F(ChatTemplateUtilsTest, GetChatTemplateForModelWithManualOverrideToolsAtEndFalse) { +TEST_F( + ChatTemplateUtilsTest, + GetChatTemplateForModelWithManualOverrideToolsAtEndFalse) { std::string manual_override = "custom template"; std::string result = getChatTemplateForModel(nullptr, manual_override, false); EXPECT_EQ(result, manual_override); } -TEST_F(ChatTemplateUtilsTest, GetChatTemplateForModelWithManualOverrideToolsAtEndTrue) { +TEST_F( + ChatTemplateUtilsTest, + GetChatTemplateForModelWithManualOverrideToolsAtEndTrue) { std::string manual_override = "custom template"; std::string result = getChatTemplateForModel(nullptr, manual_override, true); EXPECT_EQ(result, manual_override); } -TEST_F(ChatTemplateUtilsTest, GetChatTemplateForModelEmptyOverrideNullptrToolsAtEndFalse) { +TEST_F( + ChatTemplateUtilsTest, + GetChatTemplateForModelEmptyOverrideNullptrToolsAtEndFalse) { std::string result = getChatTemplateForModel(nullptr, "", false); EXPECT_EQ(result, ""); } -TEST_F(ChatTemplateUtilsTest, GetChatTemplateForModelEmptyOverrideNullptrToolsAtEndTrue) { +TEST_F( + ChatTemplateUtilsTest, + GetChatTemplateForModelEmptyOverrideNullptrToolsAtEndTrue) { std::string result = getChatTemplateForModel(nullptr, "", true); EXPECT_EQ(result, ""); } @@ -111,7 +119,8 @@ TEST_F(ChatTemplateUtilsTest, GetChatTemplateParamsNotModified) { TEST_F(ChatTemplateUtilsTest, GetChatTemplateForModelPreservesWhitespace) { std::string overrideWithSpaces = " template with spaces "; - std::string result = getChatTemplateForModel(nullptr, overrideWithSpaces, false); + std::string result = + getChatTemplateForModel(nullptr, overrideWithSpaces, false); EXPECT_EQ(result, overrideWithSpaces); } @@ -151,7 +160,8 @@ TEST_F(ChatTemplateUtilsTest, ManualOverrideTakesPrecedenceOverToolsAtEnd) { EXPECT_EQ(result, "my_custom_template"); } -TEST_F(ChatTemplateUtilsTest, ManualOverrideTakesPrecedenceOverToolsAtEndFalse) { +TEST_F( + ChatTemplateUtilsTest, ManualOverrideTakesPrecedenceOverToolsAtEndFalse) { common_params params; params.chat_template = "my_custom_template"; params.use_jinja = true; diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context.cpp index 2f57cbf539..fc4546c2b6 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context.cpp @@ -373,8 +373,6 @@ TEST_F(TextLlmContextTest, ProcessWithMultipleTools) { }); } - - TEST_F(TextLlmContextTest, DoubleTokenizeWithoutToolsAtEnd) { if (!hasValidModel()) { FAIL() << "Test model not found"; @@ -405,9 +403,7 @@ TEST_F(TextLlmContextTest, DoubleTokenizeWithoutToolsAtEnd) { } ])"; - EXPECT_NO_THROW({ - std::string output = model->processPrompt(prompt); - }); + EXPECT_NO_THROW({ std::string output = model->processPrompt(prompt); }); auto stats = model->runtimeStats(); int cacheTokens = static_cast(getStatValue(stats, "CacheTokens")); @@ -432,20 +428,15 @@ TEST_F(TextLlmContextTest, DoubleTokenizeWithToolsAtEndNoTools) { LlamaModel::Prompt prompt; prompt.input = R"([{"role": "user", "content": "Hello, how are you?"}])"; - EXPECT_NO_THROW({ - std::string output = model->processPrompt(prompt); - }); + EXPECT_NO_THROW({ std::string output = model->processPrompt(prompt); }); - // Without tools, CacheTokens should equal promptTokens (no cached conversation tokens) + // Without tools, CacheTokens should equal promptTokens (no cached + // conversation tokens) auto stats = model->runtimeStats(); int promptTokens = static_cast(getStatValue(stats, "promptTokens")); EXPECT_LT(promptTokens, 50); } - - - - TEST_F(TextLlmContextTest, DoubleTokenizationTimeOverhead) { if (!hasValidModel()) { FAIL() << "Test model not found"; @@ -539,7 +530,8 @@ TEST_F(TextLlmContextTest, DoubleTokenizationTimeOverhead) { } LlamaModel::Prompt promptNoTools; - promptNoTools.input = R"([{"role": "user", "content": "Hello, how are you?"}])"; + promptNoTools.input = + R"([{"role": "user", "content": "Hello, how are you?"}])"; auto startNoTools = std::chrono::high_resolution_clock::now(); for (int i = 0; i < numIterations; ++i) { @@ -548,8 +540,8 @@ TEST_F(TextLlmContextTest, DoubleTokenizationTimeOverhead) { } auto endNoTools = std::chrono::high_resolution_clock::now(); auto durationNoTools = - std::chrono::duration_cast(endNoTools - - startNoTools) + std::chrono::duration_cast( + endNoTools - startNoTools) .count(); auto stats = model->runtimeStats(); @@ -575,7 +567,8 @@ TEST_F(TextLlmContextTest, DoubleTokenizationTimeOverheadLargePrompt) { } const std::string promptWithTools = R"([ - {"role": "user", "content": ")" + longContent + R"("}, + {"role": "user", "content": ")" + longContent + + R"("}, { "type": "function", "name": "getWeather", @@ -648,10 +641,11 @@ TEST_F(TextLlmContextTest, DoubleTokenizationTimeOverheadLargePrompt) { int promptTokens = static_cast(getStatValue(stats, "promptTokens")); int cacheTokens = static_cast(getStatValue(stats, "CacheTokens")); - GTEST_LOG_(INFO) << "Large prompt - Double tokenization (tools_at_end=true): " - << durationDouble / numIterations << " us per iteration (" - << promptTokens << " prompt tokens, " << cacheTokens - << " cached tokens)"; + GTEST_LOG_(INFO) + << "Large prompt - Double tokenization (tools_at_end=true): " + << durationDouble / numIterations << " us per iteration (" + << promptTokens << " prompt tokens, " << cacheTokens + << " cached tokens)"; } } @@ -670,9 +664,7 @@ TEST_F(TextLlmContextTest, NPastBeforeToolsMinusOneWithoutTools) { LlamaModel::Prompt prompt; prompt.input = R"([{"role": "user", "content": "Hello, how are you?"}])"; - EXPECT_NO_THROW({ - std::string output = model->processPrompt(prompt); - }); + EXPECT_NO_THROW({ std::string output = model->processPrompt(prompt); }); llama_pos nPastBeforeTools = model->getNPastBeforeTools(); EXPECT_EQ(nPastBeforeTools, -1); @@ -708,14 +700,8 @@ TEST_F(TextLlmContextTest, NPastBeforeToolsMinusOneWhenToolsAtEndFalse) { } ])"; - EXPECT_NO_THROW({ - std::string output = model->processPrompt(prompt); - }); + EXPECT_NO_THROW({ std::string output = model->processPrompt(prompt); }); llama_pos nPastBeforeTools = model->getNPastBeforeTools(); EXPECT_EQ(nPastBeforeTools, -1); } - - - - diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context_qwen3.cpp b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context_qwen3.cpp index a8c71e2a1a..67d803d3da 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context_qwen3.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/test/unit/test_text_llm_context_qwen3.cpp @@ -42,7 +42,9 @@ double getStatValue( bool isQwen3ModelPath(const std::string& path) { std::string lowerPath = path; std::transform( - lowerPath.begin(), lowerPath.end(), lowerPath.begin(), + lowerPath.begin(), + lowerPath.end(), + lowerPath.begin(), [](unsigned char c) { return std::tolower(c); }); return lowerPath.find("qwen3") != std::string::npos; } @@ -123,9 +125,7 @@ TEST_F(TextLlmContextQwen3Test, DoubleTokenizeWithToolsAtEnd) { } ])"; - EXPECT_NO_THROW({ - std::string output = model->processPrompt(prompt); - }); + EXPECT_NO_THROW({ std::string output = model->processPrompt(prompt); }); auto stats = model->runtimeStats(); int promptTokens = static_cast(getStatValue(stats, "promptTokens")); @@ -180,9 +180,7 @@ TEST_F(TextLlmContextQwen3Test, DoubleTokenizeWithMultipleTools) { } ])"; - EXPECT_NO_THROW({ - std::string output = model->processPrompt(prompt); - }); + EXPECT_NO_THROW({ std::string output = model->processPrompt(prompt); }); auto stats = model->runtimeStats(); int promptTokens = static_cast(getStatValue(stats, "promptTokens")); @@ -223,27 +221,26 @@ TEST_F(TextLlmContextQwen3Test, DoubleTokenizeBoundaryAccuracy) { } ])"; - EXPECT_NO_THROW({ - std::string output = model->processPrompt(promptWithTools); - }); + EXPECT_NO_THROW( + { std::string output = model->processPrompt(promptWithTools); }); auto statsWithTools = model->runtimeStats(); - int promptTokensWithTools = static_cast(getStatValue(statsWithTools, "promptTokens")); + int promptTokensWithTools = + static_cast(getStatValue(statsWithTools, "promptTokens")); EXPECT_GT(promptTokensWithTools, 150); - EXPECT_NO_THROW({ - model->reset(); - }); + EXPECT_NO_THROW({ model->reset(); }); LlamaModel::Prompt promptNoTools; - promptNoTools.input = R"([{"role": "user", "content": "What is the weather in Tokyo?"}])"; + promptNoTools.input = + R"([{"role": "user", "content": "What is the weather in Tokyo?"}])"; - EXPECT_NO_THROW({ - std::string output = model->processPrompt(promptNoTools); - }); + EXPECT_NO_THROW( + { std::string output = model->processPrompt(promptNoTools); }); auto statsNoTools = model->runtimeStats(); - int promptTokensNoTools = static_cast(getStatValue(statsNoTools, "promptTokens")); + int promptTokensNoTools = + static_cast(getStatValue(statsNoTools, "promptTokens")); EXPECT_LT(promptTokensNoTools, 30); } @@ -282,9 +279,7 @@ TEST_F(TextLlmContextQwen3Test, NPastBeforeToolsSetAfterEvalWithTools) { } ])"; - EXPECT_NO_THROW({ - std::string output = model->processPrompt(prompt); - }); + EXPECT_NO_THROW({ std::string output = model->processPrompt(prompt); }); llama_pos nPastBeforeTools = model->getNPastBeforeTools(); auto stats = model->runtimeStats(); @@ -328,9 +323,7 @@ TEST_F(TextLlmContextQwen3Test, NPastBeforeToolsResetAfterResetState) { } ])"; - EXPECT_NO_THROW({ - std::string output = model->processPrompt(prompt); - }); + EXPECT_NO_THROW({ std::string output = model->processPrompt(prompt); }); llama_pos nPastBeforeToolsBeforeReset = model->getNPastBeforeTools(); EXPECT_EQ(nPastBeforeToolsBeforeReset, -1); From 11b186b68e3af4390f7110a4c7f8149375fcd5aa Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Thu, 19 Mar 2026 17:57:19 +0300 Subject: [PATCH 41/48] style(llamacpp-llm): fix remaining clang-format-19 brace-init formatting Made-with: Cursor --- .../addon/src/model-interface/LlamaModel.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp index 5324423d7e..40a312e2d6 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/LlamaModel.cpp @@ -1146,14 +1146,13 @@ std::string LlamaModel::finetune( // (e.g. flash-attn off, ubatch sizing) and gives a clean llama_context. // TODO: investigate recreating the context without a full weights reload // to reduce latency when the backend itself does not change. - reload( - FinetuneConfigOverrides{ - .active = true, - .batchSize = params.batchSize, - .microBatchSize = params.microBatchSize, - .contextLength = params.contextLength, - .gpuSupportsF16OutProd = gpuSupportsOutProdF16(), - .flashAttn = params.flashAttn}); + reload(FinetuneConfigOverrides{ + .active = true, + .batchSize = params.batchSize, + .microBatchSize = params.microBatchSize, + .contextLength = params.contextLength, + .gpuSupportsF16OutProd = gpuSupportsOutProdF16(), + .flashAttn = params.flashAttn}); llama_context* ctx = getContext(); llama_model* mdl = getModel(); From 1bb65561f382caa5a97adc1b6434ce172cbba369 Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Thu, 19 Mar 2026 19:26:17 +0300 Subject: [PATCH 42/48] chore: remove accidentally committed binary file The file packages/ocr-onnx/big_and_clear_watermarks.png was unintentionally staged during merge conflict resolution. Made-with: Cursor --- packages/ocr-onnx/big_and_clear_watermarks.png | Bin 879152 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 packages/ocr-onnx/big_and_clear_watermarks.png diff --git a/packages/ocr-onnx/big_and_clear_watermarks.png b/packages/ocr-onnx/big_and_clear_watermarks.png deleted file mode 100644 index 0d39508e0ac532a8fe096064a2ebee8880b54fca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 879152 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ˁHdgI(Me_TJhXF^gt%(qcm~ZFJz5`J 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%0D2w<%rk+7S3Vuw2k@+iRXMda{gQgr` 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�&6UH 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 From 02a327a58a71bf2f8be1c20848217ca72dc503f2 Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Thu, 19 Mar 2026 19:59:35 +0300 Subject: [PATCH 43/48] chore(llm): bump version to 0.14.0 Made-with: Cursor --- packages/qvac-lib-infer-llamacpp-llm/CHANGELOG.md | 2 +- packages/qvac-lib-infer-llamacpp-llm/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/CHANGELOG.md b/packages/qvac-lib-infer-llamacpp-llm/CHANGELOG.md index cd875f11fb..9c99acb184 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/CHANGELOG.md +++ b/packages/qvac-lib-infer-llamacpp-llm/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## [0.13.1] - 2026-03-19 +## [0.14.0] - 2026-03-19 ### Added diff --git a/packages/qvac-lib-infer-llamacpp-llm/package.json b/packages/qvac-lib-infer-llamacpp-llm/package.json index 89cb192489..d09f84e089 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/package.json +++ b/packages/qvac-lib-infer-llamacpp-llm/package.json @@ -1,6 +1,6 @@ { "name": "@qvac/llm-llamacpp", - "version": "0.13.0", + "version": "0.14.0", "description": "llama addon for qvac", "addon": true, "scripts": { From 7d3398881cee6ce3731c34ed68ff50a10df0dc83 Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Thu, 19 Mar 2026 20:01:46 +0300 Subject: [PATCH 44/48] chore: remove working artifacts from feature branch Made-with: Cursor --- .../new-tests-results.xml | 135 ------- .../prefill_offset_implementation_plan.md | 341 ------------------ 2 files changed, 476 deletions(-) delete mode 100644 packages/qvac-lib-infer-llamacpp-llm/new-tests-results.xml delete mode 100644 packages/qvac-lib-infer-llamacpp-llm/prefill_offset_implementation_plan.md diff --git a/packages/qvac-lib-infer-llamacpp-llm/new-tests-results.xml b/packages/qvac-lib-infer-llamacpp-llm/new-tests-results.xml deleted file mode 100644 index 34c1f7152c..0000000000 --- a/packages/qvac-lib-infer-llamacpp-llm/new-tests-results.xml +++ /dev/null @@ -1,135 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/qvac-lib-infer-llamacpp-llm/prefill_offset_implementation_plan.md b/packages/qvac-lib-infer-llamacpp-llm/prefill_offset_implementation_plan.md deleted file mode 100644 index ac48469120..0000000000 --- a/packages/qvac-lib-infer-llamacpp-llm/prefill_offset_implementation_plan.md +++ /dev/null @@ -1,341 +0,0 @@ -# Prefill with Offset — Implementation Plan - -## Goal - -Add an `offset` parameter to the eval methods in the LLM addon's C++ layer. When provided, the KV cache is trimmed to `offset` position before evaluating new tokens. Combined with `prefill=true` (from PR #689), this enables the tools-at-end KV cache optimization entirely in C++, with no JS API changes. - -## Context - -The tools-at-end optimization (see `Pitch_tools_at_end_of_prompt.md`) requires: -1. Trimming the KV cache tail (remove old tools + response tokens) -2. Prefilling known tokens (previous response + new query + new tools) from a specific cache position -3. Generating from the warm cache - -PR #689 adds `prefill=true` which evaluates tokens into the KV cache without generating. But it always appends at `nPast_` — there's no way to say "go back to position X and prefill from there." The `offset` parameter fills that gap. - -## How It Works - -``` -offset = -1 (default): current behavior, eval starts from nPast_ -offset >= 0: trim KV cache to that position, then eval new tokens from there -``` - -When `evalMessageWithTools` receives `offset >= 0 && offset < nPast_`: -1. Call `removeLastNTokens(nPast_ - offset)` — this trims the KV cache and sets `nPast_ = offset` -2. Proceed with normal token evaluation starting from the new `nPast_` - -This is atomic — trim + eval in a single call. No need for the caller to manually call `removeLastNTokens` then `evalMessage` separately. - -## End-to-End Flow (tools-at-end optimization) - -This is how `processPrompt()` would use offset + prefill internally: - -### Turn 1 (cold start) -``` -KV cache: empty -Prompt: - -1. evalMessageWithTools(msgs, tools1, ..., prefill=false, offset=-1) - -> tokens evaluated at pos 0..N-1, nPast_ = N -2. generateResponse() -> model generates, nPast_ = N + G -3. Track: toolTokenCount_ = T, responseTokenCount_ = G - Cache state: [system | user-q-1 | tools-1 | response-1] - pos 0 pos N-T pos N pos N+G -``` - -### Turn 2 (tools changed) -``` -KV cache: [system | user-q-1 | tools-1 | response-1] -Want: [system | user-q-1 | response-1 | user-q-2 | tools-2] - -offset = N - T (position just before old tools) - -1. Build full message array: [system, user-q-1, assistant-response-1, user-q-2] + tools-2 -2. evalMessageWithTools(msgs, tools2, ..., prefill=false, offset=N-T) - -> removeLastNTokens(nPast_ - offset) trims tools-1 + response-1 - -> KV cache: [system | user-q-1] - -> tokenizeChat produces full prompt tokens - -> only NEW tokens (after the cached prefix) are evaluated - -> nPast_ updated to include response-1 + user-q-2 + tools-2 -3. generateResponse() -> model generates turn 2 response -``` - -Note: The prefill flag is for when you want to eval without generating (preload context). The offset works with both `prefill=true` and `prefill=false`. - ---- - -## Files to Change - -All files are under `packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/`. - -### 1. LlmContext.hpp (virtual interface) - -**What:** Add `offset` parameter to both virtual method signatures. - -**Current (after PR #689):** -```cpp -virtual bool evalMessage( - const std::vector& chatMsgs, bool isCacheLoaded, - bool prefill) = 0; - -virtual bool evalMessageWithTools( - const std::vector& chatMsgs, - const std::vector& tools, bool isCacheLoaded, - bool prefill) = 0; -``` - -**New:** -```cpp -virtual bool evalMessage( - const std::vector& chatMsgs, bool isCacheLoaded, - bool prefill, llama_pos offset = -1) = 0; - -virtual bool evalMessageWithTools( - const std::vector& chatMsgs, - const std::vector& tools, bool isCacheLoaded, - bool prefill, llama_pos offset = -1) = 0; -``` - -**Lines affected:** ~114-128 (the two virtual declarations and their doc comments) - -**Doc comment addition for both methods:** -```cpp -* @param offset - KV cache position to trim to before evaluation. -* -1 means no trimming (default, eval from current nPast_). -* >= 0 trims cache to this position, then evaluates from there. -``` - ---- - -### 2. TextLlmContext.hpp (override declarations) - -**What:** Update override signatures to match new virtual interface. - -**Current (after PR #689):** -```cpp -bool evalMessage( - const std::vector& chatMsgs, - bool isCacheLoaded, bool prefill) override; - -bool evalMessageWithTools( - const std::vector& chatMsgs, - const std::vector& tools, bool isCacheLoaded, - bool prefill) override; -``` - -**New:** -```cpp -bool evalMessage( - const std::vector& chatMsgs, - bool isCacheLoaded, bool prefill, llama_pos offset = -1) override; - -bool evalMessageWithTools( - const std::vector& chatMsgs, - const std::vector& tools, bool isCacheLoaded, - bool prefill, llama_pos offset = -1) override; -``` - -**Lines affected:** ~30-45 - ---- - -### 3. TextLlmContext.cpp (implementation) - -**What:** Two changes — update signatures + add trim logic. - -#### 3a. evalMessage (forwarding method, ~line 256) - -**Current (after PR #689):** -```cpp -bool TextLlmContext::evalMessage( - const std::vector& chatMsgs, bool isCacheLoaded, - bool prefill) { - return evalMessageWithTools(chatMsgs, {}, isCacheLoaded, prefill); -} -``` - -**New:** -```cpp -bool TextLlmContext::evalMessage( - const std::vector& chatMsgs, bool isCacheLoaded, - bool prefill, llama_pos offset) { - return evalMessageWithTools(chatMsgs, {}, isCacheLoaded, prefill, offset); -} -``` - -#### 3b. evalMessageWithTools (main method, ~line 261) - -**Current (after PR #689):** -```cpp -bool TextLlmContext::evalMessageWithTools( - const std::vector& chatMsgs, - const std::vector& tools, bool isCacheLoaded, - bool prefill) { - std::vector inputTokens; - tokenizeChat(chatMsgs, tools, inputTokens, isCacheLoaded); - // ... rest of method -``` - -**New:** -```cpp -bool TextLlmContext::evalMessageWithTools( - const std::vector& chatMsgs, - const std::vector& tools, bool isCacheLoaded, - bool prefill, llama_pos offset) { - - // Trim KV cache to offset position if specified - if (offset >= 0 && offset < nPast_) { - removeLastNTokens(nPast_ - offset); - } - - std::vector inputTokens; - tokenizeChat(chatMsgs, tools, inputTokens, isCacheLoaded); - // ... rest of method unchanged -``` - -**Why this works:** `removeLastNTokens` calls `llama_memory_seq_rm` to remove entries from the KV cache and decrements `nPast_`. The existing eval loop uses `llama_pos count = nPast_` (line ~319) as its starting position, so new tokens are naturally placed right after the offset. - ---- - -### 4. MtmdLlmContext.hpp (override declarations) - -**What:** Same signature update as TextLlmContext.hpp. - -**Current (after PR #689):** -```cpp -bool evalMessage( - const std::vector& chatMsgs, - bool isCacheLoaded, bool prefill) override; - -bool evalMessageWithTools( - const std::vector& chatMsgs, - const std::vector& tools, bool isCacheLoaded, - bool prefill) override; -``` - -**New:** -```cpp -bool evalMessage( - const std::vector& chatMsgs, - bool isCacheLoaded, bool prefill, llama_pos offset = -1) override; - -bool evalMessageWithTools( - const std::vector& chatMsgs, - const std::vector& tools, bool isCacheLoaded, - bool prefill, llama_pos offset = -1) override; -``` - -**Lines affected:** ~37-52 - ---- - -### 5. MtmdLlmContext.cpp (implementation) - -**What:** Same pattern as TextLlmContext.cpp — update signatures + add trim logic. - -#### 5a. evalMessage (forwarding method, ~line 210) - -**New:** -```cpp -bool MtmdLlmContext::evalMessage( - const std::vector& chatMsgs, bool isCacheLoaded, - bool prefill, llama_pos offset) { - return evalMessageWithTools(chatMsgs, {}, isCacheLoaded, prefill, offset); -} -``` - -#### 5b. evalMessageWithTools (main method, ~line 215) - -**New (add trim block at top):** -```cpp -bool MtmdLlmContext::evalMessageWithTools( - const std::vector& chatMsgs, - const std::vector& tools, bool isCacheLoaded, - bool prefill, llama_pos offset) { - - // Trim KV cache to offset position if specified - if (offset >= 0 && offset < nPast_) { - removeLastNTokens(nPast_ - offset); - } - - mtmd::input_chunks chunks(mtmd_input_chunks_init()); - tokenizeChat(chatMsgs, tools, chunks, isCacheLoaded); - // ... rest unchanged -``` - ---- - -### 6. LlamaModel.cpp — processPrompt() passes offset - -**What:** Thread `offset` from the internal call site into eval methods. For now, always pass `-1` (no trim) to keep existing behavior. The tools-at-end optimization will set a real offset later. - -**Current (after PR #689, ~line 262):** -```cpp -bool evalOk = - resolved.tools.empty() - ? llmContext_->evalMessage( - resolved.chatMsgs, resolved.isCacheLoaded, prompt.prefill) - : llmContext_->evalMessageWithTools( - resolved.chatMsgs, resolved.tools, - resolved.isCacheLoaded, prompt.prefill); -``` - -**No change needed here** — since the default value is `offset = -1` in the virtual declarations, existing call sites don't need to be updated. The offset will only be passed explicitly when the tools-at-end optimization is implemented in `processPrompt()`. - ---- - -## Files NOT Changed - -| File | Why | -|------|-----| -| `LlamaModel.hpp` | `Prompt` struct not touched — offset is internal to C++, not from JS | -| `index.js` | JS API unchanged | -| `index.d.ts` | TypeScript types unchanged | -| `CacheManager.hpp/.cpp` | Cache manager deals with disk sessions, not in-flight cache trimming | - ---- - -## Testing - -### Unit-level validation for offset - -Add to `test/integration/api-behavior.test.js`: - -```js -test('prefill with offset trims cache and re-evaluates', { timeout: 600_000 }, async t => { - const { model } = await setupModel(t) - - // 1. Normal run to populate cache - const r1 = await model.run(BASE_PROMPT) - await collectResponse(r1) - const cacheAfterR1 = toNumber(r1?.stats?.CacheTokens) - t.ok(cacheAfterR1 > 0, 'cache populated after first run') - - // 2. Prefill with offset=0 should trim entire cache, then re-evaluate - const r2 = await model.run(BASE_PROMPT, { prefill: true, offset: 0 }) - await collectResponse(r2) - const cacheAfterR2 = toNumber(r2?.stats?.CacheTokens) - t.ok(cacheAfterR2 > 0, 'cache repopulated after prefill with offset') - - // 3. Normal run after prefill should still work - const r3 = await model.run(BASE_PROMPT) - const output = await collectResponse(r3) - t.ok(output.length > 0, 'generation works after prefill with offset') -}) -``` - -Note: This test requires exposing `offset` via JS (`RunOptions`). If offset stays internal-only in C++, this test would need to be a C++ unit test instead. - ---- - -## Summary - -| Change | Files | Lines of new logic | -|--------|-------|--------------------| -| Add `offset` param to virtual interface | `LlmContext.hpp` | signature only | -| Update TextLlm override signatures | `TextLlmContext.hpp` | signature only | -| Add trim-to-offset logic in TextLlm | `TextLlmContext.cpp` | 3 lines | -| Update MtmdLlm override signatures | `MtmdLlmContext.hpp` | signature only | -| Add trim-to-offset logic in MtmdLlm | `MtmdLlmContext.cpp` | 3 lines | - -Total new logic: ~6 lines across 2 files. The rest is signature propagation. From 2ddac418b30b0cb034c230dc7074b94b7ae33f99 Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Thu, 19 Mar 2026 20:05:19 +0300 Subject: [PATCH 45/48] chore: remove accidentally committed sdk model history file Made-with: Cursor --- packages/sdk/models/history/58d5f78.txt | 72 ------------------------- 1 file changed, 72 deletions(-) delete mode 100644 packages/sdk/models/history/58d5f78.txt diff --git a/packages/sdk/models/history/58d5f78.txt b/packages/sdk/models/history/58d5f78.txt deleted file mode 100644 index 418b52f78f..0000000000 --- a/packages/sdk/models/history/58d5f78.txt +++ /dev/null @@ -1,72 +0,0 @@ -commit=58d5f7823d35a25509f2e68cb9035646ec9f1985 -timestamp=2026-03-09T14:03:50.201Z -previous_count=293 -new_count=297 - -[added] -WHISPER_FRENCH_BASE_F16 -WHISPER_FRENCH_BASE_Q8_0 -WHISPER_FRENCH_TINY_F16 -WHISPER_FRENCH_TINY_Q8_0 -WHISPER_GERMAN_BASE_F16 -WHISPER_GERMAN_BASE_Q8_0 -WHISPER_GERMAN_TINY_F16 -WHISPER_GERMAN_TINY_Q8_0 -WHISPER_ITALIAN_BASE_F16 -WHISPER_ITALIAN_BASE_Q8_0 -WHISPER_ITALIAN_TINY_F16 -WHISPER_ITALIAN_TINY_Q8_0 -WHISPER_JAPANESE_BASE_F16 -WHISPER_JAPANESE_BASE_Q8_0 -WHISPER_JAPANESE_TINY_F16 -WHISPER_JAPANESE_TINY_Q8_0 -WHISPER_NORWEGIAN_TINY -WHISPER_PORTUGUESE_BASE_F16 -WHISPER_PORTUGUESE_BASE_Q8_0 -WHISPER_PORTUGUESE_TINY_F16 -WHISPER_PORTUGUESE_TINY_Q8_0 -WHISPER_RUSSIAN_BASE_F16 -WHISPER_RUSSIAN_BASE_Q8_0 -WHISPER_RUSSIAN_TINY_F16 -WHISPER_RUSSIAN_TINY_Q8_0 -WHISPER_SPANISH_TINY_F16 -WHISPER_SPANISH_TINY_Q8_0 -OCR_RECOGNIZER_CRNN_MOBILENET_V3_SMALL -OCR_DETECTOR_DB_MOBILENET_V3_LARGE -OCR_DETECTOR_DB_RESNET50 -OCR_RECOGNIZER_PARSEQ -PARAKEET_DECODER_INT8 -PARAKEET_ENCODER_INT8 -PARAKEET_PREPROCESSOR_INT8 - -[removed] -PARAKEET_DECODER_INT8 -PARAKEET_ENCODER_INT8 -PARAKEET_PREPROCESSOR_INT8 -WHISPER_FRENCH_BASE_F16 -WHISPER_FRENCH_BASE_Q8_0 -WHISPER_FRENCH_TINY_F16 -WHISPER_FRENCH_TINY_Q8_0 -WHISPER_GERMAN_BASE_F16 -WHISPER_GERMAN_BASE_Q8_0 -WHISPER_GERMAN_TINY_F16 -WHISPER_GERMAN_TINY_Q8_0 -WHISPER_ITALIAN_BASE_F16 -WHISPER_ITALIAN_BASE_Q8_0 -WHISPER_ITALIAN_TINY_F16 -WHISPER_ITALIAN_TINY_Q8_0 -WHISPER_JAPANESE_BASE_F16 -WHISPER_JAPANESE_BASE_Q8_0 -WHISPER_JAPANESE_TINY_F16 -WHISPER_JAPANESE_TINY_Q8_0 -WHISPER_NORWEGIAN_TINY -WHISPER_PORTUGUESE_BASE_F16 -WHISPER_PORTUGUESE_BASE_Q8_0 -WHISPER_PORTUGUESE_TINY_F16 -WHISPER_PORTUGUESE_TINY_Q8_0 -WHISPER_RUSSIAN_BASE_F16 -WHISPER_RUSSIAN_BASE_Q8_0 -WHISPER_RUSSIAN_TINY_F16 -WHISPER_RUSSIAN_TINY_Q8_0 -WHISPER_SPANISH_TINY_F16 -WHISPER_SPANISH_TINY_Q8_0 From 79dab19d0b06077b12f3e9564a0bfbf4fd9bb53c Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Thu, 19 Mar 2026 20:09:32 +0300 Subject: [PATCH 46/48] doc: add dynamic-tools examples to README Made-with: Cursor --- packages/qvac-lib-infer-llamacpp-llm/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/qvac-lib-infer-llamacpp-llm/README.md b/packages/qvac-lib-infer-llamacpp-llm/README.md index ef0ecf9539..1d58866ef4 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/README.md +++ b/packages/qvac-lib-infer-llamacpp-llm/README.md @@ -300,6 +300,8 @@ For the full API, dataset format, parameters, and examples, see the **[Finetunin - [LoRA Finetuning](./examples/simple-lora-finetune.js) – Basic LoRA finetuning. - [LoRA Finetuning Pause/Resume](./examples/simple-lora-finetune-pause-resume.js) – Pause and resume finetuning. - [LoRA Inference](./examples/simple-lora-inference.js) – Inference with a finetuned LoRA adapter. +- [Bench Tools Placement](./examples/benchToolsPlacement.js) – Benchmarks standard vs `tools_at_end` placement across multi-turn conversations. +- [Test Tool Removal](./examples/testToolRemoval.js) – Demonstrates dynamic tool addition and removal between turns. ## OCR with Vision-Language Models From 22603f9c0a5bf3bb4891d95853fa977e321a439c Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Thu, 19 Mar 2026 20:20:06 +0300 Subject: [PATCH 47/48] fix(llm): reset use_jinja from params_ instead of save/restore Made-with: Cursor --- .../addon/src/model-interface/MtmdLlmContext.cpp | 3 +-- .../addon/src/model-interface/TextLlmContext.cpp | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp index 6573d054d8..6179f803bb 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp @@ -205,11 +205,10 @@ void MtmdLlmContext::tokenizeChat( } if (dynamicToolsState().toolsAtEnd() && !tools.empty()) { - auto savedUseJinja = inputs.use_jinja; inputs.tools = {}; inputs.add_generation_prompt = false; auto promptNoTools = getPrompt(tmpls_.get(), inputs); - inputs.use_jinja = savedUseJinja; + inputs.use_jinja = params_.use_jinja; if (!promptNoTools.empty()) { mtmd_input_text textNoTools; diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp index 62ca039fb5..fafff5caef 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp @@ -219,14 +219,13 @@ void TextLlmContext::tokenizeChat( inputTokens = common_tokenize(lctx_, prompt, addSpecial, true); if (dynamicToolsState().toolsAtEnd() && !tools.empty()) { - auto savedUseJinja = inputs.use_jinja; inputs.tools = {}; inputs.add_generation_prompt = false; auto promptNoTools = getPrompt(tmpls_.get(), inputs); auto tokensNoTools = common_tokenize(lctx_, promptNoTools, addSpecial, true); - inputs.use_jinja = savedUseJinja; + inputs.use_jinja = params_.use_jinja; dynamicToolsState().setConversationOnlyTokens(tokensNoTools.size()); assert( dynamicToolsState().conversationOnlyTokens() <= From b9a54ec08a01a8cf4cf3a6c617aee5f0b4d36f00 Mon Sep 17 00:00:00 2001 From: Dmitry Malishev Date: Thu, 19 Mar 2026 20:47:02 +0300 Subject: [PATCH 48/48] fix(llm): reset use_jinja before second getPrompt call Made-with: Cursor --- .../addon/src/model-interface/MtmdLlmContext.cpp | 2 +- .../addon/src/model-interface/TextLlmContext.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp index 6179f803bb..afc9f5811e 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/MtmdLlmContext.cpp @@ -207,8 +207,8 @@ void MtmdLlmContext::tokenizeChat( if (dynamicToolsState().toolsAtEnd() && !tools.empty()) { inputs.tools = {}; inputs.add_generation_prompt = false; - auto promptNoTools = getPrompt(tmpls_.get(), inputs); inputs.use_jinja = params_.use_jinja; + auto promptNoTools = getPrompt(tmpls_.get(), inputs); if (!promptNoTools.empty()) { mtmd_input_text textNoTools; diff --git a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp index fafff5caef..9c1da490e2 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp +++ b/packages/qvac-lib-infer-llamacpp-llm/addon/src/model-interface/TextLlmContext.cpp @@ -221,11 +221,10 @@ void TextLlmContext::tokenizeChat( if (dynamicToolsState().toolsAtEnd() && !tools.empty()) { inputs.tools = {}; inputs.add_generation_prompt = false; + inputs.use_jinja = params_.use_jinja; auto promptNoTools = getPrompt(tmpls_.get(), inputs); auto tokensNoTools = common_tokenize(lctx_, promptNoTools, addSpecial, true); - - inputs.use_jinja = params_.use_jinja; dynamicToolsState().setConversationOnlyTokens(tokensNoTools.size()); assert( dynamicToolsState().conversationOnlyTokens() <=