{{- bos_token -}} {%- set preserve_thinking = preserve_thinking | default(false) -%} {%- set enable_thinking = enable_thinking | default(true) -%} {%- macro render_value(v) -%} {%- if v is string -%} {{- v -}} {%- elif v is boolean -%} {{- "true" if v else "false" -}} {%- elif v is none -%} {{- "null" -}} {%- elif v is mapping or (v is sequence and v is not string) -%} {{- v | tojson -}} {%- else -%} {{- v -}} {%- endif -%} {%- endmacro -%} {%- macro parse_content(content) -%} {%- if content is string -%} {{- content -}} {%- elif content is mapping and content.get("type") == "image" -%} {{- "<|vision_start|><|image|><|vision_end|>" -}} {%- elif content is mapping and content.get("type") == "video" -%} {{- "<|vision_start|><|video|><|vision_end|>" -}} {%- elif content is mapping and content.get("type") == "text" -%} {{- (content.get("text") or "") | string -}} {%- elif content is mapping -%} {{- content | tojson -}} {%- elif content is iterable -%} {%- set _ns = namespace(result="") -%} {%- for item in content -%} {%- if item is string -%} {%- set _ns.result = _ns.result + item -%} {%- elif item is mapping and item.get("type") == "image" -%} {%- set _ns.result = _ns.result + "<|vision_start|><|image|><|vision_end|>" -%} {%- elif item is mapping and item.get("type") == "video" -%} {%- set _ns.result = _ns.result + "<|vision_start|><|video|><|vision_end|>" -%} {%- elif item is mapping and item.get("type") == "text" -%} {%- set _ns.result = _ns.result + ((item.get("text") or "") | string) -%} {%- else -%} {%- set _ns.result = _ns.result + (item | tojson) -%} {%- endif -%} {%- endfor -%} {{- _ns.result -}} {%- endif -%} {%- endmacro -%} {%- macro render_tool_calls(tool_calls) -%} {%- for tool_call in tool_calls -%} {%- if not loop.first -%}{{- "\n\n" -}}{%- endif -%} {%- set func = tool_call["function"] if "function" in tool_call else tool_call -%} {%- set func_args = func.get("arguments") -%} {%- if func_args is string and (func_args | trim) not in ["", "{}", "null"] -%} {{- raise_exception("Tool call arguments must be a mapping, got a JSON-encoded string: parse arguments with json.loads() before applying the chat template") -}} {%- endif -%} {{- "\n\n" -}} {%- if func_args is mapping -%} {%- for arg_name, arg_value in func_args.items() -%} {{- "\n" + render_value(arg_value) + "\n\n" -}} {%- endfor -%} {%- endif -%} {{- "\n" -}} {%- endfor -%} {%- endmacro -%} {%- macro tool_to_json(tool) -%} {%- set fn = tool.function if tool.function is defined else tool -%} {%- set ns_t = namespace(first=true) -%} {{- "{" -}} {%- for k, v in fn.items() -%} {%- if k != "defer_loading" -%} {%- if not ns_t.first -%}{{- ", " -}}{%- endif -%} {%- set ns_t.first = false -%} {{- k | tojson -}}{{- ": " -}}{{- v | tojson -}} {%- endif -%} {%- endfor -%} {{- "}" -}} {%- endmacro -%} {#- a tool_reference content part (vLLM, SGLang) names a tool from `tools`, usually a deferred one; it renders as that tool's definition -#} {%- macro is_tool_reference(item) -%} {{- "1" if item is mapping and item.get("type") == "tool_reference" else "" -}} {%- endmacro -%} {%- macro referenced_tool_to_json(name) -%} {%- set _ns = namespace(found=none) -%} {%- for tool in tools or [] -%} {%- set fn = tool.function if tool.function is defined else tool -%} {%- if fn.name == name -%} {%- set _ns.found = fn -%} {%- endif -%} {%- endfor -%} {%- if _ns.found is none -%} {{- raise_exception("tool_reference names a tool that is not in tools: " + name | string) -}} {%- endif -%} {{- tool_to_json(_ns.found) -}} {%- endmacro -%} {%- macro render_tool_response(content) -%} {#- content that already carries the tag (pre-formatted by the caller) is passed through as-is instead of being wrapped a second time -#} {%- if content is string and "" in content -%} {{- content -}} {%- else -%} {{- "\n" -}} {%- if content is string -%} {{- content -}} {%- elif content is mapping -%} {{- parse_content(content) -}} {%- elif content is iterable -%} {%- for item in content -%} {%- if not loop.first -%}{{- "\n" -}}{%- endif -%} {%- if is_tool_reference(item) -%} {#- consecutive references share one block -#} {%- if loop.first or not is_tool_reference(loop.previtem) -%} {{- "\n" -}} {%- endif -%} {{- referenced_tool_to_json(item.name) -}} {%- if loop.last or not is_tool_reference(loop.nextitem) -%} {{- "\n" -}} {%- endif -%} {%- elif item is mapping and item.result is defined and item.result is mapping and item.result.tools is defined -%} {{- "\n" -}} {%- set _tl = item.result.tools -%} {%- if _tl is string -%} {{- _tl -}} {%- elif _tl is mapping -%} {{- tool_to_json(_tl) -}} {%- else -%} {%- for t in _tl -%} {%- if not loop.first -%}{{- "\n" -}}{%- endif -%} {{- tool_to_json(t) -}} {%- endfor -%} {%- endif -%} {{- "\n" -}} {%- else -%} {{- parse_content(item) -}} {%- endif -%} {%- endfor -%} {%- endif -%} {{- "\n" -}} {%- endif -%} {%- endmacro -%} {%- set ns = namespace(system_prompt="", last_user_index=-1) -%} {%- if messages and messages[0]["role"] == "system" -%} {%- if messages[0].get("content") -%} {%- set ns.system_prompt = parse_content(messages[0]["content"]) -%} {%- endif -%} {%- set messages = messages[1:] -%} {%- endif -%} {%- if tools -%} {%- set tools_ns = namespace(lines=[]) -%} {%- for tool in tools -%} {%- set fn = tool.function if tool.function is defined else tool -%} {%- set _dyn = (fn.defer_loading is defined and fn.defer_loading) or (tool.defer_loading is defined and tool.defer_loading) -%} {%- if not _dyn -%} {%- set tools_ns.lines = tools_ns.lines + [tool_to_json(fn)] -%} {%- endif -%} {%- endfor -%} {%- if tools_ns.lines -%} {%- set ns.system_prompt = ns.system_prompt + ("\n\n" if ns.system_prompt else "") + "\n" + (tools_ns.lines | join("\n")) + "\n" -%} {%- endif -%} {%- endif -%} {%- if ns.system_prompt -%} {{- "<|im_start|>system\n" + ns.system_prompt + "<|im_end|>\n" -}} {%- endif -%} {%- for message in messages -%} {%- if message["role"] == "user" -%} {%- set ns.last_user_index = loop.index0 -%} {%- endif -%} {%- endfor -%} {#- vLLM's and SGLang's Anthropic /v1/messages adapters split one tool_result that carries tool_reference blocks into consecutive tool messages with the same tool_call_id (text first, references second). Merge such runs into one tool turn so they render exactly like a single OpenAI-format tool message whose content holds the same items. -#} {%- set carry = namespace(pending=[]) -%} {%- for message in messages -%} {%- set _next = messages[loop.index0 + 1] if not loop.last else none -%} {%- set _merge = message.role == "tool" and not message.get("additional_tools") and _next is not none and _next.role == "tool" and not _next.get("additional_tools") and message.get("tool_call_id") and _next.get("tool_call_id") == message.get("tool_call_id") -%} {%- set _items = [] -%} {%- if message.role == "tool" and not message.get("additional_tools") -%} {%- set _c = message.get("content") -%} {%- if _c is string -%} {%- set _items = [{"type": "text", "text": _c}] if _c else [] -%} {%- elif _c is mapping -%} {%- set _items = [_c] -%} {%- elif _c -%} {%- set _items = _c | list -%} {%- endif -%} {%- endif -%} {%- if _merge -%} {%- set carry.pending = carry.pending + _items -%} {%- else -%} {{- "<|im_start|>" + message.role + "\n" -}} {%- if message.role == "assistant" -%} {%- generation -%} {%- set thinking = message.thinking if message.thinking is defined else message.reasoning if message.reasoning is defined else message.reasoning_content -%} {%- set keep_thinking = preserve_thinking or loop.index0 > ns.last_user_index -%} {%- if thinking is defined and keep_thinking -%} {{- "" + (thinking or "") + "" -}} {%- endif -%} {%- set _cfm_tag = "CONTINUE_FINAL_MESSAGE_TAG " -%} {%- set _has_cfm = false -%} {%- set content = "" -%} {%- if message.get("content") -%} {%- set content = parse_content(message.content) -%} {%- endif -%} {%- if not keep_thinking -%} {%- if "" in content -%} {%- set content = content.split("")[-1] | trim -%} {%- endif -%} {%- set content = "" + content -%} {%- endif -%} {%- if content.endswith(_cfm_tag) -%} {%- set _has_cfm = true -%} {%- set _trunc_len = (content | length) - (_cfm_tag | length) -%} {%- set content = content[:_trunc_len] -%} {%- endif -%} {{- content -}} {%- if message.tool_calls -%} {{- render_tool_calls(message.tool_calls) -}} {%- endif -%} {%- if _has_cfm -%} {{- _cfm_tag -}} {%- endif -%} {{- "<|im_end|>\n" -}} {%- endgeneration -%} {%- elif message.role == "tool" -%} {%- if message.get("additional_tools") -%} {%- set _at = message["additional_tools"] -%} {#- definitions may live in additional_tools itself, or in content with additional_tools used as a plain truthy flag -#} {%- if _at is mapping or (_at is sequence and _at is not string) -%} {%- set _src = _at -%} {%- else -%} {%- set _src = message.get("content") -%} {%- endif -%} {#- nothing to reveal: skip the wrapper entirely rather than emitting an empty block -#} {%- if _src is string and "" in _src -%} {{- _src -}} {%- elif _src is string and "" in _src -%} {{- "\n" + _src + "\n" -}} {%- elif _src -%} {{- "\n\n" -}} {%- if _src is string -%} {{- _src -}} {%- elif _src is mapping -%} {{- tool_to_json(_src) -}} {%- else -%} {%- for t in _src -%} {%- if not loop.first -%}{{- "\n" -}}{%- endif -%} {{- tool_to_json(t) -}} {%- endfor -%} {%- endif -%} {{- "\n\n" -}} {%- endif -%} {%- elif carry.pending -%} {{- render_tool_response(carry.pending + _items) -}} {%- set carry.pending = [] -%} {%- else -%} {#- an empty or missing result still gets the wrapper, so every tool turn has the same shape -#} {{- render_tool_response(message.get("content") or "") -}} {%- endif -%} {{- "<|im_end|>\n" -}} {%- else %} {%- if message.get("content") -%} {{- parse_content(message["content"]) -}} {%- endif -%} {{- "<|im_end|>\n" -}} {%- endif %} {%- endif -%} {%- endfor -%} {%- if add_generation_prompt -%} {{- "<|im_start|>assistant\n" -}} {%- if enable_thinking -%} {{- "" -}} {%- else -%} {{- "" -}} {%- endif -%} {%- endif -%}