Guest User

Untitled

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