char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
acecd5603
char/aliceai-t5-moe
1#include "parsers.h" 2 3// MiniCPM5 format: 4// - Reasoning: <think>{reasoning}</think> (optional) 5// - Tool calls: <function name="foo"><param name="bar">value</param></function> 6common_chat_params common_chat_params_init_minicpm5 (const common_chat_template & tmpl , 7const autoparser::generation_params & inputs ) { 8common_chat_params data ; 9 10data .prompt = common_chat_template_direct_apply_impl (tmpl ,inputs ); 11data .generation_prompt = common_chat_template_generation_prompt_impl (tmpl ,inputs ); 12data .format = COMMON_CHAT_FORMAT_PEG_NATIVE ; 13data .supports_thinking = true; 14data .preserved_tokens = { 15"<function" , 16"<param" , 17"</function>" , 18"</param>" , 19"<think>" , 20"</think>" , 21 }; 22 23data .thinking_start_tag = "<think>" ; 24data .thinking_end_tags = {"</think>" }; 25 26data .message_delimiters = { 27 {COMMON_CHAT_ROLE_ASSISTANT ,"<|im_start|>assistant" }, 28 {COMMON_CHAT_ROLE_TOOL ,"<|im_start|>user\n<tool_response>" }, 29 {COMMON_CHAT_ROLE_USER ,"<|im_start|>user" }, 30 {COMMON_CHAT_ROLE_SYSTEM ,"<|im_start|>system" }, 31 }; 32 33auto has_tools = inputs .tools .is_array ()&& !inputs .tools .empty (); 34auto has_response_format = inputs .json_schema .is_object ()&& !inputs .json_schema .empty (); 35auto extract_reasoning = inputs .reasoning_format != COMMON_REASONING_FORMAT_NONE ; 36auto include_grammar = has_response_format || (has_tools && inputs .tool_choice != COMMON_CHAT_TOOL_CHOICE_NONE ); 37 38if (inputs .has_continuation ()) { 39const auto & msg = inputs .continue_msg ; 40 41data .generation_prompt = "<|im_start|>assistant\n<think>\n" + msg .reasoning_content ; 42if (inputs .continue_final_message == COMMON_CHAT_CONTINUATION_CONTENT ) { 43data .generation_prompt += "\n</think>\n\n" + msg .render_content (); 44 } 45 46data .prompt += data .generation_prompt ; 47 } 48 49auto parser = build_chat_peg_parser ([& ](common_chat_peg_builder & p ) { 50auto generation_prompt = p .literal ("<|im_start|>assistant\n" ); 51 52auto reasoning = p .eps (); 53if (extract_reasoning ) { 54reasoning = ("<think>" <<p .reasoning (p .until ("</think>" )) <<"</think>" )+ p .space (); 55 } 56 57// Response format parser 58if (has_response_format ) { 59return generation_prompt + reasoning + p .content (p .schema (p .json (),"response-format" ,inputs .json_schema )); 60 } 61 62if (has_tools && inputs .tool_choice != COMMON_CHAT_TOOL_CHOICE_NONE ) { 63// CDATA lets a value carry characters that would otherwise close the tag (e.g. 64// </param>); capture the inner text only, excluding the CDATA markers. 65auto string_value = p .choice ({ 66p .literal ("<![CDATA[" )+ p .ac (p .tool_arg_string_value (p .until ("]]>" ))+ p .literal ("]]>" ),"]]>" )+ p .tool_arg_close (p .literal ("</param>" )), 67p .negate (p .literal ("< { 72const auto & function = tool .at ("function" ); 73const std::string name = function .at ("name" ); 74 75 std::vector < common_peg_parser > arg_rules ; 76foreach_parameter (function , [& ](const common_chat_schema_property & prop ,const common_chat_schema_document_ptr & doc ) { 77auto value_parser = p .eps (); 78if (prop .schema -> may_be_string ()) { 79value_parser = string_value ; 80 }else { 81value_parser = p .tool_arg_json_value ( 82p .schema (p .json (),"tool-" + name + "-arg-" + prop .name + "-schema" ,doc ,* prop .schema ) 83 )+ p .tool_arg_close (p .literal ("</param>" )); 84 } 85 86arg_rules .push_back (p .tool_arg ( 87p .tool_arg_open (p .literal ("<param name=\"" )+ p .tool_arg_name (p .literal (prop .name ))+ p .literal ("\">" ))+ 88value_parser 89 )); 90 }); 91 92auto args = p .eps (); 93if (!arg_rules .empty ()) { 94args = p .zero_or_more (p .choice (arg_rules )+ p .space ()); 95 } 96 97auto tool_parser = p .tool ( 98p .tool_open (p .literal ("<function name=\"" )+ p .tool_name (p .literal (name ))+ p .literal ("\">" )) 99 <<p .tool_args (args ) 100 <<p .tool_close (p .literal ("</function>" ))); 101 102tool_choice |=p .rule ("tool-" + name ,tool_parser ); 103 }); 104 105auto max_calls = inputs .parallel_tool_calls ?-1 :1 ; 106auto tool_calls = p .trigger_rule ("tool-call" ,p .repeat (tool_choice + p .space (),1 ,max_calls )); 107 108auto content = p .content (p .until ("<function" )); 109 110return generation_prompt + reasoning + content + tool_calls + p .end (); 111 } 112 113return generation_prompt + reasoning + p .content (p .rest ())+ p .end (); 114 }); 115 116data .parser = parser .save (); 117 118if (include_grammar ) { 119data .grammar_lazy = !(has_response_format || (has_tools && inputs .tool_choice == COMMON_CHAT_TOOL_CHOICE_REQUIRED )); 120data .grammar = build_grammar ([& ](const common_grammar_builder & builder ) { 121parser .build_grammar (builder ,data .grammar_lazy ); 122 }); 123 124data .grammar_triggers = { 125 {COMMON_GRAMMAR_TRIGGER_TYPE_WORD ,"<function" }, 126 }; 127 } 128 129return data ; 130}