Skip to content

Commit 582420e

Browse files
author
ochafik
committed
Simplify phi-4 parser (use parse_json_tool_calls)
1 parent aa5694f commit 582420e

File tree

1 file changed

+3
-83
lines changed

1 file changed

+3
-83
lines changed

common/chat.cpp

Lines changed: 3 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1438,89 +1438,9 @@ static common_chat_params common_chat_params_init_phi_4(const common_chat_templa
14381438
}
14391439

14401440
static 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

Comments
 (0)