darkc0de commited on
Commit
c12e388
·
verified ·
1 Parent(s): 50a37d3

(Trained with Unsloth)

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ tokenizer.json filter=lfs diff=lfs merge=lfs -text
chat_template.jinja ADDED
@@ -0,0 +1,598 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- set template_version = "qwen3.8-safe-v3.1" %}
2
+ {#- -------------------------------------------------------------------------
3
+ Whitespace contract: every tag opener in this file carries a leading minus,
4
+ so it strips the whitespace and newlines that precede it. All emitted text
5
+ comes from string literals, which makes the rendered prompt byte-exact and
6
+ free of incidental newlines. Comment tags need the minus just as much as
7
+ block tags do; a plain comment tag breaks the strip chain and leaks the
8
+ surrounding indentation into the prompt.
9
+ ------------------------------------------------------------------------- -#}
10
+ {#- The message list has to exist before anything else can inspect it. -#}
11
+ {%- if not messages %}
12
+ {{- raise_exception('No messages provided.') }}
13
+ {%- endif %}
14
+ {#- -------------------------------------------------------------------------
15
+ Configuration
16
+ ------------------------------------------------------------------------- -#}
17
+ {%- set _requested_tool_format =
18
+ tool_call_format if tool_call_format is defined else 'xml'
19
+ %}
20
+ {%- if _requested_tool_format not in ('auto', 'xml', 'json') %}
21
+ {{- raise_exception(
22
+ 'Unexpected tool_call_format ' ~ _requested_tool_format ~
23
+ '. Supported values are xml (default), auto, and json.'
24
+ ) }}
25
+ {%- endif %}
26
+ {%- set add_vision_id = add_vision_id if add_vision_id is defined else false %}
27
+ {%- set enable_thinking = enable_thinking if enable_thinking is defined else true %}
28
+ {%- set auto_disable_thinking_with_tools =
29
+ auto_disable_thinking_with_tools
30
+ if auto_disable_thinking_with_tools is defined
31
+ else false
32
+ %}
33
+ {%- if preserve_reasoning is defined
34
+ and preserve_reasoning is not none
35
+ and preserve_thinking is defined
36
+ and preserve_thinking is not none
37
+ and preserve_reasoning != preserve_thinking %}
38
+ {{- raise_exception(
39
+ 'preserve_reasoning and preserve_thinking were both provided with conflicting values.'
40
+ ) }}
41
+ {%- endif %}
42
+ {%- if preserve_reasoning is defined and preserve_reasoning is not none %}
43
+ {%- set _preserve_thinking = preserve_reasoning %}
44
+ {%- elif preserve_thinking is defined and preserve_thinking is not none %}
45
+ {%- set _preserve_thinking = preserve_thinking %}
46
+ {%- else %}
47
+ {%- set _preserve_thinking = true %}
48
+ {%- endif %}
49
+ {%- set max_tool_arg_chars =
50
+ max_tool_arg_chars if max_tool_arg_chars is defined else 0
51
+ %}
52
+ {%- set max_tool_response_chars =
53
+ max_tool_response_chars if max_tool_response_chars is defined else 0
54
+ %}
55
+ {%- if max_tool_arg_chars is not number or max_tool_arg_chars < 0 %}
56
+ {{- raise_exception('max_tool_arg_chars must be a non-negative number.') }}
57
+ {%- endif %}
58
+ {%- if max_tool_response_chars is not number or max_tool_response_chars < 0 %}
59
+ {{- raise_exception('max_tool_response_chars must be a non-negative number.') }}
60
+ {%- endif %}
61
+ {%- if tools is defined and tools is not none and tools %}
62
+ {%- if tools is string or tools is mapping or tools is not iterable %}
63
+ {{- raise_exception('tools must be an iterable list of tool definitions.') }}
64
+ {%- endif %}
65
+ {%- set _has_tools = true %}
66
+ {%- else %}
67
+ {%- set _has_tools = false %}
68
+ {%- endif %}
69
+ {#- -------------------------------------------------------------------------
70
+ Resolve the tool-call wire format.
71
+
72
+ OpenAI-compatible servers hand assistant tool calls back with
73
+ `function.arguments` as a JSON *string*, not a mapping. The XML parameter
74
+ form needs the individual key/value pairs, and a chat template cannot
75
+ decode a JSON string: the standard chat-template environment provides
76
+ `tojson` but no inverse, and no codepoint-to-character primitive, so a
77
+ hand-rolled scanner could not decode \uXXXX escapes correctly. Guessing
78
+ would silently corrupt tool arguments, which is worse than any error.
79
+
80
+ The deployment-safe default is XML, matching Qwen's native tool-call wire
81
+ format and the qwen3_coder tool parser. A caller can explicitly request
82
+ tool_call_format='auto' to render the whole prompt in JSON form whenever a
83
+ historical tool call carries string arguments. That path is lossless,
84
+ needs no decoding, and keeps the system-prompt instructions and rendered
85
+ history in one consistent format. Histories whose arguments are all
86
+ mappings still render as XML, byte-identically to tool_call_format='xml'.
87
+
88
+ A caller that uses the default XML mode (or explicitly pins 'xml') still
89
+ gets a hard error for non-empty string arguments, because that request
90
+ cannot be honoured faithfully in the native XML parameter representation.
91
+ ------------------------------------------------------------------------- -#}
92
+ {%- set format_scan = namespace(has_json_string_arguments=false) %}
93
+ {%- for message in messages %}
94
+ {%- if message.role == 'assistant'
95
+ and message.tool_calls is defined
96
+ and message.tool_calls is not none
97
+ and message.tool_calls
98
+ and message.tool_calls is not string
99
+ and message.tool_calls is not mapping
100
+ and message.tool_calls is iterable %}
101
+ {%- for tool_call in message.tool_calls %}
102
+ {%- if tool_call.function is defined
103
+ and tool_call.function is not none %}
104
+ {%- set _tc = tool_call.function %}
105
+ {%- else %}
106
+ {%- set _tc = tool_call %}
107
+ {%- endif %}
108
+ {%- if _tc.arguments is defined
109
+ and _tc.arguments is not none
110
+ and _tc.arguments is string
111
+ and _tc.arguments | trim
112
+ and _tc.arguments | trim != '{}' %}
113
+ {%- set format_scan.has_json_string_arguments = true %}
114
+ {%- endif %}
115
+ {%- endfor %}
116
+ {%- endif %}
117
+ {%- endfor %}
118
+ {%- if _requested_tool_format == 'auto' %}
119
+ {%- if format_scan.has_json_string_arguments %}
120
+ {%- set _tool_format = 'json' %}
121
+ {%- else %}
122
+ {%- set _tool_format = 'xml' %}
123
+ {%- endif %}
124
+ {%- else %}
125
+ {%- set _tool_format = _requested_tool_format %}
126
+ {%- endif %}
127
+ {%- set _thinking_enabled = enable_thinking %}
128
+ {%- if auto_disable_thinking_with_tools and _has_tools %}
129
+ {%- set _thinking_enabled = false %}
130
+ {%- endif %}
131
+ {#- Normalize and validate reasoning effort even when thinking is disabled.
132
+ Explicit null follows the template default; OpenAI-style `minimal` maps to
133
+ low, while `none` disables thinking for this render. -#}
134
+ {%- if reasoning_effort is undefined or reasoning_effort is none %}
135
+ {%- set _effort_raw = 'medium' %}
136
+ {%- else %}
137
+ {%- set _effort_raw = reasoning_effort %}
138
+ {%- endif %}
139
+ {%- if _effort_raw == 'none' %}
140
+ {%- set _thinking_enabled = false %}
141
+ {%- set _reasoning_effort = 'xhigh' %}
142
+ {%- elif _effort_raw == 'high' or _effort_raw == 'xhigh' %}
143
+ {%- set _reasoning_effort = 'xhigh' %}
144
+ {%- elif _effort_raw == 'medium' %}
145
+ {%- set _reasoning_effort = 'medium' %}
146
+ {%- elif _effort_raw == 'minimal' or _effort_raw == 'low' %}
147
+ {%- set _reasoning_effort = 'low' %}
148
+ {%- else %}
149
+ {{- raise_exception(
150
+ 'Unexpected reasoning effort ' ~ _effort_raw ~
151
+ '. Supported values are none, minimal/low, medium, and high/xhigh; null uses the medium default.'
152
+ ) }}
153
+ {%- endif %}
154
+ {%- set reasoning_instructions = '' %}
155
+ {%- if _thinking_enabled %}
156
+ {%- if _reasoning_effort == 'xhigh' %}
157
+ {%- set reasoning_instructions =
158
+ '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.'
159
+ %}
160
+ {%- elif _reasoning_effort == 'low' %}
161
+ {%- set reasoning_instructions =
162
+ 'Reasoning effort is set to low. Keep your thinking brief and focused, moving directly to the conclusion without unnecessary elaboration.'
163
+ %}
164
+ {%- endif %}
165
+ {%- endif %}
166
+ {#- -------------------------------------------------------------------------
167
+ Content rendering
168
+ ------------------------------------------------------------------------- -#}
169
+ {%- set image_count = namespace(value=0) %}
170
+ {%- set video_count = namespace(value=0) %}
171
+ {%- macro render_content(content, do_vision_count, is_system_content=false) %}
172
+ {%- if content is string %}
173
+ {{- content }}
174
+ {%- elif content is iterable and content is not mapping %}
175
+ {%- for item in content %}
176
+ {%- if item is not mapping %}
177
+ {{- raise_exception(
178
+ 'Content-list items must be mappings with a supported text, image, or video type.'
179
+ ) }}
180
+ {%- endif %}
181
+ {%- set _item_type = item.type if 'type' in item else none %}
182
+ {%- if _item_type is not none
183
+ and _item_type not in ('text', 'image', 'image_url', 'video') %}
184
+ {{- raise_exception(
185
+ 'Unexpected content item type ' ~ _item_type ~ '.'
186
+ ) }}
187
+ {%- endif %}
188
+ {%- set _is_image =
189
+ _item_type == 'image'
190
+ or _item_type == 'image_url'
191
+ or 'image' in item
192
+ or 'image_url' in item
193
+ %}
194
+ {%- set _is_video =
195
+ _item_type == 'video'
196
+ or 'video' in item
197
+ %}
198
+ {%- if _is_image and _is_video %}
199
+ {{- raise_exception(
200
+ 'A content item cannot contain both image and video data.'
201
+ ) }}
202
+ {%- elif _item_type == 'text' and (_is_image or _is_video) %}
203
+ {{- raise_exception(
204
+ 'A text content item cannot also contain image or video data.'
205
+ ) }}
206
+ {%- elif _is_image %}
207
+ {%- if is_system_content %}
208
+ {{- raise_exception(
209
+ 'System and developer messages cannot contain images.'
210
+ ) }}
211
+ {%- endif %}
212
+ {%- if do_vision_count %}
213
+ {%- set image_count.value = image_count.value + 1 %}
214
+ {%- endif %}
215
+ {%- if add_vision_id %}
216
+ {{- 'Picture ' ~ image_count.value ~ ': ' }}
217
+ {%- endif %}
218
+ {{- '<|vision_start|><|image_pad|><|vision_end|>' }}
219
+ {%- elif _is_video %}
220
+ {%- if is_system_content %}
221
+ {{- raise_exception(
222
+ 'System and developer messages cannot contain videos.'
223
+ ) }}
224
+ {%- endif %}
225
+ {%- if do_vision_count %}
226
+ {%- set video_count.value = video_count.value + 1 %}
227
+ {%- endif %}
228
+ {%- if add_vision_id %}
229
+ {{- 'Video ' ~ video_count.value ~ ': ' }}
230
+ {%- endif %}
231
+ {{- '<|vision_start|><|video_pad|><|vision_end|>' }}
232
+ {%- elif _item_type == 'text' or 'text' in item %}
233
+ {%- if 'text' not in item or item.text is not string %}
234
+ {{- raise_exception(
235
+ 'Text content items must contain a string text field.'
236
+ ) }}
237
+ {%- endif %}
238
+ {{- item.text }}
239
+ {%- else %}
240
+ {{- raise_exception(
241
+ 'Unexpected item in content list. Expected text, image, or video content.'
242
+ ) }}
243
+ {%- endif %}
244
+ {%- endfor %}
245
+ {%- elif content is none or content is undefined %}
246
+ {{- '' }}
247
+ {%- else %}
248
+ {{- raise_exception('Unexpected content type.') }}
249
+ {%- endif %}
250
+ {%- endmacro %}
251
+ {#- -------------------------------------------------------------------------
252
+ Validate and merge leading system/developer messages
253
+ ------------------------------------------------------------------------- -#}
254
+ {%- set head = namespace(count=0, seen_non_system=false) %}
255
+ {%- for message in messages %}
256
+ {%- set _is_system =
257
+ message.role == 'system' or message.role == 'developer'
258
+ %}
259
+ {%- if _is_system %}
260
+ {%- if head.seen_non_system %}
261
+ {{- raise_exception(
262
+ 'System and developer messages must appear before all user, assistant, and tool messages.'
263
+ ) }}
264
+ {%- endif %}
265
+ {%- set head.count = head.count + 1 %}
266
+ {%- else %}
267
+ {%- set head.seen_non_system = true %}
268
+ {%- endif %}
269
+ {%- endfor %}
270
+ {%- set system_state = namespace(content='') %}
271
+ {%- for message in messages[:head.count] %}
272
+ {%- set _part =
273
+ render_content(message.content, false, true) | trim
274
+ %}
275
+ {%- if _part %}
276
+ {%- if system_state.content %}
277
+ {%- set system_state.content =
278
+ system_state.content ~ '\n\n' ~ _part
279
+ %}
280
+ {%- else %}
281
+ {%- set system_state.content = _part %}
282
+ {%- endif %}
283
+ {%- endif %}
284
+ {%- endfor %}
285
+ {%- set _system_content = system_state.content %}
286
+ {%- set _msgs = messages[head.count:] %}
287
+ {#- -------------------------------------------------------------------------
288
+ System prompt and tool instructions
289
+ ------------------------------------------------------------------------- -#}
290
+ {%- if _has_tools %}
291
+ {{- '<|im_start|>system\n' }}
292
+ {%- if reasoning_instructions %}
293
+ {{- reasoning_instructions ~ '\n\n' }}
294
+ {%- endif %}
295
+ {{- '# Tools\n\nYou have access to the following functions:\n\n<tools>' }}
296
+ {%- for tool in tools %}
297
+ {{- '\n' }}
298
+ {{- tool | tojson }}
299
+ {%- endfor %}
300
+ {{- '\n</tools>' }}
301
+ {%- if _tool_format == 'json' %}
302
+ {{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\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- Function calls MUST follow the specified format: a single JSON object with "name" and "arguments" keys must be nested within <tool_call></tool_call> XML tags\n- Required parameters MUST be specified\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\n</IMPORTANT>' }}
303
+ {%- else %}
304
+ {{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\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- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags\n- Required parameters MUST be specified\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\n</IMPORTANT>' }}
305
+ {%- endif %}
306
+ {%- if _system_content %}
307
+ {{- '\n\n' ~ _system_content }}
308
+ {%- endif %}
309
+ {{- '<|im_end|>\n' }}
310
+ {%- else %}
311
+ {%- if _system_content %}
312
+ {{- '<|im_start|>system\n'
313
+ ~ (reasoning_instructions ~ '\n\n' if reasoning_instructions else '')
314
+ ~ _system_content
315
+ ~ '<|im_end|>\n'
316
+ }}
317
+ {%- elif reasoning_instructions %}
318
+ {{- '<|im_start|>system\n'
319
+ ~ reasoning_instructions
320
+ ~ '<|im_end|>\n'
321
+ }}
322
+ {%- endif %}
323
+ {%- endif %}
324
+ {#- -------------------------------------------------------------------------
325
+ Find the last real user query
326
+ ------------------------------------------------------------------------- -#}
327
+ {%- set ns = namespace(
328
+ multi_step_tool=true,
329
+ last_query_index=(_msgs | length) - 1
330
+ ) %}
331
+ {%- for message in _msgs[::-1] %}
332
+ {%- set index = (_msgs | length - 1) - loop.index0 %}
333
+ {%- if ns.multi_step_tool and message.role == 'user' %}
334
+ {%- set _rendered_user =
335
+ render_content(message.content, false) | trim
336
+ %}
337
+ {%- if not (
338
+ _rendered_user.startswith('<tool_response>')
339
+ and _rendered_user.endswith('</tool_response>')
340
+ ) %}
341
+ {%- set ns.multi_step_tool = false %}
342
+ {%- set ns.last_query_index = index %}
343
+ {%- endif %}
344
+ {%- endif %}
345
+ {%- endfor %}
346
+ {%- if ns.multi_step_tool %}
347
+ {{- raise_exception('No user query found in messages.') }}
348
+ {%- endif %}
349
+ {#- -------------------------------------------------------------------------
350
+ Conversation rendering
351
+ ------------------------------------------------------------------------- -#}
352
+ {%- set history_state = namespace(previous_role='') %}
353
+ {%- for message in _msgs %}
354
+ {%- set content =
355
+ render_content(message.content, true) | trim
356
+ %}
357
+ {%- if message.role == 'user' %}
358
+ {{- '<|im_start|>user\n'
359
+ ~ content
360
+ ~ '<|im_end|>\n'
361
+ }}
362
+ {%- elif message.role == 'assistant' %}
363
+ {%- set reasoning_content = '' %}
364
+ {#- Prefer current vLLM's `reasoning` field, then retain compatibility
365
+ with older `reasoning_content` and other servers' `thinking`. -#}
366
+ {%- if message.reasoning is defined
367
+ and message.reasoning is not none %}
368
+ {%- if message.reasoning is string %}
369
+ {%- set reasoning_content = message.reasoning %}
370
+ {%- else %}
371
+ {%- set reasoning_content =
372
+ message.reasoning | string
373
+ %}
374
+ {%- endif %}
375
+ {%- elif message.reasoning_content is defined
376
+ and message.reasoning_content is not none %}
377
+ {%- if message.reasoning_content is string %}
378
+ {%- set reasoning_content = message.reasoning_content %}
379
+ {%- else %}
380
+ {%- set reasoning_content =
381
+ message.reasoning_content | string
382
+ %}
383
+ {%- endif %}
384
+ {%- elif message.thinking is defined
385
+ and message.thinking is not none %}
386
+ {%- if message.thinking is string %}
387
+ {%- set reasoning_content = message.thinking %}
388
+ {%- else %}
389
+ {%- set reasoning_content =
390
+ message.thinking | string
391
+ %}
392
+ {%- endif %}
393
+ {%- endif %}
394
+ {%- set reasoning_content = reasoning_content | trim %}
395
+ {#- Preserve the original invariant: when thinking is preserved,
396
+ always reconstruct the thinking block, even when it is empty. -#}
397
+ {%- if _preserve_thinking
398
+ or loop.index0 > ns.last_query_index %}
399
+ {{- '<|im_start|>assistant\n<think>\n'
400
+ ~ reasoning_content
401
+ ~ '\n</think>\n\n'
402
+ ~ content
403
+ }}
404
+ {%- else %}
405
+ {{- '<|im_start|>assistant\n' ~ content }}
406
+ {%- endif %}
407
+ {%- if message.tool_calls is defined
408
+ and message.tool_calls is not none
409
+ and message.tool_calls %}
410
+ {%- if message.tool_calls is string
411
+ or message.tool_calls is mapping
412
+ or message.tool_calls is not iterable %}
413
+ {{- raise_exception(
414
+ 'assistant.tool_calls must be an iterable list of tool calls.'
415
+ ) }}
416
+ {%- endif %}
417
+ {%- for tool_call in message.tool_calls %}
418
+ {%- if tool_call.function is defined
419
+ and tool_call.function is not none %}
420
+ {%- set tc = tool_call.function %}
421
+ {%- else %}
422
+ {%- set tc = tool_call %}
423
+ {%- endif %}
424
+ {%- if tc.name is not defined
425
+ or tc.name is none
426
+ or tc.name is not string
427
+ or not tc.name %}
428
+ {{- raise_exception(
429
+ 'Every tool call must have a non-empty string name.'
430
+ ) }}
431
+ {%- endif %}
432
+ {%- set tc_name = tc.name %}
433
+ {%- if _tool_format == 'json' %}
434
+ {%- if loop.first %}
435
+ {%- if content | trim %}
436
+ {{- '\n\n<tool_call>\n' }}
437
+ {%- else %}
438
+ {{- '<tool_call>\n' }}
439
+ {%- endif %}
440
+ {%- else %}
441
+ {{- '\n<tool_call>\n' }}
442
+ {%- endif %}
443
+ {%- set _json_arguments = '{}' %}
444
+ {%- if tc.arguments is defined
445
+ and tc.arguments is not none %}
446
+ {%- if tc.arguments is mapping %}
447
+ {%- set _json_arguments =
448
+ tc.arguments | tojson
449
+ %}
450
+ {%- elif tc.arguments is string %}
451
+ {%- set _raw_arguments =
452
+ tc.arguments | trim
453
+ %}
454
+ {%- if _raw_arguments %}
455
+ {%- if not (
456
+ _raw_arguments.startswith('{')
457
+ and _raw_arguments.endswith('}')
458
+ ) %}
459
+ {{- raise_exception(
460
+ 'JSON tool-call arguments must be a JSON object string.'
461
+ ) }}
462
+ {%- endif %}
463
+ {%- set _json_arguments =
464
+ _raw_arguments
465
+ %}
466
+ {%- endif %}
467
+ {%- else %}
468
+ {{- raise_exception(
469
+ 'JSON tool-call arguments must be a mapping or a JSON object string.'
470
+ ) }}
471
+ {%- endif %}
472
+ {%- endif %}
473
+ {{- '{"name": ' }}
474
+ {{- tc_name | tojson }}
475
+ {{- ', "arguments": ' }}
476
+ {{- _json_arguments }}
477
+ {{- '}\n</tool_call>' }}
478
+ {%- else %}
479
+ {%- if loop.first %}
480
+ {%- if content | trim %}
481
+ {{- '\n\n<tool_call>\n<function='
482
+ ~ tc_name
483
+ ~ '>\n'
484
+ }}
485
+ {%- else %}
486
+ {{- '<tool_call>\n<function='
487
+ ~ tc_name
488
+ ~ '>\n'
489
+ }}
490
+ {%- endif %}
491
+ {%- else %}
492
+ {{- '\n<tool_call>\n<function='
493
+ ~ tc_name
494
+ ~ '>\n'
495
+ }}
496
+ {%- endif %}
497
+ {%- if tc.arguments is defined
498
+ and tc.arguments is not none %}
499
+ {%- if tc.arguments is mapping %}
500
+ {%- for args_name, args_value
501
+ in tc.arguments | items %}
502
+ {%- set _argument_name =
503
+ args_name | string
504
+ %}
505
+ {{- '<parameter='
506
+ ~ _argument_name
507
+ ~ '>\n'
508
+ }}
509
+ {#- Preserve strings verbatim. Serialize every
510
+ other type as JSON so booleans and null stay
511
+ true/false/null instead of True/False/None. -#}
512
+ {%- if args_value is string %}
513
+ {%- set _argument_value =
514
+ args_value
515
+ %}
516
+ {%- else %}
517
+ {%- set _argument_value =
518
+ args_value | tojson
519
+ %}
520
+ {%- endif %}
521
+ {%- if max_tool_arg_chars > 0
522
+ and _argument_value | length
523
+ > max_tool_arg_chars %}
524
+ {{- _argument_value[:max_tool_arg_chars] }}
525
+ {{- '\n[TRUNCATED — original length '
526
+ ~ (_argument_value | length | string)
527
+ ~ ' chars]'
528
+ }}
529
+ {%- else %}
530
+ {{- _argument_value }}
531
+ {%- endif %}
532
+ {{- '\n</parameter>\n' }}
533
+ {%- endfor %}
534
+ {%- elif tc.arguments is string %}
535
+ {%- set _raw_arguments =
536
+ tc.arguments | trim
537
+ %}
538
+ {%- if _raw_arguments
539
+ and _raw_arguments != '{}' %}
540
+ {{- raise_exception(
541
+ 'tool_call_format="xml" requires tool-call arguments to be mappings, but received a JSON string. Parse the JSON string into a mapping before applying the template, or set tool_call_format="auto" (or "json") to use the lossless JSON tool-call representation.'
542
+ ) }}
543
+ {%- endif %}
544
+ {%- else %}
545
+ {{- raise_exception(
546
+ 'XML tool-call arguments must be a mapping. Parse JSON-string arguments before applying the template.'
547
+ ) }}
548
+ {%- endif %}
549
+ {%- endif %}
550
+ {{- '</function>\n</tool_call>' }}
551
+ {%- endif %}
552
+ {%- endfor %}
553
+ {%- endif %}
554
+ {{- '<|im_end|>\n' }}
555
+ {%- elif message.role == 'tool' %}
556
+ {%- if history_state.previous_role != 'tool' %}
557
+ {{- '<|im_start|>user' }}
558
+ {%- endif %}
559
+ {%- if max_tool_response_chars > 0
560
+ and content | length > max_tool_response_chars %}
561
+ {%- set content =
562
+ content[:max_tool_response_chars]
563
+ ~ '\n[TRUNCATED — original length '
564
+ ~ (content | length | string)
565
+ ~ ' chars]'
566
+ %}
567
+ {%- endif %}
568
+ {{- '\n<tool_response>\n' }}
569
+ {{- content }}
570
+ {{- '\n</tool_response>' }}
571
+ {%- if loop.last %}
572
+ {{- '<|im_end|>\n' }}
573
+ {%- elif _msgs[loop.index0 + 1].role != 'tool' %}
574
+ {{- '<|im_end|>\n' }}
575
+ {%- endif %}
576
+ {%- elif message.role == 'system'
577
+ or message.role == 'developer' %}
578
+ {{- raise_exception(
579
+ 'System and developer messages must appear only at the beginning of the conversation.'
580
+ ) }}
581
+ {%- else %}
582
+ {{- raise_exception(
583
+ 'Unexpected message role ' ~ message.role ~ '.'
584
+ ) }}
585
+ {%- endif %}
586
+ {%- set history_state.previous_role = message.role %}
587
+ {%- endfor %}
588
+ {#- -------------------------------------------------------------------------
589
+ Generation prompt
590
+ ------------------------------------------------------------------------- -#}
591
+ {%- if add_generation_prompt %}
592
+ {{- '<|im_start|>assistant\n' }}
593
+ {%- if not _thinking_enabled %}
594
+ {{- '<think>\n\n</think>\n\n' }}
595
+ {%- else %}
596
+ {{- '<think>\n' }}
597
+ {%- endif %}
598
+ {%- endif %}
config.json ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "Qwen3_5ForConditionalGeneration"
4
+ ],
5
+ "torch_dtype": "bfloat16",
6
+ "image_token_id": 248056,
7
+ "language_model_only": false,
8
+ "model_type": "qwen3_5",
9
+ "text_config": {
10
+ "attention_bias": false,
11
+ "attention_dropout": 0.0,
12
+ "attn_output_gate": true,
13
+ "bos_token_id": 248044,
14
+ "torch_dtype": "bfloat16",
15
+ "eos_token_id": 248044,
16
+ "full_attention_interval": 4,
17
+ "head_dim": 256,
18
+ "hidden_act": "silu",
19
+ "hidden_size": 5120,
20
+ "initializer_range": 0.02,
21
+ "intermediate_size": 17408,
22
+ "layer_types": [
23
+ "linear_attention",
24
+ "linear_attention",
25
+ "linear_attention",
26
+ "full_attention",
27
+ "linear_attention",
28
+ "linear_attention",
29
+ "linear_attention",
30
+ "full_attention",
31
+ "linear_attention",
32
+ "linear_attention",
33
+ "linear_attention",
34
+ "full_attention",
35
+ "linear_attention",
36
+ "linear_attention",
37
+ "linear_attention",
38
+ "full_attention",
39
+ "linear_attention",
40
+ "linear_attention",
41
+ "linear_attention",
42
+ "full_attention",
43
+ "linear_attention",
44
+ "linear_attention",
45
+ "linear_attention",
46
+ "full_attention",
47
+ "linear_attention",
48
+ "linear_attention",
49
+ "linear_attention",
50
+ "full_attention",
51
+ "linear_attention",
52
+ "linear_attention",
53
+ "linear_attention",
54
+ "full_attention",
55
+ "linear_attention",
56
+ "linear_attention",
57
+ "linear_attention",
58
+ "full_attention",
59
+ "linear_attention",
60
+ "linear_attention",
61
+ "linear_attention",
62
+ "full_attention",
63
+ "linear_attention",
64
+ "linear_attention",
65
+ "linear_attention",
66
+ "full_attention",
67
+ "linear_attention",
68
+ "linear_attention",
69
+ "linear_attention",
70
+ "full_attention",
71
+ "linear_attention",
72
+ "linear_attention",
73
+ "linear_attention",
74
+ "full_attention",
75
+ "linear_attention",
76
+ "linear_attention",
77
+ "linear_attention",
78
+ "full_attention",
79
+ "linear_attention",
80
+ "linear_attention",
81
+ "linear_attention",
82
+ "full_attention",
83
+ "linear_attention",
84
+ "linear_attention",
85
+ "linear_attention",
86
+ "full_attention"
87
+ ],
88
+ "linear_conv_kernel_dim": 4,
89
+ "linear_key_head_dim": 128,
90
+ "linear_num_key_heads": 16,
91
+ "linear_num_value_heads": 48,
92
+ "linear_value_head_dim": 128,
93
+ "mamba_ssm_dtype": "float32",
94
+ "max_position_embeddings": 262144,
95
+ "model_type": "qwen3_5_text",
96
+ "mtp_num_hidden_layers": 1,
97
+ "mtp_use_dedicated_embeddings": false,
98
+ "num_attention_heads": 24,
99
+ "num_hidden_layers": 64,
100
+ "num_key_value_heads": 4,
101
+ "output_gate_type": "swish",
102
+ "pad_token_id": null,
103
+ "partial_rotary_factor": 0.25,
104
+ "rms_norm_eps": 1e-06,
105
+ "rope_parameters": {
106
+ "mrope_interleaved": true,
107
+ "mrope_section": [
108
+ 11,
109
+ 11,
110
+ 10
111
+ ],
112
+ "partial_rotary_factor": 0.25,
113
+ "rope_theta": 10000000,
114
+ "rope_type": "default"
115
+ },
116
+ "tie_word_embeddings": false,
117
+ "use_cache": true,
118
+ "vocab_size": 248320
119
+ },
120
+ "tie_word_embeddings": false,
121
+ "video_token_id": 248057,
122
+ "vision_config": {
123
+ "deepstack_visual_indexes": [],
124
+ "depth": 27,
125
+ "torch_dtype": "bfloat16",
126
+ "hidden_act": "gelu_pytorch_tanh",
127
+ "hidden_size": 1152,
128
+ "in_channels": 3,
129
+ "initializer_range": 0.02,
130
+ "intermediate_size": 4304,
131
+ "model_type": "qwen3_5_vision",
132
+ "num_heads": 16,
133
+ "num_position_embeddings": 2304,
134
+ "out_hidden_size": 5120,
135
+ "patch_size": 16,
136
+ "spatial_merge_size": 2,
137
+ "temporal_patch_size": 2
138
+ },
139
+ "vision_end_token_id": 248054,
140
+ "vision_start_token_id": 248053
141
+ }
generation_config.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token_id": 248044,
3
+ "do_sample": true,
4
+ "eos_token_id": [
5
+ 248046,
6
+ 248044
7
+ ],
8
+ "pad_token_id": 248044,
9
+ "temperature": 1.0,
10
+ "top_k": 20,
11
+ "top_p": 0.95,
12
+ "transformers_version": "5.10.2"
13
+ }
processor_config.json ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "image_processor": {
3
+ "do_convert_rgb": true,
4
+ "do_normalize": true,
5
+ "do_rescale": true,
6
+ "do_resize": true,
7
+ "image_mean": [
8
+ 0.5,
9
+ 0.5,
10
+ 0.5
11
+ ],
12
+ "image_processor_type": "Qwen2VLImageProcessor",
13
+ "image_std": [
14
+ 0.5,
15
+ 0.5,
16
+ 0.5
17
+ ],
18
+ "merge_size": 2,
19
+ "patch_size": 16,
20
+ "resample": 3,
21
+ "rescale_factor": 0.00392156862745098,
22
+ "size": {
23
+ "longest_edge": 16777216,
24
+ "shortest_edge": 65536
25
+ },
26
+ "temporal_patch_size": 2
27
+ },
28
+ "processor_class": "Qwen3VLProcessor",
29
+ "video_processor": {
30
+ "do_convert_rgb": true,
31
+ "do_normalize": true,
32
+ "do_rescale": true,
33
+ "do_resize": true,
34
+ "do_sample_frames": true,
35
+ "fps": 2,
36
+ "image_mean": [
37
+ 0.5,
38
+ 0.5,
39
+ 0.5
40
+ ],
41
+ "image_std": [
42
+ 0.5,
43
+ 0.5,
44
+ 0.5
45
+ ],
46
+ "max_frames": 768,
47
+ "max_video_tokens": 768,
48
+ "merge_size": 2,
49
+ "min_frames": 4,
50
+ "patch_size": 16,
51
+ "resample": 3,
52
+ "rescale_factor": 0.00392156862745098,
53
+ "return_metadata": false,
54
+ "size": {
55
+ "longest_edge": 25165824,
56
+ "shortest_edge": 4096
57
+ },
58
+ "temporal_patch_size": 2,
59
+ "video_processor_type": "Qwen3VLVideoProcessor"
60
+ }
61
+ }
tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:06b9509352d2af50381ab2247e083b80d32d5c0aba91c272ca9ff729b6a0e523
3
+ size 19989325
tokenizer_config.json ADDED
@@ -0,0 +1,301 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "audio_bos_token": "<|audio_start|>",
4
+ "audio_eos_token": "<|audio_end|>",
5
+ "audio_token": "<|audio_pad|>",
6
+ "backend": "tokenizers",
7
+ "bos_token": null,
8
+ "clean_up_tokenization_spaces": false,
9
+ "eos_token": "<|im_end|>",
10
+ "errors": "replace",
11
+ "image_token": "<|image_pad|>",
12
+ "is_local": true,
13
+ "local_files_only": false,
14
+ "model_max_length": 262144,
15
+ "model_specific_special_tokens": {
16
+ "audio_bos_token": "<|audio_start|>",
17
+ "audio_eos_token": "<|audio_end|>",
18
+ "audio_token": "<|audio_pad|>",
19
+ "image_token": "<|image_pad|>",
20
+ "video_token": "<|video_pad|>",
21
+ "vision_bos_token": "<|vision_start|>",
22
+ "vision_eos_token": "<|vision_end|>"
23
+ },
24
+ "pad_token": "<|endoftext|>",
25
+ "padding_side": "left",
26
+ "pretokenize_regex": "(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\\r\\n\\p{L}\\p{N}]?[\\p{L}\\p{M}]+|\\p{N}| ?[^\\s\\p{L}\\p{M}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+",
27
+ "processor_class": "Qwen3VLProcessor",
28
+ "split_special_tokens": false,
29
+ "tokenizer_class": "Qwen2Tokenizer",
30
+ "unk_token": null,
31
+ "video_token": "<|video_pad|>",
32
+ "vision_bos_token": "<|vision_start|>",
33
+ "vision_eos_token": "<|vision_end|>",
34
+ "added_tokens_decoder": {
35
+ "248044": {
36
+ "content": "<|endoftext|>",
37
+ "single_word": false,
38
+ "lstrip": false,
39
+ "rstrip": false,
40
+ "normalized": false,
41
+ "special": true
42
+ },
43
+ "248045": {
44
+ "content": "<|im_start|>",
45
+ "single_word": false,
46
+ "lstrip": false,
47
+ "rstrip": false,
48
+ "normalized": false,
49
+ "special": true
50
+ },
51
+ "248046": {
52
+ "content": "<|im_end|>",
53
+ "single_word": false,
54
+ "lstrip": false,
55
+ "rstrip": false,
56
+ "normalized": false,
57
+ "special": true
58
+ },
59
+ "248047": {
60
+ "content": "<|object_ref_start|>",
61
+ "single_word": false,
62
+ "lstrip": false,
63
+ "rstrip": false,
64
+ "normalized": false,
65
+ "special": true
66
+ },
67
+ "248048": {
68
+ "content": "<|object_ref_end|>",
69
+ "single_word": false,
70
+ "lstrip": false,
71
+ "rstrip": false,
72
+ "normalized": false,
73
+ "special": true
74
+ },
75
+ "248049": {
76
+ "content": "<|box_start|>",
77
+ "single_word": false,
78
+ "lstrip": false,
79
+ "rstrip": false,
80
+ "normalized": false,
81
+ "special": true
82
+ },
83
+ "248050": {
84
+ "content": "<|box_end|>",
85
+ "single_word": false,
86
+ "lstrip": false,
87
+ "rstrip": false,
88
+ "normalized": false,
89
+ "special": true
90
+ },
91
+ "248051": {
92
+ "content": "<|quad_start|>",
93
+ "single_word": false,
94
+ "lstrip": false,
95
+ "rstrip": false,
96
+ "normalized": false,
97
+ "special": true
98
+ },
99
+ "248052": {
100
+ "content": "<|quad_end|>",
101
+ "single_word": false,
102
+ "lstrip": false,
103
+ "rstrip": false,
104
+ "normalized": false,
105
+ "special": true
106
+ },
107
+ "248053": {
108
+ "content": "<|vision_start|>",
109
+ "single_word": false,
110
+ "lstrip": false,
111
+ "rstrip": false,
112
+ "normalized": false,
113
+ "special": true
114
+ },
115
+ "248054": {
116
+ "content": "<|vision_end|>",
117
+ "single_word": false,
118
+ "lstrip": false,
119
+ "rstrip": false,
120
+ "normalized": false,
121
+ "special": true
122
+ },
123
+ "248055": {
124
+ "content": "<|vision_pad|>",
125
+ "single_word": false,
126
+ "lstrip": false,
127
+ "rstrip": false,
128
+ "normalized": false,
129
+ "special": true
130
+ },
131
+ "248056": {
132
+ "content": "<|image_pad|>",
133
+ "single_word": false,
134
+ "lstrip": false,
135
+ "rstrip": false,
136
+ "normalized": false,
137
+ "special": true
138
+ },
139
+ "248057": {
140
+ "content": "<|video_pad|>",
141
+ "single_word": false,
142
+ "lstrip": false,
143
+ "rstrip": false,
144
+ "normalized": false,
145
+ "special": true
146
+ },
147
+ "248058": {
148
+ "content": "<tool_call>",
149
+ "single_word": false,
150
+ "lstrip": false,
151
+ "rstrip": false,
152
+ "normalized": false,
153
+ "special": false
154
+ },
155
+ "248059": {
156
+ "content": "</tool_call>",
157
+ "single_word": false,
158
+ "lstrip": false,
159
+ "rstrip": false,
160
+ "normalized": false,
161
+ "special": false
162
+ },
163
+ "248060": {
164
+ "content": "<|fim_prefix|>",
165
+ "single_word": false,
166
+ "lstrip": false,
167
+ "rstrip": false,
168
+ "normalized": false,
169
+ "special": false
170
+ },
171
+ "248061": {
172
+ "content": "<|fim_middle|>",
173
+ "single_word": false,
174
+ "lstrip": false,
175
+ "rstrip": false,
176
+ "normalized": false,
177
+ "special": false
178
+ },
179
+ "248062": {
180
+ "content": "<|fim_suffix|>",
181
+ "single_word": false,
182
+ "lstrip": false,
183
+ "rstrip": false,
184
+ "normalized": false,
185
+ "special": false
186
+ },
187
+ "248063": {
188
+ "content": "<|fim_pad|>",
189
+ "single_word": false,
190
+ "lstrip": false,
191
+ "rstrip": false,
192
+ "normalized": false,
193
+ "special": false
194
+ },
195
+ "248064": {
196
+ "content": "<|repo_name|>",
197
+ "single_word": false,
198
+ "lstrip": false,
199
+ "rstrip": false,
200
+ "normalized": false,
201
+ "special": false
202
+ },
203
+ "248065": {
204
+ "content": "<|file_sep|>",
205
+ "single_word": false,
206
+ "lstrip": false,
207
+ "rstrip": false,
208
+ "normalized": false,
209
+ "special": false
210
+ },
211
+ "248066": {
212
+ "content": "<tool_response>",
213
+ "single_word": false,
214
+ "lstrip": false,
215
+ "rstrip": false,
216
+ "normalized": false,
217
+ "special": false
218
+ },
219
+ "248067": {
220
+ "content": "</tool_response>",
221
+ "single_word": false,
222
+ "lstrip": false,
223
+ "rstrip": false,
224
+ "normalized": false,
225
+ "special": false
226
+ },
227
+ "248068": {
228
+ "content": "<think>",
229
+ "single_word": false,
230
+ "lstrip": false,
231
+ "rstrip": false,
232
+ "normalized": false,
233
+ "special": false
234
+ },
235
+ "248069": {
236
+ "content": "</think>",
237
+ "single_word": false,
238
+ "lstrip": false,
239
+ "rstrip": false,
240
+ "normalized": false,
241
+ "special": false
242
+ },
243
+ "248070": {
244
+ "content": "<|audio_start|>",
245
+ "single_word": false,
246
+ "lstrip": false,
247
+ "rstrip": false,
248
+ "normalized": false,
249
+ "special": true
250
+ },
251
+ "248071": {
252
+ "content": "<|audio_end|>",
253
+ "single_word": false,
254
+ "lstrip": false,
255
+ "rstrip": false,
256
+ "normalized": false,
257
+ "special": true
258
+ },
259
+ "248072": {
260
+ "content": "<tts_pad>",
261
+ "single_word": false,
262
+ "lstrip": false,
263
+ "rstrip": false,
264
+ "normalized": false,
265
+ "special": true
266
+ },
267
+ "248073": {
268
+ "content": "<tts_text_bos>",
269
+ "single_word": false,
270
+ "lstrip": false,
271
+ "rstrip": false,
272
+ "normalized": false,
273
+ "special": true
274
+ },
275
+ "248074": {
276
+ "content": "<tts_text_eod>",
277
+ "single_word": false,
278
+ "lstrip": false,
279
+ "rstrip": false,
280
+ "normalized": false,
281
+ "special": true
282
+ },
283
+ "248075": {
284
+ "content": "<tts_text_bos_single>",
285
+ "single_word": false,
286
+ "lstrip": false,
287
+ "rstrip": false,
288
+ "normalized": false,
289
+ "special": true
290
+ },
291
+ "248076": {
292
+ "content": "<|audio_pad|>",
293
+ "single_word": false,
294
+ "lstrip": false,
295
+ "rstrip": false,
296
+ "normalized": false,
297
+ "special": true
298
+ }
299
+ },
300
+ "chat_template": "{%- set template_version = \"qwen3.8-safe-v3.1\" %}\n{#- -------------------------------------------------------------------------\n Whitespace contract: every tag opener in this file carries a leading minus,\n so it strips the whitespace and newlines that precede it. All emitted text\n comes from string literals, which makes the rendered prompt byte-exact and\n free of incidental newlines. Comment tags need the minus just as much as\n block tags do; a plain comment tag breaks the strip chain and leaks the\n surrounding indentation into the prompt.\n ------------------------------------------------------------------------- -#}\n{#- The message list has to exist before anything else can inspect it. -#}\n{%- if not messages %}\n {{- raise_exception('No messages provided.') }}\n{%- endif %}\n{#- -------------------------------------------------------------------------\n Configuration\n ------------------------------------------------------------------------- -#}\n{%- set _requested_tool_format =\n tool_call_format if tool_call_format is defined else 'xml'\n%}\n{%- if _requested_tool_format not in ('auto', 'xml', 'json') %}\n {{- raise_exception(\n 'Unexpected tool_call_format ' ~ _requested_tool_format ~\n '. Supported values are xml (default), auto, and json.'\n ) }}\n{%- endif %}\n{%- set add_vision_id = add_vision_id if add_vision_id is defined else false %}\n{%- set enable_thinking = enable_thinking if enable_thinking is defined else true %}\n{%- set auto_disable_thinking_with_tools =\n auto_disable_thinking_with_tools\n if auto_disable_thinking_with_tools is defined\n else false\n%}\n{%- if preserve_reasoning is defined\n and preserve_reasoning is not none\n and preserve_thinking is defined\n and preserve_thinking is not none\n and preserve_reasoning != preserve_thinking %}\n {{- raise_exception(\n 'preserve_reasoning and preserve_thinking were both provided with conflicting values.'\n ) }}\n{%- endif %}\n{%- if preserve_reasoning is defined and preserve_reasoning is not none %}\n {%- set _preserve_thinking = preserve_reasoning %}\n{%- elif preserve_thinking is defined and preserve_thinking is not none %}\n {%- set _preserve_thinking = preserve_thinking %}\n{%- else %}\n {%- set _preserve_thinking = true %}\n{%- endif %}\n{%- set max_tool_arg_chars =\n max_tool_arg_chars if max_tool_arg_chars is defined else 0\n%}\n{%- set max_tool_response_chars =\n max_tool_response_chars if max_tool_response_chars is defined else 0\n%}\n{%- if max_tool_arg_chars is not number or max_tool_arg_chars < 0 %}\n {{- raise_exception('max_tool_arg_chars must be a non-negative number.') }}\n{%- endif %}\n{%- if max_tool_response_chars is not number or max_tool_response_chars < 0 %}\n {{- raise_exception('max_tool_response_chars must be a non-negative number.') }}\n{%- endif %}\n{%- if tools is defined and tools is not none and tools %}\n {%- if tools is string or tools is mapping or tools is not iterable %}\n {{- raise_exception('tools must be an iterable list of tool definitions.') }}\n {%- endif %}\n {%- set _has_tools = true %}\n{%- else %}\n {%- set _has_tools = false %}\n{%- endif %}\n{#- -------------------------------------------------------------------------\n Resolve the tool-call wire format.\n\n OpenAI-compatible servers hand assistant tool calls back with\n `function.arguments` as a JSON *string*, not a mapping. The XML parameter\n form needs the individual key/value pairs, and a chat template cannot\n decode a JSON string: the standard chat-template environment provides\n `tojson` but no inverse, and no codepoint-to-character primitive, so a\n hand-rolled scanner could not decode \\uXXXX escapes correctly. Guessing\n would silently corrupt tool arguments, which is worse than any error.\n\n The deployment-safe default is XML, matching Qwen's native tool-call wire\n format and the qwen3_coder tool parser. A caller can explicitly request\n tool_call_format='auto' to render the whole prompt in JSON form whenever a\n historical tool call carries string arguments. That path is lossless,\n needs no decoding, and keeps the system-prompt instructions and rendered\n history in one consistent format. Histories whose arguments are all\n mappings still render as XML, byte-identically to tool_call_format='xml'.\n\n A caller that uses the default XML mode (or explicitly pins 'xml') still\n gets a hard error for non-empty string arguments, because that request\n cannot be honoured faithfully in the native XML parameter representation.\n ------------------------------------------------------------------------- -#}\n{%- set format_scan = namespace(has_json_string_arguments=false) %}\n{%- for message in messages %}\n {%- if message.role == 'assistant'\n and message.tool_calls is defined\n and message.tool_calls is not none\n and message.tool_calls\n and message.tool_calls is not string\n and message.tool_calls is not mapping\n and message.tool_calls is iterable %}\n {%- for tool_call in message.tool_calls %}\n {%- if tool_call.function is defined\n and tool_call.function is not none %}\n {%- set _tc = tool_call.function %}\n {%- else %}\n {%- set _tc = tool_call %}\n {%- endif %}\n {%- if _tc.arguments is defined\n and _tc.arguments is not none\n and _tc.arguments is string\n and _tc.arguments | trim\n and _tc.arguments | trim != '{}' %}\n {%- set format_scan.has_json_string_arguments = true %}\n {%- endif %}\n {%- endfor %}\n {%- endif %}\n{%- endfor %}\n{%- if _requested_tool_format == 'auto' %}\n {%- if format_scan.has_json_string_arguments %}\n {%- set _tool_format = 'json' %}\n {%- else %}\n {%- set _tool_format = 'xml' %}\n {%- endif %}\n{%- else %}\n {%- set _tool_format = _requested_tool_format %}\n{%- endif %}\n{%- set _thinking_enabled = enable_thinking %}\n{%- if auto_disable_thinking_with_tools and _has_tools %}\n {%- set _thinking_enabled = false %}\n{%- endif %}\n{#- Normalize and validate reasoning effort even when thinking is disabled.\n Explicit null follows the template default; OpenAI-style `minimal` maps to\n low, while `none` disables thinking for this render. -#}\n{%- if reasoning_effort is undefined or reasoning_effort is none %}\n {%- set _effort_raw = 'medium' %}\n{%- else %}\n {%- set _effort_raw = reasoning_effort %}\n{%- endif %}\n{%- if _effort_raw == 'none' %}\n {%- set _thinking_enabled = false %}\n {%- set _reasoning_effort = 'xhigh' %}\n{%- elif _effort_raw == 'high' or _effort_raw == 'xhigh' %}\n {%- set _reasoning_effort = 'xhigh' %}\n{%- elif _effort_raw == 'medium' %}\n {%- set _reasoning_effort = 'medium' %}\n{%- elif _effort_raw == 'minimal' or _effort_raw == 'low' %}\n {%- set _reasoning_effort = 'low' %}\n{%- else %}\n {{- raise_exception(\n 'Unexpected reasoning effort ' ~ _effort_raw ~\n '. Supported values are none, minimal/low, medium, and high/xhigh; null uses the medium default.'\n ) }}\n{%- endif %}\n{%- set reasoning_instructions = '' %}\n{%- if _thinking_enabled %}\n {%- if _reasoning_effort == 'xhigh' %}\n {%- set reasoning_instructions =\n '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.'\n %}\n {%- elif _reasoning_effort == 'low' %}\n {%- set reasoning_instructions =\n 'Reasoning effort is set to low. Keep your thinking brief and focused, moving directly to the conclusion without unnecessary elaboration.'\n %}\n {%- endif %}\n{%- endif %}\n{#- -------------------------------------------------------------------------\n Content rendering\n ------------------------------------------------------------------------- -#}\n{%- set image_count = namespace(value=0) %}\n{%- set video_count = namespace(value=0) %}\n{%- macro render_content(content, do_vision_count, is_system_content=false) %}\n {%- if content is string %}\n {{- content }}\n {%- elif content is iterable and content is not mapping %}\n {%- for item in content %}\n {%- if item is not mapping %}\n {{- raise_exception(\n 'Content-list items must be mappings with a supported text, image, or video type.'\n ) }}\n {%- endif %}\n {%- set _item_type = item.type if 'type' in item else none %}\n {%- if _item_type is not none\n and _item_type not in ('text', 'image', 'image_url', 'video') %}\n {{- raise_exception(\n 'Unexpected content item type ' ~ _item_type ~ '.'\n ) }}\n {%- endif %}\n {%- set _is_image =\n _item_type == 'image'\n or _item_type == 'image_url'\n or 'image' in item\n or 'image_url' in item\n %}\n {%- set _is_video =\n _item_type == 'video'\n or 'video' in item\n %}\n {%- if _is_image and _is_video %}\n {{- raise_exception(\n 'A content item cannot contain both image and video data.'\n ) }}\n {%- elif _item_type == 'text' and (_is_image or _is_video) %}\n {{- raise_exception(\n 'A text content item cannot also contain image or video data.'\n ) }}\n {%- elif _is_image %}\n {%- if is_system_content %}\n {{- raise_exception(\n 'System and developer messages cannot contain images.'\n ) }}\n {%- endif %}\n {%- if do_vision_count %}\n {%- set image_count.value = image_count.value + 1 %}\n {%- endif %}\n {%- if add_vision_id %}\n {{- 'Picture ' ~ image_count.value ~ ': ' }}\n {%- endif %}\n {{- '<|vision_start|><|image_pad|><|vision_end|>' }}\n {%- elif _is_video %}\n {%- if is_system_content %}\n {{- raise_exception(\n 'System and developer messages cannot contain videos.'\n ) }}\n {%- endif %}\n {%- if do_vision_count %}\n {%- set video_count.value = video_count.value + 1 %}\n {%- endif %}\n {%- if add_vision_id %}\n {{- 'Video ' ~ video_count.value ~ ': ' }}\n {%- endif %}\n {{- '<|vision_start|><|video_pad|><|vision_end|>' }}\n {%- elif _item_type == 'text' or 'text' in item %}\n {%- if 'text' not in item or item.text is not string %}\n {{- raise_exception(\n 'Text content items must contain a string text field.'\n ) }}\n {%- endif %}\n {{- item.text }}\n {%- else %}\n {{- raise_exception(\n 'Unexpected item in content list. Expected text, image, or video content.'\n ) }}\n {%- endif %}\n {%- endfor %}\n {%- elif content is none or content is undefined %}\n {{- '' }}\n {%- else %}\n {{- raise_exception('Unexpected content type.') }}\n {%- endif %}\n{%- endmacro %}\n{#- -------------------------------------------------------------------------\n Validate and merge leading system/developer messages\n ------------------------------------------------------------------------- -#}\n{%- set head = namespace(count=0, seen_non_system=false) %}\n{%- for message in messages %}\n {%- set _is_system =\n message.role == 'system' or message.role == 'developer'\n %}\n {%- if _is_system %}\n {%- if head.seen_non_system %}\n {{- raise_exception(\n 'System and developer messages must appear before all user, assistant, and tool messages.'\n ) }}\n {%- endif %}\n {%- set head.count = head.count + 1 %}\n {%- else %}\n {%- set head.seen_non_system = true %}\n {%- endif %}\n{%- endfor %}\n{%- set system_state = namespace(content='') %}\n{%- for message in messages[:head.count] %}\n {%- set _part =\n render_content(message.content, false, true) | trim\n %}\n {%- if _part %}\n {%- if system_state.content %}\n {%- set system_state.content =\n system_state.content ~ '\\n\\n' ~ _part\n %}\n {%- else %}\n {%- set system_state.content = _part %}\n {%- endif %}\n {%- endif %}\n{%- endfor %}\n{%- set _system_content = system_state.content %}\n{%- set _msgs = messages[head.count:] %}\n{#- -------------------------------------------------------------------------\n System prompt and tool instructions\n ------------------------------------------------------------------------- -#}\n{%- if _has_tools %}\n {{- '<|im_start|>system\\n' }}\n {%- if reasoning_instructions %}\n {{- reasoning_instructions ~ '\\n\\n' }}\n {%- endif %}\n {{- '# Tools\\n\\nYou have access to the following functions:\\n\\n<tools>' }}\n {%- for tool in tools %}\n {{- '\\n' }}\n {{- tool | tojson }}\n {%- endfor %}\n {{- '\\n</tools>' }}\n {%- if _tool_format == 'json' %}\n {{- '\\n\\nIf you choose to call a function ONLY reply in the following format with NO suffix:\\n\\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- Function calls MUST follow the specified format: a single JSON object with \"name\" and \"arguments\" keys must be nested within <tool_call></tool_call> XML tags\\n- Required parameters MUST be specified\\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\\n</IMPORTANT>' }}\n {%- else %}\n {{- '\\n\\nIf you choose to call a function ONLY reply in the following format with NO suffix:\\n\\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- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags\\n- Required parameters MUST be specified\\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\\n</IMPORTANT>' }}\n {%- endif %}\n {%- if _system_content %}\n {{- '\\n\\n' ~ _system_content }}\n {%- endif %}\n {{- '<|im_end|>\\n' }}\n{%- else %}\n {%- if _system_content %}\n {{- '<|im_start|>system\\n'\n ~ (reasoning_instructions ~ '\\n\\n' if reasoning_instructions else '')\n ~ _system_content\n ~ '<|im_end|>\\n'\n }}\n {%- elif reasoning_instructions %}\n {{- '<|im_start|>system\\n'\n ~ reasoning_instructions\n ~ '<|im_end|>\\n'\n }}\n {%- endif %}\n{%- endif %}\n{#- -------------------------------------------------------------------------\n Find the last real user query\n ------------------------------------------------------------------------- -#}\n{%- set ns = namespace(\n multi_step_tool=true,\n last_query_index=(_msgs | length) - 1\n) %}\n{%- for message in _msgs[::-1] %}\n {%- set index = (_msgs | length - 1) - loop.index0 %}\n {%- if ns.multi_step_tool and message.role == 'user' %}\n {%- set _rendered_user =\n render_content(message.content, false) | trim\n %}\n {%- if not (\n _rendered_user.startswith('<tool_response>')\n and _rendered_user.endswith('</tool_response>')\n ) %}\n {%- set ns.multi_step_tool = false %}\n {%- set ns.last_query_index = index %}\n {%- endif %}\n {%- endif %}\n{%- endfor %}\n{%- if ns.multi_step_tool %}\n {{- raise_exception('No user query found in messages.') }}\n{%- endif %}\n{#- -------------------------------------------------------------------------\n Conversation rendering\n ------------------------------------------------------------------------- -#}\n{%- set history_state = namespace(previous_role='') %}\n{%- for message in _msgs %}\n {%- set content =\n render_content(message.content, true) | trim\n %}\n {%- if message.role == 'user' %}\n {{- '<|im_start|>user\\n'\n ~ content\n ~ '<|im_end|>\\n'\n }}\n {%- elif message.role == 'assistant' %}\n {%- set reasoning_content = '' %}\n {#- Prefer current vLLM's `reasoning` field, then retain compatibility\n with older `reasoning_content` and other servers' `thinking`. -#}\n {%- if message.reasoning is defined\n and message.reasoning is not none %}\n {%- if message.reasoning is string %}\n {%- set reasoning_content = message.reasoning %}\n {%- else %}\n {%- set reasoning_content =\n message.reasoning | string\n %}\n {%- endif %}\n {%- elif message.reasoning_content is defined\n and message.reasoning_content is not none %}\n {%- if message.reasoning_content is string %}\n {%- set reasoning_content = message.reasoning_content %}\n {%- else %}\n {%- set reasoning_content =\n message.reasoning_content | string\n %}\n {%- endif %}\n {%- elif message.thinking is defined\n and message.thinking is not none %}\n {%- if message.thinking is string %}\n {%- set reasoning_content = message.thinking %}\n {%- else %}\n {%- set reasoning_content =\n message.thinking | string\n %}\n {%- endif %}\n {%- endif %}\n {%- set reasoning_content = reasoning_content | trim %}\n {#- Preserve the original invariant: when thinking is preserved,\n always reconstruct the thinking block, even when it is empty. -#}\n {%- if _preserve_thinking\n or loop.index0 > ns.last_query_index %}\n {{- '<|im_start|>assistant\\n<think>\\n'\n ~ reasoning_content\n ~ '\\n</think>\\n\\n'\n ~ content\n }}\n {%- else %}\n {{- '<|im_start|>assistant\\n' ~ content }}\n {%- endif %}\n {%- if message.tool_calls is defined\n and message.tool_calls is not none\n and message.tool_calls %}\n {%- if message.tool_calls is string\n or message.tool_calls is mapping\n or message.tool_calls is not iterable %}\n {{- raise_exception(\n 'assistant.tool_calls must be an iterable list of tool calls.'\n ) }}\n {%- endif %}\n {%- for tool_call in message.tool_calls %}\n {%- if tool_call.function is defined\n and tool_call.function is not none %}\n {%- set tc = tool_call.function %}\n {%- else %}\n {%- set tc = tool_call %}\n {%- endif %}\n {%- if tc.name is not defined\n or tc.name is none\n or tc.name is not string\n or not tc.name %}\n {{- raise_exception(\n 'Every tool call must have a non-empty string name.'\n ) }}\n {%- endif %}\n {%- set tc_name = tc.name %}\n {%- if _tool_format == 'json' %}\n {%- if loop.first %}\n {%- if content | trim %}\n {{- '\\n\\n<tool_call>\\n' }}\n {%- else %}\n {{- '<tool_call>\\n' }}\n {%- endif %}\n {%- else %}\n {{- '\\n<tool_call>\\n' }}\n {%- endif %}\n {%- set _json_arguments = '{}' %}\n {%- if tc.arguments is defined\n and tc.arguments is not none %}\n {%- if tc.arguments is mapping %}\n {%- set _json_arguments =\n tc.arguments | tojson\n %}\n {%- elif tc.arguments is string %}\n {%- set _raw_arguments =\n tc.arguments | trim\n %}\n {%- if _raw_arguments %}\n {%- if not (\n _raw_arguments.startswith('{')\n and _raw_arguments.endswith('}')\n ) %}\n {{- raise_exception(\n 'JSON tool-call arguments must be a JSON object string.'\n ) }}\n {%- endif %}\n {%- set _json_arguments =\n _raw_arguments\n %}\n {%- endif %}\n {%- else %}\n {{- raise_exception(\n 'JSON tool-call arguments must be a mapping or a JSON object string.'\n ) }}\n {%- endif %}\n {%- endif %}\n {{- '{\"name\": ' }}\n {{- tc_name | tojson }}\n {{- ', \"arguments\": ' }}\n {{- _json_arguments }}\n {{- '}\\n</tool_call>' }}\n {%- else %}\n {%- if loop.first %}\n {%- if content | trim %}\n {{- '\\n\\n<tool_call>\\n<function='\n ~ tc_name\n ~ '>\\n'\n }}\n {%- else %}\n {{- '<tool_call>\\n<function='\n ~ tc_name\n ~ '>\\n'\n }}\n {%- endif %}\n {%- else %}\n {{- '\\n<tool_call>\\n<function='\n ~ tc_name\n ~ '>\\n'\n }}\n {%- endif %}\n {%- if tc.arguments is defined\n and tc.arguments is not none %}\n {%- if tc.arguments is mapping %}\n {%- for args_name, args_value\n in tc.arguments | items %}\n {%- set _argument_name =\n args_name | string\n %}\n {{- '<parameter='\n ~ _argument_name\n ~ '>\\n'\n }}\n {#- Preserve strings verbatim. Serialize every\n other type as JSON so booleans and null stay\n true/false/null instead of True/False/None. -#}\n {%- if args_value is string %}\n {%- set _argument_value =\n args_value\n %}\n {%- else %}\n {%- set _argument_value =\n args_value | tojson\n %}\n {%- endif %}\n {%- if max_tool_arg_chars > 0\n and _argument_value | length\n > max_tool_arg_chars %}\n {{- _argument_value[:max_tool_arg_chars] }}\n {{- '\\n[TRUNCATED — original length '\n ~ (_argument_value | length | string)\n ~ ' chars]'\n }}\n {%- else %}\n {{- _argument_value }}\n {%- endif %}\n {{- '\\n</parameter>\\n' }}\n {%- endfor %}\n {%- elif tc.arguments is string %}\n {%- set _raw_arguments =\n tc.arguments | trim\n %}\n {%- if _raw_arguments\n and _raw_arguments != '{}' %}\n {{- raise_exception(\n 'tool_call_format=\"xml\" requires tool-call arguments to be mappings, but received a JSON string. Parse the JSON string into a mapping before applying the template, or set tool_call_format=\"auto\" (or \"json\") to use the lossless JSON tool-call representation.'\n ) }}\n {%- endif %}\n {%- else %}\n {{- raise_exception(\n 'XML tool-call arguments must be a mapping. Parse JSON-string arguments before applying the template.'\n ) }}\n {%- endif %}\n {%- endif %}\n {{- '</function>\\n</tool_call>' }}\n {%- endif %}\n {%- endfor %}\n {%- endif %}\n {{- '<|im_end|>\\n' }}\n {%- elif message.role == 'tool' %}\n {%- if history_state.previous_role != 'tool' %}\n {{- '<|im_start|>user' }}\n {%- endif %}\n {%- if max_tool_response_chars > 0\n and content | length > max_tool_response_chars %}\n {%- set content =\n content[:max_tool_response_chars]\n ~ '\\n[TRUNCATED — original length '\n ~ (content | length | string)\n ~ ' chars]'\n %}\n {%- endif %}\n {{- '\\n<tool_response>\\n' }}\n {{- content }}\n {{- '\\n</tool_response>' }}\n {%- if loop.last %}\n {{- '<|im_end|>\\n' }}\n {%- elif _msgs[loop.index0 + 1].role != 'tool' %}\n {{- '<|im_end|>\\n' }}\n {%- endif %}\n {%- elif message.role == 'system'\n or message.role == 'developer' %}\n {{- raise_exception(\n 'System and developer messages must appear only at the beginning of the conversation.'\n ) }}\n {%- else %}\n {{- raise_exception(\n 'Unexpected message role ' ~ message.role ~ '.'\n ) }}\n {%- endif %}\n {%- set history_state.previous_role = message.role %}\n{%- endfor %}\n{#- -------------------------------------------------------------------------\n Generation prompt\n ------------------------------------------------------------------------- -#}\n{%- if add_generation_prompt %}\n {{- '<|im_start|>assistant\\n' }}\n {%- if not _thinking_enabled %}\n {{- '<think>\\n\\n</think>\\n\\n' }}\n {%- else %}\n {{- '<think>\\n' }}\n {%- endif %}\n{%- endif %}"
301
+ }