| 1610 | return data; |
| 1611 | } |
| 1612 | static void common_chat_parse_hermes_2_pro(common_chat_msg_parser & builder) { |
| 1613 | builder.try_parse_reasoning("<think>", "</think>"); |
| 1614 | if (!builder.syntax().parse_tool_calls) { |
| 1615 | builder.add_content(builder.consume_rest()); |
| 1616 | return; |
| 1617 | } |
| 1618 | |
| 1619 | static const common_regex open_regex( |
| 1620 | "(?:" |
| 1621 | "(```(?:xml|json)?\\n\\s*)?" // match 1 (block_start) |
| 1622 | "(" // match 2 (open_tag) |
| 1623 | "<tool_call>" |
| 1624 | "|<function_call>" |
| 1625 | "|<tool>" |
| 1626 | "|<tools>" |
| 1627 | "|<response>" |
| 1628 | "|<json>" |
| 1629 | "|<xml>" |
| 1630 | "|<JSON>" |
| 1631 | ")?" |
| 1632 | "(\\s*\\{\\s*\"name\")" // match 3 (named tool call) |
| 1633 | ")" |
| 1634 | "|<function=([^>]+)>" // match 4 (function name) |
| 1635 | "|<function name=\"([^\"]+)\">" // match 5 (function name again) |
| 1636 | ); |
| 1637 | |
| 1638 | if (auto res = builder.try_find_regex(open_regex)) { |
| 1639 | const auto & block_start = res->groups[1]; |
| 1640 | std::string block_end = block_start.empty() ? "" : "```"; |
| 1641 | |
| 1642 | const auto & open_tag = res->groups[2]; |
| 1643 | std::string close_tag; |
| 1644 | |
| 1645 | if (!res->groups[3].empty()) { |
| 1646 | builder.move_to(res->groups[3].begin); |
| 1647 | close_tag = open_tag.empty() ? "" : "</" + builder.str(open_tag).substr(1); |
| 1648 | |
| 1649 | if (auto tool_call = builder.try_consume_json_with_dumped_args({{"arguments"}})) { |
| 1650 | if (!builder.add_tool_call(tool_call->value) || tool_call->is_partial) { |
| 1651 | throw common_chat_msg_partial_exception("incomplete tool call"); |
| 1652 | } |
| 1653 | builder.consume_spaces(); |
| 1654 | builder.consume_literal(close_tag); |
| 1655 | builder.consume_spaces(); |
| 1656 | if (!block_end.empty()) { |
| 1657 | builder.consume_literal(block_end); |
| 1658 | builder.consume_spaces(); |
| 1659 | } |
| 1660 | builder.add_content(builder.consume_rest()); |
| 1661 | } else { |
| 1662 | throw common_chat_msg_partial_exception("failed to parse tool call"); |
| 1663 | } |
| 1664 | } else { |
| 1665 | auto function_name = builder.str(res->groups[4]); |
| 1666 | if (function_name.empty()) { |
| 1667 | function_name = builder.str(res->groups[5]); |
| 1668 | } |
| 1669 | GGML_ASSERT(!function_name.empty()); |
no test coverage detected