From e05fcb1944787ddc425d7695b07f382df342e768 Mon Sep 17 00:00:00 2001 From: crat0z <11581854+crat0z@users.noreply.github.com> Date: Thu, 25 Sep 2025 20:56:48 -0400 Subject: [PATCH 1/2] common : fix reasoning before forced tool call via tool_choice = required --- common/chat.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/common/chat.cpp b/common/chat.cpp index ce53f89f786b8..b1b30431d6f07 100644 --- a/common/chat.cpp +++ b/common/chat.cpp @@ -1615,9 +1615,14 @@ static common_chat_params common_chat_params_init_gpt_oss(const common_chat_temp ) ); }); + + auto not_end = builder.add_rule("not-end", + "[^<] | \"<\" [^|] | \"<|\" [^e] | \"<|e\" [^n] | \"<|en\" [^d] | \"<|end\" [^|] | \"<|end|\" [^>]"); + auto analysis = builder.add_rule("analysis", + "\"<|channel|>analysis<|message|>\" ( " + not_end + " )* \"<|end|>\""); auto recipient_in_role = builder.add_rule("recipient_in_role", - "\"<|start|>assistant\"? \" to=functions.\" ( " + + "(" + analysis + ")?" + "\"<|start|>assistant\"? \" to=functions.\" ( " + string_join(tool_rules_recipient_in_role, " | ") + " )" ); From 006c5a18afaec54815e73d86eb146bfd7869c202 Mon Sep 17 00:00:00 2001 From: Alde Rojas Date: Sat, 27 Sep 2025 15:30:25 -0500 Subject: [PATCH 2/2] common : improve reasoning and commentary handling when tool_choice is required (cherry picked from commit c746984956d6882c2de73d53ae2bb3bdf889e475) --- common/chat.cpp | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/common/chat.cpp b/common/chat.cpp index b1b30431d6f07..e2bacdcf52753 100644 --- a/common/chat.cpp +++ b/common/chat.cpp @@ -1615,23 +1615,37 @@ static common_chat_params common_chat_params_init_gpt_oss(const common_chat_temp ) ); }); - - auto not_end = builder.add_rule("not-end", - "[^<] | \"<\" [^|] | \"<|\" [^e] | \"<|e\" [^n] | \"<|en\" [^d] | \"<|end\" [^|] | \"<|end|\" [^>]"); - auto analysis = builder.add_rule("analysis", - "\"<|channel|>analysis<|message|>\" ( " + not_end + " )* \"<|end|>\""); - - auto recipient_in_role = builder.add_rule("recipient_in_role", - "(" + analysis + ")?" + "\"<|start|>assistant\"? \" to=functions.\" ( " + - string_join(tool_rules_recipient_in_role, " | ") + " )" - ); auto recipient_in_channel = builder.add_rule("recipient_in_channel", channel + " \" to=functions.\" ( " + string_join(tool_rules_recipient_in_channel, " | ") + " )" ); - builder.add_rule("root", recipient_in_role + " | " + recipient_in_channel); + if (data.grammar_lazy) { + auto recipient_in_role = builder.add_rule("recipient_in_role", + "\"<|start|>assistant\"? \" to=functions.\" ( " + + string_join(tool_rules_recipient_in_role, " | ") + " )" + ); + + builder.add_rule("root", recipient_in_role + " | " + recipient_in_channel); + } else { + auto not_end = builder.add_rule("not-end", + "[^<] | \"<\" [^|] | \"<|\" [^e] | \"<|e\" [^n] | \"<|en\" [^d] | \"<|end\" [^|] | \"<|end|\" [^>]"); + auto analysis = builder.add_rule("analysis", + "\"<|channel|>analysis<|message|>\" ( " + not_end + " )* \"<|end|>\""); + auto commentary = builder.add_rule("commentary", + "\"<|channel|>commentary<|message|>\" ( " + not_end + " )* \"<|end|>\""); + + auto recipient_in_role = builder.add_rule("recipient_in_role", + "\" to=functions.\" ( " + string_join(tool_rules_recipient_in_role, " | ") + " )" + ); + + builder.add_rule("root", + "( " + analysis + " \"<|start|>assistant\" )? " + + "( " + commentary + " \"<|start|>assistant\" )? " + + "( " + recipient_in_role + " | " + recipient_in_channel + " )" + ); + } // Trigger on tool calls that appear in the commentary channel data.grammar_triggers.push_back({