@@ -598,133 +598,7 @@ common_chat_templates_ptr common_chat_templates_init(
598598 " {%- if false %}" );
599599 }
600600
601- // Fix "Unknown method: items at row NN, column MM" by replace receiver.items() to (receiver | items)
602- // TODO: Delete this when upstream minja fix tojson problem
603- constexpr auto replaceToJsonInTemplate = [](const std::string& input) {
604- constexpr auto isIdentifierChar = [](char c) {
605- return std::isalnum (c) || c == ' _' ;
606- };
607- constexpr auto matchBrackets = [](const std::string& s, size_t startPos, size_t & endPos) {
608- size_t pos = startPos;
609- int bracketCount = 0 ;
610- bool inString = false ;
611- char stringChar = 0 ;
612- while (pos < s.length ()) {
613- char c = s[pos];
614- if (!inString && (c == ' "' || c == ' \' ' )) {
615- inString = true ;
616- stringChar = c;
617- } else if (inString && c == stringChar) {
618- int backslashCount = 0 ;
619- size_t checkPos = pos - 1 ;
620- while (/* checkPos >= 0 && */ checkPos < s.size () && s[checkPos] == ' \\ ' ) {
621- backslashCount++;
622- checkPos--;
623- }
624- if (backslashCount % 2 == 0 ) {
625- inString = false ;
626- stringChar = 0 ;
627- }
628- }
629- if (!inString) {
630- if (c == ' (' ) {
631- bracketCount++;
632- } else if (c == ' )' ) {
633- bracketCount--;
634- if (bracketCount == 0 ) {
635- endPos = pos;
636- return true ;
637- }
638- }
639- }
640- pos++;
641- }
642- return false ;
643- };
644- constexpr auto isCompleteItemsCall = [matchBrackets](const std::string& s, size_t dotPos) {
645- if (s.compare (dotPos, 6 , " .items" ) != 0 ) return false ;
646- size_t itemsEnd = dotPos + 6 ;
647- if (itemsEnd >= s.length () || s[itemsEnd] != ' (' ) return false ;
648- size_t openParen = itemsEnd;
649- size_t closeParen;
650- if (!matchBrackets (s, openParen, closeParen)) return false ;
651- for (size_t i = openParen + 1 ; i < closeParen; i++) {
652- if (!std::isspace (s[i])) return false ;
653- }
654- return true ;
655- };
656- constexpr auto replaceItemsCall = [isCompleteItemsCall, matchBrackets, isIdentifierChar](const std::string& s, size_t dotPos) -> std::string {
657- if (!isCompleteItemsCall (s, dotPos)) return s;
658- size_t itemsEnd = dotPos + 6 ;
659- size_t openParen = itemsEnd;
660- size_t closeParen;
661- if (!matchBrackets (s, openParen, closeParen)) return s;
662- size_t varStart = dotPos;
663- while (varStart > 0 && (isIdentifierChar (s[varStart - 1 ]) || s[varStart - 1 ] == ' .' )) {
664- varStart--;
665- }
666- std::string var = s.substr (varStart, dotPos - varStart);
667- return s.substr (0 , varStart) + " (" + var + " | items)" + s.substr (closeParen + 1 );
668- };
669- constexpr auto processTemplateBlock = [replaceItemsCall](const std::string& block) {
670- std::string result = block;
671- size_t pos = 0 ;
672- while (pos < result.length ()) {
673- size_t nextToJson = std::string::npos;
674- size_t nextItems = result.find (" .items" , pos);
675- size_t nextPos = std::string::npos;
676- bool isToJson = false ;
677- if (nextToJson != std::string::npos && (nextItems == std::string::npos || nextToJson < nextItems)) {
678- nextPos = nextToJson;
679- isToJson = true ;
680- } else if (nextItems != std::string::npos) {
681- nextPos = nextItems;
682- isToJson = false ;
683- }
684- if (nextPos == std::string::npos) break ;
685- if (isToJson) {
686- GGML_ASSERT (false );
687- } else {
688- std::string replaced = replaceItemsCall (result, nextPos);
689- if (replaced != result) {
690- result = replaced;
691- pos = nextPos + 8 ;
692- } else {
693- pos = nextPos + 1 ;
694- }
695- }
696- }
697- return result;
698- };
699- if (input.empty ()) {
700- return input;
701- }
702- std::string result = input;
703- size_t pos = 0 ;
704- while (pos < result.length ()) {
705- if (result.compare (pos, 2 , " {{" ) == 0 || result.compare (pos, 2 , " {%" ) == 0 ) {
706- std::string endMarker = result.compare (pos, 2 , " {{" ) == 0 ? " }}" : " %}" ;
707- size_t endPos = result.find (endMarker, pos + 2 );
708- if (endPos != std::string::npos) {
709- std::string block = result.substr (pos + 2 , endPos - pos - 2 );
710- std::string processedBlock = processTemplateBlock (block);
711- if (processedBlock != block) {
712- result = result.substr (0 , pos + 2 ) + processedBlock + result.substr (endPos);
713- endPos = pos + 2 + processedBlock.length ();
714- pos = endPos;
715- continue ;
716- }
717- pos = endPos + 2 ;
718- } else break ;
719- } else pos++;
720- }
721- return result;
722- };
723- default_template_src = replaceToJsonInTemplate (default_template_src);
724-
725- // Fix MiniMax-M2 template bug:
726- // 1. Type of tool_call.arguments not checked
727- // 2. last_tool_call.name should be tool_call.function.name rather than tool_call.name
601+ // Fix MiniMax-M2 template bug: last_tool_call.name should be tool_call.function.name rather than tool_call.name
728602 // TODO: remove this once the template is fixed.
729603 if (default_template_src.find (" ]~!b[" ) != std::string::npos
730604 && default_template_src.find (" ]~b]" ) != std::string::npos) {
@@ -1254,7 +1128,7 @@ inline bool parse_xml_tool_calls(common_chat_msg_parser & builder, const struct
12541128 return ;
12551129 }
12561130 }
1257- LOG_DBG (" Failed to parse partial GLM 4.5 tool call, fallback to non-partial: %s\n " , tool_str.c_str ());
1131+ LOG_DBG (" Failed to parse partial XML-Style tool call, fallback to non-partial: %s\n " , tool_str.c_str ());
12581132 };
12591133
12601134 bool recovery = true ;
@@ -1413,7 +1287,7 @@ inline bool parse_xml_tool_calls(common_chat_msg_parser & builder, const struct
14131287 if (tc->groups [0 ].end - tc->groups [0 ].begin == form.tool_end .size ()) {
14141288 // Add the parsed tool call
14151289 if (!builder.add_tool_call (function_name, " " , arguments.dump ())) {
1416- throw common_chat_msg_partial_exception (" Failed to add GLM tool call" );
1290+ throw common_chat_msg_partial_exception (" Failed to add XML-Style tool call" );
14171291 }
14181292 recovery = false ;
14191293 continue ;
0 commit comments