AutoParser: improve reasoning budget and handling of space/newline in tool calls (#1819)

common/chat, server: refactor, move all conversion functions to common, add tests (#20690)

jinja : remove unused header (#22310)

common : fix jinja warnings with clang 21 (#22313)

Signed-off-by: Adrien Gallouët <angt@huggingface.co>

chat: fix handling of space in reasoning markers (#22353)

* chat: fix handling of space in reasoning markers

common : re-arm reasoning budget after DONE on new <think> (#22323)

common : determine generation prompt using longest common prefix (#22657)

common/autoparser: fixes for newline handling / forced tool calls (#22654)

* chat/autoparser: the fixes

* Move optspace() to chat-peg-parser, comment out server tests invalidated due to content now allowed with forced tool calls.

* Trim whitespace on apply instead

common/chat : preserve media markers for typed-content templates (#22634)

common : revert reasoning budget +inf logit bias (#22740)

common : do not wrap raw strings in schema parser for tagged parsers (#22827)

common : enable streaming JSON argument values (#23173)

* common : remove atomic from json arguments

* common : remove parsing logic on JSON arguments

common : do not pass prompt tokens to reasoning budget sampler (#22488)

reasoning-budget: clone should do a deep-copy (#23095)

Co-authored-by: Piotr Wilkin (ilintar) <piotr.wilkin@syndatis.com>
This commit is contained in:
firecoperana
2026-05-19 08:34:19 +03:00
committed by GitHub
co-authored by Piotr Wilkin
parent 40aae0b6d8
commit f645ed1e2d
24 changed files with 1267 additions and 754 deletions
+1 -1
View File
@@ -1331,7 +1331,7 @@ static void test_nemotron_reasoning_detection(testing & t) {
// Check reasoning markers
t.assert_equal("reasoning_start should be '<think>\\n'", "<think>\n", analysis.reasoning.start);
t.assert_equal("reasoning_end should be '</think>'", "</think>", analysis.reasoning.end);
t.assert_equal("reasoning_end should be '\\n</think>\\n'", "\n</think>\n", analysis.reasoning.end);
// Check reasoning mode detection
// Nemotron uses tag-based reasoning; prefill handles the template's forced markers
+454 -35
View File
@@ -7,6 +7,7 @@
//
#include "../src/llama-grammar.h"
#include "../src/unicode.h"
#include "../example/server/server-chat.h"
#include "chat-auto-parser.h"
#include "chat.h"
#include "common.h"
@@ -541,6 +542,36 @@ static common_chat_tool edit_tool{
})",
};
static common_chat_tool manage_todo_list_tool{
/* .name = */ "manage_todo_list",
/* .description = */ "Create or update the todo list",
/* .parameters = */ R"({
"type": "object",
"properties": {
"todos": {
"type": "array",
"description": "List of TODO list items"
}
},
"required": ["todos"]
})",
};
static common_chat_tool run_in_terminal_tool{
/* .name = */ "run_in_terminal",
/* .description = */ "Run a shell command.",
/* .parameters = */ R"({
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "Shell command to run"
}
},
"required": ["command"]
})",
};
static common_chat_tool magic_tool{
/* .name = */ "magic",
/* .description = */ "Magic tool that takes a hash",
@@ -1378,6 +1409,16 @@ class peg_test_builder {
return *this;
}
peg_test_builder & tool_choice(common_chat_tool_choice choice) {
tc_.params.tool_choice = choice;
return *this;
}
peg_test_builder & messages(std::vector<common_chat_msg> messages) {
tc_.params.messages = std::move(messages);
return *this;
}
// Execute the test
void run() {
// Check template filter
@@ -1514,6 +1555,117 @@ static void test_tools_oaicompat_json_conversion() {
common_chat_tools_to_json_oaicompat({ special_function_tool }).dump(2));
}
static void test_convert_responses_to_chatcmpl() {
LOG_DBG("%s\n", __func__);
// Test basic conversion with input messages (user/assistant alternating)
{
json input = json::parse(R"({
"input": [
{
"type": "message",
"role": "user",
"content": "hi wassup"
},
{
"type": "message",
"role": "assistant",
"content": "Hey! 👋 Not much, just here ready to chat. What's up with you? Anything I can help you with today?"
},
{
"type": "message",
"role": "user",
"content": "hi"
}
],
"model": "gpt-5-mini",
"stream": false,
"text": {},
"reasoning": {
"effort": "medium"
}
})");
json result = server_chat_convert_responses_to_chatcmpl(input);
// Verify messages were converted correctly
assert_equals(true, result.contains("messages"));
assert_equals(true, result.at("messages").is_array());
assert_equals((size_t)3, result.at("messages").size());
// Check first message (user)
const auto & msg0 = result.at("messages")[0];
assert_equals(std::string("user"), msg0.at("role").get<std::string>());
assert_equals(true, msg0.at("content").is_array());
assert_equals(std::string("text"), msg0.at("content")[0].at("type").get<std::string>());
assert_equals(std::string("hi wassup"), msg0.at("content")[0].at("text").get<std::string>());
// Check second message (assistant)
const auto & msg1 = result.at("messages")[1];
assert_equals(std::string("assistant"), msg1.at("role").get<std::string>());
assert_equals(true, msg1.at("content").is_array());
assert_equals(std::string("text"), msg1.at("content")[0].at("type").get<std::string>());
assert_equals(std::string("Hey! 👋 Not much, just here ready to chat. What's up with you? Anything I can help you with today?"), msg1.at("content")[0].at("text").get<std::string>());
// Check third message (user)
const auto & msg2 = result.at("messages")[2];
assert_equals(std::string("user"), msg2.at("role").get<std::string>());
assert_equals(true, msg2.at("content").is_array());
assert_equals(std::string("text"), msg2.at("content")[0].at("type").get<std::string>());
assert_equals(std::string("hi"), msg2.at("content")[0].at("text").get<std::string>());
// Verify other fields preserved
assert_equals(std::string("gpt-5-mini"), result.at("model").get<std::string>());
assert_equals(false, result.at("stream").get<bool>());
}
// Test string input
{
json input = json::parse(R"({
"input": "Hello, world!",
"model": "test-model"
})");
json result = server_chat_convert_responses_to_chatcmpl(input);
assert_equals((size_t)1, result.at("messages").size());
const auto & msg = result.at("messages")[0];
assert_equals(std::string("user"), msg.at("role").get<std::string>());
assert_equals(std::string("Hello, world!"), msg.at("content").get<std::string>());
}
// Test with instructions (system message)
{
json input = json::parse(R"({
"input": "Hello",
"instructions": "You are a helpful assistant.",
"model": "test-model"
})");
json result = server_chat_convert_responses_to_chatcmpl(input);
assert_equals((size_t)2, result.at("messages").size());
const auto & sys_msg = result.at("messages")[0];
assert_equals(std::string("system"), sys_msg.at("role").get<std::string>());
assert_equals(std::string("You are a helpful assistant."), sys_msg.at("content").get<std::string>());
}
// Test with max_output_tokens conversion
{
json input = json::parse(R"({
"input": "Hello",
"model": "test-model",
"max_output_tokens": 100
})");
json result = server_chat_convert_responses_to_chatcmpl(input);
assert_equals(true, result.contains("max_tokens"));
assert_equals(false, result.contains("max_output_tokens"));
assert_equals(100, result.at("max_tokens").get<int>());
}
}
static void test_template_output_peg_parsers(bool detailed_debug) {
LOG_DBG("%s\n", __func__);
@@ -1530,22 +1682,16 @@ static void test_template_output_peg_parsers(bool detailed_debug) {
// Qwen3.5 (basically same as Nemotron, but keeping separate tests just in case)
auto tst = peg_tester("models/templates/Qwen3.5-4B.jinja", detailed_debug);
tst.test("I'm\nthinking</think>Hello, world!\nWhat's up?")
tst.test("I'm\nthinking\n</think>\n\nHello, world!\nWhat's up?")
.reasoning_format(COMMON_REASONING_FORMAT_AUTO)
.enable_thinking(true)
.expect(message_assist_thoughts)
.run();
tst.test("I'm\nthinking\n</think>\nHello, world!\nWhat's up?")
tst.test("I'm\nthinking\n</think>\n\nHello, world!\nWhat's up?")
.enable_thinking(true)
.reasoning_format(COMMON_REASONING_FORMAT_NONE)
.expect_content("<think>\nI'm\nthinking\n</think>\nHello, world!\nWhat's up?")
.run();
tst.test("I'm\nthinking\n</think>\nHello, world!\nWhat's up?")
.enable_thinking(true)
.reasoning_format(COMMON_REASONING_FORMAT_AUTO)
.expect(message_assist_thoughts)
.expect_content("<think>\nI'm\nthinking\n</think>\n\nHello, world!\nWhat's up?")
.run();
tst.test(
@@ -1561,7 +1707,7 @@ static void test_template_output_peg_parsers(bool detailed_debug) {
.run();
tst.test(
"I'm\nthinking\n</think>\n"
"I'm\nthinking\n</think>\n\n"
"<tool_call>\n"
"<function=special_function>\n"
"<parameter=arg1>\n1\n</parameter>\n"
@@ -1619,7 +1765,7 @@ static void test_template_output_peg_parsers(bool detailed_debug) {
tst.test(
"I need to output the invoice details in JSON\n"
"</think>\n"
"</think>\n\n"
R"({"amount": 123.45, "date": "2025-12-03"})")
.reasoning_format(COMMON_REASONING_FORMAT_AUTO)
.enable_thinking(true)
@@ -1639,7 +1785,7 @@ static void test_template_output_peg_parsers(bool detailed_debug) {
"hello()\n"
"</parameter>\n"
"</function>\n"
"</tool_call></think>\n"
"</tool_call>\n</think>\n\n"
"<tool_call>\n"
"<function=python>\n"
"<parameter=code>\n"
@@ -1649,23 +1795,23 @@ static void test_template_output_peg_parsers(bool detailed_debug) {
"hello()\n"
"</parameter>\n"
"</function>\n"
"</tool_call>"
)
"</tool_call>")
.enable_thinking(true)
.reasoning_format(COMMON_REASONING_FORMAT_AUTO)
.tools({
python_tool
})
.expect_reasoning("Let's call a tool: <tool_call>\n"
"<function=python>\n"
"<parameter=code>\n"
"def hello():\n"
" print(\"Not the real call!\")\n"
"\n"
"hello()\n"
"</parameter>\n"
"</function>\n"
"</tool_call>")
.expect_reasoning(
"Let's call a tool: <tool_call>\n"
"<function=python>\n"
"<parameter=code>\n"
"def hello():\n"
" print(\"Not the real call!\")\n"
"\n"
"hello()\n"
"</parameter>\n"
"</function>\n"
"</tool_call>")
.expect_tool_calls({
{ "python", "{\"code\": \"def hello():\\n print(\\\"Hello, world!\\\")\\n\\nhello()\"}", {} },
})
@@ -1694,6 +1840,219 @@ static void test_template_output_peg_parsers(bool detailed_debug) {
.tools({ empty_args_tool_no_properties })
.expect(message_with_tool_calls("empty_args_no_props", "{}"))
.run();
// Edge cases when reasoning traces are not sent
tst.test(
"<think>\n\n</think>\n\n"
"<tool_call>\n"
"<function=special_function>\n"
"<parameter=arg1>\n1\n</parameter>\n"
"</function>\n"
"</tool_call>")
.reasoning_format(COMMON_REASONING_FORMAT_AUTO)
.tools({
special_function_tool
})
.expect_reasoning("<think>\n\n")
.expect_tool_calls({ { "special_function", "{\"arg1\": 1}", "" } })
.run();
tst.test(
"</think>\n\n"
"<tool_call>\n"
"<function=special_function>\n"
"<parameter=arg1>\n1\n</parameter>\n"
"</function>\n"
"</tool_call>")
.reasoning_format(COMMON_REASONING_FORMAT_AUTO)
.tools({
special_function_tool
})
.expect_reasoning("")
.expect_tool_calls({ { "special_function", "{\"arg1\": 1}", "" } })
.run();
tst.test(
"</think>\n\n"
"<tool_call>\n"
"<function=run_in_terminal>\n"
"<parameter=command>\n"
"pwd\n"
"</parameter>\n"
"</function>\n"
"</tool_call>")
.reasoning_format(COMMON_REASONING_FORMAT_AUTO)
.enable_thinking(true)
.tools({
run_in_terminal_tool
})
.expect_tool_calls({
{ "run_in_terminal", R"({"command": "pwd"})", {} },
})
.run();
tst.test(
"</think>\n\n"
"Let me inspect the current directory.\n"
"<tool_call>\n"
"<function=run_in_terminal>\n"
"<parameter=command>\n"
"pwd\n"
"</parameter>\n"
"</function>\n"
"</tool_call>")
.reasoning_format(COMMON_REASONING_FORMAT_AUTO)
.enable_thinking(true)
.tools({
run_in_terminal_tool
})
.expect_content("Let me inspect the current directory.\n")
.expect_tool_calls({
{ "run_in_terminal", R"({"command": "pwd"})", {} },
})
.run();
tst.test(
"</think>\n\n"
"Let me inspect the current directory.\n"
"<tool_call>\n"
"<function=run_in_terminal>\n"
"<parameter=command>\n"
"pwd\n"
"</parameter>\n"
"</function>\n"
"</tool_call>")
.reasoning_format(COMMON_REASONING_FORMAT_AUTO)
.enable_thinking(true)
.tools({
run_in_terminal_tool
})
.tool_choice(COMMON_CHAT_TOOL_CHOICE_REQUIRED)
.expect_content("Let me inspect the current directory.\n")
.expect_tool_calls({
{ "run_in_terminal", R"({"command": "pwd"})", {} },
})
.run();
tst.test(
"I should inspect the directory.\n"
"</think>\n\n"
"Let me inspect it now.\n"
"<tool_call>\n"
"<function=run_in_terminal>\n"
"<parameter=command>\n"
"pwd\n"
"</parameter>\n"
"</function>\n"
"</tool_call>")
.reasoning_format(COMMON_REASONING_FORMAT_AUTO)
.enable_thinking(true)
.tools({
run_in_terminal_tool
})
.expect_reasoning("I should inspect the directory.")
.expect_content("Let me inspect it now.\n")
.expect_tool_calls({
{ "run_in_terminal", R"({"command": "pwd"})", {} },
})
.run();
tst.test(
"I might call <tool_call> later, but I am still thinking.\n"
"</think>\n\n"
"Final answer without tools.")
.reasoning_format(COMMON_REASONING_FORMAT_AUTO)
.enable_thinking(true)
.tools({ run_in_terminal_tool })
.expect_reasoning("I might call <tool_call> later, but I am still thinking.")
.expect_content("Final answer without tools.")
.run();
{
common_chat_msg user_start;
user_start.role = "user";
user_start.content = "Create a todo list, then inspect the repository.";
common_chat_msg assistant_todos =
simple_assist_msg("", "", "manage_todo_list",
R"({"todos":[{"item":"Inspect repository","selected":false}]})", "call_todos");
common_chat_msg tool_result;
tool_result.role = "tool";
tool_result.content = "Successfully wrote todo list";
tool_result.tool_call_id = "call_todos";
common_chat_msg user_continue;
user_continue.role = "user";
user_continue.content = "Proceed.";
tst.test(
"I need to run a terminal command.\n"
"</think>\n\n"
"<tool_call>\n"
"<function=run_in_terminal>\n"
"<parameter=command>\n"
"pwd\n"
"</parameter>\n"
"</function>\n"
"</tool_call>")
.reasoning_format(COMMON_REASONING_FORMAT_AUTO)
.enable_thinking(true)
.tools({
manage_todo_list_tool, run_in_terminal_tool
})
.messages({ user_start, assistant_todos, tool_result, user_continue })
.expect_reasoning("I need to run a terminal command.")
.expect_tool_calls({
{ "run_in_terminal", R"({"command": "pwd"})", {} },
})
.run();
tst.test(
"I need to run a terminal command.\n"
"</think>\n\n"
"Let me inspect the current directory.\n"
"<tool_call>\n"
"<function=run_in_terminal>\n"
"<parameter=command>\n"
"pwd\n"
"</parameter>\n"
"</function>\n"
"</tool_call>")
.reasoning_format(COMMON_REASONING_FORMAT_AUTO)
.enable_thinking(true)
.tools({
manage_todo_list_tool, run_in_terminal_tool
})
.tool_choice(COMMON_CHAT_TOOL_CHOICE_REQUIRED)
.messages({ user_start, assistant_todos, tool_result, user_continue })
.expect_reasoning("I need to run a terminal command.")
.expect_content("Let me inspect the current directory.\n")
.expect_tool_calls({
{ "run_in_terminal", R"({"command": "pwd"})", {} },
})
.run();
tst.test(
"</think>\n\n"
"<tool_call>\n"
"<function=run_in_terminal>\n"
"<parameter=command>\n"
"pwd\n"
"</parameter>\n"
"</function>\n"
"</tool_call>")
.reasoning_format(COMMON_REASONING_FORMAT_AUTO)
.enable_thinking(true)
.tools({
manage_todo_list_tool, run_in_terminal_tool
})
.messages({ user_start, assistant_todos, tool_result, user_continue })
.expect_tool_calls({
{ "run_in_terminal", R"({"command": "pwd"})", {} },
})
.run();
}
}
{
@@ -1882,7 +2241,7 @@ static void test_template_output_peg_parsers(bool detailed_debug) {
"hello()\n"
"</parameter>\n"
"</function>\n"
"</tool_call></think>\n"
"</tool_call>\n</think>\n"
"<tool_call>\n"
"<function=python>\n"
"<parameter=code>\n"
@@ -3335,7 +3694,7 @@ static void test_template_output_peg_parsers(bool detailed_debug) {
.run();
// Tool call with reasoning (enable_thinking=true)
tst.test("I'm\nthinking</think><tool_call>\n{\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}</tool_call>")
tst.test("I'm\nthinking\n</think>\n\n<tool_call>\n{\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}</tool_call>")
.enable_thinking(true)
.reasoning_format(COMMON_REASONING_FORMAT_AUTO)
.tools({ special_function_tool })
@@ -3359,7 +3718,7 @@ static void test_template_output_peg_parsers(bool detailed_debug) {
.run();
// Tool call with reasoning and content
tst.test("I need to call a function</think>"
tst.test("I need to call a function\n</think>\n\n"
"Let me check the time.<tool_call>\n{\"name\": \"get_time\", \"arguments\": {\"city\": \"XYZCITY\"}}</tool_call>")
.enable_thinking(true)
.reasoning_format(COMMON_REASONING_FORMAT_AUTO)
@@ -3386,7 +3745,7 @@ static void test_template_output_peg_parsers(bool detailed_debug) {
// fake tool call marker in reasoning
tst.test(
"Let me think about <tool_call>\n{\"name\": \"special_function\", \"arguments\": {\"arg1\": 2}}</tool_call> hmm</think>"
"Let me think about <tool_call>\n{\"name\": \"special_function\", \"arguments\": {\"arg1\": 2}}</tool_call> hmm\n</think>\n\n"
"<tool_call>\n{\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}</tool_call>")
.enable_thinking(true)
.reasoning_format(COMMON_REASONING_FORMAT_AUTO)
@@ -3414,11 +3773,11 @@ static void test_template_output_peg_parsers(bool detailed_debug) {
// Format: <minimax:tool_call><invoke name="func"><parameter name="key">value</parameter></invoke></minimax:tool_call>
{
auto tst = peg_tester("models/templates/MiniMax-M2.jinja", detailed_debug);
tst.test("</think>Hello, world!\nWhat's up?").enable_thinking(true).reasoning_format(COMMON_REASONING_FORMAT_AUTO).expect(message_assist).run();
tst.test("\n</think>\n\nHello, world!\nWhat's up?").enable_thinking(true).reasoning_format(COMMON_REASONING_FORMAT_AUTO).expect(message_assist).run();
tst.test("I'm\nthinking</think>Hello, world!\nWhat's up?").enable_thinking(true).reasoning_format(COMMON_REASONING_FORMAT_AUTO).expect(message_assist_thoughts).run();
tst.test("I'm\nthinking\n</think>\n\nHello, world!\nWhat's up?").enable_thinking(true).reasoning_format(COMMON_REASONING_FORMAT_AUTO).expect(message_assist_thoughts).run();
tst.test("Let's call a tool:</think><minimax:tool_call>\n<invoke name=\"empty_args\">\n</invoke>\n</minimax:tool_call>").
tst.test("Let's call a tool:\n</think>\n\n<minimax:tool_call>\n<invoke name=\"empty_args\">\n</invoke>\n</minimax:tool_call>").
enable_thinking(true).
reasoning_format(COMMON_REASONING_FORMAT_AUTO).
tools({ empty_args_tool }).
@@ -3426,7 +3785,7 @@ static void test_template_output_peg_parsers(bool detailed_debug) {
run();
tst.test(
"</think><minimax:tool_call>\n<invoke name=\"special_function\">\n<parameter "
"\n</think>\n\n<minimax:tool_call>\n<invoke name=\"special_function\">\n<parameter "
"name=\"arg1\">1</parameter>\n</invoke>\n</minimax:tool_call>")
.tools({ special_function_tool })
.expect(message_assist_call)
@@ -3579,6 +3938,51 @@ static void test_template_output_peg_parsers(bool detailed_debug) {
.run();
}
// Reka Edge
{
auto tst = peg_tester("models/templates/Reka-Edge.jinja", detailed_debug);
tst.test("Hello, world!\nWhat's up?")
.enable_thinking(false)
.expect(message_assist)
.run();
tst.test("I'm\nthinking\n</think>\n\nHello, world!\nWhat's up?")
.enable_thinking(true)
.reasoning_format(COMMON_REASONING_FORMAT_DEEPSEEK)
.expect(message_assist_thoughts)
.run();
tst.test("<tool_call>\n{\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}\n</tool_call>")
.enable_thinking(false)
.tools({ special_function_tool })
.expect(message_assist_call)
.run();
tst.test("Hello, world!\nWhat's up?\n<tool_call>\n{\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}\n</tool_call>")
.enable_thinking(false)
.tools({ special_function_tool })
.expect(message_assist_call_content)
.run();
tst.test("I'm\nthinking\n</think>\n\n<tool_call>\n{\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}\n</tool_call>")
.enable_thinking(true)
.reasoning_format(COMMON_REASONING_FORMAT_DEEPSEEK)
.tools({ special_function_tool })
.expect(message_assist_call_thoughts)
.run();
tst.test("<tool_call>\n{\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}\n</tool_call>\n<tool_call>\n{\"name\": \"special_function_with_opt\", \"arguments\": {\"arg1\": 1, \"arg2\": 2}}\n</tool_call>")
.enable_thinking(false)
.parallel_tool_calls(true)
.tools({ special_function_tool, special_function_tool_with_optional_param })
.expect_tool_calls({
{ "special_function", R"({"arg1": 1})", {} },
{ "special_function_with_opt", R"({"arg1": 1, "arg2": 2})", {} },
})
.run();
tst.test("<tool_call>\n{\"name\": \"special_function\", \"arguments\": {\"arg")
.enable_thinking(false)
.tools({ special_function_tool })
.is_partial(true)
.expect(message_assist_call_cutoff_args)
.run();
}
// Apriel 1.5
{
auto tst = peg_tester("models/templates/unsloth-Apriel-1.5.jinja", detailed_debug);
@@ -3833,7 +4237,8 @@ static void test_template_output_peg_parsers(bool detailed_debug) {
{
auto tst = peg_tester("models/templates/StepFun3.5-Flash.jinja", detailed_debug);
tst.test("I was thinking</think>\nNow I'm not.").
tst.test("I was thinking\n</think>\nNow I'm not.").
enable_thinking(true).
reasoning_format(COMMON_REASONING_FORMAT_DEEPSEEK).
expect_reasoning("I was thinking").
@@ -4181,7 +4586,7 @@ int main(int argc, char ** argv) {
bool detailed_debug = false;
bool only_run_filtered = false;
// Check for --template flag
// Check for --template and --detailed flags
for (int i = 1; i < argc; i++) {
std::string arg = argv[i];
if (arg == "--template" && i + 1 < argc) {
@@ -4206,7 +4611,20 @@ int main(int argc, char ** argv) {
}
#ifndef _WIN32
if (argc > 1) {
// Check if any argument is a .jinja file (for template format detection mode)
bool has_jinja_files = false;
for (int i = 1; i < argc; i++) {
std::string arg = argv[i];
if (arg == "--detailed") {
continue;
}
if (arg.size() >= 6 && arg.rfind(".jinja") == arg.size() - 6) {
has_jinja_files = true;
break;
}
}
if (has_jinja_files) {
common_chat_templates_inputs inputs;
common_chat_msg msg;
msg.role = "user";
@@ -4239,6 +4657,7 @@ int main(int argc, char ** argv) {
test_msg_diffs_compute();
test_msgs_oaicompat_json_conversion();
test_tools_oaicompat_json_conversion();
test_convert_responses_to_chatcmpl();
test_developer_role_to_system_workaround();
test_template_output_peg_parsers(detailed_debug);
std::cout << "\n[chat] All tests passed!" << '\n';