From e2d9525a1357cccf228d5987169ec5bb3894a886 Mon Sep 17 00:00:00 2001 From: Anri Lombard Date: Tue, 30 Dec 2025 07:55:39 +0200 Subject: [PATCH 1/2] chat: make tool description and parameters optional per OpenAI spec Per the OpenAI API specification, both 'description' and 'parameters' fields in tool function definitions are optional. Previously, the parser would throw an exception if these fields were missing. Attempts to fix #17667 --- common/chat.cpp | 4 ++-- tests/test-chat.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/common/chat.cpp b/common/chat.cpp index 0a426f44786..eb81408a8b1 100644 --- a/common/chat.cpp +++ b/common/chat.cpp @@ -380,8 +380,8 @@ std::vector common_chat_tools_parse_oaicompat(const json & too const auto & function = tool.at("function"); result.push_back({ /* .name = */ function.at("name"), - /* .description = */ function.at("description"), - /* .parameters = */ function.at("parameters").dump(), + /* .description = */ function.contains("description") ? function.at("description") : "", + /* .parameters = */ (function.contains("parameters") ? function.at("parameters") : json::object()).dump(), }); } } diff --git a/tests/test-chat.cpp b/tests/test-chat.cpp index 02af5251cc6..2cba4cce987 100644 --- a/tests/test-chat.cpp +++ b/tests/test-chat.cpp @@ -724,6 +724,30 @@ static void test_tools_oaicompat_json_conversion() { "]" ), common_chat_tools_to_json_oaicompat({special_function_tool}).dump(2)); + + { + auto tools_no_params = common_chat_tools_parse_oaicompat(json::parse( + R"([{"type": "function", "function": {"name": "test_func", "description": "A test"}}])")); + assert_equals((size_t) 1, tools_no_params.size()); + assert_equals(std::string("test_func"), tools_no_params[0].name); + assert_equals(std::string("A test"), tools_no_params[0].description); + assert_equals(std::string("{}"), tools_no_params[0].parameters); + } + { + auto tools_no_desc = common_chat_tools_parse_oaicompat(json::parse( + R"([{"type": "function", "function": {"name": "test_func", "parameters": {"type": "object"}}}])")); + assert_equals((size_t) 1, tools_no_desc.size()); + assert_equals(std::string("test_func"), tools_no_desc[0].name); + assert_equals(std::string(""), tools_no_desc[0].description); + } + { + auto tools_minimal = common_chat_tools_parse_oaicompat(json::parse( + R"([{"type": "function", "function": {"name": "test_func"}}])")); + assert_equals((size_t) 1, tools_minimal.size()); + assert_equals(std::string("test_func"), tools_minimal[0].name); + assert_equals(std::string(""), tools_minimal[0].description); + assert_equals(std::string("{}"), tools_minimal[0].parameters); + } } static void test_template_output_parsers() { From 98cf5f01b5a3a89e72c8416658822d4e1ce57cd3 Mon Sep 17 00:00:00 2001 From: Anri Lombard Date: Wed, 31 Dec 2025 06:39:41 +0200 Subject: [PATCH 2/2] refactor: use value() for cleaner optional field access --- common/chat.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/chat.cpp b/common/chat.cpp index eb81408a8b1..a24ba861519 100644 --- a/common/chat.cpp +++ b/common/chat.cpp @@ -380,8 +380,8 @@ std::vector common_chat_tools_parse_oaicompat(const json & too const auto & function = tool.at("function"); result.push_back({ /* .name = */ function.at("name"), - /* .description = */ function.contains("description") ? function.at("description") : "", - /* .parameters = */ (function.contains("parameters") ? function.at("parameters") : json::object()).dump(), + /* .description = */ function.value("description", ""), + /* .parameters = */ function.value("parameters", json::object()).dump(), }); } }