peculiar-ragdoll commited on
Commit
435b6b8
·
verified ·
1 Parent(s): 79edd43

Rebase Sharp onto froggeric v22.1 (terseness-only, medium default); archive v22-sharp

Browse files
README.md CHANGED
@@ -37,17 +37,16 @@ With the *Sharp* template, Qwen3.8-27b (medium effort) gets smarter **and** uses
37
  ## Straight to the point
38
 
39
  This is froggeric's [Qwen-Fixed-Chat-Templates](https://huggingface.co/froggeric/Qwen-Fixed-Chat-Templates)
40
- `v22`, with a force-appended system prompt spliced in. The base fixes issues, the addition makes it better.
41
-
42
- > **v22 (the Qwen 3.8 update).** Now covers Qwen 3.8 alongside 3.5/3.6 and adds
43
- > prompt-directed reasoning-effort steering (`xhigh`/`high`/`medium`/`low`), which upstream
44
- > **defaults to `xhigh`** it injects a "think at maximum effort" system line even when the
45
- > caller asks for nothing. That default is a behavioral change from `v21.3`, so this Sharp build
46
- > **suppresses it**: when no effort is requested you get the tuned terseness behavior and nothing
47
- > else, exactly as v1. An *explicit* effort still passes straight through to upstream's machinery
48
- > and renders the feature survives, it just isn't forced on. Pass it via `chat_template_kwargs`
49
- > (a bare top-level `reasoning_effort` field is dropped by OpenAI-style servers before the template
50
- > sees it):
51
  >
52
  > ```json
53
  > {"messages": [...], "chat_template_kwargs": {"reasoning_effort": "low"}}
@@ -58,13 +57,13 @@ This is froggeric's [Qwen-Fixed-Chat-Templates](https://huggingface.co/froggeric
58
  the **v1** template baked into those builds — that is the exact template embedded in those GGUF and
59
  MLX builds (`template_version = "qwen3.6-froggeric-v21.3"`, terseness, no reasoning-effort steering),
60
  and it lives here in [`archive/v1-qwen3.6-froggeric-v21.3/`](archive/v1-qwen3.6-froggeric-v21.3). The
61
- `chat_template.jinja` at the root of this repo is the newer **v22** described above; drop it in to
62
  move a model onto it. The template is published separately because it is the portable part — the
63
  thing worth reusing is not tied to either model.
64
 
65
  ## What it changes
66
 
67
- Fourteen inserted lines. Everything else is byte-identical to upstream v22.
68
 
69
  ```jinja
70
  {%- set _terse %}
@@ -78,15 +77,12 @@ If a user request is genuinely ambiguous, ask a sharp question, don't guess.
78
  {%- else %}
79
  {%- set _sc = (_sc | trim) ~ '\n\n' ~ (_terse | trim) %}
80
  {%- endif %}
81
- {%- if reasoning_effort is not defined %}
82
- {%- set reasoning_instructions = '' %}
83
- {%- endif %}
84
  ```
85
 
86
- Two things happen here. The `if/else` keeps **your own system prompt** — the terseness block is
87
- appended after it, nothing you pass in is replaced. The final `if` blanks upstream's
88
- reasoning-effort line **only when the caller didn't ask for one**, so the forced-`xhigh` default is
89
- gone but an explicit `reasoning_effort` still renders (see the v22 note above).
90
 
91
  ## Impact
92
 
@@ -183,8 +179,8 @@ when the file was taken from a model repo rather than from here.
183
  ## Setting reasoning effort
184
 
185
  By default there is no reasoning-effort instruction — you get the tuned terseness behavior and
186
- nothing else. To turn steering back on for a request, set `reasoning_effort` to `low`, `medium`,
187
- `high`, or `xhigh`. **How you pass it depends on the runtime, and one obvious-looking channel does
188
  not work:**
189
 
190
  | How you pass it | oMLX | llama.cpp | transformers | Works? |
 
37
  ## Straight to the point
38
 
39
  This is froggeric's [Qwen-Fixed-Chat-Templates](https://huggingface.co/froggeric/Qwen-Fixed-Chat-Templates)
40
+ `v22.1`, with a force-appended system prompt spliced in. The base fixes issues, the addition makes it better.
41
+
42
+ > **v22.1 (current upstream).** Covers Qwen 3.8 alongside 3.5/3.6 and adds prompt-directed
43
+ > reasoning-effort steering (`none`/`minimal`/`low`/`medium`/`high`/`xhigh`) plus inline
44
+ > `<|think_…|>` control tags. As of **v22.1 the default effort is `medium`** a neutral baseline
45
+ > that injects **no** steering line when the caller asks for nothing. (Earlier v22 forced `xhigh`
46
+ > by default; froggeric fixed that upstream, so this Sharp build no longer suppresses anything
47
+ > out of the box you get the tuned terseness behavior and nothing else, exactly as v1.) An
48
+ > *explicit* effort still renders; pass it via `chat_template_kwargs` (a bare top-level
49
+ > `reasoning_effort` field is dropped by OpenAI-style servers before the template sees it):
 
50
  >
51
  > ```json
52
  > {"messages": [...], "chat_template_kwargs": {"reasoning_effort": "low"}}
 
57
  the **v1** template baked into those builds — that is the exact template embedded in those GGUF and
58
  MLX builds (`template_version = "qwen3.6-froggeric-v21.3"`, terseness, no reasoning-effort steering),
59
  and it lives here in [`archive/v1-qwen3.6-froggeric-v21.3/`](archive/v1-qwen3.6-froggeric-v21.3). The
60
+ `chat_template.jinja` at the root of this repo is the newer **v22.1** described above; drop it in to
61
  move a model onto it. The template is published separately because it is the portable part — the
62
  thing worth reusing is not tied to either model.
63
 
64
  ## What it changes
65
 
66
+ Eleven inserted lines. Everything else is byte-identical to upstream v22.1.
67
 
68
  ```jinja
69
  {%- set _terse %}
 
77
  {%- else %}
78
  {%- set _sc = (_sc | trim) ~ '\n\n' ~ (_terse | trim) %}
79
  {%- endif %}
 
 
 
80
  ```
81
 
82
+ One thing happens here: the `if/else` keeps **your own system prompt** — the terseness block is
83
+ appended after it, nothing you pass in is replaced. No effort-suppression is needed anymore: v22.1
84
+ already defaults to `medium`, which injects no reasoning-effort line unless you ask for one (earlier
85
+ v22 forced `xhigh`; see the v22.1 note above). An explicit `reasoning_effort` still renders.
86
 
87
  ## Impact
88
 
 
179
  ## Setting reasoning effort
180
 
181
  By default there is no reasoning-effort instruction — you get the tuned terseness behavior and
182
+ nothing else (that is exactly what `medium` renders). To turn steering *on* for a request, set
183
+ `reasoning_effort` to `low`, `high`, or `xhigh`. **How you pass it depends on the runtime, and one obvious-looking channel does
184
  not work:**
185
 
186
  | How you pass it | oMLX | llama.cpp | transformers | Works? |
archive/v22-sharp/chat_template.jinja ADDED
@@ -0,0 +1,345 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- set template_version = "qwen3.8-froggeric-v22" %}
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 _has_tools = (tools is defined and tools and tools is iterable and tools is not mapping) %}
18
+ {%- set ns_state = namespace(thinking=enable_thinking) %}
19
+ {%- if auto_disable_thinking_with_tools and _has_tools %}
20
+ {%- set ns_state.thinking = false %}
21
+ {%- endif %}
22
+ {%- for msg in messages %}
23
+ {%- if msg.role == 'system' or msg.role == 'developer' or msg.role == 'user' %}
24
+ {%- if msg.content is string %}
25
+ {%- if '<|think_off|>' in msg.content %}
26
+ {%- set ns_state.thinking = false %}
27
+ {%- elif '<|think_on|>' in msg.content %}
28
+ {%- set ns_state.thinking = true %}
29
+ {%- endif %}
30
+ {%- elif msg.content is iterable and msg.content is not mapping %}
31
+ {%- for item in msg.content %}
32
+ {%- if item is mapping and 'text' in item and item.text is string %}
33
+ {%- if '<|think_off|>' in item.text %}
34
+ {%- set ns_state.thinking = false %}
35
+ {%- elif '<|think_on|>' in item.text %}
36
+ {%- set ns_state.thinking = true %}
37
+ {%- endif %}
38
+ {%- endif %}
39
+ {%- endfor %}
40
+ {%- endif %}
41
+ {%- endif %}
42
+ {%- endfor %}
43
+ {%- set _effort_raw = reasoning_effort if reasoning_effort is defined else 'xhigh' %}
44
+ {%- if _effort_raw == 'high' or _effort_raw == 'xhigh' %}
45
+ {%- set _reasoning_effort = 'xhigh' %}
46
+ {%- elif _effort_raw == 'low' %}
47
+ {%- set _reasoning_effort = 'low' %}
48
+ {%- elif _effort_raw == 'medium' %}
49
+ {%- set _reasoning_effort = 'medium' %}
50
+ {%- else %}
51
+ {%- set _reasoning_effort = 'xhigh' %}
52
+ {%- endif %}
53
+ {%- set reasoning_instructions = '' %}
54
+ {%- if ns_state.thinking %}
55
+ {%- if _reasoning_effort == 'xhigh' %}
56
+ {%- 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.' %}
57
+ {%- elif _reasoning_effort == 'low' %}
58
+ {%- set reasoning_instructions = 'Reasoning effort is set to low. Keep your thinking brief and focused, moving directly to the conclusion without unnecessary elaboration.' %}
59
+ {%- endif %}
60
+ {%- endif %}
61
+ {%- macro render_content(content, do_vision_count, is_system_content=false) %}
62
+ {%- if content is string %}
63
+ {{- content }}
64
+ {%- elif content is iterable and content is not mapping %}
65
+ {%- for item in content %}
66
+ {%- if item is mapping %}
67
+ {%- if item.type == 'image' or 'image' in item or 'image_url' in item %}
68
+ {%- if is_system_content %}
69
+ {{- raise_exception('System message cannot contain images.') }}
70
+ {%- endif %}
71
+ {%- if do_vision_count %}
72
+ {%- set image_count.value = image_count.value + 1 %}
73
+ {%- endif %}
74
+ {%- if add_vision_id %}
75
+ {{- 'Picture ' ~ image_count.value ~ ': ' }}
76
+ {%- endif %}
77
+ {{- '<|vision_start|><|image_pad|><|vision_end|>' }}
78
+ {%- elif item.type == 'video' or 'video' in item %}
79
+ {%- if is_system_content %}
80
+ {{- raise_exception('System message cannot contain videos.') }}
81
+ {%- endif %}
82
+ {%- if do_vision_count %}
83
+ {%- set video_count.value = video_count.value + 1 %}
84
+ {%- endif %}
85
+ {%- if add_vision_id %}
86
+ {{- 'Video ' ~ video_count.value ~ ': ' }}
87
+ {%- endif %}
88
+ {{- '<|vision_start|><|video_pad|><|vision_end|>' }}
89
+ {%- elif 'text' in item %}
90
+ {{- item.text }}
91
+ {%- else %}
92
+ {{- raise_exception('Unexpected item type in content.') }}
93
+ {%- endif %}
94
+ {%- else %}
95
+ {{- item | string }}
96
+ {%- endif %}
97
+ {%- endfor %}
98
+ {%- elif content is none or content is undefined %}
99
+ {{- '' }}
100
+ {%- else %}
101
+ {{- raise_exception('Unexpected content type.') }}
102
+ {%- endif %}
103
+ {%- endmacro %}
104
+ {%- if not messages %}
105
+ {{- raise_exception('No messages provided.') }}
106
+ {%- endif %}
107
+ {%- set _first_role = messages[0].role %}
108
+ {%- if _first_role == 'system' or _first_role == 'developer' %}
109
+ {%- set _sys_msg = messages[0] %}
110
+ {%- set _msgs = messages[1:] %}
111
+ {%- else %}
112
+ {%- set _sys_msg = none %}
113
+ {%- set _msgs = messages %}
114
+ {%- endif %}
115
+ {%- set _sc = '' %}
116
+ {%- if _sys_msg is not none %}
117
+ {%- set _sc = render_content(_sys_msg.content, false, true) | trim %}
118
+ {%- if '<|think_off|>' in _sc %}
119
+ {%- set _sc = _sc.split('<|think_off|>') | join('') | trim %}
120
+ {%- elif '<|think_on|>' in _sc %}
121
+ {%- set _sc = _sc.split('<|think_on|>') | join('') | trim %}
122
+ {%- endif %}
123
+ {%- endif %}
124
+ {%- set _terse %}
125
+ Answer directly, after thinking. Lead with the answer, then only what it needs to be correct and usable.
126
+ Never: open with preamble or pleasantries; restate the question; add filler transitions; hedge with niceties; or repeat a point you've already made.
127
+ 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.
128
+ If a user request is genuinely ambiguous, ask a sharp question, don't guess.
129
+ {%- endset %}
130
+ {%- if not _sc %}
131
+ {%- set _sc = _terse | trim %}
132
+ {%- else %}
133
+ {%- set _sc = (_sc | trim) ~ '\n\n' ~ (_terse | trim) %}
134
+ {%- endif %}
135
+ {%- if reasoning_effort is not defined %}
136
+ {%- set reasoning_instructions = '' %}
137
+ {%- endif %}
138
+ {%- if _has_tools %}
139
+ {{- '<|im_start|>system\n' }}
140
+ {%- if reasoning_instructions %}
141
+ {{- reasoning_instructions + '\n\n' }}
142
+ {%- endif %}
143
+ {{- '# Tools\n\nYou have access to the following functions:\n\n<tools>' }}
144
+ {%- for tool in tools %}
145
+ {{- '\n' }}
146
+ {{- tool | tojson }}
147
+ {%- endfor %}
148
+ {{- '\n</tools>' }}
149
+ {%- if _tool_format == 'json' %}
150
+ {{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<think>\nBrief explanation of tool call\n</think>\n<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- 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- Function calls MUST follow the specified format: a single JSON object with "name" and "arguments" keys inside <tool_call></tool_call> XML tags.\n- If you choose to call a tool, you MUST output the <tool_call> block IMMEDIATELY after thinking, with NO conversational text before it.\n- 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>' }}
151
+ {%- else %}
152
+ {{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<think>\nBrief explanation of tool call\n</think>\n<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- 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- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags.\n- If you choose to call a tool, you MUST output the <tool_call> block IMMEDIATELY after thinking, with NO conversational text before it.\n- 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>' }}
153
+ {%- endif %}
154
+ {%- if _sc %}
155
+ {{- '\n\n' + _sc }}
156
+ {%- endif %}
157
+ {{- '<|im_end|>\n' }}
158
+ {%- else %}
159
+ {%- if _sc %}
160
+ {{- '<|im_start|>system\n' + (reasoning_instructions + '\n\n' if reasoning_instructions else '') + _sc + '<|im_end|>\n' }}
161
+ {%- elif reasoning_instructions %}
162
+ {{- '<|im_start|>system\n' + reasoning_instructions + '<|im_end|>\n' }}
163
+ {%- endif %}
164
+ {%- endif %}
165
+ {%- set _last_idx = _msgs | length - 1 %}
166
+ {%- set ns = namespace(multi_step_tool=true, last_query_index=_last_idx) %}
167
+ {%- for message in _msgs[::-1] %}
168
+ {%- set index = (_msgs | length - 1) - loop.index0 %}
169
+ {%- if ns.multi_step_tool and message.role == 'user' %}
170
+ {%- set _rc = render_content(message.content, false) | trim %}
171
+ {%- if not (_rc.startswith('<tool_response>') and _rc.endswith('</tool_response>')) %}
172
+ {%- set ns.multi_step_tool = false %}
173
+ {%- set ns.last_query_index = index %}
174
+ {%- endif %}
175
+ {%- endif %}
176
+ {%- endfor %}
177
+ {%- if ns.multi_step_tool %}
178
+ {%- if _last_idx > 50 %}
179
+ {%- set ns.last_query_index = _last_idx %}
180
+ {%- else %}
181
+ {%- set ns.last_query_index = 0 %}
182
+ {%- endif %}
183
+ {%- endif %}
184
+ {%- set ns2 = namespace(prev_role='', consecutive_failures=0) %}
185
+ {%- for message in _msgs %}
186
+ {%- set is_system = (message.role == "system" or message.role == "developer") %}
187
+ {%- set content = render_content(message.content, true, is_system) | trim %}
188
+ {%- if is_system or message.role == 'user' %}
189
+ {%- if '<|think_off|>' in content %}
190
+ {%- set content = content.split('<|think_off|>') | join('') | trim %}
191
+ {%- elif '<|think_on|>' in content %}
192
+ {%- set content = content.split('<|think_on|>') | join('') | trim %}
193
+ {%- endif %}
194
+ {%- endif %}
195
+ {%- if is_system %}
196
+ {{- '<|im_start|>system\n' + content + '<|im_end|>\n' }}
197
+ {%- elif message.role == 'user' %}
198
+ {%- set ns2.consecutive_failures = 0 %}
199
+ {{- '<|im_start|>user\n' + content + '<|im_end|>\n' }}
200
+ {%- elif message.role == 'assistant' %}
201
+ {%- set reasoning_content = '' %}
202
+ {%- if message.reasoning_content is defined and message.reasoning_content is not none %}
203
+ {%- if message.reasoning_content is string %}
204
+ {%- set reasoning_content = message.reasoning_content %}
205
+ {%- else %}
206
+ {%- set reasoning_content = message.reasoning_content | string %}
207
+ {%- endif %}
208
+ {%- elif message.thinking is defined and message.thinking is not none %}
209
+ {%- if message.thinking is string %}
210
+ {%- set reasoning_content = message.thinking %}
211
+ {%- else %}
212
+ {%- set reasoning_content = message.thinking | string %}
213
+ {%- endif %}
214
+ {%- else %}
215
+ {%- set _think_end = '' %}
216
+ {%- if content.startswith('</think>') %}
217
+ {%- set _think_end = '</think>' %}
218
+ {%- elif content.startswith('</thinking>') %}
219
+ {%- set _think_end = '</thinking>' %}
220
+ {%- elif '\n</think>' in content %}
221
+ {%- set _think_end = '\n</think>' %}
222
+ {%- elif '\n</thinking>' in content %}
223
+ {%- set _think_end = '\n</thinking>' %}
224
+ {%- elif '\n</ think>' in content %}
225
+ {%- set _think_end = '\n</ think>' %}
226
+ {%- elif '\n</think >' in content %}
227
+ {%- set _think_end = '\n</think >' %}
228
+ {%- endif %}
229
+ {%- if _think_end %}
230
+ {%- if 'thinking' in _think_end %}
231
+ {%- set _think_start = '<thinking>' %}
232
+ {%- else %}
233
+ {%- set _think_start = '<think>' %}
234
+ {%- endif %}
235
+ {%- set reasoning_content = content.split(_think_end)[0].rstrip('\n') %}
236
+ {%- if _think_start in reasoning_content %}
237
+ {%- set reasoning_content = reasoning_content.split(_think_start)[-1].lstrip('\n') %}
238
+ {%- endif %}
239
+ {%- set content = content.split(_think_end)[-1].lstrip('\n') %}
240
+ {%- endif %}
241
+ {%- endif %}
242
+ {%- set reasoning_content = reasoning_content | trim %}
243
+ {%- if (_preserve_thinking or loop.index0 > ns.last_query_index) and reasoning_content %}
244
+ {{- '<|im_start|>assistant\n<think>\n' + reasoning_content + '\n</think>\n\n' + content }}
245
+ {%- else %}
246
+ {{- '<|im_start|>assistant\n' + content }}
247
+ {%- endif %}
248
+ {%- if message.tool_calls is defined and message.tool_calls and message.tool_calls is iterable and message.tool_calls is not mapping %}
249
+ {%- for tool_call in message.tool_calls %}
250
+ {%- if tool_call.function is defined and tool_call.function is not none %}
251
+ {%- set tc = tool_call.function %}
252
+ {%- else %}
253
+ {%- set tc = tool_call %}
254
+ {%- endif %}
255
+ {%- set tc_name = tc.name if (tc.name is defined and tc.name is not none) else '' %}
256
+ {%- if _tool_format == 'json' %}
257
+ {%- if not loop.first or content | trim %}
258
+ {{- '\n\n' }}
259
+ {%- endif %}
260
+ {%- set _args = '{}' %}
261
+ {%- if tc.arguments is defined and tc.arguments is not none %}
262
+ {%- if tc.arguments is mapping %}
263
+ {%- set _args = tc.arguments | tojson %}
264
+ {%- elif tc.arguments is string and tc.arguments %}
265
+ {%- set _args = tc.arguments %}
266
+ {%- endif %}
267
+ {%- endif %}
268
+ {{- '<tool_call>\n{"name": ' }}{{- tc_name | tojson }}{{- ', "arguments": ' }}{{- _args }}{{- '}\n</tool_call>' }}
269
+ {%- else %}
270
+ {%- if loop.first %}
271
+ {%- if content | trim %}
272
+ {{- '\n\n<tool_call>\n<function=' + tc_name + '>\n' }}
273
+ {%- else %}
274
+ {{- '<tool_call>\n<function=' + tc_name + '>\n' }}
275
+ {%- endif %}
276
+ {%- else %}
277
+ {{- '\n\n<tool_call>\n<function=' + tc_name + '>\n' }}
278
+ {%- endif %}
279
+ {%- if tc.arguments is defined and tc.arguments is not none %}
280
+ {%- if tc.arguments is mapping %}
281
+ {%- for args_name, args_value in tc.arguments.items() %}
282
+ {{- '<parameter=' + args_name + '>\n' }}
283
+ {%- if args_value is mapping or (args_value is sequence and args_value is not string) %}
284
+ {%- set _av = args_value | tojson %}
285
+ {%- else %}
286
+ {%- set _av = args_value | string %}
287
+ {%- endif %}
288
+ {%- if max_tool_arg_chars > 0 and _av | length > max_tool_arg_chars %}
289
+ {{- _av[:max_tool_arg_chars] + '\n[TRUNCATED — original length ' ~ (_av | length | string) ~ ' chars]' }}
290
+ {%- else %}
291
+ {{- _av }}
292
+ {%- endif %}
293
+ {{- '\n</parameter>\n' }}
294
+ {%- endfor %}
295
+ {%- elif tc.arguments is string and tc.arguments %}
296
+ {{- tc.arguments }}
297
+ {%- endif %}
298
+ {%- endif %}
299
+ {{- '</function>\n</tool_call>' }}
300
+ {%- endif %}
301
+ {%- endfor %}
302
+ {%- endif %}
303
+ {{- '<|im_end|>\n' }}
304
+ {%- elif message.role == 'tool' %}
305
+ {%- set _content_lower = content | lower %}
306
+ {%- set _content_head = _content_lower[:80] %}
307
+ {%- if content | length < 500 and '$ ' not in content and 'took ' not in _content_lower and ('"error":' in _content_head or 'error:' in _content_head or 'err!' in _content_head or 'fatal:' in _content_head or 'exception:' in _content_head or 'traceback' in _content_head or 'command not found' in _content_head or 'invalid syntax' in _content_head or 'failed to' in _content_head) %}
308
+ {%- set ns2.consecutive_failures = ns2.consecutive_failures + 1 %}
309
+ {%- else %}
310
+ {%- set ns2.consecutive_failures = 0 %}
311
+ {%- endif %}
312
+ {%- if ns2.prev_role != 'tool' %}
313
+ {{- '<|im_start|>user' }}
314
+ {%- endif %}
315
+ {%- if max_tool_response_chars > 0 and content | length > max_tool_response_chars %}
316
+ {%- set content = content[:max_tool_response_chars] + '\n[TRUNCATED — original length ' ~ (content | length | string) ~ ' chars]' %}
317
+ {%- endif %}
318
+ {{- '\n<tool_response>\n' + content }}
319
+ {%- if ns2.consecutive_failures >= 2 %}
320
+ {{- '\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.' }}
321
+ {%- elif ns2.consecutive_failures == 1 %}
322
+ {{- '\n\n⚠️ SYSTEM WARNING: The previous tool call returned an error. Diagnose the failure and retry with completely corrected arguments.' }}
323
+ {%- endif %}
324
+ {{- '\n</tool_response>' }}
325
+ {%- if loop.last %}
326
+ {{- '<|im_end|>\n' }}
327
+ {%- else %}
328
+ {%- set _next_role = _msgs[loop.index0 + 1].role %}
329
+ {%- if _next_role != 'tool' %}
330
+ {{- '<|im_end|>\n' }}
331
+ {%- endif %}
332
+ {%- endif %}
333
+ {%- else %}
334
+ {{- '<|im_start|>user\n[' + message.role + ']: ' + content + '<|im_end|>\n' }}
335
+ {%- endif %}
336
+ {%- set ns2.prev_role = message.role %}
337
+ {%- endfor %}
338
+ {%- if add_generation_prompt %}
339
+ {{- '<|im_start|>assistant\n' }}
340
+ {%- if not ns_state.thinking %}
341
+ {{- '<think>\n\n</think>\n\n' }}
342
+ {%- else %}
343
+ {{- '<think>\n' }}
344
+ {%- endif %}
345
+ {%- endif %}
archive/v22-sharp/chat_template_oneline.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ {%- set template_version = "qwen3.8-froggeric-v22" %}{%- set _tool_format = tool_call_format if tool_call_format is defined else 'xml' %}{%- set image_count = namespace(value=0) %}{%- set video_count = namespace(value=0) %}{%- set add_vision_id = add_vision_id if add_vision_id is defined else false %}{%- set enable_thinking = enable_thinking if enable_thinking is defined else true %}{%- set auto_disable_thinking_with_tools = auto_disable_thinking_with_tools if auto_disable_thinking_with_tools is defined else false %}{%- if preserve_reasoning is defined and preserve_reasoning is not none %}{%- set _preserve_thinking = preserve_reasoning %}{%- elif preserve_thinking is defined and preserve_thinking is not none %}{%- set _preserve_thinking = preserve_thinking %}{%- else %}{%- set _preserve_thinking = true %}{%- endif %}{%- set max_tool_arg_chars = max_tool_arg_chars if max_tool_arg_chars is defined else 0 %}{%- set max_tool_response_chars = max_tool_response_chars if max_tool_response_chars is defined else 0 %}{%- set _has_tools = (tools is defined and tools and tools is iterable and tools is not mapping) %}{%- set ns_state = namespace(thinking=enable_thinking) %}{%- if auto_disable_thinking_with_tools and _has_tools %}{%- set ns_state.thinking = false %}{%- endif %}{%- for msg in messages %}{%- if msg.role == 'system' or msg.role == 'developer' or msg.role == 'user' %}{%- if msg.content is string %}{%- if '<|think_off|>' in msg.content %}{%- set ns_state.thinking = false %}{%- elif '<|think_on|>' in msg.content %}{%- set ns_state.thinking = true %}{%- endif %}{%- elif msg.content is iterable and msg.content is not mapping %}{%- for item in msg.content %}{%- if item is mapping and 'text' in item and item.text is string %}{%- if '<|think_off|>' in item.text %}{%- set ns_state.thinking = false %}{%- elif '<|think_on|>' in item.text %}{%- set ns_state.thinking = true %}{%- endif %}{%- endif %}{%- endfor %}{%- endif %}{%- endif %}{%- endfor %}{%- set _effort_raw = reasoning_effort if reasoning_effort is defined else 'xhigh' %}{%- if _effort_raw == 'high' or _effort_raw == 'xhigh' %}{%- set _reasoning_effort = 'xhigh' %}{%- elif _effort_raw == 'low' %}{%- set _reasoning_effort = 'low' %}{%- elif _effort_raw == 'medium' %}{%- set _reasoning_effort = 'medium' %}{%- else %}{%- set _reasoning_effort = 'xhigh' %}{%- endif %}{%- set reasoning_instructions = '' %}{%- if ns_state.thinking %}{%- if _reasoning_effort == 'xhigh' %}{%- 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.' %}{%- elif _reasoning_effort == 'low' %}{%- set reasoning_instructions = 'Reasoning effort is set to low. Keep your thinking brief and focused, moving directly to the conclusion without unnecessary elaboration.' %}{%- endif %}{%- endif %}{%- macro render_content(content, do_vision_count, is_system_content=false) %}{%- if content is string %}{{- content }}{%- elif content is iterable and content is not mapping %}{%- for item in content %}{%- if item is mapping %}{%- if item.type == 'image' or 'image' in item or 'image_url' in item %}{%- if is_system_content %}{{- raise_exception('System message cannot contain images.') }}{%- endif %}{%- if do_vision_count %}{%- set image_count.value = image_count.value + 1 %}{%- endif %}{%- if add_vision_id %}{{- 'Picture ' ~ image_count.value ~ ': ' }}{%- endif %}{{- '<|vision_start|><|image_pad|><|vision_end|>' }}{%- elif item.type == 'video' or 'video' in item %}{%- if is_system_content %}{{- raise_exception('System message cannot contain videos.') }}{%- endif %}{%- if do_vision_count %}{%- set video_count.value = video_count.value + 1 %}{%- endif %}{%- if add_vision_id %}{{- 'Video ' ~ video_count.value ~ ': ' }}{%- endif %}{{- '<|vision_start|><|video_pad|><|vision_end|>' }}{%- elif 'text' in item %}{{- item.text }}{%- else %}{{- raise_exception('Unexpected item type in content.') }}{%- endif %}{%- else %}{{- item | string }}{%- endif %}{%- endfor %}{%- elif content is none or content is undefined %}{{- '' }}{%- else %}{{- raise_exception('Unexpected content type.') }}{%- endif %}{%- endmacro %}{%- if not messages %}{{- raise_exception('No messages provided.') }}{%- endif %}{%- set _first_role = messages[0].role %}{%- if _first_role == 'system' or _first_role == 'developer' %}{%- set _sys_msg = messages[0] %}{%- set _msgs = messages[1:] %}{%- else %}{%- set _sys_msg = none %}{%- set _msgs = messages %}{%- endif %}{%- set _sc = '' %}{%- if _sys_msg is not none %}{%- set _sc = render_content(_sys_msg.content, false, true) | trim %}{%- if '<|think_off|>' in _sc %}{%- set _sc = _sc.split('<|think_off|>') | join('') | trim %}{%- elif '<|think_on|>' in _sc %}{%- set _sc = _sc.split('<|think_on|>') | join('') | trim %}{%- endif %}{%- endif %} {%- set _terse %}
2
+ Answer directly, after thinking. Lead with the answer, then only what it needs to be correct and usable.
3
+ Never: open with preamble or pleasantries; restate the question; add filler transitions; hedge with niceties; or repeat a point you've already made.
4
+ 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.
5
+ If a user request is genuinely ambiguous, ask a sharp question, don't guess.
6
+ {%- endset %} {%- if not _sc %}{%- set _sc = _terse | trim %}{%- else %}{%- set _sc = (_sc | trim) ~ '\n\n' ~ (_terse | trim) %}{%- endif %}{%- if reasoning_effort is not defined %}{%- set reasoning_instructions = '' %}{%- endif %}{%- if _has_tools %}{{- '<|im_start|>system\n' }}{%- if reasoning_instructions %}{{- reasoning_instructions + '\n\n' }}{%- endif %}{{- '# Tools\n\nYou have access to the following functions:\n\n<tools>' }}{%- for tool in tools %}{{- '\n' }}{{- tool | tojson }}{%- endfor %}{{- '\n</tools>' }}{%- if _tool_format == 'json' %}{{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<think>\nBrief explanation of tool call\n</think>\n<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- 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- Function calls MUST follow the specified format: a single JSON object with "name" and "arguments" keys inside <tool_call></tool_call> XML tags.\n- If you choose to call a tool, you MUST output the <tool_call> block IMMEDIATELY after thinking, with NO conversational text before it.\n- 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>' }}{%- else %}{{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<think>\nBrief explanation of tool call\n</think>\n<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- 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- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags.\n- If you choose to call a tool, you MUST output the <tool_call> block IMMEDIATELY after thinking, with NO conversational text before it.\n- 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>' }}{%- endif %}{%- if _sc %}{{- '\n\n' + _sc }}{%- endif %}{{- '<|im_end|>\n' }}{%- else %}{%- if _sc %}{{- '<|im_start|>system\n' + (reasoning_instructions + '\n\n' if reasoning_instructions else '') + _sc + '<|im_end|>\n' }}{%- elif reasoning_instructions %}{{- '<|im_start|>system\n' + reasoning_instructions + '<|im_end|>\n' }}{%- endif %}{%- endif %}{%- set _last_idx = _msgs | length - 1 %}{%- set ns = namespace(multi_step_tool=true, last_query_index=_last_idx) %}{%- for message in _msgs[::-1] %}{%- set index = (_msgs | length - 1) - loop.index0 %}{%- if ns.multi_step_tool and message.role == 'user' %}{%- set _rc = render_content(message.content, false) | trim %}{%- if not (_rc.startswith('<tool_response>') and _rc.endswith('</tool_response>')) %}{%- set ns.multi_step_tool = false %}{%- set ns.last_query_index = index %}{%- endif %}{%- endif %}{%- endfor %}{%- if ns.multi_step_tool %}{%- if _last_idx > 50 %}{%- set ns.last_query_index = _last_idx %}{%- else %}{%- set ns.last_query_index = 0 %}{%- endif %}{%- endif %}{%- set ns2 = namespace(prev_role='', consecutive_failures=0) %}{%- for message in _msgs %}{%- set is_system = (message.role == "system" or message.role == "developer") %}{%- set content = render_content(message.content, true, is_system) | trim %}{%- if is_system or message.role == 'user' %}{%- if '<|think_off|>' in content %}{%- set content = content.split('<|think_off|>') | join('') | trim %}{%- elif '<|think_on|>' in content %}{%- set content = content.split('<|think_on|>') | join('') | trim %}{%- endif %}{%- endif %}{%- if is_system %}{{- '<|im_start|>system\n' + content + '<|im_end|>\n' }}{%- elif message.role == 'user' %}{%- set ns2.consecutive_failures = 0 %}{{- '<|im_start|>user\n' + content + '<|im_end|>\n' }}{%- elif message.role == 'assistant' %}{%- set reasoning_content = '' %}{%- if message.reasoning_content is defined and message.reasoning_content is not none %}{%- if message.reasoning_content is string %}{%- set reasoning_content = message.reasoning_content %}{%- else %}{%- set reasoning_content = message.reasoning_content | string %}{%- endif %}{%- elif message.thinking is defined and message.thinking is not none %}{%- if message.thinking is string %}{%- set reasoning_content = message.thinking %}{%- else %}{%- set reasoning_content = message.thinking | string %}{%- endif %}{%- else %}{%- set _think_end = '' %}{%- if content.startswith('</think>') %}{%- set _think_end = '</think>' %}{%- elif content.startswith('</thinking>') %}{%- set _think_end = '</thinking>' %}{%- elif '\n</think>' in content %}{%- set _think_end = '\n</think>' %}{%- elif '\n</thinking>' in content %}{%- set _think_end = '\n</thinking>' %}{%- elif '\n</ think>' in content %}{%- set _think_end = '\n</ think>' %}{%- elif '\n</think >' in content %}{%- set _think_end = '\n</think >' %}{%- endif %}{%- if _think_end %}{%- if 'thinking' in _think_end %}{%- set _think_start = '<thinking>' %}{%- else %}{%- set _think_start = '<think>' %}{%- endif %}{%- set reasoning_content = content.split(_think_end)[0].rstrip('\n') %}{%- if _think_start in reasoning_content %}{%- set reasoning_content = reasoning_content.split(_think_start)[-1].lstrip('\n') %}{%- endif %}{%- set content = content.split(_think_end)[-1].lstrip('\n') %}{%- endif %}{%- endif %}{%- set reasoning_content = reasoning_content | trim %}{%- if (_preserve_thinking or loop.index0 > ns.last_query_index) and reasoning_content %}{{- '<|im_start|>assistant\n<think>\n' + reasoning_content + '\n</think>\n\n' + content }}{%- else %}{{- '<|im_start|>assistant\n' + content }}{%- endif %}{%- if message.tool_calls is defined and message.tool_calls and message.tool_calls is iterable and message.tool_calls is not mapping %}{%- for tool_call in message.tool_calls %}{%- if tool_call.function is defined and tool_call.function is not none %}{%- set tc = tool_call.function %}{%- else %}{%- set tc = tool_call %}{%- endif %}{%- set tc_name = tc.name if (tc.name is defined and tc.name is not none) else '' %}{%- if _tool_format == 'json' %}{%- if not loop.first or content | trim %}{{- '\n\n' }}{%- endif %}{%- set _args = '{}' %}{%- if tc.arguments is defined and tc.arguments is not none %}{%- if tc.arguments is mapping %}{%- set _args = tc.arguments | tojson %}{%- elif tc.arguments is string and tc.arguments %}{%- set _args = tc.arguments %}{%- endif %}{%- endif %}{{- '<tool_call>\n{"name": ' }}{{- tc_name | tojson }}{{- ', "arguments": ' }}{{- _args }}{{- '}\n</tool_call>' }}{%- else %}{%- if loop.first %}{%- if content | trim %}{{- '\n\n<tool_call>\n<function=' + tc_name + '>\n' }}{%- else %}{{- '<tool_call>\n<function=' + tc_name + '>\n' }}{%- endif %}{%- else %}{{- '\n\n<tool_call>\n<function=' + tc_name + '>\n' }}{%- endif %}{%- if tc.arguments is defined and tc.arguments is not none %}{%- if tc.arguments is mapping %}{%- for args_name, args_value in tc.arguments.items() %}{{- '<parameter=' + args_name + '>\n' }}{%- if args_value is mapping or (args_value is sequence and args_value is not string) %}{%- set _av = args_value | tojson %}{%- else %}{%- set _av = args_value | string %}{%- endif %}{%- if max_tool_arg_chars > 0 and _av | length > max_tool_arg_chars %}{{- _av[:max_tool_arg_chars] + '\n[TRUNCATED — original length ' ~ (_av | length | string) ~ ' chars]' }}{%- else %}{{- _av }}{%- endif %}{{- '\n</parameter>\n' }}{%- endfor %}{%- elif tc.arguments is string and tc.arguments %}{{- tc.arguments }}{%- endif %}{%- endif %}{{- '</function>\n</tool_call>' }}{%- endif %}{%- endfor %}{%- endif %}{{- '<|im_end|>\n' }}{%- elif message.role == 'tool' %}{%- set _content_lower = content | lower %}{%- set _content_head = _content_lower[:80] %}{%- if content | length < 500 and '$ ' not in content and 'took ' not in _content_lower and ('"error":' in _content_head or 'error:' in _content_head or 'err!' in _content_head or 'fatal:' in _content_head or 'exception:' in _content_head or 'traceback' in _content_head or 'command not found' in _content_head or 'invalid syntax' in _content_head or 'failed to' in _content_head) %}{%- set ns2.consecutive_failures = ns2.consecutive_failures + 1 %}{%- else %}{%- set ns2.consecutive_failures = 0 %}{%- endif %}{%- if ns2.prev_role != 'tool' %}{{- '<|im_start|>user' }}{%- endif %}{%- if max_tool_response_chars > 0 and content | length > max_tool_response_chars %}{%- set content = content[:max_tool_response_chars] + '\n[TRUNCATED — original length ' ~ (content | length | string) ~ ' chars]' %}{%- endif %}{{- '\n<tool_response>\n' + content }}{%- if ns2.consecutive_failures >= 2 %}{{- '\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.' }}{%- elif ns2.consecutive_failures == 1 %}{{- '\n\n⚠️ SYSTEM WARNING: The previous tool call returned an error. Diagnose the failure and retry with completely corrected arguments.' }}{%- endif %}{{- '\n</tool_response>' }}{%- if loop.last %}{{- '<|im_end|>\n' }}{%- else %}{%- set _next_role = _msgs[loop.index0 + 1].role %}{%- if _next_role != 'tool' %}{{- '<|im_end|>\n' }}{%- endif %}{%- endif %}{%- else %}{{- '<|im_start|>user\n[' + message.role + ']: ' + content + '<|im_end|>\n' }}{%- endif %}{%- set ns2.prev_role = message.role %}{%- endfor %}{%- if add_generation_prompt %}{{- '<|im_start|>assistant\n' }}{%- if not ns_state.thinking %}{{- '<think>\n\n</think>\n\n' }}{%- else %}{{- '<think>\n' }}{%- endif %}{%- endif %}
chat_template.jinja CHANGED
@@ -1,4 +1,4 @@
1
- {%- set template_version = "qwen3.8-froggeric-v22" %}
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) %}
@@ -15,7 +15,20 @@
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 _has_tools = (tools is defined and tools and tools is iterable and tools is not mapping) %}
18
- {%- set ns_state = namespace(thinking=enable_thinking) %}
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  {%- if auto_disable_thinking_with_tools and _has_tools %}
20
  {%- set ns_state.thinking = false %}
21
  {%- endif %}
@@ -26,35 +39,50 @@
26
  {%- set ns_state.thinking = false %}
27
  {%- elif '<|think_on|>' in msg.content %}
28
  {%- set ns_state.thinking = true %}
 
 
 
 
 
 
 
 
 
29
  {%- endif %}
30
  {%- elif msg.content is iterable and msg.content is not mapping %}
31
  {%- for item in msg.content %}
32
- {%- if item is mapping and 'text' in item and item.text is string %}
33
- {%- if '<|think_off|>' in item.text %}
 
 
 
 
 
 
 
34
  {%- set ns_state.thinking = false %}
35
- {%- elif '<|think_on|>' in item.text %}
 
 
36
  {%- set ns_state.thinking = true %}
 
 
 
 
 
 
 
37
  {%- endif %}
38
  {%- endif %}
39
  {%- endfor %}
40
  {%- endif %}
41
  {%- endif %}
42
  {%- endfor %}
43
- {%- set _effort_raw = reasoning_effort if reasoning_effort is defined else 'xhigh' %}
44
- {%- if _effort_raw == 'high' or _effort_raw == 'xhigh' %}
45
- {%- set _reasoning_effort = 'xhigh' %}
46
- {%- elif _effort_raw == 'low' %}
47
- {%- set _reasoning_effort = 'low' %}
48
- {%- elif _effort_raw == 'medium' %}
49
- {%- set _reasoning_effort = 'medium' %}
50
- {%- else %}
51
- {%- set _reasoning_effort = 'xhigh' %}
52
- {%- endif %}
53
  {%- set reasoning_instructions = '' %}
54
  {%- if ns_state.thinking %}
55
- {%- if _reasoning_effort == 'xhigh' %}
56
  {%- 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.' %}
57
- {%- elif _reasoning_effort == 'low' %}
58
  {%- set reasoning_instructions = 'Reasoning effort is set to low. Keep your thinking brief and focused, moving directly to the conclusion without unnecessary elaboration.' %}
59
  {%- endif %}
60
  {%- endif %}
@@ -115,11 +143,13 @@
115
  {%- set _sc = '' %}
116
  {%- if _sys_msg is not none %}
117
  {%- set _sc = render_content(_sys_msg.content, false, true) | trim %}
118
- {%- if '<|think_off|>' in _sc %}
119
- {%- set _sc = _sc.split('<|think_off|>') | join('') | trim %}
120
- {%- elif '<|think_on|>' in _sc %}
121
- {%- set _sc = _sc.split('<|think_on|>') | join('') | trim %}
122
- {%- endif %}
 
 
123
  {%- endif %}
124
  {%- set _terse %}
125
  Answer directly, after thinking. Lead with the answer, then only what it needs to be correct and usable.
@@ -132,9 +162,6 @@ If a user request is genuinely ambiguous, ask a sharp question, don't guess.
132
  {%- else %}
133
  {%- set _sc = (_sc | trim) ~ '\n\n' ~ (_terse | trim) %}
134
  {%- endif %}
135
- {%- if reasoning_effort is not defined %}
136
- {%- set reasoning_instructions = '' %}
137
- {%- endif %}
138
  {%- if _has_tools %}
139
  {{- '<|im_start|>system\n' }}
140
  {%- if reasoning_instructions %}
@@ -186,11 +213,13 @@ If a user request is genuinely ambiguous, ask a sharp question, don't guess.
186
  {%- set is_system = (message.role == "system" or message.role == "developer") %}
187
  {%- set content = render_content(message.content, true, is_system) | trim %}
188
  {%- if is_system or message.role == 'user' %}
189
- {%- if '<|think_off|>' in content %}
190
- {%- set content = content.split('<|think_off|>') | join('') | trim %}
191
- {%- elif '<|think_on|>' in content %}
192
- {%- set content = content.split('<|think_on|>') | join('') | trim %}
193
- {%- endif %}
 
 
194
  {%- endif %}
195
  {%- if is_system %}
196
  {{- '<|im_start|>system\n' + content + '<|im_end|>\n' }}
@@ -286,7 +315,7 @@ If a user request is genuinely ambiguous, ask a sharp question, don't guess.
286
  {%- set _av = args_value | string %}
287
  {%- endif %}
288
  {%- if max_tool_arg_chars > 0 and _av | length > max_tool_arg_chars %}
289
- {{- _av[:max_tool_arg_chars] + '\n[TRUNCATED original length ' ~ (_av | length | string) ~ ' chars]' }}
290
  {%- else %}
291
  {{- _av }}
292
  {%- endif %}
@@ -313,7 +342,7 @@ If a user request is genuinely ambiguous, ask a sharp question, don't guess.
313
  {{- '<|im_start|>user' }}
314
  {%- endif %}
315
  {%- if max_tool_response_chars > 0 and content | length > max_tool_response_chars %}
316
- {%- set content = content[:max_tool_response_chars] + '\n[TRUNCATED original length ' ~ (content | length | string) ~ ' chars]' %}
317
  {%- endif %}
318
  {{- '\n<tool_response>\n' + content }}
319
  {%- if ns2.consecutive_failures >= 2 %}
 
1
+ {%- set template_version = "qwen3.8-froggeric-v22.1" %}
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) %}
 
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 _has_tools = (tools is defined and tools and tools is iterable and tools is not mapping) %}
18
+ {%- set _effort_raw = (reasoning_effort | string | lower) if reasoning_effort is defined and reasoning_effort is not none else 'medium' %}
19
+ {%- set _initial_thinking = enable_thinking %}
20
+ {%- set _initial_effort = 'medium' %}
21
+ {%- if _effort_raw == 'none' %}
22
+ {%- set _initial_thinking = false %}
23
+ {%- set _initial_effort = 'medium' %}
24
+ {%- elif _effort_raw == 'minimal' or _effort_raw == 'low' %}
25
+ {%- set _initial_effort = 'low' %}
26
+ {%- elif _effort_raw == 'high' or _effort_raw == 'xhigh' or _effort_raw == 'max' %}
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 %}
 
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 %}
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 %}
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 %}
 
143
  {%- set _sc = '' %}
144
  {%- if _sys_msg is not none %}
145
  {%- set _sc = render_content(_sys_msg.content, false, true) | trim %}
146
+ {%- if '<|think_off|>' in _sc %}{%- set _sc = _sc.split('<|think_off|>') | join('') | trim %}{%- endif %}
147
+ {%- if '<|think_on|>' in _sc %}{%- set _sc = _sc.split('<|think_on|>') | join('') | trim %}{%- endif %}
148
+ {%- if '<|think_xhigh|>' in _sc %}{%- set _sc = _sc.split('<|think_xhigh|>') | join('') | trim %}{%- endif %}
149
+ {%- if '<|think_high|>' in _sc %}{%- set _sc = _sc.split('<|think_high|>') | join('') | trim %}{%- endif %}
150
+ {%- if '<|think_medium|>' in _sc %}{%- set _sc = _sc.split('<|think_medium|>') | join('') | trim %}{%- endif %}
151
+ {%- if '<|think_low|>' in _sc %}{%- set _sc = _sc.split('<|think_low|>') | join('') | trim %}{%- endif %}
152
+ {%- if '<|think_minimal|>' in _sc %}{%- set _sc = _sc.split('<|think_minimal|>') | join('') | trim %}{%- endif %}
153
  {%- endif %}
154
  {%- set _terse %}
155
  Answer directly, after thinking. Lead with the answer, then only what it needs to be correct and usable.
 
162
  {%- else %}
163
  {%- set _sc = (_sc | trim) ~ '\n\n' ~ (_terse | trim) %}
164
  {%- endif %}
 
 
 
165
  {%- if _has_tools %}
166
  {{- '<|im_start|>system\n' }}
167
  {%- if reasoning_instructions %}
 
213
  {%- set is_system = (message.role == "system" or message.role == "developer") %}
214
  {%- set content = render_content(message.content, true, is_system) | trim %}
215
  {%- if is_system or message.role == 'user' %}
216
+ {%- if '<|think_off|>' in content %}{%- set content = content.split('<|think_off|>') | join('') | trim %}{%- endif %}
217
+ {%- if '<|think_on|>' in content %}{%- set content = content.split('<|think_on|>') | join('') | trim %}{%- endif %}
218
+ {%- if '<|think_xhigh|>' in content %}{%- set content = content.split('<|think_xhigh|>') | join('') | trim %}{%- endif %}
219
+ {%- if '<|think_high|>' in content %}{%- set content = content.split('<|think_high|>') | join('') | trim %}{%- endif %}
220
+ {%- if '<|think_medium|>' in content %}{%- set content = content.split('<|think_medium|>') | join('') | trim %}{%- endif %}
221
+ {%- if '<|think_low|>' in content %}{%- set content = content.split('<|think_low|>') | join('') | trim %}{%- endif %}
222
+ {%- if '<|think_minimal|>' in content %}{%- set content = content.split('<|think_minimal|>') | join('') | trim %}{%- endif %}
223
  {%- endif %}
224
  {%- if is_system %}
225
  {{- '<|im_start|>system\n' + content + '<|im_end|>\n' }}
 
315
  {%- set _av = args_value | string %}
316
  {%- endif %}
317
  {%- if max_tool_arg_chars > 0 and _av | length > max_tool_arg_chars %}
318
+ {{- _av[:max_tool_arg_chars] + '\n[TRUNCATED - original length ' ~ (_av | length | string) ~ ' chars]' }}
319
  {%- else %}
320
  {{- _av }}
321
  {%- endif %}
 
342
  {{- '<|im_start|>user' }}
343
  {%- endif %}
344
  {%- if max_tool_response_chars > 0 and content | length > max_tool_response_chars %}
345
+ {%- set content = content[:max_tool_response_chars] + '\n[TRUNCATED - original length ' ~ (content | length | string) ~ ' chars]' %}
346
  {%- endif %}
347
  {{- '\n<tool_response>\n' + content }}
348
  {%- if ns2.consecutive_failures >= 2 %}
chat_template_oneline.txt CHANGED
@@ -1,6 +1,6 @@
1
- {%- set template_version = "qwen3.8-froggeric-v22" %}{%- set _tool_format = tool_call_format if tool_call_format is defined else 'xml' %}{%- set image_count = namespace(value=0) %}{%- set video_count = namespace(value=0) %}{%- set add_vision_id = add_vision_id if add_vision_id is defined else false %}{%- set enable_thinking = enable_thinking if enable_thinking is defined else true %}{%- set auto_disable_thinking_with_tools = auto_disable_thinking_with_tools if auto_disable_thinking_with_tools is defined else false %}{%- if preserve_reasoning is defined and preserve_reasoning is not none %}{%- set _preserve_thinking = preserve_reasoning %}{%- elif preserve_thinking is defined and preserve_thinking is not none %}{%- set _preserve_thinking = preserve_thinking %}{%- else %}{%- set _preserve_thinking = true %}{%- endif %}{%- set max_tool_arg_chars = max_tool_arg_chars if max_tool_arg_chars is defined else 0 %}{%- set max_tool_response_chars = max_tool_response_chars if max_tool_response_chars is defined else 0 %}{%- set _has_tools = (tools is defined and tools and tools is iterable and tools is not mapping) %}{%- set ns_state = namespace(thinking=enable_thinking) %}{%- if auto_disable_thinking_with_tools and _has_tools %}{%- set ns_state.thinking = false %}{%- endif %}{%- for msg in messages %}{%- if msg.role == 'system' or msg.role == 'developer' or msg.role == 'user' %}{%- if msg.content is string %}{%- if '<|think_off|>' in msg.content %}{%- set ns_state.thinking = false %}{%- elif '<|think_on|>' in msg.content %}{%- set ns_state.thinking = true %}{%- endif %}{%- elif msg.content is iterable and msg.content is not mapping %}{%- for item in msg.content %}{%- if item is mapping and 'text' in item and item.text is string %}{%- if '<|think_off|>' in item.text %}{%- set ns_state.thinking = false %}{%- elif '<|think_on|>' in item.text %}{%- set ns_state.thinking = true %}{%- endif %}{%- endif %}{%- endfor %}{%- endif %}{%- endif %}{%- endfor %}{%- set _effort_raw = reasoning_effort if reasoning_effort is defined else 'xhigh' %}{%- if _effort_raw == 'high' or _effort_raw == 'xhigh' %}{%- set _reasoning_effort = 'xhigh' %}{%- elif _effort_raw == 'low' %}{%- set _reasoning_effort = 'low' %}{%- elif _effort_raw == 'medium' %}{%- set _reasoning_effort = 'medium' %}{%- else %}{%- set _reasoning_effort = 'xhigh' %}{%- endif %}{%- set reasoning_instructions = '' %}{%- if ns_state.thinking %}{%- if _reasoning_effort == 'xhigh' %}{%- 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.' %}{%- elif _reasoning_effort == 'low' %}{%- set reasoning_instructions = 'Reasoning effort is set to low. Keep your thinking brief and focused, moving directly to the conclusion without unnecessary elaboration.' %}{%- endif %}{%- endif %}{%- macro render_content(content, do_vision_count, is_system_content=false) %}{%- if content is string %}{{- content }}{%- elif content is iterable and content is not mapping %}{%- for item in content %}{%- if item is mapping %}{%- if item.type == 'image' or 'image' in item or 'image_url' in item %}{%- if is_system_content %}{{- raise_exception('System message cannot contain images.') }}{%- endif %}{%- if do_vision_count %}{%- set image_count.value = image_count.value + 1 %}{%- endif %}{%- if add_vision_id %}{{- 'Picture ' ~ image_count.value ~ ': ' }}{%- endif %}{{- '<|vision_start|><|image_pad|><|vision_end|>' }}{%- elif item.type == 'video' or 'video' in item %}{%- if is_system_content %}{{- raise_exception('System message cannot contain videos.') }}{%- endif %}{%- if do_vision_count %}{%- set video_count.value = video_count.value + 1 %}{%- endif %}{%- if add_vision_id %}{{- 'Video ' ~ video_count.value ~ ': ' }}{%- endif %}{{- '<|vision_start|><|video_pad|><|vision_end|>' }}{%- elif 'text' in item %}{{- item.text }}{%- else %}{{- raise_exception('Unexpected item type in content.') }}{%- endif %}{%- else %}{{- item | string }}{%- endif %}{%- endfor %}{%- elif content is none or content is undefined %}{{- '' }}{%- else %}{{- raise_exception('Unexpected content type.') }}{%- endif %}{%- endmacro %}{%- if not messages %}{{- raise_exception('No messages provided.') }}{%- endif %}{%- set _first_role = messages[0].role %}{%- if _first_role == 'system' or _first_role == 'developer' %}{%- set _sys_msg = messages[0] %}{%- set _msgs = messages[1:] %}{%- else %}{%- set _sys_msg = none %}{%- set _msgs = messages %}{%- endif %}{%- set _sc = '' %}{%- if _sys_msg is not none %}{%- set _sc = render_content(_sys_msg.content, false, true) | trim %}{%- if '<|think_off|>' in _sc %}{%- set _sc = _sc.split('<|think_off|>') | join('') | trim %}{%- elif '<|think_on|>' in _sc %}{%- set _sc = _sc.split('<|think_on|>') | join('') | trim %}{%- endif %}{%- endif %} {%- set _terse %}
2
  Answer directly, after thinking. Lead with the answer, then only what it needs to be correct and usable.
3
  Never: open with preamble or pleasantries; restate the question; add filler transitions; hedge with niceties; or repeat a point you've already made.
4
  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.
5
  If a user request is genuinely ambiguous, ask a sharp question, don't guess.
6
- {%- endset %} {%- if not _sc %}{%- set _sc = _terse | trim %}{%- else %}{%- set _sc = (_sc | trim) ~ '\n\n' ~ (_terse | trim) %}{%- endif %}{%- if reasoning_effort is not defined %}{%- set reasoning_instructions = '' %}{%- endif %}{%- if _has_tools %}{{- '<|im_start|>system\n' }}{%- if reasoning_instructions %}{{- reasoning_instructions + '\n\n' }}{%- endif %}{{- '# Tools\n\nYou have access to the following functions:\n\n<tools>' }}{%- for tool in tools %}{{- '\n' }}{{- tool | tojson }}{%- endfor %}{{- '\n</tools>' }}{%- if _tool_format == 'json' %}{{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<think>\nBrief explanation of tool call\n</think>\n<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- 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- Function calls MUST follow the specified format: a single JSON object with "name" and "arguments" keys inside <tool_call></tool_call> XML tags.\n- If you choose to call a tool, you MUST output the <tool_call> block IMMEDIATELY after thinking, with NO conversational text before it.\n- 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>' }}{%- else %}{{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<think>\nBrief explanation of tool call\n</think>\n<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- 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- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags.\n- If you choose to call a tool, you MUST output the <tool_call> block IMMEDIATELY after thinking, with NO conversational text before it.\n- 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>' }}{%- endif %}{%- if _sc %}{{- '\n\n' + _sc }}{%- endif %}{{- '<|im_end|>\n' }}{%- else %}{%- if _sc %}{{- '<|im_start|>system\n' + (reasoning_instructions + '\n\n' if reasoning_instructions else '') + _sc + '<|im_end|>\n' }}{%- elif reasoning_instructions %}{{- '<|im_start|>system\n' + reasoning_instructions + '<|im_end|>\n' }}{%- endif %}{%- endif %}{%- set _last_idx = _msgs | length - 1 %}{%- set ns = namespace(multi_step_tool=true, last_query_index=_last_idx) %}{%- for message in _msgs[::-1] %}{%- set index = (_msgs | length - 1) - loop.index0 %}{%- if ns.multi_step_tool and message.role == 'user' %}{%- set _rc = render_content(message.content, false) | trim %}{%- if not (_rc.startswith('<tool_response>') and _rc.endswith('</tool_response>')) %}{%- set ns.multi_step_tool = false %}{%- set ns.last_query_index = index %}{%- endif %}{%- endif %}{%- endfor %}{%- if ns.multi_step_tool %}{%- if _last_idx > 50 %}{%- set ns.last_query_index = _last_idx %}{%- else %}{%- set ns.last_query_index = 0 %}{%- endif %}{%- endif %}{%- set ns2 = namespace(prev_role='', consecutive_failures=0) %}{%- for message in _msgs %}{%- set is_system = (message.role == "system" or message.role == "developer") %}{%- set content = render_content(message.content, true, is_system) | trim %}{%- if is_system or message.role == 'user' %}{%- if '<|think_off|>' in content %}{%- set content = content.split('<|think_off|>') | join('') | trim %}{%- elif '<|think_on|>' in content %}{%- set content = content.split('<|think_on|>') | join('') | trim %}{%- endif %}{%- endif %}{%- if is_system %}{{- '<|im_start|>system\n' + content + '<|im_end|>\n' }}{%- elif message.role == 'user' %}{%- set ns2.consecutive_failures = 0 %}{{- '<|im_start|>user\n' + content + '<|im_end|>\n' }}{%- elif message.role == 'assistant' %}{%- set reasoning_content = '' %}{%- if message.reasoning_content is defined and message.reasoning_content is not none %}{%- if message.reasoning_content is string %}{%- set reasoning_content = message.reasoning_content %}{%- else %}{%- set reasoning_content = message.reasoning_content | string %}{%- endif %}{%- elif message.thinking is defined and message.thinking is not none %}{%- if message.thinking is string %}{%- set reasoning_content = message.thinking %}{%- else %}{%- set reasoning_content = message.thinking | string %}{%- endif %}{%- else %}{%- set _think_end = '' %}{%- if content.startswith('</think>') %}{%- set _think_end = '</think>' %}{%- elif content.startswith('</thinking>') %}{%- set _think_end = '</thinking>' %}{%- elif '\n</think>' in content %}{%- set _think_end = '\n</think>' %}{%- elif '\n</thinking>' in content %}{%- set _think_end = '\n</thinking>' %}{%- elif '\n</ think>' in content %}{%- set _think_end = '\n</ think>' %}{%- elif '\n</think >' in content %}{%- set _think_end = '\n</think >' %}{%- endif %}{%- if _think_end %}{%- if 'thinking' in _think_end %}{%- set _think_start = '<thinking>' %}{%- else %}{%- set _think_start = '<think>' %}{%- endif %}{%- set reasoning_content = content.split(_think_end)[0].rstrip('\n') %}{%- if _think_start in reasoning_content %}{%- set reasoning_content = reasoning_content.split(_think_start)[-1].lstrip('\n') %}{%- endif %}{%- set content = content.split(_think_end)[-1].lstrip('\n') %}{%- endif %}{%- endif %}{%- set reasoning_content = reasoning_content | trim %}{%- if (_preserve_thinking or loop.index0 > ns.last_query_index) and reasoning_content %}{{- '<|im_start|>assistant\n<think>\n' + reasoning_content + '\n</think>\n\n' + content }}{%- else %}{{- '<|im_start|>assistant\n' + content }}{%- endif %}{%- if message.tool_calls is defined and message.tool_calls and message.tool_calls is iterable and message.tool_calls is not mapping %}{%- for tool_call in message.tool_calls %}{%- if tool_call.function is defined and tool_call.function is not none %}{%- set tc = tool_call.function %}{%- else %}{%- set tc = tool_call %}{%- endif %}{%- set tc_name = tc.name if (tc.name is defined and tc.name is not none) else '' %}{%- if _tool_format == 'json' %}{%- if not loop.first or content | trim %}{{- '\n\n' }}{%- endif %}{%- set _args = '{}' %}{%- if tc.arguments is defined and tc.arguments is not none %}{%- if tc.arguments is mapping %}{%- set _args = tc.arguments | tojson %}{%- elif tc.arguments is string and tc.arguments %}{%- set _args = tc.arguments %}{%- endif %}{%- endif %}{{- '<tool_call>\n{"name": ' }}{{- tc_name | tojson }}{{- ', "arguments": ' }}{{- _args }}{{- '}\n</tool_call>' }}{%- else %}{%- if loop.first %}{%- if content | trim %}{{- '\n\n<tool_call>\n<function=' + tc_name + '>\n' }}{%- else %}{{- '<tool_call>\n<function=' + tc_name + '>\n' }}{%- endif %}{%- else %}{{- '\n\n<tool_call>\n<function=' + tc_name + '>\n' }}{%- endif %}{%- if tc.arguments is defined and tc.arguments is not none %}{%- if tc.arguments is mapping %}{%- for args_name, args_value in tc.arguments.items() %}{{- '<parameter=' + args_name + '>\n' }}{%- if args_value is mapping or (args_value is sequence and args_value is not string) %}{%- set _av = args_value | tojson %}{%- else %}{%- set _av = args_value | string %}{%- endif %}{%- if max_tool_arg_chars > 0 and _av | length > max_tool_arg_chars %}{{- _av[:max_tool_arg_chars] + '\n[TRUNCATED — original length ' ~ (_av | length | string) ~ ' chars]' }}{%- else %}{{- _av }}{%- endif %}{{- '\n</parameter>\n' }}{%- endfor %}{%- elif tc.arguments is string and tc.arguments %}{{- tc.arguments }}{%- endif %}{%- endif %}{{- '</function>\n</tool_call>' }}{%- endif %}{%- endfor %}{%- endif %}{{- '<|im_end|>\n' }}{%- elif message.role == 'tool' %}{%- set _content_lower = content | lower %}{%- set _content_head = _content_lower[:80] %}{%- if content | length < 500 and '$ ' not in content and 'took ' not in _content_lower and ('"error":' in _content_head or 'error:' in _content_head or 'err!' in _content_head or 'fatal:' in _content_head or 'exception:' in _content_head or 'traceback' in _content_head or 'command not found' in _content_head or 'invalid syntax' in _content_head or 'failed to' in _content_head) %}{%- set ns2.consecutive_failures = ns2.consecutive_failures + 1 %}{%- else %}{%- set ns2.consecutive_failures = 0 %}{%- endif %}{%- if ns2.prev_role != 'tool' %}{{- '<|im_start|>user' }}{%- endif %}{%- if max_tool_response_chars > 0 and content | length > max_tool_response_chars %}{%- set content = content[:max_tool_response_chars] + '\n[TRUNCATED — original length ' ~ (content | length | string) ~ ' chars]' %}{%- endif %}{{- '\n<tool_response>\n' + content }}{%- if ns2.consecutive_failures >= 2 %}{{- '\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.' }}{%- elif ns2.consecutive_failures == 1 %}{{- '\n\n⚠️ SYSTEM WARNING: The previous tool call returned an error. Diagnose the failure and retry with completely corrected arguments.' }}{%- endif %}{{- '\n</tool_response>' }}{%- if loop.last %}{{- '<|im_end|>\n' }}{%- else %}{%- set _next_role = _msgs[loop.index0 + 1].role %}{%- if _next_role != 'tool' %}{{- '<|im_end|>\n' }}{%- endif %}{%- endif %}{%- else %}{{- '<|im_start|>user\n[' + message.role + ']: ' + content + '<|im_end|>\n' }}{%- endif %}{%- set ns2.prev_role = message.role %}{%- endfor %}{%- if add_generation_prompt %}{{- '<|im_start|>assistant\n' }}{%- if not ns_state.thinking %}{{- '<think>\n\n</think>\n\n' }}{%- else %}{{- '<think>\n' }}{%- endif %}{%- endif %}
 
1
+ {%- set template_version = "qwen3.8-froggeric-v22.1" %}{%- set _tool_format = tool_call_format if tool_call_format is defined else 'xml' %}{%- set image_count = namespace(value=0) %}{%- set video_count = namespace(value=0) %}{%- set add_vision_id = add_vision_id if add_vision_id is defined else false %}{%- set enable_thinking = enable_thinking if enable_thinking is defined else true %}{%- set auto_disable_thinking_with_tools = auto_disable_thinking_with_tools if auto_disable_thinking_with_tools is defined else false %}{%- if preserve_reasoning is defined and preserve_reasoning is not none %}{%- set _preserve_thinking = preserve_reasoning %}{%- elif preserve_thinking is defined and preserve_thinking is not none %}{%- set _preserve_thinking = preserve_thinking %}{%- else %}{%- set _preserve_thinking = true %}{%- endif %}{%- set max_tool_arg_chars = max_tool_arg_chars if max_tool_arg_chars is defined else 0 %}{%- set max_tool_response_chars = max_tool_response_chars if max_tool_response_chars is defined else 0 %}{%- set _has_tools = (tools is defined and tools and tools is iterable and tools is not mapping) %}{%- set _effort_raw = (reasoning_effort | string | lower) if reasoning_effort is defined and reasoning_effort is not none else 'medium' %}{%- set _initial_thinking = enable_thinking %}{%- set _initial_effort = 'medium' %}{%- if _effort_raw == 'none' %}{%- set _initial_thinking = false %}{%- set _initial_effort = 'medium' %}{%- elif _effort_raw == 'minimal' or _effort_raw == 'low' %}{%- set _initial_effort = 'low' %}{%- elif _effort_raw == 'high' or _effort_raw == 'xhigh' or _effort_raw == 'max' %}{%- set _initial_effort = 'xhigh' %}{%- else %}{%- set _initial_effort = 'medium' %}{%- endif %}{%- set ns_state = namespace(thinking=_initial_thinking, effort=_initial_effort) %}{%- if auto_disable_thinking_with_tools and _has_tools %}{%- set ns_state.thinking = false %}{%- endif %}{%- for msg in messages %}{%- if msg.role == 'system' or msg.role == 'developer' or msg.role == 'user' %}{%- if msg.content is string %}{%- if '<|think_off|>' in msg.content %}{%- set ns_state.thinking = false %}{%- elif '<|think_on|>' in msg.content %}{%- set ns_state.thinking = true %}{%- elif '<|think_xhigh|>' in msg.content or '<|think_high|>' in msg.content %}{%- set ns_state.thinking = true %}{%- set ns_state.effort = 'xhigh' %}{%- elif '<|think_low|>' in msg.content or '<|think_minimal|>' in msg.content %}{%- set ns_state.thinking = true %}{%- set ns_state.effort = 'low' %}{%- elif '<|think_medium|>' in msg.content %}{%- set ns_state.thinking = true %}{%- set ns_state.effort = 'medium' %}{%- endif %}{%- elif msg.content is iterable and msg.content is not mapping %}{%- for item in msg.content %}{%- if item is string %}{%- set _item_text = item %}{%- elif item is mapping and 'text' in item and item.text is string %}{%- set _item_text = item.text %}{%- else %}{%- set _item_text = '' %}{%- endif %}{%- if _item_text %}{%- if '<|think_off|>' in _item_text %}{%- set ns_state.thinking = false %}{%- elif '<|think_on|>' in _item_text %}{%- set ns_state.thinking = true %}{%- elif '<|think_xhigh|>' in _item_text or '<|think_high|>' in _item_text %}{%- set ns_state.thinking = true %}{%- set ns_state.effort = 'xhigh' %}{%- elif '<|think_low|>' in _item_text or '<|think_minimal|>' in _item_text %}{%- set ns_state.thinking = true %}{%- set ns_state.effort = 'low' %}{%- elif '<|think_medium|>' in _item_text %}{%- set ns_state.thinking = true %}{%- set ns_state.effort = 'medium' %}{%- endif %}{%- endif %}{%- endfor %}{%- endif %}{%- endif %}{%- endfor %}{%- set reasoning_instructions = '' %}{%- if ns_state.thinking %}{%- if ns_state.effort == 'xhigh' %}{%- 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.' %}{%- elif ns_state.effort == 'low' %}{%- set reasoning_instructions = 'Reasoning effort is set to low. Keep your thinking brief and focused, moving directly to the conclusion without unnecessary elaboration.' %}{%- endif %}{%- endif %}{%- macro render_content(content, do_vision_count, is_system_content=false) %}{%- if content is string %}{{- content }}{%- elif content is iterable and content is not mapping %}{%- for item in content %}{%- if item is mapping %}{%- if item.type == 'image' or 'image' in item or 'image_url' in item %}{%- if is_system_content %}{{- raise_exception('System message cannot contain images.') }}{%- endif %}{%- if do_vision_count %}{%- set image_count.value = image_count.value + 1 %}{%- endif %}{%- if add_vision_id %}{{- 'Picture ' ~ image_count.value ~ ': ' }}{%- endif %}{{- '<|vision_start|><|image_pad|><|vision_end|>' }}{%- elif item.type == 'video' or 'video' in item %}{%- if is_system_content %}{{- raise_exception('System message cannot contain videos.') }}{%- endif %}{%- if do_vision_count %}{%- set video_count.value = video_count.value + 1 %}{%- endif %}{%- if add_vision_id %}{{- 'Video ' ~ video_count.value ~ ': ' }}{%- endif %}{{- '<|vision_start|><|video_pad|><|vision_end|>' }}{%- elif 'text' in item %}{{- item.text }}{%- else %}{{- raise_exception('Unexpected item type in content.') }}{%- endif %}{%- else %}{{- item | string }}{%- endif %}{%- endfor %}{%- elif content is none or content is undefined %}{{- '' }}{%- else %}{{- raise_exception('Unexpected content type.') }}{%- endif %}{%- endmacro %}{%- if not messages %}{{- raise_exception('No messages provided.') }}{%- endif %}{%- set _first_role = messages[0].role %}{%- if _first_role == 'system' or _first_role == 'developer' %}{%- set _sys_msg = messages[0] %}{%- set _msgs = messages[1:] %}{%- else %}{%- set _sys_msg = none %}{%- set _msgs = messages %}{%- endif %}{%- set _sc = '' %}{%- if _sys_msg is not none %}{%- set _sc = render_content(_sys_msg.content, false, true) | trim %}{%- if '<|think_off|>' in _sc %}{%- set _sc = _sc.split('<|think_off|>') | join('') | trim %}{%- endif %}{%- if '<|think_on|>' in _sc %}{%- set _sc = _sc.split('<|think_on|>') | join('') | trim %}{%- endif %}{%- if '<|think_xhigh|>' in _sc %}{%- set _sc = _sc.split('<|think_xhigh|>') | join('') | trim %}{%- endif %}{%- if '<|think_high|>' in _sc %}{%- set _sc = _sc.split('<|think_high|>') | join('') | trim %}{%- endif %}{%- if '<|think_medium|>' in _sc %}{%- set _sc = _sc.split('<|think_medium|>') | join('') | trim %}{%- endif %}{%- if '<|think_low|>' in _sc %}{%- set _sc = _sc.split('<|think_low|>') | join('') | trim %}{%- endif %}{%- if '<|think_minimal|>' in _sc %}{%- set _sc = _sc.split('<|think_minimal|>') | join('') | trim %}{%- endif %}{%- endif %} {%- set _terse %}
2
  Answer directly, after thinking. Lead with the answer, then only what it needs to be correct and usable.
3
  Never: open with preamble or pleasantries; restate the question; add filler transitions; hedge with niceties; or repeat a point you've already made.
4
  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.
5
  If a user request is genuinely ambiguous, ask a sharp question, don't guess.
6
+ {%- endset %} {%- if not _sc %}{%- set _sc = _terse | trim %}{%- else %}{%- set _sc = (_sc | trim) ~ '\n\n' ~ (_terse | trim) %}{%- endif %}{%- if _has_tools %}{{- '<|im_start|>system\n' }}{%- if reasoning_instructions %}{{- reasoning_instructions + '\n\n' }}{%- endif %}{{- '# Tools\n\nYou have access to the following functions:\n\n<tools>' }}{%- for tool in tools %}{{- '\n' }}{{- tool | tojson }}{%- endfor %}{{- '\n</tools>' }}{%- if _tool_format == 'json' %}{{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<think>\nBrief explanation of tool call\n</think>\n<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- 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- Function calls MUST follow the specified format: a single JSON object with "name" and "arguments" keys inside <tool_call></tool_call> XML tags.\n- If you choose to call a tool, you MUST output the <tool_call> block IMMEDIATELY after thinking, with NO conversational text before it.\n- 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>' }}{%- else %}{{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<think>\nBrief explanation of tool call\n</think>\n<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- 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- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags.\n- If you choose to call a tool, you MUST output the <tool_call> block IMMEDIATELY after thinking, with NO conversational text before it.\n- 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>' }}{%- endif %}{%- if _sc %}{{- '\n\n' + _sc }}{%- endif %}{{- '<|im_end|>\n' }}{%- else %}{%- if _sc %}{{- '<|im_start|>system\n' + (reasoning_instructions + '\n\n' if reasoning_instructions else '') + _sc + '<|im_end|>\n' }}{%- elif reasoning_instructions %}{{- '<|im_start|>system\n' + reasoning_instructions + '<|im_end|>\n' }}{%- endif %}{%- endif %}{%- set _last_idx = _msgs | length - 1 %}{%- set ns = namespace(multi_step_tool=true, last_query_index=_last_idx) %}{%- for message in _msgs[::-1] %}{%- set index = (_msgs | length - 1) - loop.index0 %}{%- if ns.multi_step_tool and message.role == 'user' %}{%- set _rc = render_content(message.content, false) | trim %}{%- if not (_rc.startswith('<tool_response>') and _rc.endswith('</tool_response>')) %}{%- set ns.multi_step_tool = false %}{%- set ns.last_query_index = index %}{%- endif %}{%- endif %}{%- endfor %}{%- if ns.multi_step_tool %}{%- if _last_idx > 50 %}{%- set ns.last_query_index = _last_idx %}{%- else %}{%- set ns.last_query_index = 0 %}{%- endif %}{%- endif %}{%- set ns2 = namespace(prev_role='', consecutive_failures=0) %}{%- for message in _msgs %}{%- set is_system = (message.role == "system" or message.role == "developer") %}{%- set content = render_content(message.content, true, is_system) | trim %}{%- if is_system or message.role == 'user' %}{%- if '<|think_off|>' in content %}{%- set content = content.split('<|think_off|>') | join('') | trim %}{%- endif %}{%- if '<|think_on|>' in content %}{%- set content = content.split('<|think_on|>') | join('') | trim %}{%- endif %}{%- if '<|think_xhigh|>' in content %}{%- set content = content.split('<|think_xhigh|>') | join('') | trim %}{%- endif %}{%- if '<|think_high|>' in content %}{%- set content = content.split('<|think_high|>') | join('') | trim %}{%- endif %}{%- if '<|think_medium|>' in content %}{%- set content = content.split('<|think_medium|>') | join('') | trim %}{%- endif %}{%- if '<|think_low|>' in content %}{%- set content = content.split('<|think_low|>') | join('') | trim %}{%- endif %}{%- if '<|think_minimal|>' in content %}{%- set content = content.split('<|think_minimal|>') | join('') | trim %}{%- endif %}{%- endif %}{%- if is_system %}{{- '<|im_start|>system\n' + content + '<|im_end|>\n' }}{%- elif message.role == 'user' %}{%- set ns2.consecutive_failures = 0 %}{{- '<|im_start|>user\n' + content + '<|im_end|>\n' }}{%- elif message.role == 'assistant' %}{%- set reasoning_content = '' %}{%- if message.reasoning_content is defined and message.reasoning_content is not none %}{%- if message.reasoning_content is string %}{%- set reasoning_content = message.reasoning_content %}{%- else %}{%- set reasoning_content = message.reasoning_content | string %}{%- endif %}{%- elif message.thinking is defined and message.thinking is not none %}{%- if message.thinking is string %}{%- set reasoning_content = message.thinking %}{%- else %}{%- set reasoning_content = message.thinking | string %}{%- endif %}{%- else %}{%- set _think_end = '' %}{%- if content.startswith('</think>') %}{%- set _think_end = '</think>' %}{%- elif content.startswith('</thinking>') %}{%- set _think_end = '</thinking>' %}{%- elif '\n</think>' in content %}{%- set _think_end = '\n</think>' %}{%- elif '\n</thinking>' in content %}{%- set _think_end = '\n</thinking>' %}{%- elif '\n</ think>' in content %}{%- set _think_end = '\n</ think>' %}{%- elif '\n</think >' in content %}{%- set _think_end = '\n</think >' %}{%- endif %}{%- if _think_end %}{%- if 'thinking' in _think_end %}{%- set _think_start = '<thinking>' %}{%- else %}{%- set _think_start = '<think>' %}{%- endif %}{%- set reasoning_content = content.split(_think_end)[0].rstrip('\n') %}{%- if _think_start in reasoning_content %}{%- set reasoning_content = reasoning_content.split(_think_start)[-1].lstrip('\n') %}{%- endif %}{%- set content = content.split(_think_end)[-1].lstrip('\n') %}{%- endif %}{%- endif %}{%- set reasoning_content = reasoning_content | trim %}{%- if (_preserve_thinking or loop.index0 > ns.last_query_index) and reasoning_content %}{{- '<|im_start|>assistant\n<think>\n' + reasoning_content + '\n</think>\n\n' + content }}{%- else %}{{- '<|im_start|>assistant\n' + content }}{%- endif %}{%- if message.tool_calls is defined and message.tool_calls and message.tool_calls is iterable and message.tool_calls is not mapping %}{%- for tool_call in message.tool_calls %}{%- if tool_call.function is defined and tool_call.function is not none %}{%- set tc = tool_call.function %}{%- else %}{%- set tc = tool_call %}{%- endif %}{%- set tc_name = tc.name if (tc.name is defined and tc.name is not none) else '' %}{%- if _tool_format == 'json' %}{%- if not loop.first or content | trim %}{{- '\n\n' }}{%- endif %}{%- set _args = '{}' %}{%- if tc.arguments is defined and tc.arguments is not none %}{%- if tc.arguments is mapping %}{%- set _args = tc.arguments | tojson %}{%- elif tc.arguments is string and tc.arguments %}{%- set _args = tc.arguments %}{%- endif %}{%- endif %}{{- '<tool_call>\n{"name": ' }}{{- tc_name | tojson }}{{- ', "arguments": ' }}{{- _args }}{{- '}\n</tool_call>' }}{%- else %}{%- if loop.first %}{%- if content | trim %}{{- '\n\n<tool_call>\n<function=' + tc_name + '>\n' }}{%- else %}{{- '<tool_call>\n<function=' + tc_name + '>\n' }}{%- endif %}{%- else %}{{- '\n\n<tool_call>\n<function=' + tc_name + '>\n' }}{%- endif %}{%- if tc.arguments is defined and tc.arguments is not none %}{%- if tc.arguments is mapping %}{%- for args_name, args_value in tc.arguments.items() %}{{- '<parameter=' + args_name + '>\n' }}{%- if args_value is mapping or (args_value is sequence and args_value is not string) %}{%- set _av = args_value | tojson %}{%- else %}{%- set _av = args_value | string %}{%- endif %}{%- if max_tool_arg_chars > 0 and _av | length > max_tool_arg_chars %}{{- _av[:max_tool_arg_chars] + '\n[TRUNCATED - original length ' ~ (_av | length | string) ~ ' chars]' }}{%- else %}{{- _av }}{%- endif %}{{- '\n</parameter>\n' }}{%- endfor %}{%- elif tc.arguments is string and tc.arguments %}{{- tc.arguments }}{%- endif %}{%- endif %}{{- '</function>\n</tool_call>' }}{%- endif %}{%- endfor %}{%- endif %}{{- '<|im_end|>\n' }}{%- elif message.role == 'tool' %}{%- set _content_lower = content | lower %}{%- set _content_head = _content_lower[:80] %}{%- if content | length < 500 and '$ ' not in content and 'took ' not in _content_lower and ('"error":' in _content_head or 'error:' in _content_head or 'err!' in _content_head or 'fatal:' in _content_head or 'exception:' in _content_head or 'traceback' in _content_head or 'command not found' in _content_head or 'invalid syntax' in _content_head or 'failed to' in _content_head) %}{%- set ns2.consecutive_failures = ns2.consecutive_failures + 1 %}{%- else %}{%- set ns2.consecutive_failures = 0 %}{%- endif %}{%- if ns2.prev_role != 'tool' %}{{- '<|im_start|>user' }}{%- endif %}{%- if max_tool_response_chars > 0 and content | length > max_tool_response_chars %}{%- set content = content[:max_tool_response_chars] + '\n[TRUNCATED - original length ' ~ (content | length | string) ~ ' chars]' %}{%- endif %}{{- '\n<tool_response>\n' + content }}{%- if ns2.consecutive_failures >= 2 %}{{- '\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.' }}{%- elif ns2.consecutive_failures == 1 %}{{- '\n\n⚠️ SYSTEM WARNING: The previous tool call returned an error. Diagnose the failure and retry with completely corrected arguments.' }}{%- endif %}{{- '\n</tool_response>' }}{%- if loop.last %}{{- '<|im_end|>\n' }}{%- else %}{%- set _next_role = _msgs[loop.index0 + 1].role %}{%- if _next_role != 'tool' %}{{- '<|im_end|>\n' }}{%- endif %}{%- endif %}{%- else %}{{- '<|im_start|>user\n[' + message.role + ']: ' + content + '<|im_end|>\n' }}{%- endif %}{%- set ns2.prev_role = message.role %}{%- endfor %}{%- if add_generation_prompt %}{{- '<|im_start|>assistant\n' }}{%- if not ns_state.thinking %}{{- '<think>\n\n</think>\n\n' }}{%- else %}{{- '<think>\n' }}{%- endif %}{%- endif %}
scripts/verify_template.py CHANGED
@@ -3,9 +3,9 @@
3
 
4
  python3 scripts/verify_template.py
5
 
6
- Run this before publishing, and after any edit to chat_template.jinja. It fetches upstream
7
- v21.3 fresh, so it also catches the case where froggeric ships a new version and our splice
8
- silently sits on top of a template we haven't looked at.
9
 
10
  The checks exist because each of them has a real failure mode:
11
  * diff-vs-upstream -- guards against accidentally shipping edits we didn't intend to make
@@ -46,14 +46,14 @@ def main() -> int:
46
  full = (HERE / "chat_template.jinja").read_text()
47
  mini = (HERE / "chat_template_oneline.txt").read_text()
48
 
49
- print("=== diff vs upstream v22")
50
  with urllib.request.urlopen(UPSTREAM, timeout=60) as r:
51
  up = r.read().decode()
52
  diff = [l for l in difflib.unified_diff(up.splitlines(), full.splitlines(), lineterm="")
53
  if l.startswith(("+", "-")) and not l.startswith(("+++", "---"))]
54
  check(all(l.startswith("+") for l in diff), "only insertions, no upstream lines changed")
55
- check(len(diff) == 14, f"exactly 14 inserted lines (got {len(diff)})")
56
- check('template_version = "qwen3.8-froggeric-v22"' in full, "upstream version is v22")
57
  check("Nail" not in full and "Dagger" not in full, "no model-specific identity in template")
58
 
59
  print("\n=== rendering")
@@ -73,14 +73,15 @@ def main() -> int:
73
  check("<think>t</think>" in render(full, cases["multi-turn w/ think"]),
74
  "prior thinking is retained across turns")
75
 
76
- # v22 defaults reasoning_effort to xhigh and injects a steering line; our splice suppresses that
77
- # default so out-of-the-box behavior matches tuned v1 (terseness-only) -- but an EXPLICIT effort
78
- # is still honored, so froggeric's feature survives as opt-in.
 
79
  STEER = "Reasoning effort is set to"
80
  check(STEER not in render(full, cases["no system prompt"]),
81
- "default (no reasoning_effort): xhigh steering is suppressed")
82
  check(STEER not in render(full, cases["with system prompt"]),
83
- "default with system prompt: steering still suppressed")
84
  check("Reasoning effort is set to low" in render(full, cases["no system prompt"],
85
  reasoning_effort="low"), "explicit reasoning_effort=low is still honored (opt-in)")
86
  check(MARKER in render(full, cases["no system prompt"], reasoning_effort="low"),
@@ -96,8 +97,8 @@ def main() -> int:
96
  check(render(full, msgs) == render(mini, msgs), f"{name}: oneline == full")
97
  sysblk = render(mini, cases["no system prompt"]).split("<|im_start|>system")[1] \
98
  .split("<|im_end|>")[0].strip()
99
- # v22 prepends reasoning-effort steering to the system block, so isolate the terseness tail
100
- # (it starts with "Answer directly,") and confirm ITS newlines survived minification as 4 lines.
101
  terse = "Answer directly," + sysblk.split("Answer directly,", 1)[1]
102
  check(len(terse.splitlines()) == 4, "terseness survives minification as 4 lines")
103
 
 
3
 
4
  python3 scripts/verify_template.py
5
 
6
+ Run this before publishing, and after any edit to chat_template.jinja. It fetches current
7
+ upstream (v22.1) fresh, so it also catches the case where froggeric ships a new version and our
8
+ splice silently sits on top of a template we haven't looked at.
9
 
10
  The checks exist because each of them has a real failure mode:
11
  * diff-vs-upstream -- guards against accidentally shipping edits we didn't intend to make
 
46
  full = (HERE / "chat_template.jinja").read_text()
47
  mini = (HERE / "chat_template_oneline.txt").read_text()
48
 
49
+ print("=== diff vs upstream v22.1")
50
  with urllib.request.urlopen(UPSTREAM, timeout=60) as r:
51
  up = r.read().decode()
52
  diff = [l for l in difflib.unified_diff(up.splitlines(), full.splitlines(), lineterm="")
53
  if l.startswith(("+", "-")) and not l.startswith(("+++", "---"))]
54
  check(all(l.startswith("+") for l in diff), "only insertions, no upstream lines changed")
55
+ check(len(diff) == 11, f"exactly 11 inserted lines (got {len(diff)})")
56
+ check('template_version = "qwen3.8-froggeric-v22.1"' in full, "upstream version is v22.1")
57
  check("Nail" not in full and "Dagger" not in full, "no model-specific identity in template")
58
 
59
  print("\n=== rendering")
 
73
  check("<think>t</think>" in render(full, cases["multi-turn w/ think"]),
74
  "prior thinking is retained across turns")
75
 
76
+ # v22.1 defaults reasoning_effort to MEDIUM, which injects no steering line -- so out-of-the-box
77
+ # behavior is terseness-only with no forced effort, matching tuned v1, WITHOUT us suppressing
78
+ # anything (upstream fixed the old forced-xhigh default). An EXPLICIT effort still injects steering,
79
+ # so froggeric's feature is honored as opt-in.
80
  STEER = "Reasoning effort is set to"
81
  check(STEER not in render(full, cases["no system prompt"]),
82
+ "default (no reasoning_effort): no steering line (upstream medium default)")
83
  check(STEER not in render(full, cases["with system prompt"]),
84
+ "default with system prompt: still no steering line")
85
  check("Reasoning effort is set to low" in render(full, cases["no system prompt"],
86
  reasoning_effort="low"), "explicit reasoning_effort=low is still honored (opt-in)")
87
  check(MARKER in render(full, cases["no system prompt"], reasoning_effort="low"),
 
97
  check(render(full, msgs) == render(mini, msgs), f"{name}: oneline == full")
98
  sysblk = render(mini, cases["no system prompt"]).split("<|im_start|>system")[1] \
99
  .split("<|im_end|>")[0].strip()
100
+ # the terseness tail starts with "Answer directly," (at medium default no steering precedes it);
101
+ # isolate it and confirm ITS newlines survived minification as 4 lines.
102
  terse = "Answer directly," + sysblk.split("Answer directly,", 1)[1]
103
  check(len(terse.splitlines()) == 4, "terseness survives minification as 4 lines")
104