{# DeepSeek-V3.2 DSML chat template (compatible with encoding_dsv32.py) #} {%- if thinking is not defined %}{% set thinking = false %}{% endif -%} {%- if drop_thinking is not defined %}{% set drop_thinking = true %}{% endif -%} {%- set dsml_token = "|DSML|" -%} {%- set thinking_start_token = "" -%} {%- set thinking_end_token = "" -%} {%- set eos_token = "<|end▁of▁sentence|>" -%} {# Identify last user/developer index #} {%- set ns = namespace(last_user=-1) -%} {%- for message in messages -%} {%- if message["role"] in ["user", "developer"] -%} {%- set ns.last_user = loop.index0 -%} {%- endif -%} {%- endfor -%} {# Build system prompt (concatenate all system messages) #} {%- set sp = namespace(text="") -%} {%- for message in messages -%} {%- if message["role"] == "system" -%} {%- if sp.text -%} {%- set sp.text = sp.text + "\n\n" + (message["content"] or "") -%} {%- else -%} {%- set sp.text = (message["content"] or "") -%} {%- endif -%} {%- endif -%} {%- endfor -%} {# Tools block if provided globally #} {%- if tools is defined and tools is not none -%} {%- set tool_ns = namespace(text="") -%} {%- for tool in tools -%} {%- set t = tool["function"] if tool.get("function") else tool -%} {%- if loop.first -%} {%- set tool_ns.text = tool_ns.text + (t | tojson) -%} {%- else -%} {%- set tool_ns.text = tool_ns.text + "\n" + (t | tojson) -%} {%- endif -%} {%- endfor -%} {%- set tools_block -%} ## Tools You have access to a set of tools you can use to answer the user's question. You can invoke functions by writing a "<{{ dsml_token }}function_calls>" block like the following as part of your reply to the user: <{{ dsml_token }}function_calls> <{{ dsml_token }}invoke name="$FUNCTION_NAME"> <{{ dsml_token }}parameter name="$PARAMETER_NAME" string="true|false">$PARAMETER_VALUE ... <{{ dsml_token }}invoke name="$FUNCTION_NAME2"> ... String and scalar parameters should be specified as is without any escaping or quotes, while lists and objects should use JSON format. The "string" attribute should be set to "true" for string type parameters and "false" for other types (numbers, booleans, arrays, objects). If the thinking_mode is enabled, then after function results you should strongly consider outputting a thinking block. Here is an example: <{{ dsml_token }}function_calls> ... ... {{ thinking_start_token }}...thinking about results{{ thinking_end_token }} Here are the functions available in JSONSchema format: {{ tool_ns.text }} {%- endset -%} {%- if sp.text -%} {%- set sp.text = sp.text + "\n\n" + tools_block -%} {%- else -%} {%- set sp.text = "\n\n" + tools_block -%} {%- endif -%} {%- endif -%} {# Response format on system messages #} {%- for message in messages -%} {%- if message["role"] == "system" and message.get("response_format") -%} {%- set sp.text = sp.text + "\n\n## Response Format:\n\nYou MUST strictly adhere to the following schema to reply:\n" + (message["response_format"] | tojson) -%} {%- endif -%} {%- endfor -%} {# Emit BOS and system prompt #} {{- sp.text -}} {# Render messages #} {%- for message in messages -%} {%- set idx = loop.index0 -%} {%- set role = message["role"] -%} {%- set content = message.get("content", "") if message.get("content") is not none else "" -%} {%- if role == "developer" -%} {%- set dev_content = "" -%} {%- if message.get("response_format") -%} {%- set dev_content = dev_content + "\n\n## Response Format:\n\nYou MUST strictly adhere to the following schema to reply:\n" + (message["response_format"] | tojson) -%} {%- endif -%} {%- set dev_content = dev_content + "\n\n# The user's message is: " + content -%} {{ "<|User|>" + dev_content + "<|Assistant|>" }}{{ thinking_start_token if idx == ns.last_user and thinking else thinking_end_token }} {%- elif role == "user" -%} {{ "<|User|>" + content + "<|Assistant|>" }}{{ thinking_start_token if idx == ns.last_user and thinking else thinking_end_token }} {%- elif role == "assistant" -%} {%- if message.get("tool_calls") -%} {%- set first = true -%} {%- if idx > ns.last_user and thinking and (message.get("reasoning_content") or message.get("tool_calls")) -%} {{ (message.get("reasoning_content","") if not (thinking and drop_thinking and idx <= ns.last_user) else "") + thinking_end_token }} {%- else -%} {{ message.get("reasoning_content","") if not (thinking and drop_thinking and idx <= ns.last_user) else "" }} {%- endif -%} {%- set tc = namespace(first=true) -%} {%- for tool in message["tool_calls"] -%} {%- set func = tool["function"] -%} {%- set tool_name = func["name"] -%} {%- set raw_args = func["arguments"] -%} {%- set param_ns = namespace(text="", first=true) -%} {%- if raw_args is mapping -%} {%- set parsed = raw_args -%} {%- elif raw_args is string -%} {%- set parsed = raw_args | from_json -%} {%- else -%} {%- set parsed = {} -%} {%- endif -%} {%- for k,v in parsed.items() -%} {%- set is_str = "true" if v is string else "false" -%} {%- if v is string -%} {%- set val = v -%} {%- else -%} {%- set val = v | tojson -%} {%- endif -%} {%- set piece = "<" + dsml_token + "parameter name=\"" + k + "\" string=\"" + is_str + "\">" + val + "" -%} {%- if param_ns.first -%} {%- set param_ns.text = piece -%} {%- set param_ns.first = false -%} {%- else -%} {%- set param_ns.text = param_ns.text + "\n" + piece -%} {%- endif -%} {%- endfor -%} {%- set param_block = param_ns.text -%} {%- if tc.first -%} {%- if content -%} {{ content + "\n\n<" + dsml_token + "function_calls>\n" + "<" + dsml_token + "invoke name=\"" + tool_name + "\">\n" + param_block + "\n" }} {%- else -%} {{ "\n\n<" + dsml_token + "function_calls>\n" + "<" + dsml_token + "invoke name=\"" + tool_name + "\">\n" + param_block + "\n" }} {%- endif -%} {%- set tc.first = false -%} {%- else -%} {{ "\n" + "<" + dsml_token + "invoke name=\"" + tool_name + "\">\n" + param_block + "\n" }} {%- endif -%} {%- endfor -%} {{ "\n" + eos_token }} {%- else -%} {%- if idx > ns.last_user and thinking and not (drop_thinking and idx <= ns.last_user) and message.get("reasoning_content") -%} {{ message["reasoning_content"] + thinking_end_token }} {%- endif -%} {{ content + eos_token }} {%- endif -%} {%- elif role == "tool" -%} {%- set is_first_tool = loop.index0 == 0 or messages[loop.index0 - 1]["role"] != "tool" -%} {%- set is_last_tool = loop.last or messages[loop.index0 + 1]["role"] != "tool" -%} {%- if is_first_tool -%}{{- "\n\n" -}}{%- endif -%} {{- "\n" + content + "" -}} {%- if is_last_tool -%} {{- "\n" -}} {{- ("\n\n" + thinking_start_token) if idx >= ns.last_user and thinking else ("\n\n" + thinking_end_token) -}} {%- endif -%} {%- endif -%} {%- endfor -%} {# No extra generation prompt needed; assistant prefix is handled inline #}