Greatjedi commited on
Commit
188a1b8
·
verified ·
1 Parent(s): 07b3f18

Add froggeric qwen-sharp.jinja chat template

Browse files
Files changed (1) hide show
  1. chat_templates/qwen-sharp.jinja +488 -0
chat_templates/qwen-sharp.jinja ADDED
@@ -0,0 +1,488 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- set template_version = "qwen3.8-froggeric-v22.5.0" %}
2
+ {%- set _tool_format = tool_call_format if tool_call_format is defined else 'xml' %}
3
+ {%- set image_count = namespace(value=0) %}
4
+ {%- set video_count = namespace(value=0) %}
5
+ {%- set add_vision_id = add_vision_id if add_vision_id is defined else false %}
6
+ {%- set enable_thinking = enable_thinking if enable_thinking is defined else true %}
7
+ {%- set auto_disable_thinking_with_tools = auto_disable_thinking_with_tools if auto_disable_thinking_with_tools is defined else false %}
8
+ {%- if preserve_reasoning is defined and preserve_reasoning is not none %}
9
+ {%- set _preserve_thinking = preserve_reasoning %}
10
+ {%- elif preserve_thinking is defined and preserve_thinking is not none %}
11
+ {%- set _preserve_thinking = preserve_thinking %}
12
+ {%- else %}
13
+ {%- set _preserve_thinking = true %}
14
+ {%- endif %}
15
+ {%- set max_tool_arg_chars = max_tool_arg_chars if max_tool_arg_chars is defined else 0 %}
16
+ {%- set max_tool_response_chars = max_tool_response_chars if max_tool_response_chars is defined else 0 %}
17
+ {%- set _default_reasoning_effort = 'medium' %}
18
+ {%- set _has_tools = (tools is defined and tools and tools is iterable and tools is not mapping) %}
19
+ {%- set _effort_raw = (reasoning_effort | string | lower) if reasoning_effort is defined and reasoning_effort is not none else _default_reasoning_effort %}
20
+ {%- set _initial_thinking = enable_thinking %}
21
+ {%- if _effort_raw in ('none', 'off') %}
22
+ {%- set _initial_thinking = false %}
23
+ {%- set _initial_effort = 'medium' %}
24
+ {%- elif _effort_raw in ('minimal', 'low') %}
25
+ {%- set _initial_effort = 'low' %}
26
+ {%- elif _effort_raw in ('high', 'xhigh', 'max', 'ultracode', 'extreme') %}
27
+ {%- set _initial_effort = 'xhigh' %}
28
+ {%- else %}
29
+ {%- set _initial_effort = 'medium' %}
30
+ {%- endif %}
31
+ {%- set ns_state = namespace(thinking=_initial_thinking, effort=_initial_effort) %}
32
+ {%- if auto_disable_thinking_with_tools and _has_tools %}
33
+ {%- set ns_state.thinking = false %}
34
+ {%- endif %}
35
+ {%- for msg in messages %}
36
+ {%- if msg.role == 'system' or msg.role == 'developer' or msg.role == 'user' %}
37
+ {%- if msg.content is string %}
38
+ {%- if '<|think_off|>' in msg.content %}
39
+ {%- set ns_state.thinking = false %}
40
+ {%- elif '<|think_on|>' in msg.content %}
41
+ {%- set ns_state.thinking = true %}
42
+ {%- elif '<|think_xhigh|>' in msg.content or '<|think_high|>' in msg.content or '<|think_ultracode|>' in msg.content or '<|think_extreme|>' in msg.content or '<|think_max|>' in msg.content %}
43
+ {%- set ns_state.thinking = true %}
44
+ {%- set ns_state.effort = 'xhigh' %}
45
+ {%- elif '<|think_low|>' in msg.content or '<|think_minimal|>' in msg.content %}
46
+ {%- set ns_state.thinking = true %}
47
+ {%- set ns_state.effort = 'low' %}
48
+ {%- elif '<|think_medium|>' in msg.content %}
49
+ {%- set ns_state.thinking = true %}
50
+ {%- set ns_state.effort = 'medium' %}
51
+ {%- endif %}
52
+ {%- elif msg.content is iterable and msg.content is not mapping %}
53
+ {%- for item in msg.content %}
54
+ {%- if item is string %}
55
+ {%- set _item_text = item %}
56
+ {%- elif item is mapping and 'text' in item and item.text is string %}
57
+ {%- set _item_text = item.text %}
58
+ {%- else %}
59
+ {%- set _item_text = '' %}
60
+ {%- endif %}
61
+ {%- if _item_text %}
62
+ {%- if '<|think_off|>' in _item_text %}
63
+ {%- set ns_state.thinking = false %}
64
+ {%- elif '<|think_on|>' in _item_text %}
65
+ {%- set ns_state.thinking = true %}
66
+ {%- elif '<|think_xhigh|>' in _item_text or '<|think_high|>' in _item_text or '<|think_ultracode|>' in _item_text or '<|think_extreme|>' in _item_text or '<|think_max|>' in _item_text %}
67
+ {%- set ns_state.thinking = true %}
68
+ {%- set ns_state.effort = 'xhigh' %}
69
+ {%- elif '<|think_low|>' in _item_text or '<|think_minimal|>' in _item_text %}
70
+ {%- set ns_state.thinking = true %}
71
+ {%- set ns_state.effort = 'low' %}
72
+ {%- elif '<|think_medium|>' in _item_text %}
73
+ {%- set ns_state.thinking = true %}
74
+ {%- set ns_state.effort = 'medium' %}
75
+ {%- endif %}
76
+ {%- endif %}
77
+ {%- endfor %}
78
+ {%- endif %}
79
+ {%- endif %}
80
+ {%- endfor %}
81
+ {%- set reasoning_instructions = '' %}
82
+ {%- if ns_state.thinking %}
83
+ {%- if ns_state.effort == 'xhigh' %}
84
+ {%- set reasoning_instructions = 'Reasoning effort is set to xhigh. Please think carefully through the task, validate key assumptions, consider plausible alternatives, and prioritize correctness, consistency, and clarity in the final answer.' %}
85
+ {%- elif ns_state.effort == 'low' %}
86
+ {%- set reasoning_instructions = 'Reasoning effort is set to low. Keep your thinking brief and focused, moving directly to the conclusion without unnecessary elaboration.' %}
87
+ {%- endif %}
88
+ {%- endif %}
89
+ {%- macro render_content(content, do_vision_count, is_system_content=false) %}
90
+ {%- if content is string %}
91
+ {{- content }}
92
+ {%- elif content is iterable and content is not mapping %}
93
+ {%- for item in content %}
94
+ {%- if item is mapping %}
95
+ {%- if item.type == 'image' or 'image' in item or 'image_url' in item %}
96
+ {%- if is_system_content %}
97
+ {{- raise_exception('System message cannot contain images.') }}
98
+ {%- endif %}
99
+ {%- if do_vision_count %}
100
+ {%- set image_count.value = image_count.value + 1 %}
101
+ {%- endif %}
102
+ {%- if add_vision_id %}
103
+ {{- 'Picture ' ~ image_count.value ~ ': ' }}
104
+ {%- endif %}
105
+ {{- '<|vision_start|><|image_pad|><|vision_end|>' }}
106
+ {%- elif item.type == 'video' or 'video' in item or 'video_url' in item %}
107
+ {%- if is_system_content %}
108
+ {{- raise_exception('System message cannot contain videos.') }}
109
+ {%- endif %}
110
+ {%- if do_vision_count %}
111
+ {%- set video_count.value = video_count.value + 1 %}
112
+ {%- endif %}
113
+ {%- if add_vision_id %}
114
+ {{- 'Video ' ~ video_count.value ~ ': ' }}
115
+ {%- endif %}
116
+ {{- '<|vision_start|><|video_pad|><|vision_end|>' }}
117
+ {%- elif 'text' in item %}
118
+ {{- item.text }}
119
+ {%- else %}
120
+ {{- raise_exception('Unexpected item type in content.') }}
121
+ {%- endif %}
122
+ {%- else %}
123
+ {{- item | string }}
124
+ {%- endif %}
125
+ {%- endfor %}
126
+ {%- elif content is none or content is undefined %}
127
+ {{- '' }}
128
+ {%- else %}
129
+ {{- raise_exception('Unexpected content type.') }}
130
+ {%- endif %}
131
+ {%- endmacro %}
132
+ {%- if not messages %}
133
+ {{- raise_exception('No messages provided.') }}
134
+ {%- endif %}
135
+ {%- set head = namespace(count=0, seen_non_system=false) %}
136
+ {%- for message in messages %}
137
+ {%- set _is_sys = (message.role == 'system' or message.role == 'developer') %}
138
+ {%- if _is_sys and not head.seen_non_system %}
139
+ {%- set head.count = head.count + 1 %}
140
+ {%- else %}
141
+ {%- set head.seen_non_system = true %}
142
+ {%- endif %}
143
+ {%- endfor %}
144
+ {%- set sys_state = namespace(content='') %}
145
+ {%- for message in messages[:head.count] %}
146
+ {%- set _part = render_content(message.content, false, true) | trim %}
147
+ {%- if '<|think_off|>' in _part %}{%- set _part = _part.split('<|think_off|>') | join('') | trim %}{%- endif %}
148
+ {%- if '<|think_on|>' in _part %}{%- set _part = _part.split('<|think_on|>') | join('') | trim %}{%- endif %}
149
+ {%- if '<|think_xhigh|>' in _part %}{%- set _part = _part.split('<|think_xhigh|>') | join('') | trim %}{%- endif %}
150
+ {%- if '<|think_high|>' in _part %}{%- set _part = _part.split('<|think_high|>') | join('') | trim %}{%- endif %}
151
+ {%- if '<|think_ultracode|>' in _part %}{%- set _part = _part.split('<|think_ultracode|>') | join('') | trim %}{%- endif %}
152
+ {%- if '<|think_extreme|>' in _part %}{%- set _part = _part.split('<|think_extreme|>') | join('') | trim %}{%- endif %}
153
+ {%- if '<|think_max|>' in _part %}{%- set _part = _part.split('<|think_max|>') | join('') | trim %}{%- endif %}
154
+ {%- if '<|think_medium|>' in _part %}{%- set _part = _part.split('<|think_medium|>') | join('') | trim %}{%- endif %}
155
+ {%- if '<|think_low|>' in _part %}{%- set _part = _part.split('<|think_low|>') | join('') | trim %}{%- endif %}
156
+ {%- if '<|think_minimal|>' in _part %}{%- set _part = _part.split('<|think_minimal|>') | join('') | trim %}{%- endif %}
157
+ {%- if _part %}
158
+ {%- if sys_state.content %}
159
+ {%- set sys_state.content = sys_state.content ~ '\n\n' ~ _part %}
160
+ {%- else %}
161
+ {%- set sys_state.content = _part %}
162
+ {%- endif %}
163
+ {%- endif %}
164
+ {%- endfor %}
165
+ {%- set _sc = sys_state.content %}
166
+ {%- set _msgs = messages[head.count:] %}
167
+ {%- if ns_state.thinking %}
168
+ {%- set _terse_lead = 'Answer directly, after thinking. Lead with the answer, then only what it needs to be correct and usable.' %}
169
+ {%- else %}
170
+ {%- set _terse_lead = 'Answer directly and concisely. Give the answer with only what it needs to be correct and usable.' %}
171
+ {%- endif %}
172
+ {%- set _terse_core %}
173
+ Never: open with preamble or pleasantries; restate the question; add filler transitions; hedge with niceties; or repeat a point you've already made.
174
+ Always: keep essential steps, caveats, uncertainties, and specifics — never drop correctness or a needed warning for brevity. Keep the final answer lean. Use the least structure that conveys it (plain prose when short; lists or code only when they earn their place). If genuinely uncertain, say so and explain why — never omit uncertainty for the sake of brevity.
175
+ If a user request is genuinely ambiguous, ask a sharp question, don't guess.
176
+ {%- endset %}
177
+ {%- set _terse = _terse_lead ~ '\n' ~ (_terse_core | trim) %}
178
+ {#- `terse` chat-template kwarg: default true, so behaviour is unchanged unless a caller opts out.
179
+ Pass {"terse": false} via chat_template_kwargs to serve the model with only its own system
180
+ prompt -- useful for A/B-ing the terseness effect, or when a downstream prompt conflicts. #}
181
+ {%- set _terse_on = terse if terse is defined else true %}
182
+ {%- if _terse_on %}
183
+ {%- if not _sc %}
184
+ {%- set _sc = _terse | trim %}
185
+ {%- else %}
186
+ {%- set _sc = (_sc | trim) ~ '\n\n' ~ (_terse | trim) %}
187
+ {%- endif %}
188
+ {%- endif %}
189
+ {#- Some runtimes (LM Studio's MLX backend) have no native tool-call parser and prepend their own
190
+ protocol into the system content. Emitting ours as well gives the model two contradictory tool
191
+ protocols and it follows one at random. Detect that marker and stand down; the
192
+ `suppress_tool_instructions` kwarg overrides either way where a runtime can pass template kwargs. #}
193
+ {%- set _runtime_tool_protocol = (_sc is defined and _sc and '[TOOL_REQUEST]' in _sc) %}
194
+ {%- set _suppress_tools = suppress_tool_instructions if suppress_tool_instructions is defined else _runtime_tool_protocol %}
195
+ {%- if _has_tools and not _suppress_tools %}
196
+ {{- '<|im_start|>system\n' }}
197
+ {%- if reasoning_instructions %}
198
+ {{- reasoning_instructions + '\n\n' }}
199
+ {%- endif %}
200
+ {{- '# Tools\n\nYou have access to the following functions:\n\n<tools>' }}
201
+ {%- for tool in tools %}
202
+ {{- '\n' }}
203
+ {{- tool | tojson }}
204
+ {%- endfor %}
205
+ {{- '\n</tools>' }}
206
+ {%- if _tool_format == 'json' %}
207
+ {{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n' }}
208
+ {%- if ns_state.thinking %}
209
+ {{- '<think>\nBrief explanation of tool call\n</think>\n' }}
210
+ {%- endif %}
211
+ {{- '<tool_call>\n{"name": "example_function_name", "arguments": {"example_parameter_1": "value_1", "example_parameter_2": "This is the value for the second parameter"}}\n</tool_call>\n\n<IMPORTANT>\nReminder:\n' }}
212
+ {%- if ns_state.thinking %}
213
+ {{- '- You can use the <think></think> block to plan your next tool call OR to synthesize data and formulate your final response to the user.\n- ALL explanation and reasoning MUST be placed strictly inside the <think></think> block.\n' }}
214
+ {%- endif %}
215
+ {{- '- Function calls MUST follow the specified format: a single JSON object with "name" and "arguments" keys inside <tool_call></tool_call> XML tags.\n' }}
216
+ {%- if ns_state.thinking %}
217
+ {{- '- If you choose to call a tool, you MUST output the <tool_call> block IMMEDIATELY after thinking, with NO conversational text before it.\n' }}
218
+ {%- else %}
219
+ {{- '- If you choose to call a tool, you MUST output the <tool_call> block IMMEDIATELY, with NO conversational text before it.\n' }}
220
+ {%- endif %}
221
+ {{- '- The <tool_call> tag MUST be at the very beginning of a new line, with NO spaces or indentation before it.\n- To call multiple functions, output a separate, completely closed <tool_call></tool_call> block for EACH function. Do NOT nest <tool_call> blocks.\n- If you have all necessary data, provide your final answer directly to the user without any tool call.\n</IMPORTANT>' }}
222
+ {%- else %}
223
+ {{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n' }}
224
+ {%- if ns_state.thinking %}
225
+ {{- '<think>\nBrief explanation of tool call\n</think>\n' }}
226
+ {%- endif %}
227
+ {{- '<tool_call>\n<function=example_function_name>\n<parameter=example_parameter_1>\nvalue_1\n</parameter>\n<parameter=example_parameter_2>\nThis is the value for the second parameter\nthat can span\nmultiple lines\n</parameter>\n</function>\n</tool_call>\n\n<IMPORTANT>\nReminder:\n' }}
228
+ {%- if ns_state.thinking %}
229
+ {{- '- You can use the <think></think> block to plan your next tool call OR to synthesize data and formulate your final response to the user.\n- ALL explanation and reasoning MUST be placed strictly inside the <think></think> block.\n' }}
230
+ {%- endif %}
231
+ {{- '- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags.\n' }}
232
+ {%- if ns_state.thinking %}
233
+ {{- '- If you choose to call a tool, you MUST output the <tool_call> block IMMEDIATELY after thinking, with NO conversational text before it.\n' }}
234
+ {%- else %}
235
+ {{- '- If you choose to call a tool, you MUST output the <tool_call> block IMMEDIATELY, with NO conversational text before it.\n' }}
236
+ {%- endif %}
237
+ {{- '- The <tool_call> and <function> tags MUST be at the very beginning of a new line, with NO spaces or indentation before them.\n- To call multiple functions, output a separate, completely closed <tool_call></tool_call> block for EACH function. Do NOT nest <tool_call> blocks.\n- If you have all necessary data, provide your final answer directly to the user without any tool call.\n</IMPORTANT>' }}
238
+ {%- endif %}
239
+ {%- if _sc %}
240
+ {{- '\n\n' + _sc }}
241
+ {%- endif %}
242
+ {{- '<|im_end|>\n' }}
243
+ {%- else %}
244
+ {%- if _sc %}
245
+ {{- '<|im_start|>system\n' + (reasoning_instructions + '\n\n' if reasoning_instructions else '') + _sc + '<|im_end|>\n' }}
246
+ {%- elif reasoning_instructions %}
247
+ {{- '<|im_start|>system\n' + reasoning_instructions + '<|im_end|>\n' }}
248
+ {%- endif %}
249
+ {%- endif %}
250
+ {%- set _last_idx = _msgs | length - 1 %}
251
+ {%- set ns = namespace(multi_step_tool=true, last_query_index=_last_idx) %}
252
+ {%- for message in _msgs[::-1] %}
253
+ {%- set index = (_msgs | length - 1) - loop.index0 %}
254
+ {%- if ns.multi_step_tool and message.role == 'user' %}
255
+ {%- set _rc = render_content(message.content, false) | trim %}
256
+ {%- if not (_rc.startswith('<tool_response>') and _rc.endswith('</tool_response>')) %}
257
+ {%- set ns.multi_step_tool = false %}
258
+ {%- set ns.last_query_index = index %}
259
+ {%- endif %}
260
+ {%- endif %}
261
+ {%- endfor %}
262
+ {%- if ns.multi_step_tool %}
263
+ {%- if _last_idx > 50 %}
264
+ {%- set ns.last_query_index = _last_idx %}
265
+ {%- else %}
266
+ {%- set ns.last_query_index = 0 %}
267
+ {%- endif %}
268
+ {%- endif %}
269
+ {%- set ns2 = namespace(prev_role='', consecutive_failures=0) %}
270
+ {%- for message in _msgs %}
271
+ {%- set is_system = (message.role == "system" or message.role == "developer") %}
272
+ {%- set content = render_content(message.content, true, is_system) | trim %}
273
+ {%- if is_system or message.role == 'user' %}
274
+ {%- if '<|think_off|>' in content %}{%- set content = content.split('<|think_off|>') | join('') | trim %}{%- endif %}
275
+ {%- if '<|think_on|>' in content %}{%- set content = content.split('<|think_on|>') | join('') | trim %}{%- endif %}
276
+ {%- if '<|think_xhigh|>' in content %}{%- set content = content.split('<|think_xhigh|>') | join('') | trim %}{%- endif %}
277
+ {%- if '<|think_high|>' in content %}{%- set content = content.split('<|think_high|>') | join('') | trim %}{%- endif %}
278
+ {%- if '<|think_ultracode|>' in content %}{%- set content = content.split('<|think_ultracode|>') | join('') | trim %}{%- endif %}
279
+ {%- if '<|think_extreme|>' in content %}{%- set content = content.split('<|think_extreme|>') | join('') | trim %}{%- endif %}
280
+ {%- if '<|think_max|>' in content %}{%- set content = content.split('<|think_max|>') | join('') | trim %}{%- endif %}
281
+ {%- if '<|think_medium|>' in content %}{%- set content = content.split('<|think_medium|>') | join('') | trim %}{%- endif %}
282
+ {%- if '<|think_low|>' in content %}{%- set content = content.split('<|think_low|>') | join('') | trim %}{%- endif %}
283
+ {%- if '<|think_minimal|>' in content %}{%- set content = content.split('<|think_minimal|>') | join('') | trim %}{%- endif %}
284
+ {%- endif %}
285
+ {%- if is_system %}
286
+ {{- '<|im_start|>system\n' + content + '<|im_end|>\n' }}
287
+ {%- elif message.role == 'user' %}
288
+ {%- set ns2.consecutive_failures = 0 %}
289
+ {{- '<|im_start|>user\n' + content + '<|im_end|>\n' }}
290
+ {%- elif message.role == 'assistant' %}
291
+ {%- set reasoning_content = '' %}
292
+ {%- set _explicit_reasoning = '' %}
293
+ {%- if message.reasoning_content is defined and message.reasoning_content is not none %}
294
+ {%- if message.reasoning_content is string %}
295
+ {%- set _explicit_reasoning = message.reasoning_content %}
296
+ {%- else %}
297
+ {%- set _explicit_reasoning = message.reasoning_content | string %}
298
+ {%- endif %}
299
+ {%- elif message.thinking is defined and message.thinking is not none %}
300
+ {%- if message.thinking is string %}
301
+ {%- set _explicit_reasoning = message.thinking %}
302
+ {%- else %}
303
+ {%- set _explicit_reasoning = message.thinking | string %}
304
+ {%- endif %}
305
+ {%- elif message.reasoning is defined and message.reasoning is not none %}
306
+ {%- if message.reasoning is string %}
307
+ {%- set _explicit_reasoning = message.reasoning %}
308
+ {%- else %}
309
+ {%- set _explicit_reasoning = message.reasoning | string %}
310
+ {%- endif %}
311
+ {%- endif %}
312
+ {%- if _explicit_reasoning %}
313
+ {%- set _lead_end = '' %}
314
+ {%- if content.startswith('<think>') and '</think>' in content %}
315
+ {%- set _lead_end = '</think>' %}
316
+ {%- elif content.startswith('<thinking>') and '</thinking>' in content %}
317
+ {%- set _lead_end = '</thinking>' %}
318
+ {%- elif content.startswith('</think>') %}
319
+ {%- set _lead_end = '</think>' %}
320
+ {%- elif content.startswith('</thinking>') %}
321
+ {%- set _lead_end = '</thinking>' %}
322
+ {%- endif %}
323
+ {%- if _lead_end %}
324
+ {%- set content = content.split(_lead_end)[-1].lstrip('\n') %}
325
+ {%- endif %}
326
+ {%- set reasoning_content = _explicit_reasoning %}
327
+ {%- else %}
328
+ {%- set _think_end = '' %}
329
+ {%- if content.startswith('</think>') %}
330
+ {%- set _think_end = '</think>' %}
331
+ {%- elif content.startswith('</thinking>') %}
332
+ {%- set _think_end = '</thinking>' %}
333
+ {%- elif '\n</think>' in content %}
334
+ {%- set _think_end = '\n</think>' %}
335
+ {%- elif '\n</thinking>' in content %}
336
+ {%- set _think_end = '\n</thinking>' %}
337
+ {%- elif '\n</ think>' in content %}
338
+ {%- set _think_end = '\n</ think>' %}
339
+ {%- elif '\n</think >' in content %}
340
+ {%- set _think_end = '\n</think >' %}
341
+ {%- elif content.startswith('<think>') and '</think>' in content %}
342
+ {%- set _think_end = '</think>' %}
343
+ {%- elif content.startswith('<thinking>') and '</thinking>' in content %}
344
+ {%- set _think_end = '</thinking>' %}
345
+ {%- endif %}
346
+ {%- if _think_end %}
347
+ {%- if 'thinking' in _think_end %}
348
+ {%- set _think_start = '<thinking>' %}
349
+ {%- else %}
350
+ {%- set _think_start = '<think>' %}
351
+ {%- endif %}
352
+ {%- set reasoning_content = content.split(_think_end)[0].rstrip('\n') %}
353
+ {%- if _think_start in reasoning_content %}
354
+ {%- set reasoning_content = reasoning_content.split(_think_start)[-1].lstrip('\n') %}
355
+ {%- endif %}
356
+ {%- set content = content.split(_think_end)[-1].lstrip('\n') %}
357
+ {%- endif %}
358
+ {%- endif %}
359
+ {%- set reasoning_content = reasoning_content | trim %}
360
+ {%- if (_preserve_thinking or loop.index0 > ns.last_query_index) %}
361
+ {{- '<|im_start|>assistant\n<think>\n' + reasoning_content + '\n</think>\n\n' + content }}
362
+ {%- else %}
363
+ {{- '<|im_start|>assistant\n' + content }}
364
+ {%- endif %}
365
+ {%- if message.tool_calls is defined and message.tool_calls and message.tool_calls is iterable and message.tool_calls is not mapping %}
366
+ {%- for tool_call in message.tool_calls %}
367
+ {%- if tool_call.function is defined and tool_call.function is not none %}
368
+ {%- set tc = tool_call.function %}
369
+ {%- else %}
370
+ {%- set tc = tool_call %}
371
+ {%- endif %}
372
+ {%- set tc_name = tc.name if (tc.name is defined and tc.name is not none) else '' %}
373
+ {%- if _tool_format == 'json' %}
374
+ {%- if loop.first %}
375
+ {%- if content | trim %}
376
+ {{- '\n\n' }}
377
+ {%- endif %}
378
+ {%- else %}
379
+ {{- '\n' }}
380
+ {%- endif %}
381
+ {%- set _args = '{}' %}
382
+ {%- if tc.arguments is defined and tc.arguments is not none %}
383
+ {%- if tc.arguments is mapping %}
384
+ {%- set _args = tc.arguments | tojson %}
385
+ {%- elif tc.arguments is string %}
386
+ {%- if tc.arguments %}
387
+ {%- set _args = tc.arguments %}
388
+ {%- endif %}
389
+ {%- else %}
390
+ {%- set _args = tc.arguments | tojson %}
391
+ {%- endif %}
392
+ {%- endif %}
393
+ {{- '<tool_call>\n{"name": ' }}{{- tc_name | tojson }}{{- ', "arguments": ' }}{{- _args }}{{- '}\n</tool_call>' }}
394
+ {%- else %}
395
+ {%- if loop.first %}
396
+ {%- if content | trim %}
397
+ {{- '\n\n<tool_call>\n<function=' + tc_name + '>\n' }}
398
+ {%- else %}
399
+ {{- '<tool_call>\n<function=' + tc_name + '>\n' }}
400
+ {%- endif %}
401
+ {%- else %}
402
+ {{- '\n<tool_call>\n<function=' + tc_name + '>\n' }}
403
+ {%- endif %}
404
+ {%- if tc.arguments is defined and tc.arguments is not none %}
405
+ {%- if tc.arguments is mapping %}
406
+ {%- for args_name, args_value in tc.arguments.items() %}
407
+ {{- '<parameter=' + args_name + '>\n' }}
408
+ {%- if args_value is string %}
409
+ {%- set _av = args_value %}
410
+ {%- else %}
411
+ {%- set _av = args_value | tojson %}
412
+ {%- endif %}
413
+ {%- if max_tool_arg_chars > 0 and _av | length > max_tool_arg_chars %}
414
+ {{- _av[:max_tool_arg_chars] + '\n[TRUNCATED - original length ' ~ (_av | length | string) ~ ' chars]' }}
415
+ {%- else %}
416
+ {{- _av }}
417
+ {%- endif %}
418
+ {{- '\n</parameter>\n' }}
419
+ {%- endfor %}
420
+ {%- else %}
421
+ {%- if tc.arguments is string %}
422
+ {%- set _raw_args = tc.arguments %}
423
+ {%- else %}
424
+ {%- set _raw_args = tc.arguments | tojson %}
425
+ {%- endif %}
426
+ {%- if _raw_args %}
427
+ {%- if max_tool_arg_chars > 0 and _raw_args | length > max_tool_arg_chars %}
428
+ {{- _raw_args[:max_tool_arg_chars] + '\n[TRUNCATED - original length ' ~ (_raw_args | length | string) ~ ' chars]' }}
429
+ {%- else %}
430
+ {{- _raw_args }}
431
+ {%- endif %}
432
+ {%- endif %}
433
+ {%- endif %}
434
+ {%- endif %}
435
+ {{- '</function>\n</tool_call>' }}
436
+ {%- endif %}
437
+ {%- endfor %}
438
+ {%- endif %}
439
+ {{- '<|im_end|>\n' }}
440
+ {%- elif message.role == 'tool' %}
441
+ {%- set _content_lower = content | lower %}
442
+ {%- set _content_head = _content_lower[:120] %}
443
+ {%- set _is_code_or_grep = ('throw new ' in _content_lower or 'throw error' in _content_lower or 'console.error' in _content_lower or 'logger.error' in _content_lower or 'logging.error' in _content_lower or 'import ' in _content_head or 'def ' in _content_head or 'function ' in _content_head) %}
444
+ {%- set _exit_code_zero = ('exit code: 0' in _content_head or 'process exited with code 0' in _content_head) %}
445
+ {%- set _error_field_ok = ('"error": null' in _content_head or '"error":null' in _content_head or '"error": false' in _content_head or '"error":false' in _content_head or '"error": ""' in _content_head or '"error":""' in _content_head) %}
446
+ {%- set _strong_error = (('"error":' in _content_head and not _error_field_ok) or '"status": "error"' in _content_head or '"status":"error"' in _content_head or 'traceback (most recent call last):' in _content_head or 'command not found' in _content_head or 'invalid syntax' in _content_head or 'fatal:' in _content_head or (('exit code: ' in _content_head or 'process exited with code' in _content_head) and not _exit_code_zero) or _content_head.startswith('exception:') or _content_head.startswith('failed to ')) %}
447
+ {%- set _weak_error = ('error:' in _content_head or 'err!' in _content_head) %}
448
+ {%- set _weak_suppressed = ('$ ' in _content_head or 'took ' in _content_head or content | length >= 600) %}
449
+ {%- if not _is_code_or_grep and (_strong_error or (_weak_error and not _weak_suppressed)) %}
450
+ {%- set ns2.consecutive_failures = ns2.consecutive_failures + 1 %}
451
+ {%- else %}
452
+ {%- set ns2.consecutive_failures = 0 %}
453
+ {%- endif %}
454
+ {%- if ns2.prev_role != 'tool' %}
455
+ {{- '<|im_start|>user' }}
456
+ {%- endif %}
457
+ {%- set _is_json_payload = (_tool_format == 'json' and content | trim | length > 0 and (content | trim)[:1] in ('{', '[')) %}
458
+ {%- if not _is_json_payload and max_tool_response_chars > 0 and content | length > max_tool_response_chars %}
459
+ {%- set content = content[:max_tool_response_chars] + '\n[TRUNCATED - original length ' ~ (content | length | string) ~ ' chars]' %}
460
+ {%- endif %}
461
+ {{- '\n<tool_response>\n' + content }}
462
+ {%- if ns2.consecutive_failures >= 2 %}
463
+ {{- '\n\n⚠️ SYSTEM WARNING: ' ~ ns2.consecutive_failures ~ ' consecutive tool errors detected. Your previous approach is incorrect. You MUST use a fundamentally different approach or corrected arguments.' }}
464
+ {%- elif ns2.consecutive_failures == 1 %}
465
+ {{- '\n\n⚠️ SYSTEM WARNING: The previous tool call returned an error. Diagnose the failure and retry with completely corrected arguments.' }}
466
+ {%- endif %}
467
+ {{- '\n</tool_response>' }}
468
+ {%- if loop.last %}
469
+ {{- '<|im_end|>\n' }}
470
+ {%- else %}
471
+ {%- set _next_role = _msgs[loop.index0 + 1].role %}
472
+ {%- if _next_role != 'tool' %}
473
+ {{- '<|im_end|>\n' }}
474
+ {%- endif %}
475
+ {%- endif %}
476
+ {%- else %}
477
+ {{- '<|im_start|>user\n[' + message.role + ']: ' + content + '<|im_end|>\n' }}
478
+ {%- endif %}
479
+ {%- set ns2.prev_role = message.role %}
480
+ {%- endfor %}
481
+ {%- if add_generation_prompt %}
482
+ {{- '<|im_start|>assistant\n' }}
483
+ {%- if not ns_state.thinking %}
484
+ {{- '<think>\n\n</think>\n\n' }}
485
+ {%- else %}
486
+ {{- '<think>\n' }}
487
+ {%- endif %}
488
+ {%- endif %}