@@ -1572,40 +1572,51 @@ inline void parse_msg_with_xml_tool_calls(common_chat_msg_parser & builder, cons
15721572 return out;
15731573 };
15741574
1575- // builder.consume_spaces();
1576- // builder.try_parse_reasoning(start_think, end_think);
1577-
15781575 const common_regex tool_call_start_regex (escape_regex (form.scope_start ) + " \\ s*" + escape_regex (form.tool_start ));
15791576 LOG_DBG (" Regex for tool start: %s\n " , (escape_regex (form.scope_start ) + " \\ s*" + escape_regex (form.tool_start )).c_str ());
15801577
1581- // GLM 4.5 uses format: <tool_call>function_name\n<arg_key>key</arg_key>\n<arg_value>value</arg_value>\n</tool_call>
1578+ // Parse content
15821579 bool reasoning_unclosed = builder.syntax ().thinking_forced_open ;
15831580 std::string unclosed_reasoning_content (" " );
1584- while (auto tc = builder.try_find_regex (tool_call_start_regex, std::string::npos, false )) {
1585- auto &content = tc->prelude ;
1586- auto tool_call_start = builder.str (tc->groups [0 ]);
1587- LOG_DBG (" Matched tool start: %s\n " , gbnf_format_literal (tool_call_start).c_str ());
1581+ for (;;) {
1582+ auto tc = builder.try_find_regex (tool_call_start_regex, std::string::npos, false );
1583+ std::string content;
1584+ std::string tool_call_start;
1585+
1586+ if (tc) {
1587+ content = std::move (tc->prelude );
1588+ tool_call_start = builder.str (tc->groups [0 ]);
1589+ LOG_DBG (" Matched tool start: %s\n " , gbnf_format_literal (tool_call_start).c_str ());
1590+ } else {
1591+ content = builder.consume_rest ();
1592+ }
15881593
1594+ // Handle unclosed think block
15891595 if (reasoning_unclosed) {
1590- if (auto pos = content.find (end_think); pos == std::string::npos) {
1596+ if (auto pos = content.find (end_think); pos == std::string::npos && builder. pos () != builder. input (). size () ) {
15911597 unclosed_reasoning_content += content + tool_call_start;
15921598 continue ;
15931599 } else {
1594- auto reasoning_content = content.substr (0 , pos);
1595- rstrip (reasoning_content);
1600+ std::string reasoning_content;
1601+ if (pos == std::string::npos) {
1602+ reasoning_content = std::move (content);
1603+ } else {
1604+ reasoning_content = content.substr (0 , pos);
1605+ content.erase (0 , pos + end_think.size ());
1606+ }
15961607 if (builder.syntax ().reasoning_format == COMMON_REASONING_FORMAT_NONE || builder.syntax ().reasoning_in_content ) {
15971608 if (builder.result ().content .size () != 0 ) {
15981609 builder.add_content (" \n\n " );
15991610 }
16001611 builder.add_content (start_think);
16011612 builder.add_content (unclosed_reasoning_content);
16021613 builder.add_content (reasoning_content);
1603- builder.add_content (end_think);
1614+ if (builder.pos () != builder.input ().size () || std::any_of (content.begin (), content.end (), [](unsigned char c) { return !std::isspace (c); }))
1615+ builder.add_content (end_think);
16041616 } else {
16051617 builder.add_reasoning_content (unclosed_reasoning_content);
16061618 builder.add_reasoning_content (reasoning_content);
16071619 }
1608- content.erase (0 , pos + end_think.size ());
16091620 unclosed_reasoning_content.clear ();
16101621 reasoning_unclosed = false ;
16111622 }
@@ -1616,14 +1627,13 @@ inline void parse_msg_with_xml_tool_calls(common_chat_msg_parser & builder, cons
16161627 for (auto think_start = content.rfind (start_think); think_start != std::string::npos; think_start = content.rfind (start_think, think_start - 1 )) {
16171628 if (auto think_end = content.find (end_think, think_start + start_think.size ()); think_end != std::string::npos) {
16181629 if (builder.syntax ().reasoning_format != COMMON_REASONING_FORMAT_NONE && !builder.syntax ().reasoning_in_content ) {
1619- auto reasoning_content = string_strip ( content.substr (think_start + start_think.size (), think_end - think_start - start_think.size () ));
1630+ auto reasoning_content = content.substr (think_start + start_think.size (), think_end - think_start - start_think.size ());
16201631 builder.add_reasoning_content (reasoning_content);
16211632 think_start = erase_spaces (content, think_start, think_end + end_think.size () - 1 );
16221633 }
16231634 } else {
16241635 // This <tool_call> start is in thinking block, skip this tool call
16251636 auto pos = think_start + start_think.size ();
1626- while (pos < content.size () && std::isspace (static_cast <unsigned char >(content[pos++])));
16271637 unclosed_reasoning_content = content.substr (pos) + tool_call_start;
16281638 reasoning_unclosed = true ;
16291639 content.resize (think_start);
@@ -1654,6 +1664,14 @@ inline void parse_msg_with_xml_tool_calls(common_chat_msg_parser & builder, cons
16541664 continue ;
16551665 }
16561666
1667+ // There is no tool call and all content is parsed
1668+ if (!tc) {
1669+ GGML_ASSERT (builder.pos () == builder.input ().size ());
1670+ GGML_ASSERT (unclosed_reasoning_content.empty ());
1671+ GGML_ASSERT (!reasoning_unclosed);
1672+ break ;
1673+ }
1674+
16571675 builder.move_to (tc->groups [0 ].begin );
16581676 if (!parse_xml_tool_calls (builder, form)) {
16591677 static const common_regex next_char_regex (" ." );
@@ -1662,35 +1680,6 @@ inline void parse_msg_with_xml_tool_calls(common_chat_msg_parser & builder, cons
16621680 builder.add_content (c);
16631681 }
16641682 }
1665-
1666- builder.consume_spaces ();
1667- while (builder.pos () != builder.input ().size ()) {
1668- builder.try_parse_reasoning (start_think, end_think);
1669- builder.consume_spaces ();
1670- std::string content;
1671- if (builder.syntax ().reasoning_format == COMMON_REASONING_FORMAT_NONE || builder.syntax ().reasoning_in_content ) {
1672- content = builder.consume_rest ();
1673- } else {
1674- if (auto rsn = builder.try_find_literal (start_think)) {
1675- builder.move_to (rsn->groups [0 ].begin );
1676- content = std::move (rsn->prelude );
1677- } else {
1678- content = builder.consume_rest ();
1679- }
1680- filter_unclosed_think (content, builder, end_think);
1681- }
1682- rstrip (content);
1683- if (content.size () != 0 ) {
1684- if (builder.result ().content .size () != 0 ) {
1685- builder.add_content (" \n\n " );
1686- }
1687- builder.add_content (content);
1688- }
1689- if (!builder.try_consume_literal (start_think)) {
1690- break ;
1691- }
1692- builder.move_to (builder.pos () - start_think.size ());
1693- }
16941683}
16951684
16961685static common_chat_params common_chat_params_init_generic (const common_chat_template & tmpl, const struct templates_params & inputs) {
0 commit comments