Taka008 commited on
Commit
99ab5e8
·
verified ·
1 Parent(s): 5d72e3e

Upload chat_template.jinja

Browse files
Files changed (1) hide show
  1. chat_template.jinja +13 -43
chat_template.jinja CHANGED
@@ -1,3 +1,4 @@
 
1
  {#-
2
  In addition to the normal inputs of `messages` and `tools`, this template also accepts the
3
  following kwargs:
@@ -261,12 +262,8 @@
261
  {%- endif %}
262
 
263
  {#- Render messages #}
264
- {#- tool_group tracks the names of the calls in the most recent assistant tool_calls #}
265
- {#- message (in call order) and how many of their results have been rendered, so tool #}
266
- {#- results that arrive without a "name" field (all OpenAI clients: they only carry #}
267
- {#- tool_call_id) can be attributed positionally -- the same by-order convention the #}
268
- {#- training tokenizer uses. Falling back to last_tool_call.name instead would label #}
269
- {#- every result of a parallel batch with the LAST call's function name. #}
270
  {%- set last_tool_call = namespace(name=none) %}
271
  {%- set tool_group = namespace(names=[], result_idx=0) %}
272
  {%- for message in loop_messages -%}
@@ -284,51 +281,26 @@
284
  {%- endif %}
285
  {%- endif %}
286
  {%- if "tool_calls" in message %}
287
- {#- We need very careful handling here - we want to drop the tool call analysis message if the model #}
288
- {#- has output a later <|final|> message, but otherwise we want to retain it. This is the only case #}
289
- {#- when we render CoT/analysis messages in inference. #}
290
- {%- set future_final_message = namespace(found=false) %}
291
- {#- A later final closes this tool loop and drops its reasoning -- but only #}
292
- {#- if that final is NOT the last message. When the final IS last, we are #}
293
- {#- rendering the training target that closes the loop: the model generated #}
294
- {#- that final WITH the in-loop reasoning still in context, so the render #}
295
- {#- must keep it (otherwise the prompt render is not a prefix of the full #}
296
- {#- render and the loss mask is corrupted). At inference a history final is #}
297
- {#- always followed by at least a user message, so behavior is unchanged. #}
298
- {%- for future_message in loop_messages[loop.index:] %}
299
- {%- if future_message.role == 'assistant' and "tool_calls" not in future_message and not loop.last %}
300
- {%- set future_final_message.found = true %}
301
- {%- endif %}
302
- {%- endfor %}
303
- {#- Render the analysis/CoT once, before the (possibly parallel) batch of calls. #}
304
  {%- if message.content and message.thinking %}
305
  {{- raise_exception("Cannot pass both content and thinking in an assistant message with tool calls! Put the analysis message in one or the other, but not both.") }}
306
- {%- elif message.content and not future_final_message.found %}
307
  {{- "<|start|>assistant<|channel|>analysis<|message|>" + message.content + "<|end|>" }}
308
- {%- elif message.thinking and not future_final_message.found %}
309
  {{- "<|start|>assistant<|channel|>analysis<|message|>" + message.thinking + "<|end|>" }}
310
  {%- endif %}
311
- {#- Parallel tool calling: render every call in message.tool_calls. All calls #}
312
- {#- except the last terminate with <|end|> (a continuation token, so sampling #}
313
- {#- does not stop); only the final call terminates with <|call|> (the dispatch #}
314
- {#- /stop token). A message with a single tool call therefore renders identically #}
315
- {#- to the non-parallel template. #}
316
  {%- set tool_group.names = [] %}
317
  {%- set tool_group.result_idx = 0 %}
318
  {%- for raw_tool_call in message.tool_calls %}
319
  {%- set tool_call = raw_tool_call.function if raw_tool_call.function else raw_tool_call %}
320
  {{- "<|start|>assistant to=" }}
321
  {{- "functions." + tool_call.name + "<|channel|>commentary " }}
322
- {#- Default content_type must match the training data, which always carries #}
323
- {#- "<|constrain|> json" on every assistant call. OpenAI clients never send #}
324
- {#- content_type, so a bare "json" default would replay prior calls into the #}
325
- {#- context in a header form the model never saw during training. #}
326
  {{- (tool_call.content_type if tool_call.content_type is defined else "<|constrain|> json") + "<|message|>" }}
327
- {#- Arguments are already a JSON string in our data/inference inputs, so emit #}
328
- {#- them verbatim. Applying |tojson to a string would re-encode it as a quoted, #}
329
- {#- escaped string literal (e.g. "{\"city\": \"x\"}"), which is non-standard #}
330
- {#- harmony and forces the serving wrapper into fragile unescaping. Only dict #}
331
- {#- arguments (some OpenAI clients) need |tojson. #}
332
  {{- tool_call.arguments if tool_call.arguments is string else tool_call.arguments|tojson }}
333
  {%- if loop.last %}
334
  {{- "<|call|>" }}
@@ -354,10 +326,8 @@
354
  {%- set last_tool_call.name = none %}
355
  {%- endif %}
356
  {%- elif message.role == 'tool' -%}
357
- {#- Prefer the source function name carried on the tool message itself (the tokenizer #}
358
- {#- tags each parallel result with its own call name); otherwise attribute results #}
359
- {#- positionally within the current call group (call order == result order, the #}
360
- {#- training convention); last_tool_call.name remains only as a legacy fallback. #}
361
  {%- if message.name is defined and message.name %}
362
  {%- set tool_name = message.name %}
363
  {%- elif tool_group.result_idx < tool_group.names|length %}
 
1
+ {#- chat_format=llm-jp-harmony-v1 -#}
2
  {#-
3
  In addition to the normal inputs of `messages` and `tools`, this template also accepts the
4
  following kwargs:
 
262
  {%- endif %}
263
 
264
  {#- Render messages #}
265
+ {#- tool_group: call names of the latest assistant tool_calls message, in call order, #}
266
+ {#- plus how many of their results have been rendered (nameless results are attributed by order) #}
 
 
 
 
267
  {%- set last_tool_call = namespace(name=none) %}
268
  {%- set tool_group = namespace(names=[], result_idx=0) %}
269
  {%- for message in loop_messages -%}
 
281
  {%- endif %}
282
  {%- endif %}
283
  {%- if "tool_calls" in message %}
284
+ {#- Drop-all: previous-turn analysis/CoT is never rendered. It is emitted only for the #}
285
+ {#- training target (last message, add_generation_prompt=false), once before the calls. #}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
  {%- if message.content and message.thinking %}
287
  {{- raise_exception("Cannot pass both content and thinking in an assistant message with tool calls! Put the analysis message in one or the other, but not both.") }}
288
+ {%- elif message.content and loop.last and not add_generation_prompt %}
289
  {{- "<|start|>assistant<|channel|>analysis<|message|>" + message.content + "<|end|>" }}
290
+ {%- elif message.thinking and loop.last and not add_generation_prompt %}
291
  {{- "<|start|>assistant<|channel|>analysis<|message|>" + message.thinking + "<|end|>" }}
292
  {%- endif %}
293
+ {#- Parallel tool calls: every call is rendered; all but the last end with <|end|>, #}
294
+ {#- the last with <|call|>. A single call renders as in the non-parallel template. #}
 
 
 
295
  {%- set tool_group.names = [] %}
296
  {%- set tool_group.result_idx = 0 %}
297
  {%- for raw_tool_call in message.tool_calls %}
298
  {%- set tool_call = raw_tool_call.function if raw_tool_call.function else raw_tool_call %}
299
  {{- "<|start|>assistant to=" }}
300
  {{- "functions." + tool_call.name + "<|channel|>commentary " }}
301
+ {#- content_type default must match the training data ("<|constrain|> json") #}
 
 
 
302
  {{- (tool_call.content_type if tool_call.content_type is defined else "<|constrain|> json") + "<|message|>" }}
303
+ {#- String arguments are already JSON: emit verbatim; only dict arguments need |tojson #}
 
 
 
 
304
  {{- tool_call.arguments if tool_call.arguments is string else tool_call.arguments|tojson }}
305
  {%- if loop.last %}
306
  {{- "<|call|>" }}
 
326
  {%- set last_tool_call.name = none %}
327
  {%- endif %}
328
  {%- elif message.role == 'tool' -%}
329
+ {#- Tool name: message.name if given, else by position in the current call group #}
330
+ {#- (call order == result order), else the last call (legacy fallback). #}
 
 
331
  {%- if message.name is defined and message.name %}
332
  {%- set tool_name = message.name %}
333
  {%- elif tool_group.result_idx < tool_group.names|length %}