Skip to content

Commit 624733d

Browse files
authored
common : gpt-oss handle builtin and unsolicited tool calls (#21213)
1 parent 0b6ff47 commit 624733d

2 files changed

Lines changed: 26 additions & 1 deletion

File tree

common/chat.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,10 @@ static common_chat_params common_chat_params_init_gpt_oss(const common_chat_temp
989989
auto analysis = p.ref("analysis");
990990
auto preamble = p.rule("preamble", p.literal("<|channel|>commentary<|message|>") + p.content(content) + end);
991991
auto final_msg = p.rule("final", p.literal("<|channel|>final<|message|>") + p.content(content));
992+
993+
// Consume any unsolicited tool calls, e.g. builtin functions
994+
auto unsolicited = p.rule("unsolicited", p.atomic(p.optional(channel) + p.literal(" to=") + content + end));
995+
992996
auto any = p.rule("any", preamble | analysis);
993997

994998
if (has_response_format) {
@@ -1032,7 +1036,7 @@ static common_chat_params common_chat_params_init_gpt_oss(const common_chat_temp
10321036
return p.zero_or_more(start + any) + start + (tool_call | final_msg);
10331037
}
10341038

1035-
return p.zero_or_more(start + any) + start + final_msg;
1039+
return p.zero_or_more(start + any) + start + (final_msg | unsolicited);
10361040
});
10371041

10381042
data.parser = parser.save();

tests/test-chat.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3077,6 +3077,27 @@ static void test_template_output_peg_parsers(bool detailed_debug) {
30773077
.expect_reasoning("I need to output the invoice details in JSON")
30783078
.expect_content(R"({"amount": 123.45, "date": "2025-12-03"})")
30793079
.run();
3080+
3081+
3082+
// Unsolicited tool calls. There is no good way to handle these, so we return empty content.
3083+
3084+
// Builtin function - recipient in role
3085+
tst.test(
3086+
"<|channel|>analysis<|message|>I will execute python to say hello<|end|>"
3087+
"<|start|>assistant to=container.exec<|channel|>commentary<|message|>python3 -c 'print(\"hello\")'")
3088+
.reasoning_format(COMMON_REASONING_FORMAT_AUTO)
3089+
.expect_reasoning("I will execute python to say hello")
3090+
.expect_content("")
3091+
.run();
3092+
3093+
// Builtin function - recipient in channel
3094+
tst.test(
3095+
"<|channel|>analysis<|message|>I will execute python to say hello<|end|>"
3096+
"<|start|>assistant<|channel|>commentary to=python <|constrain|>code<|message|>print(\"hello\")")
3097+
.reasoning_format(COMMON_REASONING_FORMAT_AUTO)
3098+
.expect_reasoning("I will execute python to say hello")
3099+
.expect_content("")
3100+
.run();
30803101
}
30813102

30823103
{

0 commit comments

Comments
 (0)