solved merge conficts with master
This commit is contained in:
parent
c76f04cf04
commit
3a451fc845
|
|
@ -879,6 +879,32 @@ static void common_chat_parse_deepseek_v3_1(common_chat_msg_parser & builder) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void common_chat_parse_gigachat_v3(common_chat_msg_parser & builder) {
|
||||||
|
if (!builder.syntax().parse_tool_calls) {
|
||||||
|
builder.add_content(builder.consume_rest());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regex to capture function name from JSON after "function call<|role_sep|\n"
|
||||||
|
static const common_regex function_regex(
|
||||||
|
R"(<\|message_sep\|>\n\nfunction call<\|role_sep\|>\n\s*\{\s*\"name\"\s*:\s*\"([^\"]+)\"\s*,\s*\"arguments\"\s*:)"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Closing token of a tool call
|
||||||
|
static const common_regex close_regex(
|
||||||
|
R"(\}\s*)"
|
||||||
|
);
|
||||||
|
|
||||||
|
parse_json_tool_calls(
|
||||||
|
builder,
|
||||||
|
/* block_open = */ std::nullopt,
|
||||||
|
/* function_regex_start_only = */ std::nullopt,
|
||||||
|
/* function_regex = */ function_regex,
|
||||||
|
close_regex,
|
||||||
|
/* block_close = */ std::nullopt
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
static void common_chat_parse_minimax_m2(common_chat_msg_parser & builder) {
|
static void common_chat_parse_minimax_m2(common_chat_msg_parser & builder) {
|
||||||
static const xml_tool_call_format form {
|
static const xml_tool_call_format form {
|
||||||
/* form.scope_start = */ "<minimax:tool_call>",
|
/* form.scope_start = */ "<minimax:tool_call>",
|
||||||
|
|
@ -1479,6 +1505,9 @@ static void common_chat_parse(common_chat_msg_parser & builder) {
|
||||||
case COMMON_CHAT_FORMAT_XIAOMI_MIMO:
|
case COMMON_CHAT_FORMAT_XIAOMI_MIMO:
|
||||||
common_chat_parse_xiaomi_mimo(builder);
|
common_chat_parse_xiaomi_mimo(builder);
|
||||||
break;
|
break;
|
||||||
|
case COMMON_CHAT_FORMAT_GIGACHAT_V3:
|
||||||
|
common_chat_parse_gigachat_v3(builder);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error(std::string("Unsupported format: ") + common_chat_format_name(builder.syntax().format));
|
throw std::runtime_error(std::string("Unsupported format: ") + common_chat_format_name(builder.syntax().format));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
109
common/chat.cpp
109
common/chat.cpp
|
|
@ -1677,115 +1677,6 @@ static common_chat_params common_chat_params_init_gigachat_v3(
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void common_chat_parse_gigachat_v3(common_chat_msg_parser & builder) {
|
|
||||||
if (!builder.syntax().parse_tool_calls) {
|
|
||||||
builder.add_content(builder.consume_rest());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Regex to capture function name from JSON after "function call<|role_sep|\n"
|
|
||||||
static const common_regex function_regex(
|
|
||||||
R"(<\|message_sep\|>\n\nfunction call<\|role_sep\|>\n\s*\{\s*\"name\"\s*:\s*\"([^\"]+)\"\s*,\s*\"arguments\"\s*:)"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Closing token of a tool call
|
|
||||||
static const common_regex close_regex(
|
|
||||||
R"(\}\s*)"
|
|
||||||
);
|
|
||||||
|
|
||||||
parse_json_tool_calls(
|
|
||||||
builder,
|
|
||||||
/* block_open = */ std::nullopt,
|
|
||||||
/* function_regex_start_only = */ std::nullopt,
|
|
||||||
/* function_regex = */ function_regex,
|
|
||||||
close_regex,
|
|
||||||
/* block_close = */ std::nullopt
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void common_chat_parse_deepseek_r1(common_chat_msg_parser & builder) {
|
|
||||||
builder.try_parse_reasoning("<think>", "</think>");
|
|
||||||
if (!builder.syntax().parse_tool_calls) {
|
|
||||||
builder.add_content(builder.consume_rest());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const common_regex tool_calls_begin("(?:<|tool▁calls▁begin|>|<|tool_calls_begin|>|<|tool calls begin|>|<|tool\\\\_calls\\\\_begin|>|<|tool▁calls|>)");
|
|
||||||
static const common_regex tool_calls_end("<|tool▁calls▁end|>");
|
|
||||||
static const common_regex function_regex("(?:<|tool▁call▁begin|>)?function<|tool▁sep|>([^\n]+)\n```json\n");
|
|
||||||
static const common_regex close_regex("```[\\s\\r\\n]*<|tool▁call▁end|>");
|
|
||||||
|
|
||||||
parse_json_tool_calls(
|
|
||||||
builder,
|
|
||||||
/* block_open= */ tool_calls_begin,
|
|
||||||
/* function_regex_start_only= */ std::nullopt,
|
|
||||||
function_regex,
|
|
||||||
close_regex,
|
|
||||||
tool_calls_end);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void common_chat_parse_deepseek_v3_1_content(common_chat_msg_parser & builder) {
|
|
||||||
static const common_regex function_regex("(?:<|tool▁call▁begin|>)?([^\\n<]+)(?:<|tool▁sep|>)");
|
|
||||||
|
|
||||||
static const common_regex close_regex("(?:[\\s]*)?<|tool▁call▁end|>");
|
|
||||||
static const common_regex tool_calls_begin("(?:<|tool▁calls▁begin|>|<|tool_calls_begin|>|<|tool calls begin|>|<|tool\\\\_calls\\\\_begin|>|<|tool▁calls|>)");
|
|
||||||
static const common_regex tool_calls_end("<|tool▁calls▁end|>");
|
|
||||||
|
|
||||||
if (!builder.syntax().parse_tool_calls) {
|
|
||||||
LOG_DBG("%s: not parse_tool_calls\n", __func__);
|
|
||||||
builder.add_content(builder.consume_rest());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_DBG("%s: parse_tool_calls\n", __func__);
|
|
||||||
|
|
||||||
parse_json_tool_calls(
|
|
||||||
builder,
|
|
||||||
/* block_open= */ tool_calls_begin,
|
|
||||||
/* function_regex_start_only= */ std::nullopt,
|
|
||||||
function_regex,
|
|
||||||
close_regex,
|
|
||||||
tool_calls_end);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void common_chat_parse_deepseek_v3_1(common_chat_msg_parser & builder) {
|
|
||||||
// DeepSeek V3.1 outputs reasoning content between "<think>" and "</think>" tags, followed by regular content
|
|
||||||
// First try to parse using the standard reasoning parsing method
|
|
||||||
LOG_DBG("%s: thinking_forced_open: %s\n", __func__, std::to_string(builder.syntax().thinking_forced_open).c_str());
|
|
||||||
|
|
||||||
auto start_pos = builder.pos();
|
|
||||||
auto found_end_think = builder.try_find_literal("</think>");
|
|
||||||
builder.move_to(start_pos);
|
|
||||||
|
|
||||||
if (builder.syntax().thinking_forced_open && !builder.is_partial() && !found_end_think) {
|
|
||||||
LOG_DBG("%s: no end_think, not partial, adding content\n", __func__);
|
|
||||||
common_chat_parse_deepseek_v3_1_content(builder);
|
|
||||||
} else if (builder.try_parse_reasoning("<think>", "</think>")) {
|
|
||||||
// If reasoning was parsed successfully, the remaining content is regular content
|
|
||||||
LOG_DBG("%s: parsed reasoning, adding content\n", __func__);
|
|
||||||
// </think><|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>NAME\n```json\nJSON\n```<|tool▁call▁end|><|tool▁calls▁end|>
|
|
||||||
common_chat_parse_deepseek_v3_1_content(builder);
|
|
||||||
} else {
|
|
||||||
if (builder.syntax().reasoning_format == COMMON_REASONING_FORMAT_NONE) {
|
|
||||||
LOG_DBG("%s: reasoning_format none, adding content\n", __func__);
|
|
||||||
common_chat_parse_deepseek_v3_1_content(builder);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// If no reasoning tags found, check if we should treat everything as reasoning
|
|
||||||
if (builder.syntax().thinking_forced_open) {
|
|
||||||
// If thinking is forced open but no tags found, treat everything as reasoning
|
|
||||||
LOG_DBG("%s: thinking_forced_open, adding reasoning content\n", __func__);
|
|
||||||
builder.add_reasoning_content(builder.consume_rest());
|
|
||||||
} else {
|
|
||||||
LOG_DBG("%s: no thinking_forced_open, adding content\n", __func__);
|
|
||||||
// <|tool▁call▁begin|>NAME<|tool▁sep|>JSON<|tool▁call▁end|>
|
|
||||||
common_chat_parse_deepseek_v3_1_content(builder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static common_chat_params common_chat_params_init_minimax_m2(const common_chat_template & tmpl, const struct templates_params & params) {
|
static common_chat_params common_chat_params_init_minimax_m2(const common_chat_template & tmpl, const struct templates_params & params) {
|
||||||
common_chat_params data;
|
common_chat_params data;
|
||||||
data.grammar_lazy = params.tools.is_array() && !params.tools.empty() && params.tool_choice != COMMON_CHAT_TOOL_CHOICE_REQUIRED;
|
data.grammar_lazy = params.tools.is_array() && !params.tools.empty() && params.tool_choice != COMMON_CHAT_TOOL_CHOICE_REQUIRED;
|
||||||
|
|
|
||||||
|
|
@ -3499,9 +3499,76 @@ Hey there!<|im_end|>
|
||||||
auto grammar = build_grammar(params.grammar);
|
auto grammar = build_grammar(params.grammar);
|
||||||
GGML_ASSERT(grammar && "Failed to build Qwen3-Coder grammar with union types");
|
GGML_ASSERT(grammar && "Failed to build Qwen3-Coder grammar with union types");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto tmpls = read_templates("models/templates/GigaChat3-10B-A1.8B.jinja");
|
||||||
|
std::vector<std::string> end_tokens{ "</s>", "<|message_sep|>\n\n" };
|
||||||
|
|
||||||
|
assert_equals(COMMON_CHAT_FORMAT_GIGACHAT_V3, common_chat_templates_apply(tmpls.get(), inputs_no_tools).format);
|
||||||
|
assert_equals(COMMON_CHAT_FORMAT_GIGACHAT_V3, common_chat_templates_apply(tmpls.get(), inputs_tools).format);
|
||||||
|
|
||||||
|
// Test parsing regular content
|
||||||
|
assert_msg_equals(message_assist,
|
||||||
|
common_chat_parse(
|
||||||
|
"Hello, world!\nWhat's up?",
|
||||||
|
/* is_partial= */ false,
|
||||||
|
{COMMON_CHAT_FORMAT_GIGACHAT_V3}));
|
||||||
|
|
||||||
|
// Test parsing tool calls
|
||||||
|
assert_msg_equals(message_assist_call,
|
||||||
|
common_chat_parse(
|
||||||
|
"<|message_sep|>\n\nfunction call<|role_sep|>\n{\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}",
|
||||||
|
/* is_partial= */ false,
|
||||||
|
{COMMON_CHAT_FORMAT_GIGACHAT_V3}));
|
||||||
|
|
||||||
|
// Test tool calls with extra content
|
||||||
|
assert_msg_equals(message_assist_call_content,
|
||||||
|
common_chat_parse(
|
||||||
|
"Hello, world!\nWhat's up?<|message_sep|>\n\nfunction call<|role_sep|>\n{\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}",
|
||||||
|
/* is_partial= */ false,
|
||||||
|
{COMMON_CHAT_FORMAT_GIGACHAT_V3}
|
||||||
|
));
|
||||||
|
|
||||||
|
// Test streaming
|
||||||
|
test_parser_with_streaming(message_assist_call_withopt,
|
||||||
|
"<|message_sep|>\n\nfunction call<|role_sep|>\n{\"name\": \"special_function_with_opt\", \"arguments\": {\"arg1\": 1, \"arg2\": 2}}",
|
||||||
|
[&](const std::string &msg) { return common_chat_parse(msg, /* is_partial= */ true, {
|
||||||
|
/* .format = */ COMMON_CHAT_FORMAT_GIGACHAT_V3,
|
||||||
|
/* .reasoning_format = */ COMMON_REASONING_FORMAT_NONE
|
||||||
|
}); });
|
||||||
|
|
||||||
|
// Test template generation for regular content
|
||||||
|
test_templates(tmpls.get(), end_tokens, message_assist, tools,
|
||||||
|
"Hello, world!\nWhat's up?",
|
||||||
|
/* expect_grammar_triggered= */ false);
|
||||||
|
|
||||||
|
// Test template generation for tool calls
|
||||||
|
test_templates(tmpls.get(), end_tokens, message_assist_call, tools,
|
||||||
|
"<|message_sep|>\n\nfunction call<|role_sep|>\n{\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}",
|
||||||
|
/* expect_grammar_triggered= */ true,
|
||||||
|
/* test_grammar_if_triggered= */ true,
|
||||||
|
/* common_reasoning_format= */ COMMON_REASONING_FORMAT_NONE,
|
||||||
|
/* ignore_whitespace_differences= */ true
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test template generation for tools with optional parameters
|
||||||
|
test_templates(tmpls.get(), end_tokens, message_assist_call_noopt, tools,
|
||||||
|
"<|message_sep|>\n\nfunction call<|role_sep|>\n{\"name\": \"special_function_with_opt\", \"arguments\": {\"arg1\": 1}}",
|
||||||
|
/* expect_grammar_triggered= */ true,
|
||||||
|
/* test_grammar_if_triggered= */ true,
|
||||||
|
/* common_reasoning_format= */ COMMON_REASONING_FORMAT_NONE,
|
||||||
|
/* ignore_whitespace_differences= */ true
|
||||||
|
);
|
||||||
|
test_templates(tmpls.get(), end_tokens, message_assist_call_withopt, tools,
|
||||||
|
"<|message_sep|>\n\nfunction call<|role_sep|>\n{\"name\": \"special_function_with_opt\", \"arguments\": {\"arg1\": 1, \"arg2\": 2}}",
|
||||||
|
/* expect_grammar_triggered= */ true,
|
||||||
|
/* test_grammar_if_triggered= */ true,
|
||||||
|
/* common_reasoning_format= */ COMMON_REASONING_FORMAT_NONE,
|
||||||
|
/* ignore_whitespace_differences= */ true
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
static void test_template_output_peg_parsers() {
|
static void test_template_output_peg_parsers() {
|
||||||
printf("[%s]\n", __func__);
|
printf("[%s]\n", __func__);
|
||||||
|
|
||||||
|
|
@ -3589,76 +3656,6 @@ static void test_template_output_peg_parsers() {
|
||||||
t.expect.content =R"({"amount": 123.45, "date": "2025-12-03"})";
|
t.expect.content =R"({"amount": 123.45, "date": "2025-12-03"})";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
=======
|
|
||||||
{
|
|
||||||
auto tmpls = read_templates("models/templates/GigaChat3-10B-A1.8B.jinja");
|
|
||||||
std::vector<std::string> end_tokens{ "</s>", "<|message_sep|>\n\n" };
|
|
||||||
|
|
||||||
assert_equals(COMMON_CHAT_FORMAT_GIGACHAT_V3, common_chat_templates_apply(tmpls.get(), inputs_no_tools).format);
|
|
||||||
assert_equals(COMMON_CHAT_FORMAT_GIGACHAT_V3, common_chat_templates_apply(tmpls.get(), inputs_tools).format);
|
|
||||||
|
|
||||||
// Test parsing regular content
|
|
||||||
assert_msg_equals(message_assist,
|
|
||||||
common_chat_parse(
|
|
||||||
"Hello, world!\nWhat's up?",
|
|
||||||
/* is_partial= */ false,
|
|
||||||
{COMMON_CHAT_FORMAT_GIGACHAT_V3}));
|
|
||||||
|
|
||||||
// Test parsing tool calls
|
|
||||||
assert_msg_equals(message_assist_call,
|
|
||||||
common_chat_parse(
|
|
||||||
"<|message_sep|>\n\nfunction call<|role_sep|>\n{\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}",
|
|
||||||
/* is_partial= */ false,
|
|
||||||
{COMMON_CHAT_FORMAT_GIGACHAT_V3}));
|
|
||||||
|
|
||||||
// Test tool calls with extra content
|
|
||||||
assert_msg_equals(message_assist_call_content,
|
|
||||||
common_chat_parse(
|
|
||||||
"Hello, world!\nWhat's up?<|message_sep|>\n\nfunction call<|role_sep|>\n{\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}",
|
|
||||||
/* is_partial= */ false,
|
|
||||||
{COMMON_CHAT_FORMAT_GIGACHAT_V3}
|
|
||||||
));
|
|
||||||
|
|
||||||
// Test streaming
|
|
||||||
test_parser_with_streaming(message_assist_call_withopt,
|
|
||||||
"<|message_sep|>\n\nfunction call<|role_sep|>\n{\"name\": \"special_function_with_opt\", \"arguments\": {\"arg1\": 1, \"arg2\": 2}}",
|
|
||||||
[&](const std::string &msg) { return common_chat_parse(msg, /* is_partial= */ true, {
|
|
||||||
/* .format = */ COMMON_CHAT_FORMAT_GIGACHAT_V3,
|
|
||||||
/* .reasoning_format = */ COMMON_REASONING_FORMAT_NONE
|
|
||||||
}); });
|
|
||||||
|
|
||||||
// Test template generation for regular content
|
|
||||||
test_templates(tmpls.get(), end_tokens, message_assist, tools,
|
|
||||||
"Hello, world!\nWhat's up?",
|
|
||||||
/* expect_grammar_triggered= */ false);
|
|
||||||
|
|
||||||
// Test template generation for tool calls
|
|
||||||
test_templates(tmpls.get(), end_tokens, message_assist_call, tools,
|
|
||||||
"<|message_sep|>\n\nfunction call<|role_sep|>\n{\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}",
|
|
||||||
/* expect_grammar_triggered= */ true,
|
|
||||||
/* test_grammar_if_triggered= */ true,
|
|
||||||
/* common_reasoning_format= */ COMMON_REASONING_FORMAT_NONE,
|
|
||||||
/* ignore_whitespace_differences= */ true
|
|
||||||
);
|
|
||||||
|
|
||||||
// Test template generation for tools with optional parameters
|
|
||||||
test_templates(tmpls.get(), end_tokens, message_assist_call_noopt, tools,
|
|
||||||
"<|message_sep|>\n\nfunction call<|role_sep|>\n{\"name\": \"special_function_with_opt\", \"arguments\": {\"arg1\": 1}}",
|
|
||||||
/* expect_grammar_triggered= */ true,
|
|
||||||
/* test_grammar_if_triggered= */ true,
|
|
||||||
/* common_reasoning_format= */ COMMON_REASONING_FORMAT_NONE,
|
|
||||||
/* ignore_whitespace_differences= */ true
|
|
||||||
);
|
|
||||||
test_templates(tmpls.get(), end_tokens, message_assist_call_withopt, tools,
|
|
||||||
"<|message_sep|>\n\nfunction call<|role_sep|>\n{\"name\": \"special_function_with_opt\", \"arguments\": {\"arg1\": 1, \"arg2\": 2}}",
|
|
||||||
/* expect_grammar_triggered= */ true,
|
|
||||||
/* test_grammar_if_triggered= */ true,
|
|
||||||
/* common_reasoning_format= */ COMMON_REASONING_FORMAT_NONE,
|
|
||||||
/* ignore_whitespace_differences= */ true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
>>>>>>> 6f9ffbd9d (implement gigachat v3 toolcall parser)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_msg_diffs_compute() {
|
static void test_msg_diffs_compute() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue