Skip to content

Commit bdfa87f

Browse files
committed
Tests pass in reasoning mode. Also e2e tool test passes.
1 parent 36b047c commit bdfa87f

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

common/chat.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1432,6 +1432,22 @@ static void common_chat_parse_deepseek_v3_1_content(common_chat_msg_parser & bui
14321432
static void common_chat_parse_deepseek_v3_1(common_chat_msg_parser & builder) {
14331433
// DeepSeek V3.1 outputs reasoning content between "<think>" and "</think>" tags, followed by regular content
14341434
// First try to parse using the standard reasoning parsing method
1435+
LOG_DBG("%s: thinking_forced_open: %s\n", __func__, std::to_string(builder.syntax().thinking_forced_open).c_str());
1436+
1437+
bool has_reasoning = false;
1438+
auto header_start_pos = builder.pos();
1439+
if (auto res = builder.try_find_literal("<think>")) {
1440+
has_reasoning = true;
1441+
}
1442+
if (auto res = builder.try_find_literal("</think>")) {
1443+
has_reasoning = true;
1444+
}
1445+
builder.move_to(header_start_pos);
1446+
if (!has_reasoning && builder.syntax().thinking_forced_open) {
1447+
LOG_DBG("%s: edge case no reasoning, adding content\n", __func__);
1448+
common_chat_parse_deepseek_v3_1_content(builder);
1449+
return;
1450+
}
14351451
if (builder.try_parse_reasoning("<think>", "</think>")) {
14361452
// If reasoning was parsed successfully, the remaining content is regular content
14371453
LOG_DBG("%s: parsed reasoning, adding content\n", __func__);

tests/test-chat-parser.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ static void assert_equals(const char* label, const T& expected, const T& actual)
213213
}
214214

215215
static void test_deepseek_v3_1_tool_calls() {
216+
//common_log_set_verbosity_thold(LOG_DEFAULT_DEBUG);
216217
// variant: happy path for when it works as the model card says it should
217218
const char* variant = "simple";
218219
common_chat_syntax syntax = {
@@ -261,6 +262,23 @@ static void test_deepseek_v3_1_tool_calls() {
261262
assert_equals(variant, std::string(""), m.content);
262263
assert_equals(variant, std::string("REASONING"), m.reasoning_content);
263264
}
265+
266+
// variant: thinking forced open + missing reasoning + no tool calls
267+
{
268+
common_chat_syntax syntax = {
269+
/* .format = */ COMMON_CHAT_FORMAT_DEEPSEEK_V3_1,
270+
/* .reasoning_format = */ COMMON_REASONING_FORMAT_DEEPSEEK,
271+
/* .reasoning_in_content = */ false,
272+
/* .thinking_forced_open = */ true,
273+
/* .parse_tool_calls = */ true,
274+
};
275+
const char* variant = "thinking_forced_open_missing_reasoning_no_tool_calls";
276+
const std::string in = "CONTENT";
277+
auto m = common_chat_parse(in, false, syntax);
278+
assert_equals<std::size_t>(variant, 0, m.tool_calls.size());
279+
assert_equals(variant, std::string("CONTENT"), m.content);
280+
assert_equals(variant, std::string(""), m.reasoning_content);
281+
}
264282
}
265283

266284
static void test_with_args(const std::string & input, const std::string & expected, bool parse_as_partial = true, bool is_partial = true) {

0 commit comments

Comments
 (0)