{#- This template extends the base model template to support tool calling. Tools are injected into the system prompt using XML tags. Tool calls use XML tags, tool responses use tags. Handles all combinations: 1. tools + user system message → single system block: tool instructions + user content 2. tools + NO system message → single synthetic system block with tool instructions 3. no tools + user system message → single system block with user content 4. no tools + no system message → minimal default system block Thinking mode: if any system message contains "thinking on", all system blocks end with "thinking on" and the generation prompt emits an open . Otherwise "thinking off" is used and is immediately closed. "thinking on" / "thinking off" is stripped from user system content and re-appended as the final line of the system block to keep it consistent. -#} {%- set loop_messages = messages %} {%- set ns = namespace(thinking=false, has_tools=false, has_system=false, system_emitted=false) %} {#- ===== Method A: Check kwarg ===== -#} {%- if enable_thinking is defined and enable_thinking %} {%- set ns.thinking = true %} {%- endif %} {#- ===== PASS 1: Scan messages to detect thinking mode and system presence ===== -#} {%- for message in loop_messages %} {%- if message['role'] == 'system' %} {%- set ns.has_system = true %} {%- if 'thinking on' in message['content'] %} {%- set ns.thinking = true %} {%- endif %} {%- endif %} {%- endfor %} {#- ===== Build tool instruction block if tools provided ===== -#} {%- if tools is defined and tools is not none and tools | length > 0 %} {%- set ns.has_tools = true %} {%- set tool_instruction %} You are a function calling AI model. You are provided with function signatures within XML tags. You may call one or more functions to assist with the user query. Don't make assumptions about what values to plug into functions. Here are the available tools: {{ tools | tojson }} For each function call, return a JSON object with function name and arguments within XML tags as follows: {"name": , "arguments": } {%- endset %} {%- endif %} {#- ===== Thinking mode suffix — appended to every system block ===== -#} {%- set thinking_suffix = "thinking on" if ns.thinking else "thinking off" %} {#- ===== SYNTHETIC SYSTEM BLOCK (only if NO system messages in conversation) ===== -#} {%- if not ns.has_system %} {%- if ns.has_tools %} {{- 'System\n' }} {{- tool_instruction + '\n\n' }} {{- thinking_suffix + '\n' }} {%- else %} {{- 'System\n' }} {{- thinking_suffix + '\n' }} {%- endif %} {%- set ns.system_emitted = true %} {%- endif %} {#- ===== PASS 2: Render messages ===== -#} {%- for message in loop_messages %} {#- ---- SYSTEM MESSAGE ---- -#} {%- if message['role'] == 'system' %} {#- Strip thinking directives from the content — we handle them via thinking_suffix -#} {%- set clean_content = message['content'] | replace('thinking on', '') | replace('thinking off', '') | trim %} {{- 'System\n' }} {%- if ns.has_tools %} {{- tool_instruction + '\n' }} {%- endif %} {%- if clean_content %} {{- clean_content + '\n' }} {%- endif %} {{- thinking_suffix + '\n' }} {%- set ns.system_emitted = true %} {#- ---- USER MESSAGE ---- -#} {%- elif message['role'] == 'user' %} {{- 'User\n' }} {{- message['content'] + '\n' }} {#- ---- ASSISTANT MESSAGE ---- -#} {%- elif message['role'] == 'assistant' %} {%- if message.tool_calls is defined and message.tool_calls | length > 0 %} {{- 'Assistant\n' }} {%- for tool_call in message.tool_calls %} {{- '\n' }} {{- {"name": tool_call.function.name, "arguments": tool_call.function.arguments} | tojson + '\n' }} {{- '\n' }} {%- endfor %} {%- else %} {{- 'Assistant\n' }} {{- message['content'] + '\n' }} {%- endif %} {#- ---- TOOL RESPONSE MESSAGE ---- -#} {%- elif message['role'] == 'tool' %} {{- 'User\n' }} {{- '\n' }} {{- message['content'] + '\n' }} {{- '\n' }} {%- endif %} {%- endfor %} {#- ===== Generation prompt ===== -#} {%- if add_generation_prompt %} {{- 'Assistant\n' }} {%- if ns.thinking %} {{- '\n' }} {%- else %} {{- '\n\n\n' }} {%- endif %} {%- endif %}