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// An assistant turn is rendered as one or more messages, each 4// "<|start|>assistant to=<recipient><|message|>{content}{END}" where END is 5// <|eom|> (more messages follow) or <|eot|> (end of turn): 6// - chain-of-thought: to=self, terminated by <|eom|> 7// - final answer: to=user, terminated by <|eot|> 8// The generation prompt is just "<|start|>assistant"; the model emits its own 9// " to=...<|message|>". 10common_chat_params common_chat_params_init_muse_glimmer (const common_chat_template & tmpl , 11const autoparser::generation_params & inputs ) { 12common_chat_params data ; 13 14data .prompt = common_chat_template_direct_apply_impl (tmpl ,inputs ); 15data .generation_prompt = "<|start|>assistant" ; 16data .format = COMMON_CHAT_FORMAT_PEG_NATIVE ; 17data .supports_thinking = true; 18 19data .preserved_tokens = { 20"<|start|>" ,"<|message|>" ,"<|eom|>" ,"<|eot|>" , 21// ATEM tool-call markup emitted on " to=<tool>" turns. 22"<atem:function_calls>" ,"<atem:invoke" ,"<atem:parameter" ,"</atem:parameter>" , 23"</atem:invoke>" ,"</atem:function_calls>" , 24 }; 25 26data .message_delimiters = { 27 {COMMON_CHAT_ROLE_ASSISTANT ,"<|start|>assistant" }, 28 {COMMON_CHAT_ROLE_USER ,"<|start|>user" }, 29 {COMMON_CHAT_ROLE_SYSTEM ,"<|start|>system" }, 30 {COMMON_CHAT_ROLE_TOOL ,"<|start|>tool" }, 31 }; 32 33if (inputs .has_continuation ()) { 34const auto & msg = inputs .continue_msg ; 35 36data .generation_prompt = "<|start|>assistant to=self<|message|>" + msg .reasoning_content ; 37if (inputs .continue_final_message == COMMON_CHAT_CONTINUATION_CONTENT ) { 38data .generation_prompt += "<|eom|><|start|>assistant to=user<|message|>" + msg .render_content (); 39 } 40 41data .prompt += data .generation_prompt ; 42 } 43 44auto extract_reasoning = inputs .reasoning_format != COMMON_REASONING_FORMAT_NONE ; 45 46auto has_tools = inputs .tools .is_array ()&& !inputs .tools .empty (); 47// Constrained grammar whenever tools are offered. 48auto include_grammar = has_tools && inputs .tool_choice != COMMON_CHAT_TOOL_CHOICE_NONE ; 49 50auto parser = build_chat_peg_parser ([& ](common_chat_peg_builder & p ) { 51auto start = p .rule ("start" ,p .literal ("<|start|>assistant" )); 52 53if (!extract_reasoning && !include_grammar ) { 54return start + p .content (p .rest ()); 55 } 56 57if (extract_reasoning ) { 58p .rule ("analysis" ,p .literal (" to=self<|message|>" )+ p .reasoning (p .until ("<|eom|>" ))+ p .literal ("<|eom|>" )); 59 }else { 60p .rule ("analysis" ,p .literal (" to=self<|message|>" )+ p .content (p .until ("<|eom|>" ))+ p .literal ("<|eom|>" )); 61 } 62auto analysis = p .ref ("analysis" ); 63 64auto recipient = p .optional (p .literal (" to=user" )); 65auto final_msg = p .rule ("final" ,recipient + p .literal ("<|message|>" )+ 66p .content (p .until_one_of ({"<|eot|>" ,"<|eom|>" }))); 67 68if (has_tools && inputs .tool_choice != COMMON_CHAT_TOOL_CHOICE_NONE ) { 69auto string_value = p .ac ( 70p .tool_arg_string_value (p .until ("</atem:parameter>" ))+ p .tool_arg_close (p .literal ("</atem:parameter>" )), 71"</atem:parameter>" ); 72 73auto tool_choice = p .choice (); 74foreach_function (inputs .tools , [& ](const json & tool ) { 75const auto & function = tool .at ("function" ); 76const std::string name = function .at ("name" ); 77 78 std::vector < common_peg_parser > arg_rules ; 79foreach_parameter (function , [& ](const common_chat_schema_property & prop ,const common_chat_schema_document_ptr & doc ) { 80auto value_parser = p .eps (); 81if (prop .schema -> may_be_string ()) { 82value_parser = string_value ; 83 }else { 84value_parser = p .tool_arg_json_value ( 85p .schema (p .json (),"tool-" + name + "-arg-" + prop .name + "-schema" ,doc ,* prop .schema )) 86+ p .tool_arg_close (p .literal ("</atem:parameter>" )); 87 } 88 89arg_rules .push_back (p .tool_arg ( 90p .tool_arg_open (p .literal ("<atem:parameter name=\"" )+ p .tool_arg_name (p .literal (prop .name ))+ p .literal ("\">" ))+ 91value_parser )); 92 }); 93 94auto args = p .eps (); 95if (!arg_rules .empty ()) { 96args = p .zero_or_more (p .choice (arg_rules )+ p .space ()); 97 } 98 99auto tool_parser = p .tool ( 100p .tool_open (p .literal (" to=" )+ p .until ("<|message|>" )+ 101p .literal ("<|message|><atem:function_calls>" )+ p .space ()+ 102p .literal ("<atem:invoke name=\"" )+ p .tool_name (p .literal (name ))+ p .literal ("\">" )+ p .space ()) 103 <<p .tool_args (args ) 104 <<p .tool_close (p .literal ("</atem:invoke>" )+ p .space ()+ p .literal ("</atem:function_calls>" ))); 105 106tool_choice |=p .rule ("tool-" + name ,tool_parser ); 107 }); 108 109auto tool_calls = inputs .parallel_tool_calls 110 ?p .trigger_rule ("tool-call" ,tool_choice + p .zero_or_more (p .literal ("<|eom|>" )+ start + tool_choice )) 111 :p .trigger_rule ("tool-call" ,tool_choice ); 112 113 114if (inputs .tool_choice == COMMON_CHAT_TOOL_CHOICE_REQUIRED ) { 115return p .zero_or_more (start + analysis )+ start + tool_calls ; 116 } 117auto trailing_calls = p .optional (p .literal ("<|eom|>" )+ start + tool_calls ); 118return p .zero_or_more (start + analysis )+ start + (tool_calls | (final_msg + trailing_calls )); 119 } 120 121return p .zero_or_more (start + analysis )+ start + final_msg ; 122 }); 123 124data .parser = parser .save (); 125 126if (include_grammar ) { 127data .grammar_lazy = inputs .tool_choice != COMMON_CHAT_TOOL_CHOICE_REQUIRED ; 128data .grammar = build_grammar ([& ](const common_grammar_builder & builder ) { 129parser .build_grammar (builder ,data .grammar_lazy ); 130 }); 131data .grammar_triggers = { 132 {COMMON_GRAMMAR_TRIGGER_TYPE_PATTERN , 133"<\\|start\\|>assistant( to=(?!self<\\|message\\|>)(?!user<\\|message\\|>)[^<]*?<\\|message\\|>)" }, 134 }; 135 } 136 137return data ; 138}