diff --git a/backend/cpp/llama-cpp/CMakeLists.txt b/backend/cpp/llama-cpp/CMakeLists.txt index 4a6ef1dac233..7f257098063a 100644 --- a/backend/cpp/llama-cpp/CMakeLists.txt +++ b/backend/cpp/llama-cpp/CMakeLists.txt @@ -125,4 +125,9 @@ if(LLAMA_GRPC_BUILD_TESTS) target_include_directories(thread_params_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_features(thread_params_test PRIVATE cxx_std_17) add_test(NAME thread_params_test COMMAND thread_params_test) + + add_executable(model_load_error_test model_load_error_test.cpp model_load_error.h) + target_include_directories(model_load_error_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + target_compile_features(model_load_error_test PRIVATE cxx_std_17) + add_test(NAME model_load_error_test COMMAND model_load_error_test) endif() diff --git a/backend/cpp/llama-cpp/grpc-server.cpp b/backend/cpp/llama-cpp/grpc-server.cpp index 171ae0483e70..6e2253625121 100644 --- a/backend/cpp/llama-cpp/grpc-server.cpp +++ b/backend/cpp/llama-cpp/grpc-server.cpp @@ -53,6 +53,7 @@ #include "arg.h" #include "chat-auto-parser.h" #include "llama_compat.h" // fork-skew switches, generated by prepare.sh +#include "model_load_error.h" #include "thread_params.h" #include "message_content.h" #include "passthrough_options.h" @@ -1615,7 +1616,8 @@ class BackendServiceImpl final : public backend::Backend::Service { { std::lock_guard lock(error_capture_data.error_mutex); if (!error_capture_data.captured_error.empty()) { - error_msg += ". Error: " + error_capture_data.captured_error; + error_msg += ". Error: " + + localai::model_load_error_with_hint(error_capture_data.captured_error); } else { error_msg += ". Model file may not exist or be invalid."; } diff --git a/backend/cpp/llama-cpp/model_load_error.h b/backend/cpp/llama-cpp/model_load_error.h new file mode 100644 index 000000000000..14cc6db8a144 --- /dev/null +++ b/backend/cpp/llama-cpp/model_load_error.h @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +namespace localai { + +inline std::string model_load_error_with_hint(const std::string& error) { + const std::string mismatch = "wrong number of tensors; expected "; + const std::string got = ", got "; + const std::string::size_type mismatch_pos = error.find(mismatch); + if (mismatch_pos == std::string::npos || + error.find(got, mismatch_pos + mismatch.size()) == std::string::npos) { + return error; + } + + return error + + " Hint: the model may be incompatible with this llama.cpp backend " + "or the GGUF file may be corrupt. Try a newer compatible backend " + "and verify or re-download the model file."; +} + +} // namespace localai diff --git a/backend/cpp/llama-cpp/model_load_error_test.cpp b/backend/cpp/llama-cpp/model_load_error_test.cpp new file mode 100644 index 000000000000..6b3164ba703b --- /dev/null +++ b/backend/cpp/llama-cpp/model_load_error_test.cpp @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT + +#include "model_load_error.h" + +#include +#include + +int main() { + const std::string issue_error = + "llama_model_load: error loading model: done_getting_tensors: wrong number of tensors; expected 2131, got 720; " + "llama_model_load_from_file_impl: failed to load model"; + const std::string issue_result = localai::model_load_error_with_hint(issue_error); + assert(issue_result.compare(0, issue_error.size(), issue_error) == 0); + assert(issue_result.find("incompatible") != std::string::npos); + assert(issue_result.find("corrupt") != std::string::npos); + + const std::string generic_error = + "wrong number of tensors; expected 42, got 17"; + const std::string generic_result = localai::model_load_error_with_hint(generic_error); + assert(generic_result.compare(0, generic_error.size(), generic_error) == 0); + assert(generic_result.size() > generic_error.size()); + + const std::string unrelated_error = "failed to open GGUF file"; + assert(localai::model_load_error_with_hint(unrelated_error) == unrelated_error); +} diff --git a/backend/cpp/llama-cpp/prepare.sh b/backend/cpp/llama-cpp/prepare.sh index e658a940ae86..1e8e7692b264 100644 --- a/backend/cpp/llama-cpp/prepare.sh +++ b/backend/cpp/llama-cpp/prepare.sh @@ -21,6 +21,10 @@ done cp -r CMakeLists.txt llama.cpp/tools/grpc-server/ cp -r grpc-server.cpp llama.cpp/tools/grpc-server/ +# Model-load diagnostics (included by grpc-server.cpp) and their standalone +# regression test. +cp -r model_load_error.h llama.cpp/tools/grpc-server/ +cp -r model_load_error_test.cpp llama.cpp/tools/grpc-server/ # Shared message-reconstruction helpers (included by grpc-server.cpp) and their # unit test (compiled only when -DLLAMA_GRPC_BUILD_TESTS=ON). cp -r message_content.h llama.cpp/tools/grpc-server/