wezzel98765 commited on
Commit
c851457
·
verified ·
1 Parent(s): fdbea77

Update chat_template.jinja

Browse files
Files changed (1) hide show
  1. chat_template.jinja +180 -158
chat_template.jinja CHANGED
@@ -1,36 +1,52 @@
 
1
  {%- set image_count = namespace(value=0) %}
2
  {%- set video_count = namespace(value=0) %}
 
 
 
 
 
 
 
 
 
 
 
3
  {%- macro render_content(content, do_vision_count, is_system_content=false) %}
4
  {%- if content is string %}
5
  {{- content }}
6
  {%- elif content is iterable and content is not mapping %}
7
  {%- for item in content %}
8
- {%- if 'image' in item or 'image_url' in item or item.type == 'image' %}
9
- {%- if is_system_content %}
10
- {{- raise_exception('System message cannot contain images.') }}
11
- {%- endif %}
12
- {%- if do_vision_count %}
13
- {%- set image_count.value = image_count.value + 1 %}
14
- {%- endif %}
15
- {%- if add_vision_id is defined and add_vision_id %}
16
- {{- 'Picture ' ~ image_count.value ~ ': ' }}
17
- {%- endif %}
18
- {{- '<|vision_start|><|image_pad|><|vision_end|>' }}
19
- {%- elif 'video' in item or item.type == 'video' %}
20
- {%- if is_system_content %}
21
- {{- raise_exception('System message cannot contain videos.') }}
22
- {%- endif %}
23
- {%- if do_vision_count %}
24
- {%- set video_count.value = video_count.value + 1 %}
25
- {%- endif %}
26
- {%- if add_vision_id is defined and add_vision_id %}
27
- {{- 'Video ' ~ video_count.value ~ ': ' }}
 
 
 
 
 
 
 
28
  {%- endif %}
29
- {{- '<|vision_start|><|video_pad|><|vision_end|>' }}
30
- {%- elif 'text' in item %}
31
- {{- item.text }}
32
  {%- else %}
33
- {{- raise_exception('Unexpected item type in content.') }}
34
  {%- endif %}
35
  {%- endfor %}
36
  {%- elif content is none or content is undefined %}
@@ -39,38 +55,36 @@
39
  {{- raise_exception('Unexpected content type.') }}
40
  {%- endif %}
41
  {%- endmacro %}
42
- {%- set ns_flags = namespace(enable_thinking=true, has_tools=false, last_tool_failed=false, consecutive_failures=0) %}
43
- {%- if enable_thinking is defined %}
44
- {%- set ns_flags.enable_thinking = enable_thinking %}
45
- {%- endif %}
46
  {%- if not messages %}
47
  {{- raise_exception('No messages provided.') }}
48
  {%- endif %}
49
- {%- set system_content = '' %}
50
- {%- set has_system = false %}
51
- {%- if messages[0].role == 'system' or messages[0].role == 'developer' %}
52
- {%- set has_system = true %}
53
- {%- set system_content = render_content(messages[0].content, false, true)|trim %}
54
- {%- if '<|think_off|>' in system_content %}
55
- {%- set ns_flags.enable_thinking = false %}
56
- {%- set system_content = system_content | replace('<|think_off|>', '') %}
57
- {%- endif %}
58
- {%- if '<|think_on|>' in system_content %}
59
- {%- set ns_flags.enable_thinking = true %}
60
- {%- set system_content = system_content | replace('<|think_on|>', '') %}
 
 
 
 
 
61
  {%- endif %}
62
- {%- set system_content = system_content | trim %}
63
  {%- endif %}
64
- {%- if tools and tools is iterable and tools is not mapping %}
65
- {%- set ns_flags.has_tools = true %}
66
  {{- '<|im_start|>system\n' }}
67
- {{- "# Tools\n\nYou have access to the following functions:\n\n<tools>" }}
68
  {%- for tool in tools %}
69
  {{- '\n' }}
70
- {%- set fn = tool.function if tool.function is defined else tool %}
71
- {{- fn | tojson }}
72
  {%- endfor %}
73
- {{- "\n</tools>" }}
74
  {%- set tool_instructions %}
75
  If you choose to call a function ONLY reply in the following format with NO suffix:
76
 
@@ -102,162 +116,170 @@ Reminder:
102
  </IMPORTANT>
103
  {%- endset %}
104
  {{- '\n\n' ~ tool_instructions | trim }}
105
- {%- if has_system and system_content %}
106
- {{- '\n\n' + system_content }}
107
  {%- endif %}
108
  {{- '<|im_end|>\n' }}
109
- {%- elif has_system and system_content %}
110
- {{- '<|im_start|>system\n' + system_content + '<|im_end|>\n' }}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  {%- endif %}
112
- {%- for message in messages %}
 
113
  {%- set is_system = (message.role == "system" or message.role == "developer") %}
114
- {%- set content = render_content(message.content, true, is_system)|trim %}
115
  {%- if '<|think_off|>' in content %}
116
- {%- set ns_flags.enable_thinking = false %}
117
- {%- set content = content | replace('<|think_off|>', '') | trim %}
118
  {%- elif '<|think_on|>' in content %}
119
- {%- set ns_flags.enable_thinking = true %}
120
- {%- set content = content | replace('<|think_on|>', '') | trim %}
121
  {%- endif %}
122
  {%- if is_system %}
123
- {%- if not loop.first and content %}
124
- {{- '<|im_start|>system\n' + content + '<|im_end|>\n' }}
125
- {%- endif %}
126
- {%- elif message.role == "user" %}
127
- {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>\n' }}
128
- {%- set ns_flags.last_tool_failed = false %}
129
- {%- set ns_flags.consecutive_failures = 0 %}
130
- {%- elif message.role == "assistant" %}
131
- {%- set ns_flags.last_tool_failed = false %}
132
  {%- set reasoning_content = '' %}
133
- {%- if message.reasoning_content is string %}
134
- {%- set reasoning_content = message.reasoning_content %}
 
 
 
 
135
  {%- else %}
136
- {%- set think_end_token = '' %}
137
  {%- if '</think>' in content %}
138
- {%- set think_end_token = '</think>' %}
139
  {%- elif '</thinking>' in content %}
140
- {%- set think_end_token = '</thinking>' %}
141
  {%- elif '</ think>' in content %}
142
- {%- set think_end_token = '</ think>' %}
143
  {%- elif '</think >' in content %}
144
- {%- set think_end_token = '</think >' %}
145
  {%- endif %}
146
- {%- if think_end_token %}
147
- {%- set reasoning_parts = content.split(think_end_token) %}
148
- {%- set reasoning_content = reasoning_parts[0] %}
149
- {%- set content = reasoning_parts[1:] | join(think_end_token) %}
150
- {%- if '<think>' in reasoning_content %}
151
- {%- set r_prefix = reasoning_content.split('<think>')[0] | trim %}
152
- {%- set reasoning_content = reasoning_content.split('<think>')[1:] | join('<think>') | trim %}
153
- {%- set content = (r_prefix ~ '\n' ~ content) | trim %}
154
- {%- endif %}
155
- {%- elif '<think>' in content %}
156
- {%- set prefix = content.split('<think>')[0] %}
157
- {%- set think_part = content.split('<think>')[1:] | join('<think>') %}
158
- {%- if '<tool_call>' in think_part %}
159
- {%- set reasoning_content = think_part.split('<tool_call>')[0] %}
160
- {%- set content = prefix ~ '\n<tool_call>' ~ think_part.split('<tool_call>')[1:] | join('<tool_call>') %}
161
  {%- else %}
162
- {%- set reasoning_content = think_part %}
163
- {%- set content = prefix %}
164
  {%- endif %}
 
 
 
 
 
165
  {%- endif %}
166
  {%- endif %}
167
  {%- set reasoning_content = reasoning_content | trim %}
168
- {%- set content = content | trim %}
169
- {%- if message.tool_calls and message.tool_calls is iterable and message.tool_calls is not mapping %}
170
- {%- if '<tool_call>' in content %}
171
- {%- set content = content.split('<tool_call>')[0] | trim %}
172
- {%- endif %}
173
- {%- endif %}
174
- {%- set show_think = true %}
175
- {%- if preserve_thinking is defined and preserve_thinking == false %}
176
- {%- set show_think = false %}
177
- {%- endif %}
178
- {%- if not reasoning_content %}
179
- {%- set show_think = false %}
180
- {%- endif %}
181
-
182
- {%- if show_think and ns_flags.enable_thinking is not false %}
183
- {%- if content %}
184
- {{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content + '\n</think>\n' + content }}
185
- {%- else %}
186
- {{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content + '\n</think>' }}
187
- {%- endif %}
188
  {%- else %}
189
- {%- if content %}
190
- {{- '<|im_start|>' + message.role + '\n' + content }}
191
- {%- else %}
192
- {{- '<|im_start|>' + message.role }}
193
- {%- endif %}
194
  {%- endif %}
195
- {%- if message.tool_calls and message.tool_calls is iterable and message.tool_calls is not mapping %}
196
  {%- for tool_call in message.tool_calls %}
197
- {%- if tool_call.function is defined %}
198
- {%- set tool_call = tool_call.function %}
 
 
199
  {%- endif %}
200
- {{- '\n<tool_call>\n' }}
201
- {{- '<function=' ~ tool_call.name ~ '>\n' }}
202
- {%- if tool_call.arguments is defined and tool_call.arguments is mapping %}
203
- {%- if tool_call.arguments | length > 0 %}
204
- {%- for args_name in tool_call.arguments %}
205
- {%- set args_value = tool_call.arguments[args_name] %}
206
- {{- '<parameter=' ~ args_name ~ '>\n' }}
207
- {%- set args_value = args_value | tojson if args_value is mapping or (args_value is iterable and args_value is not string) else args_value | string %}
208
- {{- args_value }}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  {{- '\n</parameter>\n' }}
210
  {%- endfor %}
211
- {%- endif %}
212
- {%- elif tool_call.arguments is defined and tool_call.arguments is string %}
213
- {%- if tool_call.arguments | trim | length > 0 %}
214
- {{- tool_call.arguments }}
215
- {{- '\n' }}
216
  {%- endif %}
217
  {%- endif %}
218
- {{- '</function>\n</tool_call>' }}
 
 
 
 
219
  {%- endfor %}
220
  {%- endif %}
221
  {{- '<|im_end|>\n' }}
222
- {%- elif message.role == "tool" %}
223
- {%- set content_lower = content | lower %}
224
- {%- if content | length < 500
225
- and '$ ' not in content
226
- and 'took ' not in content_lower
227
- and ('"error":' in content_lower or 'error:' in content_lower or 'exception:' in content_lower or 'traceback' in content_lower or 'command not found' in content_lower or 'invalid syntax' in content_lower or 'failed to' in content_lower) %}
228
- {%- set ns_flags.last_tool_failed = true %}
229
- {%- set ns_flags.consecutive_failures = ns_flags.consecutive_failures + 1 %}
230
  {%- else %}
231
- {%- set ns_flags.last_tool_failed = false %}
232
- {%- set ns_flags.consecutive_failures = 0 %}
233
  {%- endif %}
234
- {%- if loop.index0 > 0 and messages[loop.index0 - 1].role != "tool" %}
235
  {{- '<|im_start|>user' }}
236
  {%- endif %}
237
- {{- '\n<tool_response>\n' }}
238
- {{- content }}
239
- {%- if ns_flags.last_tool_failed %}
240
- {%- if ns_flags.consecutive_failures >= 2 %}
241
- {{- '\n\n⚠️ SYSTEM WARNING: ' ~ ns_flags.consecutive_failures ~ ' consecutive tool errors detected. Your previous approach is incorrect. You MUST use a fundamentally different approach or corrected arguments.' }}
242
- {%- else %}
243
- {{- '\n\n⚠️ SYSTEM WARNING: The previous tool call returned an error. Diagnose the failure and retry with completely corrected arguments.' }}
244
- {%- endif %}
245
  {%- endif %}
246
  {{- '\n</tool_response>' }}
247
- {%- if not loop.last and messages[loop.index0 + 1].role != "tool" %}
248
- {{- '<|im_end|>\n' }}
249
- {%- elif loop.last %}
250
  {{- '<|im_end|>\n' }}
 
 
 
 
 
251
  {%- endif %}
252
  {%- else %}
253
- {{- raise_exception('Unexpected message role.') }}
254
  {%- endif %}
 
255
  {%- endfor %}
256
  {%- if add_generation_prompt %}
257
  {{- '<|im_start|>assistant\n' }}
258
- {%- if ns_flags.enable_thinking is false %}
259
  {{- '<think>\n</think>\n' }}
260
- {%- elif ns_flags.last_tool_failed and ns_flags.consecutive_failures >= 2 %}
261
  {{- '<think>\n</think>\n' }}
262
  {%- else %}
263
  {{- '<think>\n' }}
 
1
+ {%- set template_version = "qwen3.6-froggeric-v20" %}
2
  {%- set image_count = namespace(value=0) %}
3
  {%- set video_count = namespace(value=0) %}
4
+ {%- set add_vision_id = add_vision_id if add_vision_id is defined else false %}
5
+ {%- set enable_thinking = enable_thinking if enable_thinking is defined else true %}
6
+ {%- set auto_disable_thinking_with_tools = auto_disable_thinking_with_tools if auto_disable_thinking_with_tools is defined else false %}
7
+ {%- set _preserve_thinking = preserve_thinking if preserve_thinking is defined else false %}
8
+ {%- set max_tool_arg_chars = max_tool_arg_chars if max_tool_arg_chars is defined else 0 %}
9
+ {%- set max_tool_response_chars = max_tool_response_chars if max_tool_response_chars is defined else 0 %}
10
+ {%- set _has_tools = (tools is defined and tools and tools is iterable and tools is not mapping) %}
11
+ {%- set ns_state = namespace(thinking=enable_thinking) %}
12
+ {%- if auto_disable_thinking_with_tools and _has_tools %}
13
+ {%- set ns_state.thinking = false %}
14
+ {%- endif %}
15
  {%- macro render_content(content, do_vision_count, is_system_content=false) %}
16
  {%- if content is string %}
17
  {{- content }}
18
  {%- elif content is iterable and content is not mapping %}
19
  {%- for item in content %}
20
+ {%- if item is mapping %}
21
+ {%- if item.type == 'image' or 'image' in item or 'image_url' in item %}
22
+ {%- if is_system_content %}
23
+ {{- raise_exception('System message cannot contain images.') }}
24
+ {%- endif %}
25
+ {%- if do_vision_count %}
26
+ {%- set image_count.value = image_count.value + 1 %}
27
+ {%- endif %}
28
+ {%- if add_vision_id %}
29
+ {{- 'Picture ' ~ image_count.value ~ ': ' }}
30
+ {%- endif %}
31
+ {{- '<|vision_start|><|image_pad|><|vision_end|>' }}
32
+ {%- elif item.type == 'video' or 'video' in item %}
33
+ {%- if is_system_content %}
34
+ {{- raise_exception('System message cannot contain videos.') }}
35
+ {%- endif %}
36
+ {%- if do_vision_count %}
37
+ {%- set video_count.value = video_count.value + 1 %}
38
+ {%- endif %}
39
+ {%- if add_vision_id %}
40
+ {{- 'Video ' ~ video_count.value ~ ': ' }}
41
+ {%- endif %}
42
+ {{- '<|vision_start|><|video_pad|><|vision_end|>' }}
43
+ {%- elif 'text' in item %}
44
+ {{- item.text }}
45
+ {%- else %}
46
+ {{- raise_exception('Unexpected item type in content.') }}
47
  {%- endif %}
 
 
 
48
  {%- else %}
49
+ {{- item | string }}
50
  {%- endif %}
51
  {%- endfor %}
52
  {%- elif content is none or content is undefined %}
 
55
  {{- raise_exception('Unexpected content type.') }}
56
  {%- endif %}
57
  {%- endmacro %}
 
 
 
 
58
  {%- if not messages %}
59
  {{- raise_exception('No messages provided.') }}
60
  {%- endif %}
61
+ {%- set _first_role = messages[0].role %}
62
+ {%- if _first_role == 'system' or _first_role == 'developer' %}
63
+ {%- set _sys_msg = messages[0] %}
64
+ {%- set _msgs = messages[1:] %}
65
+ {%- else %}
66
+ {%- set _sys_msg = none %}
67
+ {%- set _msgs = messages %}
68
+ {%- endif %}
69
+ {%- set _sc = '' %}
70
+ {%- if _sys_msg is not none %}
71
+ {%- set _sc = render_content(_sys_msg.content, false, true) | trim %}
72
+ {%- if '<|think_off|>' in _sc %}
73
+ {%- set ns_state.thinking = false %}
74
+ {%- set _sc = _sc.split('<|think_off|>') | join('') | trim %}
75
+ {%- elif '<|think_on|>' in _sc %}
76
+ {%- set ns_state.thinking = true %}
77
+ {%- set _sc = _sc.split('<|think_on|>') | join('') | trim %}
78
  {%- endif %}
 
79
  {%- endif %}
80
+ {%- if _has_tools %}
 
81
  {{- '<|im_start|>system\n' }}
82
+ {{- '# Tools\n\nYou have access to the following functions:\n\n<tools>' }}
83
  {%- for tool in tools %}
84
  {{- '\n' }}
85
+ {{- tool | tojson }}
 
86
  {%- endfor %}
87
+ {{- '\n</tools>' }}
88
  {%- set tool_instructions %}
89
  If you choose to call a function ONLY reply in the following format with NO suffix:
90
 
 
116
  </IMPORTANT>
117
  {%- endset %}
118
  {{- '\n\n' ~ tool_instructions | trim }}
119
+ {%- if _sc %}
120
+ {{- '\n\n' + _sc }}
121
  {%- endif %}
122
  {{- '<|im_end|>\n' }}
123
+ {%- else %}
124
+ {%- if _sc %}
125
+ {{- '<|im_start|>system\n' + _sc + '<|im_end|>\n' }}
126
+ {%- endif %}
127
+ {%- endif %}
128
+ {%- set _last_idx = _msgs | length - 1 %}
129
+ {%- set ns = namespace(multi_step_tool=true, last_query_index=_last_idx) %}
130
+ {%- for message in _msgs[::-1] %}
131
+ {%- set index = (_msgs | length - 1) - loop.index0 %}
132
+ {%- if ns.multi_step_tool and message.role == 'user' %}
133
+ {%- set _rc = render_content(message.content, false) | trim %}
134
+ {%- if not (_rc.startswith('<tool_response>') and _rc.endswith('</tool_response>')) %}
135
+ {%- set ns.multi_step_tool = false %}
136
+ {%- set ns.last_query_index = index %}
137
+ {%- endif %}
138
+ {%- endif %}
139
+ {%- endfor %}
140
+ {%- if ns.multi_step_tool %}
141
+ {%- if _last_idx > 50 %}
142
+ {%- set ns.last_query_index = _last_idx %}
143
+ {%- else %}
144
+ {%- set ns.last_query_index = 0 %}
145
+ {%- endif %}
146
  {%- endif %}
147
+ {%- set ns2 = namespace(prev_role='', consecutive_failures=0) %}
148
+ {%- for message in _msgs %}
149
  {%- set is_system = (message.role == "system" or message.role == "developer") %}
150
+ {%- set content = render_content(message.content, true, is_system) | trim %}
151
  {%- if '<|think_off|>' in content %}
152
+ {%- set ns_state.thinking = false %}
153
+ {%- set content = content.split('<|think_off|>') | join('') | trim %}
154
  {%- elif '<|think_on|>' in content %}
155
+ {%- set ns_state.thinking = true %}
156
+ {%- set content = content.split('<|think_on|>') | join('') | trim %}
157
  {%- endif %}
158
  {%- if is_system %}
159
+ {{- '<|im_start|>system\n' + content + '<|im_end|>\n' }}
160
+ {%- elif message.role == 'user' %}
161
+ {%- set ns2.consecutive_failures = 0 %}
162
+ {{- '<|im_start|>user\n' + content + '<|im_end|>\n' }}
163
+ {%- elif message.role == 'assistant' %}
 
 
 
 
164
  {%- set reasoning_content = '' %}
165
+ {%- if message.reasoning_content is defined and message.reasoning_content is not none %}
166
+ {%- if message.reasoning_content is string %}
167
+ {%- set reasoning_content = message.reasoning_content %}
168
+ {%- else %}
169
+ {%- set reasoning_content = message.reasoning_content | string %}
170
+ {%- endif %}
171
  {%- else %}
172
+ {%- set _think_end = '' %}
173
  {%- if '</think>' in content %}
174
+ {%- set _think_end = '</think>' %}
175
  {%- elif '</thinking>' in content %}
176
+ {%- set _think_end = '</thinking>' %}
177
  {%- elif '</ think>' in content %}
178
+ {%- set _think_end = '</ think>' %}
179
  {%- elif '</think >' in content %}
180
+ {%- set _think_end = '</think >' %}
181
  {%- endif %}
182
+ {%- if _think_end %}
183
+ {%- if _think_end == '</thinking>' %}
184
+ {%- set _think_start = '<thinking>' %}
 
 
 
 
 
 
 
 
 
 
 
 
185
  {%- else %}
186
+ {%- set _think_start = '<think>' %}
 
187
  {%- endif %}
188
+ {%- set reasoning_content = content.split(_think_end)[0].rstrip('\n') %}
189
+ {%- if _think_start in reasoning_content %}
190
+ {%- set reasoning_content = reasoning_content.split(_think_start)[-1].lstrip('\n') %}
191
+ {%- endif %}
192
+ {%- set content = content.split(_think_end)[-1].lstrip('\n') %}
193
  {%- endif %}
194
  {%- endif %}
195
  {%- set reasoning_content = reasoning_content | trim %}
196
+ {%- if (_preserve_thinking or loop.index0 > ns.last_query_index) and reasoning_content %}
197
+ {{- '<|im_start|>assistant\n<think>\n' + reasoning_content + '\n</think>\n\n' + content }}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
  {%- else %}
199
+ {{- '<|im_start|>assistant\n' + content }}
 
 
 
 
200
  {%- endif %}
201
+ {%- if message.tool_calls is defined and message.tool_calls and message.tool_calls is iterable and message.tool_calls is not mapping %}
202
  {%- for tool_call in message.tool_calls %}
203
+ {%- if tool_call.function is defined and tool_call.function is not none %}
204
+ {%- set tc = tool_call.function %}
205
+ {%- else %}
206
+ {%- set tc = tool_call %}
207
  {%- endif %}
208
+ {%- if loop.first %}
209
+ {%- if content | trim %}
210
+ {{- '\n\n<tool_call>\n<function=' + tc.name + '>\n' }}
211
+ {%- else %}
212
+ {{- '<tool_call>\n<function=' + tc.name + '>\n' }}
213
+ {%- endif %}
214
+ {%- else %}
215
+ {{- '\n\n<tool_call>\n<function=' + tc.name + '>\n' }}
216
+ {%- endif %}
217
+ {%- if tc.arguments is defined and tc.arguments is not none %}
218
+ {%- if tc.arguments is mapping %}
219
+ {%- for args_name, args_value in tc.arguments.items() %}
220
+ {{- '<parameter=' + args_name + '>\n' }}
221
+ {%- if args_value is mapping or (args_value is sequence and args_value is not string) %}
222
+ {%- set _av = args_value | tojson %}
223
+ {%- else %}
224
+ {%- set _av = args_value | string %}
225
+ {%- endif %}
226
+ {%- if max_tool_arg_chars > 0 and _av | length > max_tool_arg_chars %}
227
+ {{- _av[:max_tool_arg_chars] + '\n[TRUNCATED — original length ' ~ (_av | length | string) ~ ' chars]' }}
228
+ {%- else %}
229
+ {{- _av }}
230
+ {%- endif %}
231
  {{- '\n</parameter>\n' }}
232
  {%- endfor %}
233
+ {%- elif tc.arguments is string and tc.arguments %}
234
+ {{- tc.arguments }}
 
 
 
235
  {%- endif %}
236
  {%- endif %}
237
+ {%- if loop.last %}
238
+ {{- '</function>\n</tool_call>\n' }}
239
+ {%- else %}
240
+ {{- '</function>\n</tool_call>' }}
241
+ {%- endif %}
242
  {%- endfor %}
243
  {%- endif %}
244
  {{- '<|im_end|>\n' }}
245
+ {%- elif message.role == 'tool' %}
246
+ {%- set _content_lower = content | lower %}
247
+ {%- if content | length < 500 and '$ ' not in content and 'took ' not in _content_lower and ('"error":' in _content_lower or 'error:' in _content_lower or 'exception:' in _content_lower or 'traceback' in _content_lower or 'command not found' in _content_lower or 'invalid syntax' in _content_lower or 'failed to' in _content_lower) %}
248
+ {%- set ns2.consecutive_failures = ns2.consecutive_failures + 1 %}
 
 
 
 
249
  {%- else %}
250
+ {%- set ns2.consecutive_failures = 0 %}
 
251
  {%- endif %}
252
+ {%- if ns2.prev_role != 'tool' %}
253
  {{- '<|im_start|>user' }}
254
  {%- endif %}
255
+ {%- if max_tool_response_chars > 0 and content | length > max_tool_response_chars %}
256
+ {%- set content = content[:max_tool_response_chars] + '\n[TRUNCATED — original length ' ~ (content | length | string) ~ ' chars]' %}
257
+ {%- endif %}
258
+ {{- '\n<tool_response>\n' + content }}
259
+ {%- if ns2.consecutive_failures >= 2 %}
260
+ {{- '\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.' }}
261
+ {%- elif ns2.consecutive_failures == 1 %}
262
+ {{- '\n\n⚠️ SYSTEM WARNING: The previous tool call returned an error. Diagnose the failure and retry with completely corrected arguments.' }}
263
  {%- endif %}
264
  {{- '\n</tool_response>' }}
265
+ {%- if loop.last %}
 
 
266
  {{- '<|im_end|>\n' }}
267
+ {%- else %}
268
+ {%- set _next_role = _msgs[loop.index0 + 1].role %}
269
+ {%- if _next_role != 'tool' %}
270
+ {{- '<|im_end|>\n' }}
271
+ {%- endif %}
272
  {%- endif %}
273
  {%- else %}
274
+ {{- '<|im_start|>user\n[' + message.role + ']: ' + content + '<|im_end|>\n' }}
275
  {%- endif %}
276
+ {%- set ns2.prev_role = message.role %}
277
  {%- endfor %}
278
  {%- if add_generation_prompt %}
279
  {{- '<|im_start|>assistant\n' }}
280
+ {%- if not ns_state.thinking %}
281
  {{- '<think>\n</think>\n' }}
282
+ {%- elif ns2.consecutive_failures >= 2 %}
283
  {{- '<think>\n</think>\n' }}
284
  {%- else %}
285
  {{- '<think>\n' }}