From 0cc5b14959ee3a813bd787baaef50a170493547a Mon Sep 17 00:00:00 2001 From: Aldehir Rojas Date: Tue, 25 Aug 2026 09:33:00 -0500 Subject: [PATCH] chat : scope qwen3-coder workarounds (#27679) --- common/chat.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/common/chat.cpp b/common/chat.cpp index 24618d35a..743ecde0a 100644 --- a/common/chat.cpp +++ b/common/chat.cpp @@ -1177,6 +1177,8 @@ static common_chat_params common_chat_params_init_qwen3_coder(const common_chat_ "", }; + auto is_qwen3_coder = !supports_reasoning; + if (supports_reasoning) { data.thinking_start_tag = ""; // Support both and as reasoning end sequences. @@ -1217,13 +1219,15 @@ static common_chat_params common_chat_params_init_qwen3_coder(const common_chat_ std::vector tool_call_starts = { "" }; - // Match complete opener for Qwen3-Coder models that occasionally omit the - // starting . The model may hallucinate a tool name, but it is preferable over - // constraining on - foreach_function(inputs.tools, [&](const json & tool) { - const std::string name = tool.at("function").at("name"); - tool_call_starts.push_back(""); - }); + if (is_qwen3_coder) { + // Match complete opener for Qwen3-Coder models that occasionally omit the + // starting . The model may hallucinate a tool name, but it is preferable over + // constraining on + foreach_function(inputs.tools, [&](const json & tool) { + const std::string name = tool.at("function").at("name"); + tool_call_starts.push_back(""); + }); + } auto parser = build_chat_peg_parser([&](common_chat_peg_builder & p) { auto generation_prompt = p.literal(GEN_PREFIX); @@ -1288,10 +1292,13 @@ static common_chat_params common_chat_params_init_qwen3_coder(const common_chat_ auto min_calls = inputs.tool_choice == COMMON_CHAT_TOOL_CHOICE_REQUIRED ? 1 : 0; + auto tool_call_body = tool_choice + "" + p.space(); + auto tool_call = p.rule("tool-call", "\n" + tool_call_body); + // Qwen3-Coder models may occasionally omit the token. - auto tool_call_body = tool_choice + "" + p.space(); - auto tool_call_first = p.rule("tool-call-first", p.optional(p.literal("\n")) + tool_call_body); - auto tool_call = p.rule("tool-call", "\n" + tool_call_body); + auto tool_call_first = is_qwen3_coder ? + p.rule("tool-call-first", p.optional(p.literal("\n")) + tool_call_body) : + tool_call; auto calls = inputs.parallel_tool_calls ? tool_call_first + p.zero_or_more(tool_call) : tool_call_first; auto tool_calls = p.trigger_rule("tool-call-root", p.repeat(calls, min_calls, 1));