Guest User

Untitled

a guest
Jul 30th, 2026
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.84 KB | None | 0 0
  1. {#- Keep Python's floating type spelling when the jinja engine compacts 1.0 to 1. -#}
  2. {%- macro json_scalar(value) -%}
  3. {%- set serialized = value | tojson(ensure_ascii=false, separators=(',', ':')) -%}
  4. {%- if value is float and '.' not in serialized and 'e' not in (serialized | lower) -%}
  5. {{- serialized -}}{{- '.0' -}}
  6. {%- else -%}
  7. {{- serialized -}}
  8. {%- endif -%}
  9. {%- endmacro -%}
  10.  
  11. {%- macro canonical_json(value) -%}
  12. {%- if value is mapping -%}
  13. {{- '{' -}}
  14. {%- for key, item in value | dictsort(case_sensitive=true) -%}
  15. {{- (key | string) | tojson(ensure_ascii=false, separators=(',', ':')) -}}{{- ':' -}}
  16. {{- canonical_json(item) -}}
  17. {%- if not loop.last -%}{{- ',' -}}{%- endif -%}
  18. {%- endfor -%}
  19. {{- '}' -}}
  20. {%- elif value is sequence and value is not string -%}
  21. {{- '[' -}}
  22. {%- for item in value -%}
  23. {{- canonical_json(item) -}}
  24. {%- if not loop.last -%}{{- ',' -}}{%- endif -%}
  25. {%- endfor -%}
  26. {{- ']' -}}
  27. {%- else -%}
  28. {{- json_scalar(value) -}}
  29. {%- endif -%}
  30. {%- endmacro -%}
  31.  
  32. {#- Advance across insignificant JSON whitespace. -#}
  33. {%- macro json_skip_ws(source, state) -%}
  34. {%- set scan = namespace(done=false) -%}
  35. {%- for ignored in range(source | length) -%}
  36. {%- if not scan.done and state.pos < source | length -%}
  37. {%- set ch = source[state.pos] -%}
  38. {%- if ch == ' ' or ch == '\t' or ch == '\r' or ch == '\n' -%}
  39. {%- set state.pos = state.pos + 1 -%}
  40. {%- else -%}
  41. {%- set scan.done = true -%}
  42. {%- endif -%}
  43. {%- endif -%}
  44. {%- endfor -%}
  45. {%- endmacro -%}
  46.  
  47. {#-
  48. Decode a JSON string under Transformers, then re-encode it like json.dumps.
  49. llama.cpp converts string arguments to objects after capability detection;
  50. the fallback keeps engine-only parsing safe without runtime-only filters.
  51. -#}
  52. {%- macro json_string(source, state) -%}
  53. {%- if lipsum is defined -%}
  54. {%- set out = namespace(decoded='', done=false, code=0, low=0) -%}
  55. {%- set hex_values = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, 'a': 10, 'b': 11, 'c': 12, 'd': 13, 'e': 14, 'f': 15} -%}
  56. {%- set state.pos = state.pos + 1 -%}
  57. {%- for ignored in range(source | length) -%}
  58. {%- if not out.done and state.pos < source | length -%}
  59. {%- set ch = source[state.pos] -%}
  60. {%- set state.pos = state.pos + 1 -%}
  61. {%- if ch == '"' -%}
  62. {%- set out.done = true -%}
  63. {%- elif ch != '\\' -%}
  64. {%- set out.decoded = out.decoded + ch -%}
  65. {%- elif state.pos < source | length -%}
  66. {%- set escape = source[state.pos] -%}
  67. {%- set state.pos = state.pos + 1 -%}
  68. {%- if escape == '"' -%}{%- set out.decoded = out.decoded + '"' -%}
  69. {%- elif escape == '\\' -%}{%- set out.decoded = out.decoded + '\\' -%}
  70. {%- elif escape == '/' -%}{%- set out.decoded = out.decoded + '/' -%}
  71. {%- elif escape == 'b' -%}{%- set out.decoded = out.decoded + '\b' -%}
  72. {%- elif escape == 'f' -%}{%- set out.decoded = out.decoded + '\f' -%}
  73. {%- elif escape == 'n' -%}{%- set out.decoded = out.decoded + '\n' -%}
  74. {%- elif escape == 'r' -%}{%- set out.decoded = out.decoded + '\r' -%}
  75. {%- elif escape == 't' -%}{%- set out.decoded = out.decoded + '\t' -%}
  76. {%- elif escape == 'u' -%}
  77. {%- set out.code = 0 -%}
  78. {%- for offset in range(4) -%}
  79. {%- set digit = source[state.pos + offset] | lower -%}
  80. {%- set out.code = out.code * 16 + hex_values[digit] -%}
  81. {%- endfor -%}
  82. {%- set state.pos = state.pos + 4 -%}
  83. {%- if out.code >= 55296 and out.code <= 56319 and source[state.pos:state.pos + 2] == '\\u' -%}
  84. {%- set out.low = 0 -%}
  85. {%- for offset in range(4) -%}
  86. {%- set digit = source[state.pos + 2 + offset] | lower -%}
  87. {%- set out.low = out.low * 16 + hex_values[digit] -%}
  88. {%- endfor -%}
  89. {%- if out.low >= 56320 and out.low <= 57343 -%}
  90. {%- set out.code = 65536 + (out.code - 55296) * 1024 + out.low - 56320 -%}
  91. {%- set state.pos = state.pos + 6 -%}
  92. {%- endif -%}
  93. {%- endif -%}
  94. {%- set out.decoded = out.decoded + ('%c' % out.code) -%}
  95. {%- else -%}
  96. {%- set out.decoded = out.decoded + escape -%}
  97. {%- endif -%}
  98. {%- endif -%}
  99. {%- endif -%}
  100. {%- endfor -%}
  101. {%- set state.string_value = out.decoded -%}
  102. {{- out.decoded | tojson(ensure_ascii=false, separators=(',', ':')) -}}
  103. {%- else -%}
  104. {%- set out = namespace(start=state.pos, escaped=false, done=false) -%}
  105. {%- set state.pos = state.pos + 1 -%}
  106. {%- for ignored in range(source | length) -%}
  107. {%- if not out.done and state.pos < source | length -%}
  108. {%- set ch = source[state.pos] -%}
  109. {%- set state.pos = state.pos + 1 -%}
  110. {%- if out.escaped -%}
  111. {%- set out.escaped = false -%}
  112. {%- elif ch == '\\' -%}
  113. {%- set out.escaped = true -%}
  114. {%- elif ch == '"' -%}
  115. {%- set out.done = true -%}
  116. {%- endif -%}
  117. {%- endif -%}
  118. {%- endfor -%}
  119. {%- set state.string_value = source[out.start:state.pos] -%}
  120. {{- source[out.start:state.pos] -}}
  121. {%- endif -%}
  122. {%- endmacro -%}
  123.  
  124. {#-
  125. Move the cursor across one complete JSON value without rendering it. Object
  126. parsing uses the raw slice to sort members before recursively rendering them.
  127. -#}
  128. {%- macro json_scan_value(source, state) -%}
  129. {{- json_skip_ws(source, state) -}}
  130. {%- set scan = namespace(depth=0, quoted=false, escaped=false, done=false) -%}
  131. {%- for ignored in range(source | length) -%}
  132. {%- if not scan.done and state.pos < source | length -%}
  133. {%- set ch = source[state.pos] -%}
  134. {%- if scan.quoted -%}
  135. {%- set state.pos = state.pos + 1 -%}
  136. {%- if ch == '"' and not scan.escaped -%}
  137. {%- set scan.quoted = false -%}
  138. {%- elif ch == '\\' and not scan.escaped -%}
  139. {%- set scan.escaped = true -%}
  140. {%- else -%}
  141. {%- set scan.escaped = false -%}
  142. {%- endif -%}
  143. {%- elif ch == '"' -%}
  144. {%- set scan.quoted = true -%}
  145. {%- set state.pos = state.pos + 1 -%}
  146. {%- elif ch == '{' or ch == '[' -%}
  147. {%- set scan.depth = scan.depth + 1 -%}
  148. {%- set state.pos = state.pos + 1 -%}
  149. {%- elif ch == '}' or ch == ']' -%}
  150. {%- if scan.depth > 0 -%}
  151. {%- set scan.depth = scan.depth - 1 -%}
  152. {%- set state.pos = state.pos + 1 -%}
  153. {%- else -%}
  154. {%- set scan.done = true -%}
  155. {%- endif -%}
  156. {%- elif ch == ',' and scan.depth == 0 -%}
  157. {%- set scan.done = true -%}
  158. {%- else -%}
  159. {%- set state.pos = state.pos + 1 -%}
  160. {%- endif -%}
  161. {%- endif -%}
  162. {%- endfor -%}
  163. {%- endmacro -%}
  164.  
  165. {#- Parse and canonically render one JSON value from source at state.pos. -#}
  166. {%- macro canonical_json_text_value(source, state) -%}
  167. {{- json_skip_ws(source, state) -}}
  168. {%- if state.pos >= source | length -%}
  169. {{- '{}' -}}
  170. {%- elif source[state.pos] == '"' -%}
  171. {{- json_string(source, state) -}}
  172. {%- elif source[state.pos] == '{' -%}
  173. {%- set state.pos = state.pos + 1 -%}
  174. {{- json_skip_ws(source, state) -}}
  175. {%- set object_state = namespace(pairs=[], done=false) -%}
  176. {%- if state.pos < source | length and source[state.pos] == '}' -%}
  177. {%- set state.pos = state.pos + 1 -%}
  178. {%- set object_state.done = true -%}
  179. {%- endif -%}
  180. {%- for ignored in range(source | length) -%}
  181. {%- if not object_state.done -%}
  182. {{- json_skip_ws(source, state) -}}
  183. {%- set key = json_string(source, state) -%}
  184. {%- set sort_key = state.string_value -%}
  185. {{- json_skip_ws(source, state) -}}
  186. {%- if state.pos < source | length and source[state.pos] == ':' -%}
  187. {%- set state.pos = state.pos + 1 -%}
  188. {%- endif -%}
  189. {{- json_skip_ws(source, state) -}}
  190. {%- set value_start = state.pos -%}
  191. {{- json_scan_value(source, state) -}}
  192. {#- json.loads keeps the final member when a key is duplicated. -#}
  193. {%- set unique = namespace(pairs=[]) -%}
  194. {%- for previous in object_state.pairs -%}
  195. {%- if previous[0] != sort_key -%}
  196. {%- set unique.pairs = unique.pairs + [previous] -%}
  197. {%- endif -%}
  198. {%- endfor -%}
  199. {%- set object_state.pairs = unique.pairs + [[sort_key, key, source[value_start:state.pos]]] -%}
  200. {{- json_skip_ws(source, state) -}}
  201. {%- if state.pos < source | length and source[state.pos] == ',' -%}
  202. {%- set state.pos = state.pos + 1 -%}
  203. {%- else -%}
  204. {%- if state.pos < source | length and source[state.pos] == '}' -%}
  205. {%- set state.pos = state.pos + 1 -%}
  206. {%- endif -%}
  207. {%- set object_state.done = true -%}
  208. {%- endif -%}
  209. {%- endif -%}
  210. {%- endfor -%}
  211. {{- '{' -}}
  212. {%- for pair in object_state.pairs | sort(case_sensitive=true, attribute=0) -%}
  213. {{- pair[1] -}}{{- ':' -}}
  214. {%- set child_state = namespace(pos=0, string_value='') -%}
  215. {{- canonical_json_text_value(pair[2], child_state) -}}
  216. {%- if not loop.last -%}{{- ',' -}}{%- endif -%}
  217. {%- endfor -%}
  218. {{- '}' -}}
  219. {%- elif source[state.pos] == '[' -%}
  220. {%- set state.pos = state.pos + 1 -%}
  221. {{- '[' -}}
  222. {{- json_skip_ws(source, state) -}}
  223. {%- set array_state = namespace(done=false, first=true) -%}
  224. {%- if state.pos < source | length and source[state.pos] == ']' -%}
  225. {%- set state.pos = state.pos + 1 -%}
  226. {%- set array_state.done = true -%}
  227. {%- endif -%}
  228. {%- for ignored in range(source | length) -%}
  229. {%- if not array_state.done -%}
  230. {%- if not array_state.first -%}{{- ',' -}}{%- endif -%}
  231. {%- set array_state.first = false -%}
  232. {{- canonical_json_text_value(source, state) -}}
  233. {{- json_skip_ws(source, state) -}}
  234. {%- if state.pos < source | length and source[state.pos] == ',' -%}
  235. {%- set state.pos = state.pos + 1 -%}
  236. {%- else -%}
  237. {%- if state.pos < source | length and source[state.pos] == ']' -%}
  238. {%- set state.pos = state.pos + 1 -%}
  239. {%- endif -%}
  240. {%- set array_state.done = true -%}
  241. {%- endif -%}
  242. {%- endif -%}
  243. {%- endfor -%}
  244. {{- ']' -}}
  245. {%- else -%}
  246. {%- set scalar = namespace(start=state.pos, done=false) -%}
  247. {%- for ignored in range(source | length) -%}
  248. {%- if not scalar.done and state.pos < source | length -%}
  249. {%- set ch = source[state.pos] -%}
  250. {%- if ch == ',' or ch == '}' or ch == ']' or ch == ' ' or ch == '\t' or ch == '\r' or ch == '\n' -%}
  251. {%- set scalar.done = true -%}
  252. {%- else -%}
  253. {%- set state.pos = state.pos + 1 -%}
  254. {%- endif -%}
  255. {%- endif -%}
  256. {%- endfor -%}
  257. {%- set token = source[scalar.start:state.pos] -%}
  258. {%- if token == 'true' or token == 'false' or token == 'null' -%}
  259. {{- token -}}
  260. {%- elif '.' in token or 'e' in token or 'E' in token -%}
  261. {{- json_scalar(token | float) -}}
  262. {%- else -%}
  263. {{- token | int | tojson(ensure_ascii=false, separators=(',', ':')) -}}
  264. {%- endif -%}
  265. {%- endif -%}
  266. {%- endmacro -%}
  267.  
  268. {%- macro canonical_json_text(source) -%}
  269. {%- set text = source | trim -%}
  270. {%- if not text -%}
  271. {{- '{}' -}}
  272. {%- else -%}
  273. {%- set state = namespace(pos=0, string_value='') -%}
  274. {{- canonical_json_text_value(text, state) -}}
  275. {%- endif -%}
  276. {%- endmacro -%}
  277.  
  278. {#-
  279. OpenAI clients use either an argument mapping or a JSON-encoded object.
  280. Non-object/empty oddities degrade to {} instead of raising. Object parsing
  281. recursively sorts keys, keeps the last duplicate key (json.loads behavior),
  282. decodes JSON escapes under Transformers, and preserves array order.
  283. -#}
  284. {%- macro canonical_arguments(arguments) -%}
  285. {%- if arguments is mapping -%}
  286. {{- canonical_json(arguments) -}}
  287. {%- elif arguments is string -%}
  288. {%- set source = arguments | trim -%}
  289. {%- if source and source[0] == '{' -%}
  290. {{- canonical_json_text(source) -}}
  291. {%- else -%}
  292. {{- '{}' -}}
  293. {%- endif -%}
  294. {%- else -%}
  295. {{- '{}' -}}
  296. {%- endif -%}
  297. {%- endmacro -%}
  298.  
  299. {#-
  300. Match Python f"{float(effort):.2f}" followed by trailing-zero removal.
  301. llama.cpp's jinja engine has no round filter; the bit table handles binary64 midpoint equality.
  302. -#}
  303. {%- macro reasoning_effort_text(effort) -%}
  304. {%- set eff = effort -%}
  305. {%- if eff is string -%}
  306. {%- set e = eff | trim | lower -%}
  307. {%- if e == 'none' -%}{%- set eff = 0.0 -%}
  308. {%- elif e == 'minimal' -%}{%- set eff = 0.1 -%}
  309. {%- elif e == 'low' -%}{%- set eff = 0.2 -%}
  310. {%- elif e == 'medium' -%}{%- set eff = 0.7 -%}
  311. {%- elif e == 'high' -%}{%- set eff = 0.9 -%}
  312. {%- elif e == 'xhigh' -%}{%- set eff = 0.99 -%}
  313. {%- elif e == 'max' -%}{%- set eff = 0.99 -%}
  314. {%- else -%}{%- set eff = e | float(-1.0) -%}
  315. {%- endif -%}
  316. {%- endif -%}
  317. {%- set value = eff | float -%}
  318. {%- if value < 0 or value > 0.99 -%}
  319.  
  320. {%- endif -%}
  321. {%- if value == value | int and value >= 0 and value <= 1 -%}
  322. {{- value | int -}}
  323. {%- else -%}
  324. {%- set midpoint_rounds_up = '1011011011010100100100100111000111000111100011100011111100000001111110000001111110000001111111000000' -%}
  325. {%- set rounded = namespace(hundredths=0) -%}
  326. {%- for lower_hundredth in range(100) -%}
  327. {%- set boundary = (lower_hundredth + 0.5) / 100 -%}
  328. {%- if value > boundary or (value == boundary and midpoint_rounds_up[lower_hundredth] == '1') -%}
  329. {%- set rounded.hundredths = lower_hundredth + 1 -%}
  330. {%- endif -%}
  331. {%- endfor -%}
  332. {%- if rounded.hundredths == 100 -%}
  333. {{- '1' -}}
  334. {%- elif rounded.hundredths == 0 -%}
  335. {{- '0' -}}
  336. {%- elif rounded.hundredths % 10 == 0 -%}
  337. {{- '0.' -}}{{- (rounded.hundredths / 10) | int -}}
  338. {%- elif rounded.hundredths < 10 -%}
  339. {{- '0.0' -}}{{- rounded.hundredths -}}
  340. {%- else -%}
  341. {{- '0.' -}}{{- rounded.hundredths -}}
  342. {%- endif -%}
  343. {%- endif -%}
  344. {%- endmacro -%}
  345.  
  346. {%- macro role_token(role) -%}
  347. {%- if role == 'user' -%}{{- '<|message_user|>' -}}
  348. {%- elif role == 'assistant' -%}{{- '<|message_model|>' -}}
  349. {%- elif role == 'system' or role == 'developer' -%}{{- '<|message_system|>' -}}
  350. {%- elif role == 'tool' -%}{{- '<|message_tool|>' -}}
  351. {%- endif -%}
  352. {%- endmacro -%}
  353.  
  354. {%- macro emit_message(role, kind, content='', author_name='') -%}
  355. {{- role_token(role) -}}
  356. {%- if author_name -%}{{- author_name -}}{%- endif -%}
  357. {%- if kind == 'text' -%}
  358. {{- '<|content_text|>' -}}{{- content -}}
  359. {%- elif kind == 'thinking' -%}
  360. {{- '<|content_thinking|>' -}}{{- content -}}
  361. {%- elif kind == 'xml' -%}
  362. {{- '<|content_xml|>' -}}{{- content -}}
  363. {%- elif kind == 'invoke_tool_json' -%}
  364. {{- '<|content_invoke_tool_json|>' -}}{{- content -}}
  365. {%- elif kind == 'image' -%}
  366. {{- '<|content_image|><|image|>' -}}
  367. {%- elif kind == 'audio' -%}
  368. {{- '<|content_audio_input|><|audio|><|audio_end|>' -}}
  369. {%- endif -%}
  370. {{- '<|end_message|>' -}}
  371. {%- endmacro -%}
  372.  
  373. {# MODIFIED: Check `thinking` parameter to override the system instructions for effort level #}
  374. {%- set effort_value = reasoning_effort if (reasoning_effort is defined and reasoning_effort is not none) else 0.9 -%}
  375. {%- if thinking is defined and thinking == false -%}
  376. {%- set effort_value = 0.0 -%}
  377. {%- endif -%}
  378.  
  379. {%- set eff_ns = namespace(emitted=false) -%}
  380. {%- set first_ns = namespace(idx=-1) -%}
  381. {%- for m in messages -%}
  382. {%- if first_ns.idx == -1 and m.get('role') not in ['system', 'developer'] -%}
  383. {%- set first_ns.idx = loop.index0 -%}
  384. {%- endif -%}
  385. {%- endfor -%}
  386.  
  387. {%- if tools is defined and tools -%}
  388. {{- '<|message_system|>tool_declare<|content_xml|>[' -}}
  389. {%- for tool in tools -%}
  390. {%- set function = tool.get('function', {}) if tool.get('function', {}) is mapping else {} -%}
  391. {%- set description = function.get('description') or '' -%}
  392. {%- set parameters = function.get('parameters') or {} -%}
  393. {%- set tool_type = tool.get('type', 'function') -%}
  394. {{- '{"description":' -}}{{- canonical_json(description) -}}
  395. {{- ',"name":' -}}{{- canonical_json(function.get('name')) -}}
  396. {{- ',"parameters":' -}}{{- canonical_json(parameters) -}}
  397. {{- ',"type":' -}}{{- canonical_json(tool_type) -}}{{- '}' -}}
  398. {%- if not loop.last -%}{{- ',' -}}{%- endif -%}
  399. {%- endfor -%}
  400. {{- ']<|end_message|>' -}}
  401. {%- endif -%}
  402.  
  403. {#- Last-user boundary used only by the opt-in preserve_thinking=false mode. -#}
  404. {%- set thinking_state = namespace(last_user_index=messages | length - 1, found_user=false) -%}
  405. {%- for index in range(messages | length - 1, -1, -1) -%}
  406. {%- if not thinking_state.found_user and messages[index].get('role') == 'user' -%}
  407. {%- set thinking_state.last_user_index = index -%}
  408. {%- set thinking_state.found_user = true -%}
  409. {%- endif -%}
  410. {%- endfor -%}
  411.  
  412. {%- for message in messages -%}
  413. {%- set message_index = loop.index0 -%}
  414. {%- set role = message.get('role') -%}
  415. {%- if not eff_ns.emitted and loop.index0 == first_ns.idx -%}
  416. {{- emit_message('system', 'text', 'Thinking effort level: ' + reasoning_effort_text(effort_value)) -}}
  417. {%- set eff_ns.emitted = true -%}
  418. {%- endif -%}
  419. {%- if role == 'tool' -%}
  420. {%- set resolved = namespace(name=message.get('name') or '') -%}
  421. {%- if not resolved.name and message.get('tool_call_id') -%}
  422. {%- for prior in messages[:message_index] -%}
  423. {%- if prior.get('role') == 'assistant' -%}
  424. {%- for call in prior.get('tool_calls') or [] -%}
  425. {%- if call.get('id') and (call.get('id') | string) == message.get('tool_call_id') -%}
  426. {%- set prior_function = call.get('function', {}) if call.get('function', {}) is mapping else {} -%}
  427. {%- set resolved.name = prior_function.get('name') or '' -%}
  428. {%- endif -%}
  429. {%- endfor -%}
  430. {%- endif -%}
  431. {%- endfor -%}
  432. {%- endif -%}
  433. {%- set tool_content = message.get('content', '') -%}
  434. {%- if tool_content is none -%}
  435. {%- set tool_content = '' -%}
  436. {%- elif tool_content is mapping or (tool_content is sequence and tool_content is not string) -%}
  437. {%- set tool_content = canonical_json(tool_content) -%}
  438. {%- elif tool_content is not string -%}
  439. {%- set tool_content = canonical_json(tool_content) -%}
  440. {%- endif -%}
  441. {{- emit_message('tool', 'text', tool_content, resolved.name | string) -}}
  442. {%- elif role == 'user' or role == 'assistant' or role == 'system' or role == 'developer' -%}
  443. {%- set turn_out -%}
  444. {%- if role == 'assistant' and message.get('reasoning_content') is string and message.get('reasoning_content') and
  445. ((preserve_thinking is not defined) or preserve_thinking is not false or message_index > thinking_state.last_user_index) -%}
  446. {{- emit_message('assistant', 'thinking', message.get('reasoning_content')) -}}
  447. {%- endif -%}
  448.  
  449. {%- set content = message.get('content', '') -%}
  450. {#- Makes llama.cpp retain typed arrays rather than flattening them. -#}
  451. {%- set content_probe = content[0] if content is sequence and content | length > 0 else none -%}
  452. {%- if content is string -%}
  453. {%- if '<__media_' in content -%}
  454. {#- Flattened media markers: each part becomes its own message block. The runtime may
  455. randomize the marker suffix, so split on the stable prefix and re-emit the exact
  456. marker text; the runtime then expands it into the typed content sentinel plus the
  457. media embedding rows. -#}
  458. {%- for segment in content.split('<__media_') -%}
  459. {%- if loop.first -%}
  460. {%- if segment -%}{{- emit_message(role, 'text', segment) -}}{%- endif -%}
  461. {%- else -%}
  462. {%- set mparts = segment.split('>') -%}
  463. {%- set rest = mparts[1:] | join('>') -%}
  464. {{- role_token(role) -}}{{- '<__media_' + mparts[0] + '>' -}}{{- '<|end_message|>' -}}
  465. {%- if rest -%}{{- emit_message(role, 'text', rest) -}}{%- endif -%}
  466. {%- endif -%}
  467. {%- endfor -%}
  468. {%- elif content -%}
  469. {{- emit_message(role, 'text', content) -}}
  470. {%- endif -%}
  471. {%- elif content is sequence -%}
  472. {%- for part in content -%}
  473. {%- if part is string -%}
  474. {{- emit_message(role, 'text', part) -}}
  475. {%- elif part is mapping -%}
  476. {%- set part_type = part.get('type') -%}
  477. {%- if part_type is none or part_type == 'text' or part_type == 'input_text' -%}
  478. {%- set part_text = part.get('text', '') -%}
  479. {{- emit_message(role, 'text', part_text if part_text is string else '') -}}
  480. {%- elif part_type == 'image' or part_type == 'input_image' or part_type == 'image_url' -%}
  481. {{- emit_message(role, 'image') -}}
  482. {%- elif part_type == 'audio' or part_type == 'input_audio' or part_type == 'audio_url' -%}
  483. {{- emit_message(role, 'audio') -}}
  484. {%- endif -%}
  485. {%- endif -%}
  486. {%- endfor -%}
  487. {%- endif -%}
  488.  
  489. {%- if role == 'assistant' -%}
  490. {%- for call in message.get('tool_calls') or [] -%}
  491. {%- set function = call.get('function', {}) if call.get('function', {}) is mapping else {} -%}
  492. {%- if function.get('name') is string -%}
  493. {%- set raw_arguments = function.get('arguments') or {} -%}
  494. {%- set arguments_json = canonical_arguments(raw_arguments) -%}
  495. {%- set invocation = '{"name":' + canonical_json(function.get('name')) + ',"args":' + arguments_json + '}' -%}
  496. {{- emit_message('assistant', 'invoke_tool_json', invocation, function.get('name')) -}}
  497. {%- endif -%}
  498. {%- endfor -%}
  499. {%- endif -%}
  500. {%- endset -%}
  501. {{- turn_out -}}
  502. {#- Close each historical model turn, but never emit a bare terminator for an
  503. assistant message that rendered no blocks. -#}
  504. {%- if role == 'assistant' and turn_out -%}
  505. {{- '<|content_model_end_sampling|>' -}}
  506. {%- endif -%}
  507. {%- else -%}
  508.  
  509. {%- endif -%}
  510. {%- endfor -%}
  511.  
  512. {%- if not eff_ns.emitted -%}
  513. {{- emit_message('system', 'text', 'Thinking effort level: ' + reasoning_effort_text(effort_value)) -}}
  514. {%- endif -%}
  515.  
  516. {# MODIFIED: Prefill the Assistant text token to skip thinking if thinking=false #}
  517. {%- if add_generation_prompt is defined and add_generation_prompt -%}
  518. {%- if thinking is defined and thinking == false -%}
  519. {{- '<|message_model|><|content_text|>' -}}
  520. {%- else -%}
  521. {{- '<|message_model|>' -}}
  522. {%- endif -%}
  523. {%- endif -%}
  524. {#- Unsloth translation to jinja from TML's parser #}
Advertisement
Add Comment
Please, Sign In to add comment