Skip to content

Commit 4690db1

Browse files
committed
add support for reasoning_format and parse_tool_calls
1 parent ea70649 commit 4690db1

File tree

1 file changed

+25
-8
lines changed

1 file changed

+25
-8
lines changed

common/chat.cpp

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1364,15 +1364,27 @@ static void common_chat_parse_gpt_oss(common_chat_msg_parser & builder) {
13641364
);
13651365
static const common_regex builtin_tool_call_regex("(?:browser|python)[\\s\\S]*<\\|message\\|>");
13661366

1367-
auto consume_until_next = [&]() {
1368-
if (auto res = builder.try_find_regex(start_regex, std::string::npos, false)) {
1367+
// Save the start of the message so we can roll back when we encounter a tool call and parse_tool_calls == false.
1368+
size_t message_start_pos = 0;
1369+
1370+
// Similarly, save the channel start so we can roll back to defer reasoning parsing to builder.
1371+
size_t channel_start_pos = 0;
1372+
1373+
auto consume_until_next = [&](size_t from = std::string::npos) {
1374+
if (auto res = builder.try_find_regex(start_regex, from, false)) {
13691375
auto begin = res->groups[0].begin;
13701376
builder.move_to(begin);
13711377
return res->prelude;
13721378
}
13731379
return builder.consume_rest();
13741380
};
13751381

1382+
auto consume_whole_message = [&]() {
1383+
// Move back to the start and consume up to the next message
1384+
builder.move_to(message_start_pos);
1385+
return consume_until_next(message_start_pos + 1);
1386+
};
1387+
13761388
auto tool_call = [&]() {
13771389
if (auto res = builder.try_consume_regex(user_tool_call_regex)) {
13781390
auto name = builder.str(res->groups[1]);
@@ -1391,7 +1403,7 @@ static void common_chat_parse_gpt_oss(common_chat_msg_parser & builder) {
13911403
if (builder.syntax().parse_tool_calls) {
13921404
tool_call();
13931405
} else {
1394-
consume_until_next();
1406+
builder.add_content(consume_whole_message());
13951407
}
13961408
} else if (builder.try_consume_regex(message_regex)) {
13971409
if (!builder.try_find_regex(end_regex)) {
@@ -1414,18 +1426,22 @@ static void common_chat_parse_gpt_oss(common_chat_msg_parser & builder) {
14141426
if (builder.try_consume_regex(to_regex)) {
14151427
tool_call(); // built-in tools can be called in the analysis channel
14161428
} else if (builder.try_consume_regex(message_regex)) {
1417-
if (auto res = builder.try_find_regex(end_regex, std::string::npos, false)) {
1418-
builder.add_reasoning_content(res->prelude);
1429+
// Defer reasoning parsing to builder
1430+
builder.move_to(channel_start_pos);
1431+
1432+
if (builder.syntax().reasoning_format != COMMON_REASONING_FORMAT_NONE) {
1433+
builder.try_parse_reasoning("<|channel|>analysis<|message|>", "<|end|>");
14191434
} else {
1420-
builder.add_reasoning_content(builder.consume_rest());
1435+
builder.add_content(consume_until_next());
14211436
}
14221437
} else {
14231438
throw common_chat_msg_parse_exception("expected: <|message|>, got: " + consume_until_next());
14241439
}
14251440
};
14261441

14271442
auto channel = [&]() {
1428-
if (builder.try_consume_regex(channel_regex)) {
1443+
if (auto channel = builder.try_consume_regex(channel_regex)) {
1444+
channel_start_pos = channel->groups[0].begin;
14291445
if (auto res = builder.try_consume_regex(channel_type_regexp)) {
14301446
auto type = builder.str(res->groups[0]);
14311447
if (type == "analysis") {
@@ -1456,7 +1472,8 @@ static void common_chat_parse_gpt_oss(common_chat_msg_parser & builder) {
14561472
}
14571473

14581474
// Read in complete messages until done or partial exception raised
1459-
while (builder.try_find_literal("<|start|>")) {
1475+
while (auto res = builder.try_find_literal("<|start|>")) {
1476+
message_start_pos = res->groups[0].begin;
14601477
try {
14611478
start();
14621479
} catch (const common_chat_msg_parse_exception & e) {

0 commit comments

Comments
 (0)