Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions common/chat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1366,9 +1366,9 @@ static common_chat_params common_chat_params_init_deepseek_v3_1(const common_cha
auto parameters = function.at("parameters");
builder.resolve_refs(parameters);
tool_rules.push_back(builder.add_rule(name + "-call",
"( \"<|tool▁call▁begin|>\" )? \"function<|tool▁sep|>" + name + "\\n"
"```json\\n\" " + builder.add_schema(name + "-args", parameters) + " "
"\"```<|tool▁call▁end|>\""));
"( \"<|tool▁call▁begin|>\" )? \"" + name + "<|tool▁sep|>"
"\" " + builder.add_schema(name + "-args", parameters) + " "
"\"<|tool▁call▁end|>\""));
});
// Distill Qwen 7B & 32B models seem confused re/ syntax of their tool call opening tag,
// so we accept common variants (then it's all constrained)
Expand Down Expand Up @@ -1421,9 +1421,9 @@ static void common_chat_parse_deepseek_r1(common_chat_msg_parser & builder) {
}

static void common_chat_parse_deepseek_v3_1_content(common_chat_msg_parser & builder) {
static const common_regex function_regex("(?:<|tool▁call▁begin|>)?(?:function<|tool▁sep|>)?([^\\n<]+)(?:\\n```json\\n|<|tool▁sep|>)");
static const common_regex function_regex("(?:<|tool▁call▁begin|>)?([^\\n<]+)(?:<|tool▁sep|>)");

static const common_regex close_regex("(?:[\\n]*```[\\s\\r\\n]*)?<|tool▁call▁end|>");
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|>");

Expand Down
24 changes: 6 additions & 18 deletions tests/test-chat-parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,19 +243,7 @@ static void test_deepseek_v3_1_tool_calls() {
assert_equals(variant, std::string(""), msg.content);
assert_equals(variant, std::string(""), msg.reasoning_content);

// variant: function + fenced JSON
{
const std::string variant("fenced");
const std::string in = "<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_time\n```json\n{\"city\": \"Tokyo\"}\n```<|tool▁call▁end|><|tool▁calls▁end|>";
auto m = common_chat_parse(in, false, syntax);
assert_equals<std::size_t>(variant, 1, m.tool_calls.size());
assert_equals(variant, std::string("get_time"), m.tool_calls[0].name);
assert_equals(variant, std::string("{\"city\":\"Tokyo\"}"), m.tool_calls[0].arguments);
assert_equals(variant, std::string(""), m.content);
assert_equals(variant, std::string(""), m.reasoning_content);
}

// variant: function + fenced JSON + thinking open
// variant: simple + thinking open
{
common_chat_syntax syntax = {
/* .format = */ COMMON_CHAT_FORMAT_DEEPSEEK_V3_1,
Expand All @@ -264,8 +252,8 @@ static void test_deepseek_v3_1_tool_calls() {
/* .thinking_forced_open = */ true,
/* .parse_tool_calls = */ true,
};
const std::string variant("fenced_thinking");
const std::string in = "REASONING</think><|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_time\n```json\n{\"city\": \"Tokyo\"}\n```<|tool▁call▁end|><|tool▁calls▁end|>";
const std::string variant("simple_thinking");
const std::string in = "REASONING</think><|tool▁calls▁begin|><|tool▁call▁begin|>get_time<|tool▁sep|>{\"city\": \"Tokyo\"}<|tool▁call▁end|><|tool▁calls▁end|>";
auto m = common_chat_parse(in, false, syntax);
assert_equals<std::size_t>(variant, 1, m.tool_calls.size());
assert_equals(variant, std::string("get_time"), m.tool_calls[0].name);
Expand Down Expand Up @@ -295,7 +283,7 @@ static void test_deepseek_v3_1_tool_calls() {
}


// variant: thinking forced open + tool call in reasoning content + function + fenced JSON
// variant: thinking forced open + tool call in reasoning content
{
common_chat_syntax syntax = {
/* .format = */ COMMON_CHAT_FORMAT_DEEPSEEK_V3_1,
Expand All @@ -304,8 +292,8 @@ static void test_deepseek_v3_1_tool_calls() {
/* .thinking_forced_open = */ true,
/* .parse_tool_calls = */ true,
};
const std::string variant("thinking_forced_open_tool_call_in_reasoning_fenced_thinking");
const std::string in = "REASONING<|tool▁calls▁begin|><|tool▁call▁begin|>get_time2<|tool▁sep|>{\"city\": \"Tokyo2\"}<|tool▁call▁end|><|tool▁calls▁end|>REASONING</think><|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_time\n```json\n{\"city\": \"Tokyo\"}\n```<|tool▁call▁end|><|tool▁calls▁end|>";
const std::string variant("thinking_forced_open_tool_call_in_reasoning");
const std::string in = "REASONING<|tool▁calls▁begin|><|tool▁call▁begin|>get_time2<|tool▁sep|>{\"city\": \"Tokyo2\"}<|tool▁call▁end|><|tool▁calls▁end|>REASONING</think><|tool▁calls▁begin|><|tool▁call▁begin|>get_time<|tool▁sep|>{\"city\": \"Tokyo\"}<|tool▁call▁end|><|tool▁calls▁end|>";
auto m = common_chat_parse(in, false, syntax);
assert_equals<std::size_t>(variant, 1, m.tool_calls.size());
assert_equals(variant, std::string("get_time"), m.tool_calls[0].name);
Expand Down
21 changes: 4 additions & 17 deletions tests/test-chat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1804,24 +1804,11 @@ static void test_template_output_parsers() {
/* .thinking_forced_open = */ false,
/* .parse_tool_calls = */ true,
}));
// variant: function + fenced JSON
assert_msg_equals(
simple_assist_msg("", "", "get_time", "{\"city\":\"Tokyo\"}"),
common_chat_parse(
"<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_time\n```json\n{\"city\": \"Tokyo\"}\n```<|tool▁call▁end|><|tool▁calls▁end|>",
/* is_partial= */ false,
{
COMMON_CHAT_FORMAT_DEEPSEEK_V3_1,
/* .reasoning_format = */ COMMON_REASONING_FORMAT_DEEPSEEK,
/* .reasoning_in_content = */ false,
/* .thinking_forced_open = */ false,
/* .parse_tool_calls = */ true,
}));
// variant: function + fenced JSON + thinking open
// variant: simple + thinking open
assert_msg_equals(
simple_assist_msg("", "REASONING", "get_time", "{\"city\":\"Tokyo\"}"),
common_chat_parse(
"REASONING</think><|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_time\n```json\n{\"city\": \"Tokyo\"}\n```<|tool▁call▁end|><|tool▁calls▁end|>",
"REASONING</think><|tool▁calls▁begin|><|tool▁call▁begin|>get_time<|tool▁sep|>{\"city\": \"Tokyo\"}<|tool▁call▁end|><|tool▁calls▁end|>",
/* is_partial= */ false,
{
COMMON_CHAT_FORMAT_DEEPSEEK_V3_1,
Expand All @@ -1848,11 +1835,11 @@ static void test_template_output_parsers() {
/* .thinking_forced_open = */ false,
/* .parse_tool_calls = */ true,
}));
// variant: thinking forced open + tool call in reasoning content + function + fenced JSON
// variant: thinking forced open + tool call in reasoning content
assert_msg_equals(
simple_assist_msg("", "REASONING<|tool▁calls▁begin|><|tool▁call▁begin|>get_time2<|tool▁sep|>{\"city\": \"Tokyo2\"}<|tool▁call▁end|><|tool▁calls▁end|>REASONING", "get_time", "{\"city\":\"Tokyo\"}"),
common_chat_parse(
"REASONING<|tool▁calls▁begin|><|tool▁call▁begin|>get_time2<|tool▁sep|>{\"city\": \"Tokyo2\"}<|tool▁call▁end|><|tool▁calls▁end|>REASONING</think><|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_time\n```json\n{\"city\": \"Tokyo\"}\n```<|tool▁call▁end|><|tool▁calls▁end|>",
"REASONING<|tool▁calls▁begin|><|tool▁call▁begin|>get_time2<|tool▁sep|>{\"city\": \"Tokyo2\"}<|tool▁call▁end|><|tool▁calls▁end|>REASONING</think><|tool▁calls▁begin|><|tool▁call▁begin|>get_time<|tool▁sep|>{\"city\": \"Tokyo\"}<|tool▁call▁end|><|tool▁calls▁end|>",
/* is_partial= */ false,
{
COMMON_CHAT_FORMAT_DEEPSEEK_V3_1,
Expand Down
Loading