@@ -656,7 +656,6 @@ static void parse_json_tool_calls(
}
from = std : : string : : npos ;
builder . add_content ( res - > prelude ) ;
auto maybe_raw_python = name = = " python " & & allow_raw_python ;
if ( builder . input ( ) [ builder . pos ( ) ] = = ' { ' | | ! maybe_raw_python ) {
if ( auto arguments = builder . try_consume_json_with_dumped_args ( { { } } ) ) {
@@ -686,7 +685,6 @@ static void parse_json_tool_calls(
} ;
if ( block_open ) {
if ( auto res = builder . try_find_regex ( * block_open ) ) {
builder . add_content ( res - > prelude ) ;
parse_tool_calls ( ) ;
} else {
builder . add_content ( builder . consume_rest ( ) ) ;
@@ -699,7 +697,6 @@ static void parse_json_tool_calls(
static void parse_prefixed_json_tool_call_array ( common_chat_msg_parser & builder , const common_regex & prefix , size_t rstrip_prefix = 0 ) {
static const std : : vector < std : : vector < std : : string > > args_paths = { { " arguments " } } ;
if ( auto res = builder . try_find_regex ( prefix ) ) {
builder . add_content ( res - > prelude ) ;
builder . move_back ( rstrip_prefix ) ;
auto tool_calls = builder . consume_json_with_dumped_args ( args_paths ) ;
if ( ! builder . add_tool_calls ( tool_calls . value ) | | tool_calls . is_partial ) {
@@ -835,6 +832,10 @@ static common_chat_params common_chat_params_init_generic(const common_chat_temp
return data ;
}
static void common_chat_parse_generic ( common_chat_msg_parser & builder ) {
if ( ! builder . syntax ( ) . parse_tool_calls ) {
builder . add_content ( builder . consume_rest ( ) ) ;
return ;
}
static const std : : vector < std : : vector < std : : string > > content_paths = {
{ " response " } ,
} ;
@@ -907,6 +908,11 @@ static common_chat_params common_chat_params_init_mistral_nemo(const common_chat
return data ;
}
static void common_chat_parse_mistral_nemo ( common_chat_msg_parser & builder ) {
if ( ! builder . syntax ( ) . parse_tool_calls ) {
builder . add_content ( builder . consume_rest ( ) ) ;
return ;
}
static const common_regex prefix ( regex_escape ( " [TOOL_CALLS] " ) ) ;
parse_prefixed_json_tool_call_array ( builder , prefix ) ;
}
@@ -1001,7 +1007,6 @@ static void common_chat_parse_command_r7b(common_chat_msg_parser & builder) {
if ( auto res = builder . try_find_regex ( start_action_regex ) ) {
// If we didn't extract thoughts, prelude includes them.
builder . add_content ( res - > prelude ) ;
auto tool_calls = builder . consume_json_with_dumped_args ( { { " parameters " } } ) ;
for ( const auto & tool_call : tool_calls . value ) {
std : : string name = tool_call . contains ( " tool_name " ) ? tool_call . at ( " tool_name " ) : " " ;
@@ -1016,11 +1021,7 @@ static void common_chat_parse_command_r7b(common_chat_msg_parser & builder) {
}
builder . consume_regex ( end_action_regex ) ;
} else if ( auto res = builder . try_find_regex ( start_response_regex ) ) {
// If we didn't extract thoughts, prelude includes them.
builder . add_content ( res - > prelude ) ;
if ( auto res = builder . try_find_regex ( end_response_regex ) ) {
builder . add_content ( res - > prelude ) ;
} else {
if ( ! builder . try_find_regex ( end_response_regex ) ) {
builder . add_content ( builder . consume_rest ( ) ) ;
throw common_chat_msg_partial_exception ( end_response_regex . str ( ) ) ;
}
@@ -1128,6 +1129,11 @@ static common_chat_params common_chat_params_init_llama_3_x(const common_chat_te
return data ;
}
static void common_chat_parse_llama_3_1 ( common_chat_msg_parser & builder , bool with_builtin_tools = false ) {
if ( ! builder . syntax ( ) . parse_tool_calls ) {
builder . add_content ( builder . consume_rest ( ) ) ;
return ;
}
static const common_regex function_regex (
" \\ s* \\ { \\ s*(?: \" type \" \\ s*: \\ s* \" function \" \\ s*, \\ s*)? \" name \" \\ s*: \\ s* \" ([^ \" ]+) \" \\ s*, \\ s* \" parameters \" \\ s*: " ) ;
static const common_regex close_regex ( " \\ } \\ s* " ) ;
@@ -1138,8 +1144,6 @@ static void common_chat_parse_llama_3_1(common_chat_msg_parser & builder, bool w
if ( with_builtin_tools ) {
static const common_regex builtin_call_regex ( " < \\ |python_tag \\ |> " ) ;
if ( auto res = builder . try_find_regex ( builtin_call_regex ) ) {
builder . add_content ( res - > prelude ) ;
auto fun_res = builder . consume_regex ( function_name_regex ) ;
auto function_name = builder . str ( fun_res . groups [ 1 ] ) ;
@@ -1255,6 +1259,10 @@ static common_chat_params common_chat_params_init_deepseek_r1(const common_chat_
}
static void common_chat_parse_deepseek_r1 ( common_chat_msg_parser & builder ) {
builder . try_parse_reasoning ( " <think> " , " </think> " ) ;
if ( ! builder . syntax ( ) . parse_tool_calls ) {
builder . add_content ( builder . consume_rest ( ) ) ;
return ;
}
static const common_regex tool_calls_begin ( " (?:<| tool▁calls▁begin| >|<| tool_calls_begin| >|<| tool calls begin| >|<| tool \\ \\ _calls \\ \\ _begin| >|<| tool▁calls| >) " ) ;
static const common_regex tool_calls_end ( " <| tool▁calls▁end| > " ) ;
@@ -1316,6 +1324,10 @@ static common_chat_params common_chat_params_init_firefunction_v2(const common_c
return data ;
}
static void common_chat_parse_firefunction_v2 ( common_chat_msg_parser & builder ) {
if ( ! builder . syntax ( ) . parse_tool_calls ) {
builder . add_content ( builder . consume_rest ( ) ) ;
return ;
}
static const common_regex prefix ( regex_escape ( " functools[ " ) ) ;
parse_prefixed_json_tool_call_array ( builder , prefix , /* rstrip_prefix= */ 1 ) ;
}
@@ -1457,15 +1469,12 @@ static common_chat_params common_chat_params_init_functionary_v3_1_llama_3_1(con
return data ;
}
static void common_chat_parse_functionary_v3_1_llama_3_1 ( common_chat_msg_parser & builder ) {
// This version of Functionary still supports the llama 3.1 tool call format for the python tool.
static const common_regex python_tag_regex ( regex_escape ( " <|python_tag|> " ) ) ;
if ( auto res = builder . try_find_regex ( python_tag_regex ) ) {
builder . add_content ( res - > prelude ) ;
auto arguments = wrap_code_as_arguments ( builder , builder . consume_rest ( ) ) ;
builder . add_tool_call ( " python " , " " , arguments ) ;
if ( ! builder . syntax ( ) . parse_ tool_ calls ) {
builder . add_content ( builder . consume_rest ( ) ) ;
return ;
}
// This version of Functionary still supports the llama 3.1 tool call format for the python tool.
static const common_regex python_tag_regex ( regex_escape ( " <|python_tag|> " ) ) ;
static const common_regex function_regex ( R " (<function=( \ w+)>) " ) ;
static const common_regex close_regex ( R " (</function>) " ) ;
@@ -1477,6 +1486,12 @@ static void common_chat_parse_functionary_v3_1_llama_3_1(common_chat_msg_parser
function_regex ,
close_regex ,
std : : nullopt ) ;
if ( auto res = builder . try_find_regex ( python_tag_regex ) ) {
auto arguments = wrap_code_as_arguments ( builder , builder . consume_rest ( ) ) ;
builder . add_tool_call ( " python " , " " , arguments ) ;
return ;
}
}
static common_chat_params common_chat_params_init_hermes_2_pro ( const common_chat_template & tmpl , const struct templates_params & inputs ) {
@@ -1595,6 +1610,10 @@ static common_chat_params common_chat_params_init_hermes_2_pro(const common_chat
}
static void common_chat_parse_hermes_2_pro ( common_chat_msg_parser & builder ) {
builder . try_parse_reasoning ( " <think> " , " </think> " ) ;
if ( ! builder . syntax ( ) . parse_tool_calls ) {
builder . add_content ( builder . consume_rest ( ) ) ;
return ;
}
static const common_regex open_regex (
" (?: "
@@ -1616,8 +1635,6 @@ static void common_chat_parse_hermes_2_pro(common_chat_msg_parser & builder) {
) ;
if ( auto res = builder . try_find_regex ( open_regex ) ) {
builder . add_content ( res - > prelude ) ;
const auto & block_start = res - > groups [ 1 ] ;
std : : string block_end = block_start . empty ( ) ? " " : " ``` " ;
@@ -1853,10 +1870,10 @@ static void common_chat_parse_content_only(common_chat_msg_parser & builder) {
builder . add_content ( builder . consume_rest ( ) ) ;
}
static void common_chat_parse ( common_chat_msg_parser & builder , common_chat_format format ) {
LOG_DBG ( " Parsing input with format %s: %s \n " , common_chat_format_name ( format ) , builder . input ( ) . c_str ( ) ) ;
static void common_chat_parse ( common_chat_msg_parser & builder ) {
LOG_DBG ( " Parsing input with format %s: %s \n " , common_chat_format_name ( builder . syntax ( ) . format) , builder . input ( ) . c_str ( ) ) ;
switch ( format ) {
switch ( builder . syntax ( ) . format) {
case COMMON_CHAT_FORMAT_CONTENT_ONLY :
common_chat_parse_content_only ( builder ) ;
break ;
@@ -1891,7 +1908,7 @@ static void common_chat_parse(common_chat_msg_parser & builder, common_chat_form
common_chat_parse_command_r7b ( builder ) ;
break ;
default :
throw std : : runtime_error ( std : : string ( " Unsupported format: " ) + common_chat_format_name ( format ) ) ;
throw std : : runtime_error ( std : : string ( " Unsupported format: " ) + common_chat_format_name ( builder . syntax ( ) . format) ) ;
}
builder . finish ( ) ;
}
@@ -1899,7 +1916,7 @@ static void common_chat_parse(common_chat_msg_parser & builder, common_chat_form
common_chat_msg common_chat_parse ( const std : : string & input , bool is_partial , const common_chat_syntax & syntax ) {
common_chat_msg_parser builder ( input , is_partial , syntax ) ;
try {
common_chat_parse ( builder , syntax . format );
common_chat_parse ( builder ) ;
} catch ( const common_chat_msg_partial_exception & ex ) {
LOG_DBG ( " Partial parse: %s \n " , ex . what ( ) ) ;
if ( ! is_partial ) {