char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
3fc65063d
char/aliceai-t5-moe
1{%- macro format_parameters ( properties , required ) - %} 2{%- set standard_keys = [ 'description' , 'type' , 'properties' , 'required' , 'nullable' ] - %} 3{%- set ns = namespace ( found_first = false ) - %} 4{%- for key , value in properties | dictsort -%} 5{%- set add_comma = false -%} 6{%- if key not in standard_keys -%} 7{%- if ns . found_first %} ,{% endif -%} 8{%- set ns . found_first = true -%} 9{{ key }} :{ 10{%- if value [ 'description' ] - %} 11 description:<|"|>{{ value [ 'description' ] }} <|"|> 12{%- set add_comma = true -%} 13{%- endif -%} 14{%- if value [ 'type' ] | upper == 'STRING' -%} 15{%- if value [ 'enum' ] - %} 16{%- if add_comma %} ,{%- else -%} {%- set add_comma = true -%} {% endif -%} 17 enum:{{ format_argument ( value [ 'enum' ]) }} 18{%- endif -%} 19{%- elif value [ 'type' ] | upper == 'ARRAY' -%} 20{%- if value [ 'items' ] is mapping and value [ 'items' ] - %} 21{%- if add_comma %} ,{%- else -%} {%- set add_comma = true -%} {% endif -%} 22 items:{ 23{%- set ns_items = namespace ( found_first = false ) - %} 24{%- for item_key , item_value in value [ 'items' ] | dictsort -%} 25{%- if item_value is not none -%} 26{%- if ns_items . found_first %} ,{% endif -%} 27{%- set ns_items . found_first = true -%} 28{%- if item_key == 'properties' -%} 29 properties:{ 30{%- if item_value is mapping -%} 31{{ - format_parameters ( item_value , value [ 'items' ][ 'required' ] | default ([])) - }} 32{%- endif -%} 33 } 34{%- elif item_key == 'required' -%} 35 required:[ 36{%- for req_item in item_value -%} 37 <|"|>{{ - req_item - }} <|"|> 38{%- if not loop . last %} ,{% endif -%} 39{%- endfor -%} 40 ] 41{%- elif item_key == 'type' -%} 42{%- if item_value is string -%} 43 type:{{ format_argument ( item_value | upper ) }} 44{%- else -%} 45 type:{{ format_argument ( item_value | map ( 'upper' ) | list ) }} 46{%- endif -%} 47{%- else -%} 48{{ item_key }} :{{ format_argument ( item_value ) }} 49{%- endif -%} 50{%- endif -%} 51{%- endfor -%} 52 } 53{%- endif -%} 54{%- endif -%} 55{%- if value [ 'nullable' ] %} 56{%- if add_comma %} ,{%- else -%} {%- set add_comma = true -%} {% endif -%} 57 nullable:true 58{%- endif -%} 59{%- if value [ 'type' ] | upper == 'OBJECT' -%} 60{%- if value [ 'properties' ] is defined and value [ 'properties' ] is mapping -%} 61{%- if add_comma %} ,{%- else -%} {%- set add_comma = true -%} {% endif -%} 62 properties:{ 63{{ - format_parameters ( value [ 'properties' ], value [ 'required' ] | default ([])) - }} 64 } 65{%- elif value is mapping -%} 66{%- if add_comma %} ,{%- else -%} {%- set add_comma = true -%} {% endif -%} 67 properties:{ 68{{ - format_parameters ( value , value [ 'required' ] | default ([])) - }} 69 } 70{%- endif -%} 71{%- if value [ 'required' ] - %} 72{%- if add_comma %} ,{%- else -%} {%- set add_comma = true -%} {% endif -%} 73 required:[ 74{%- for item in value [ 'required' ] | default ([]) - %} 75 <|"|>{{ - item - }} <|"|> 76{%- if not loop . last %} ,{% endif -%} 77{%- endfor -%} 78 ] 79{%- endif -%} 80{%- endif -%} 81{%- if add_comma %} ,{%- else -%} {%- set add_comma = true -%} {% endif -%} 82 type:<|"|>{{ value [ 'type' ] | upper }} <|"|>} 83{%- endif -%} 84{%- endfor -%} 85{%- endmacro -%} 86{%- macro format_function_declaration ( tool_data ) - %} 87 declaration:{{ - tool_data [ 'function' ][ 'name' ] - }} {description:<|"|>{{ - tool_data [ 'function' ][ 'description' ] - }} <|"|> 88{%- set params = tool_data [ 'function' ][ 'parameters' ] - %} 89{%- if params -%} 90 ,parameters:{ 91{%- if params [ 'properties' ] - %} 92 properties:{{{ - format_parameters ( params [ 'properties' ], params [ 'required' ]) - }} }, 93{%- endif -%} 94{%- if params [ 'required' ] - %} 95 required:[ 96{%- for item in params [ 'required' ] - %} 97 <|"|>{{ - item - }} <|"|> 98{{ - ',' if not loop . last - }} 99{%- endfor -%} 100 ], 101{%- endif -%} 102{%- if params [ 'type' ] - %} 103 type:<|"|>{{ - params [ 'type' ] | upper - }} <|"|>} 104{%- endif -%} 105{%- endif -%} 106{%- if 'response' in tool_data [ 'function' ] - %} 107{%- set response_declaration = tool_data [ 'function' ][ 'response' ] - %} 108 ,response:{ 109{%- if response_declaration [ 'description' ] - %} 110 description:<|"|>{{ - response_declaration [ 'description' ] - }} <|"|>, 111{%- endif -%} 112{%- if response_declaration [ 'type' ] | upper == 'OBJECT' -%} 113 type:<|"|>{{ - response_declaration [ 'type' ] | upper - }} <|"|>} 114{%- endif -%} 115{%- endif -%} 116 } 117{%- endmacro -%} 118{%- macro format_argument ( argument , escape_keys = True ) - %} 119{%- if argument is string -%} 120{{ - '<|" |> ' + argument + ' <| "|>' - }} 121{%- elif argument is boolean -%} 122{{ - 'true' if argument else 'false' - }} 123{%- elif argument is mapping -%} 124{{ - '{' - }} 125{%- set ns = namespace ( found_first = false ) - %} 126{%- for key , value in argument | dictsort -%} 127{%- if ns . found_first %} ,{% endif -%} 128{%- set ns . found_first = true -%} 129{%- if escape_keys -%} 130{{ - '<|" |> ' + key + ' <| "|>' - }} 131{%- else -%} 132{{ - key - }} 133{%- endif -%} 134 :{{ - format_argument ( value , escape_keys = escape_keys ) - }} 135{%- endfor -%} 136{{ - '}' - }} 137{%- elif argument is sequence -%} 138{{ - '[' - }} 139{%- for item in argument -%} 140{{ - format_argument ( item , escape_keys = escape_keys ) - }} 141{%- if not loop . last %} ,{% endif -%} 142{%- endfor -%} 143{{ - ']' - }} 144{%- else -%} 145{{ - argument - }} 146{%- endif -%} 147{%- endmacro -%} 148{%- macro strip_thinking ( text ) - %} 149{%- set ns = namespace ( result = '' ) - %} 150{%- for part in text . split ( '<channel|>' ) - %} 151{%- if '<|channel>' in part -%} 152{%- set ns . result = ns . result + part . split ( '<|channel>' )[ 0 ] - %} 153{%- else -%} 154{%- set ns . result = ns . result + part -%} 155{%- endif -%} 156{%- endfor -%} 157{{ - ns . result | trim - }} 158{%- endmacro -%} 159 160{%- macro format_tool_response_block ( tool_name , response ) - %} 161{{ - '<|tool_response>' - }} 162{%- if response is mapping -%} 163{{ - 'response:' + tool_name + '{' - }} 164{%- for key , value in response | dictsort -%} 165{{ - key - }} :{{ - format_argument ( value , escape_keys = False ) - }} 166{%- if not loop . last %} ,{% endif -%} 167{%- endfor -%} 168{{ - '}' - }} 169{%- else -%} 170{{ - 'response:' + tool_name + '{value:' + format_argument ( response , escape_keys = False ) + '}' - }} 171{%- endif -%} 172{{ - '<tool_response|>' - }} 173{%- endmacro -%} 174 175{%- set ns = namespace ( prev_message_type = None ) - %} 176{%- set loop_messages = messages -%} 177{{ - bos_token - }} 178{#- Handle System/Tool Definitions Block -#} 179{%- if ( enable_thinking is defined and enable_thinking ) or tools or messages [ 0 ][ 'role' ] in [ 'system' , 'developer' ] - %} 180{{ - '<|turn>system\n' - }} 181 182{#- Inject Thinking token at the very top of the FIRST system turn -#} 183{%- if enable_thinking is defined and enable_thinking -%} 184{{ - '<|think|>\n' - }} 185{%- set ns . prev_message_type = 'think' -%} 186{%- endif -%} 187 188{%- if messages [ 0 ][ 'role' ] in [ 'system' , 'developer' ] - %} 189{{ - messages [ 0 ][ 'content' ] | trim - }} 190{%- set loop_messages = messages [ 1 :] - %} 191{%- endif -%} 192 193{%- if tools -%} 194{%- for tool in tools %} 195{{ - '<|tool>' - }} 196{{ - format_function_declaration ( tool ) | trim - }} 197{{ - '<tool|>' - }} 198{%- endfor %} 199{%- set ns . prev_message_type = 'tool' -%} 200{%- endif -%} 201 202{{ - '<turn|>\n' - }} 203{%- endif %} 204 205{#- Pre-scan: find last user message index for reasoning guard -#} 206{%- set ns_turn = namespace ( last_user_idx =- 1 ) - %} 207{%- for i in range ( loop_messages | length ) - %} 208{%- if loop_messages [ i ][ 'role' ] == 'user' -%} 209{%- set ns_turn . last_user_idx = i -%} 210{%- endif -%} 211{%- endfor -%} 212 213{#- Loop through messages -#} 214{%- for message in loop_messages -%} 215{%- if message [ 'role' ] != 'tool' -%} 216{%- set ns . prev_message_type = None -%} 217{%- set role = 'model' if message [ 'role' ] == 'assistant' else message [ 'role' ] - %} 218{#- Detect continuation: suppress duplicate <|turn>model when previous non-tool message was also assistant -#} 219{%- set prev_nt = namespace ( role = None , found = false ) - %} 220{%- if loop . index0 > 0 -%} 221{%- for j in range ( loop . index0 - 1 , - 1 , - 1 ) - %} 222{%- if not prev_nt . found -%} 223{%- if loop_messages [ j ][ 'role' ] != 'tool' -%} 224{%- set prev_nt . role = loop_messages [ j ][ 'role' ] - %} 225{%- set prev_nt . found = true -%} 226{%- endif -%} 227{%- endif -%} 228{%- endfor -%} 229{%- endif -%} 230{%- set continue_same_model_turn = ( role == 'model' and prev_nt . role == 'assistant' ) - %} 231{%- if not continue_same_model_turn -%} 232{{ - '<|turn>' + role + '\n' }} 233{%- endif -%} 234 235{#- Render reasoning/reasoning_content as thinking channel -#} 236{%- set thinking_text = message . get ( 'reasoning' ) or message . get ( 'reasoning_content' ) - %} 237{%- if thinking_text and loop . index0 > ns_turn . last_user_idx and message . get ( 'tool_calls' ) - %} 238{{ - '<|channel>thought\n' + thinking_text + '\n<channel|>' - }} 239{%- endif -%} 240 241{%- if message [ 'tool_calls' ] - %} 242{%- for tool_call in message [ 'tool_calls' ] - %} 243{%- set function = tool_call [ 'function' ] - %} 244{{ - '<|tool_call>call:' + function [ 'name' ] + '{' - }} 245{%- if function [ 'arguments' ] is mapping -%} 246{%- set ns_args = namespace ( found_first = false ) - %} 247{%- for key , value in function [ 'arguments' ] | dictsort -%} 248{%- if ns_args . found_first %} ,{% endif -%} 249{%- set ns_args . found_first = true -%} 250{{ - key - }} :{{ - format_argument ( value , escape_keys = False ) - }} 251{%- endfor -%} 252{%- elif function [ 'arguments' ] is string -%} 253{{ - function [ 'arguments' ] - }} 254{%- endif -%} 255{{ - '}<tool_call|>' - }} 256{%- endfor -%} 257{%- set ns . prev_message_type = 'tool_call' -%} 258{%- endif -%} 259 260{%- set ns_tr_out = namespace ( flag = false ) - %} 261{%- if message . get ( 'tool_responses' ) - %} 262{#- Legacy: tool_responses embedded on the assistant message (Google/Gemma native) -#} 263{%- for tool_response in message [ 'tool_responses' ] - %} 264{{ - format_tool_response_block ( tool_response [ 'name' ] | default ( 'unknown' ), tool_response [ 'response' ]) - }} 265{%- set ns_tr_out . flag = true -%} 266{%- set ns . prev_message_type = 'tool_response' -%} 267{%- endfor -%} 268{%- elif message . get ( 'tool_calls' ) - %} 269{#- OpenAI Chat Completions: forward-scan consecutive role:tool messages -#} 270{%- set ns_tool_scan = namespace ( stopped = false ) - %} 271{%- for k in range ( loop . index0 + 1 , loop_messages | length ) - %} 272{%- if ns_tool_scan . stopped -%} 273{%- elif loop_messages [ k ][ 'role' ] != 'tool' -%} 274{%- set ns_tool_scan . stopped = true -%} 275{%- else -%} 276{%- set follow = loop_messages [ k ] - %} 277{#- Resolve tool_call_id to function name -#} 278{%- set ns_tname = namespace ( name = follow . get ( 'name' ) | default ( 'unknown' )) - %} 279{%- for tc in message [ 'tool_calls' ] - %} 280{%- if tc . get ( 'id' ) == follow . get ( 'tool_call_id' ) - %} 281{%- set ns_tname . name = tc [ 'function' ][ 'name' ] - %} 282{%- endif -%} 283{%- endfor -%} 284{#- Handle content as string or content-parts array -#} 285{%- set tool_body = follow . get ( 'content' ) - %} 286{%- if tool_body is string -%} 287{{ - format_tool_response_block ( ns_tname . name , tool_body ) - }} 288{%- elif tool_body is sequence and tool_body is not string -%} 289{%- set ns_txt = namespace ( s = '' ) - %} 290{%- for part in tool_body -%} 291{%- if part . get ( 'type' ) == 'text' -%} 292{%- set ns_txt . s = ns_txt . s + ( part . get ( 'text' ) | default ( '' )) - %} 293{%- endif -%} 294{%- endfor -%} 295{{ - format_tool_response_block ( ns_tname . name , ns_txt . s ) - }} 296{%- else -%} 297{{ - format_tool_response_block ( ns_tname . name , tool_body ) - }} 298{%- endif -%} 299{%- set ns_tr_out . flag = true -%} 300{%- set ns . prev_message_type = 'tool_response' -%} 301{%- endif -%} 302{%- endfor -%} 303{%- endif -%} 304 305{%- if message [ 'content' ] is string -%} 306{%- if role == 'model' -%} 307{{ - strip_thinking ( message [ 'content' ]) - }} 308{%- else -%} 309{{ - message [ 'content' ] | trim - }} 310{%- endif -%} 311{%- elif message [ 'content' ] is sequence -%} 312{%- for item in message [ 'content' ] - %} 313{%- if item [ 'type' ] == 'text' -%} 314{%- if role == 'model' -%} 315{{ - strip_thinking ( item [ 'text' ]) - }} 316{%- else -%} 317{{ - item [ 'text' ] | trim - }} 318{%- endif -%} 319{%- elif item [ 'type' ] == 'image' -%} 320{{ - '<|image|>' - }} 321{%- set ns . prev_message_type = 'image' -%} 322{%- elif item [ 'type' ] == 'audio' -%} 323{{ - '<|audio|>' - }} 324{%- set ns . prev_message_type = 'audio' -%} 325{%- elif item [ 'type' ] == 'video' -%} 326{{ - '<|video|>' - }} 327{%- set ns . prev_message_type = 'video' -%} 328{%- endif -%} 329{%- endfor -%} 330{%- endif -%} 331 332{%- if ns . prev_message_type == 'tool_call' and not ns_tr_out . flag -%} 333{{ - '<|tool_response>' - }} 334{%- elif not ( ns_tr_out . flag and not message . get ( 'content' )) - %} 335{{ - '<turn|>\n' - }} 336{%- endif -%} 337{%- endif -%} 338{%- endfor -%} 339 340{%- if add_generation_prompt -%} 341{%- if ns . prev_message_type != 'tool_response' and ns . prev_message_type != 'tool_call' -%} 342{{ - '<|turn>model\n' - }} 343{%- if not enable_thinking | default ( false ) - %} 344{{ - '<|channel>thought\n<channel|>' - }} 345{%- endif -%} 346{%- endif -%} 347{%- endif -%}