{# Harness-neutral nanochat chat template. Training adapters normalize tool turns into assistant content parts: text, tool_call (JSON text), and tool_output (JSON text). The call JSON keeps the source call ID, tool name, and arguments; the tool menu comes from `tools`. <|bos|> is added by the tokenizer and must not be emitted here. #} {%- set system = messages[0]['content'] if messages and messages[0]['role'] == 'system' else '' -%} {%- set ns = namespace(first_user=true) -%} {%- for message in messages -%} {%- if message['role'] == 'user' -%} {{ '<|user_start|>' }}{%- if ns.first_user and tools %}{{ tools|tojson }}{{ '\n\n' }}{%- endif -%}{%- if ns.first_user and system %}{{ system + '\n\n' }}{%- endif -%}{{ message['content'] }}{{ '<|user_end|>' }}{%- set ns.first_user = false -%} {%- elif message['role'] == 'assistant' -%} {{ '<|assistant_start|>' }}{%- if message['content'] is string -%}{{ message['content'] }}{%- else -%}{%- for part in message['content'] -%}{%- if part['type'] == 'text' -%}{{ part['text'] }}{%- elif part['type'] == 'python' -%}{{ '<|python_start|>' + part['text'] + '<|python_end|>' }}{%- elif part['type'] == 'python_output' -%}{{ '<|output_start|>' + part['text'] + '<|output_end|>' }}{%- elif part['type'] == 'tool_call' -%}{{ '' + part['text'] + '' }}{%- elif part['type'] == 'tool_output' -%}{{ '<|output_start|>' + part['text'] + '<|output_end|>' }}{%- endif -%}{%- endfor -%}{%- endif -%}{{ '<|assistant_end|>' }} {%- endif -%} {%- endfor -%} {%- if add_generation_prompt -%}{{ '<|assistant_start|>' }}{%- endif -%}