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 const xml_tool_call_format form {
|
||||
/* 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:
|
||||
common_chat_parse_xiaomi_mimo(builder);
|
||||
break;
|
||||
case COMMON_CHAT_FORMAT_GIGACHAT_V3:
|
||||
common_chat_parse_gigachat_v3(builder);
|
||||
break;
|
||||
default:
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
common_chat_params data;
|
||||
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);
|
||||
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() {
|
||||
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"})";
|
||||
});
|
||||
}
|
||||
=======
|
||||
{
|
||||
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() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue