@@ -1438,89 +1438,9 @@ static common_chat_params common_chat_params_init_phi_4(const common_chat_templa
14381438}
14391439
14401440static common_chat_msg common_chat_parse_phi_4 (const std::string & input) {
1441- common_chat_msg result;
1442- result.role = " assistant" ;
1443-
1444- std::string final_content = " " ;
1445-
1446- const std::string opening_tag = " <|tool_call|>" ;
1447- const std::string closing_tag = " </|tool_call|>" ;
1448-
1449- size_t start_pos = 0 ;
1450- while (true ) {
1451- // Find next tool call
1452- size_t tool_start = input.find (opening_tag, start_pos);
1453- if (tool_start == std::string::npos) {
1454- // No more tool calls.
1455-
1456- // Is start_pos within string bounds?
1457- if (start_pos < input.length ()) {
1458- // Add the rest of the string to final_content
1459- final_content += input.substr (start_pos);
1460- }
1461- break ;
1462- }
1463-
1464- // Add content before the tool call to final_content
1465- final_content += input.substr (start_pos, tool_start - start_pos);
1466-
1467- // Find closing tag
1468- size_t content_start = tool_start + opening_tag.length ();
1469- size_t tool_end = input.find (closing_tag, content_start);
1470-
1471- if (tool_end == std::string::npos) {
1472- // No closing tag found, so just include the rest of the string as tool.
1473- tool_end = input.length ();
1474- }
1475-
1476- // Extract tool call content
1477- std::string tool_content = input.substr (
1478- content_start,
1479- tool_end - content_start
1480- );
1481-
1482- // Try to parse the tool call
1483- try {
1484- auto tool_call = json::parse (tool_content);
1485-
1486- // Verify the required fields exist
1487- if (!tool_call.contains (" name" )) {
1488- throw std::runtime_error (" Missing 'name' field in tool call" );
1489- }
1490-
1491- if (!tool_call.contains (" arguments" )) {
1492- throw std::runtime_error (" Missing 'arguments' field in tool call" );
1493- }
1494-
1495- std::string name = tool_call[" name" ].get <std::string>();
1496-
1497- std::string arguments;
1498- try {
1499- arguments = tool_call[" arguments" ].dump ();
1500- } catch (const std::exception & e) {
1501- LOG_ERR (" Failed to serialize arguments: %s\n " , e.what ());
1502- arguments = " {}" ;
1503- }
1504-
1505- result.tool_calls .push_back ({
1506- name,
1507- arguments,
1508- /* id= */ " " ,
1509- });
1510- } catch (const std::exception & e) {
1511- // If parsing fails, include the entire tool call in the content
1512- final_content += input.substr (
1513- tool_start,
1514- tool_end + closing_tag.length () - tool_start
1515- );
1516- }
1517-
1518- // Move past this tool call for next iteration
1519- start_pos = tool_end + closing_tag.length ();
1520- }
1521-
1522- result.content = final_content;
1523- return result;
1441+ static std::regex function_regex (" <\\ |tool_call\\ |>\\ s*\\ {\\ s*\" name\"\\ s*:\\ s*\" ([^\" ]+)\"\\ s*,\\ s*\" arguments\"\\ s*:" );
1442+ static std::regex close_regex (R"( \}\s*(</\|tool_call\|>)?)" );
1443+ return parse_json_tool_calls (input, std::nullopt , function_regex, close_regex);
15241444}
15251445
15261446
0 commit comments