File size: 12,015 Bytes
31656e6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
{%- set image_count = namespace(value=0) %}

{%- set video_count = namespace(value=0) %}

{%- macro render_content(content, do_vision_count, is_system_content=false) %}

    {%- if content is string %}

        {{- content }}

    {%- elif content is iterable and content is not mapping %}

        {%- for item in content %}

            {%- if 'image' in item or 'image_url' in item or item.type == 'image' %}

                {%- if is_system_content %}

                    {{- raise_exception('System message cannot contain images.') }}

                {%- endif %}

                {%- if do_vision_count %}

                    {%- set image_count.value = image_count.value + 1 %}

                {%- endif %}

                {%- if add_vision_id is defined and add_vision_id %}

                    {{- 'Picture ' ~ image_count.value ~ ': ' }}

                {%- endif %}

                {{- '<|vision_start|><|image_pad|><|vision_end|>' }}

            {%- elif 'video' in item or item.type == 'video' %}

                {%- if is_system_content %}

                    {{- raise_exception('System message cannot contain videos.') }}

                {%- endif %}

                {%- if do_vision_count %}

                    {%- set video_count.value = video_count.value + 1 %}

                {%- endif %}

                {%- if add_vision_id is defined and add_vision_id %}

                    {{- 'Video ' ~ video_count.value ~ ': ' }}

                {%- endif %}

                {{- '<|vision_start|><|video_pad|><|vision_end|>' }}

            {%- elif 'text' in item %}

                {{- item.text }}

            {%- else %}

                {{- raise_exception('Unexpected item type in content.') }}

            {%- endif %}

        {%- endfor %}

    {%- elif content is none or content is undefined %}

        {{- '' }}

    {%- else %}

        {{- raise_exception('Unexpected content type.') }}

    {%- endif %}

{%- endmacro %}

{%- set ns_flags = namespace(enable_thinking=true) %}

{%- if enable_thinking is defined %}

    {%- set ns_flags.enable_thinking = enable_thinking %}

{%- endif %}

{%- set preserve_thinking = preserve_thinking | default(true) %}

{%- if not messages %}

    {{- raise_exception('No messages provided.') }}

{%- endif %}

{%- if add_generation_prompt is defined and add_generation_prompt and continue_final_message is defined and continue_final_message %}

    {{- raise_exception('add_generation_prompt and continue_final_message cannot both be true.') }}

{%- endif %}

{%- if tools and tools is iterable and tools is not mapping %}

    {{- '<|im_start|>system\n' }}

    {{- "# Tools\n\nYou have access to the following functions:\n\n<tools>" }}

    {%- for tool in tools %}

        {{- "\n" }}

        {{- tool | tojson }}

    {%- endfor %}

    {{- "\n</tools>" }}

    {{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<tool_call>\n<function=example_function_name>\n<parameter=example_parameter_1>\nvalue_1\n</parameter>\n<parameter=example_parameter_2>\nThis is the value for the second parameter\nthat can span\nmultiple lines\n</parameter>\n</function>\n</tool_call>\n\n<IMPORTANT>\nReminder:\n- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags\n- Required parameters MUST be specified\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\n</IMPORTANT>' }}

    {%- if messages[0].role == 'system' or messages[0].role == 'developer' %}

        {%- set content = render_content(messages[0].content, false, true)|trim %}

        {%- if '<|think_off|>' in content %}

            {%- set ns_flags.enable_thinking = false %}

            {%- set content = content.replace('<|think_off|>', '') %}

        {%- endif %}

        {%- if '<|think_on|>' in content %}

            {%- set ns_flags.enable_thinking = true %}

            {%- set content = content.replace('<|think_on|>', '') %}

        {%- endif %}

        {%- set content = content.strip() %}

        {%- if content %}

            {{- '\n\n' + content }}

        {%- endif %}

    {%- endif %}

    {{- '<|im_end|>\n' }}

{%- else %}

    {%- if messages[0].role == 'system' or messages[0].role == 'developer' %}

        {%- set content = render_content(messages[0].content, false, true)|trim %}

        {%- if '<|think_off|>' in content %}

            {%- set ns_flags.enable_thinking = false %}

            {%- set content = content.replace('<|think_off|>', '') %}

        {%- endif %}

        {%- if '<|think_on|>' in content %}

            {%- set ns_flags.enable_thinking = true %}

            {%- set content = content.replace('<|think_on|>', '') %}

        {%- endif %}

        {%- set content = content.strip() %}

        {{- '<|im_start|>system\n' + content + '<|im_end|>\n' }}

    {%- endif %}

{%- endif %}

{%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}

{%- for message in messages[::-1] %}

    {%- set index = (messages|length - 1) - loop.index0 %}

    {%- if ns.multi_step_tool and message.role == "user" %}

        {%- set content = render_content(message.content, false)|trim %}

        {%- if not(content.startswith('<tool_response>') and content.endswith('</tool_response>')) %}

            {%- set ns.multi_step_tool = false %}

            {%- set ns.last_query_index = index %}

        {%- endif %}

    {%- endif %}

{%- endfor %}

{%- if ns.multi_step_tool %}

    {%- set ns.last_query_index = messages|length - 1 %}

{%- endif %}

{%- for message in messages %}

    {%- set content = render_content(message.content, true)|trim %}

    {%- set content = content.replace('<|think_off|>', '').replace('<|think_on|>', '') %}

    {%- set content = content.strip() %}

    {%- if message.role == "system" or message.role == "developer" %}

        {%- if not loop.first %}

            {%- set sys_content = render_content(message.content, false, true)|trim %}

            {%- set sys_content = sys_content.replace('<|think_off|>', '').replace('<|think_on|>', '')|trim %}

            {{- '<|im_start|>system\n' + sys_content + '<|im_end|>' + '\n' }}

        {%- endif %}

    {%- elif message.role == "user" %}

        {{- '<|im_start|>' + message.role + '\n' + (content if content else ' ') + '<|im_end|>' + '\n' }}

    {%- elif message.role == "assistant" %}

        {%- set reasoning_content = '' %}

        {%- if message.reasoning_content is string %}

            {%- set reasoning_content = message.reasoning_content %}

        {%- else %}

            {%- set has_think_tag = false %}

            {%- set think_start_token = '<think>' %}

            {%- set think_end_token = '</think>' %}

            {%- if '</think>' in content %}

                {%- set has_think_tag = true %}

            {%- elif '</thinking>' in content %}

                {%- set has_think_tag = true %}

                {%- set think_start_token = '<thinking>' %}

                {%- set think_end_token = '</thinking>' %}

            {%- elif '<think>' in content %}

                {%- set reasoning_content = content.split('<think>')[-1].lstrip('\n') %}

                {%- set content = '' %}

            {%- elif '<thinking>' in content %}

                {%- set reasoning_content = content.split('<thinking>')[-1].lstrip('\n') %}

                {%- set content = '' %}

            {%- endif %}

            {%- if has_think_tag %}

                {%- set reasoning_content = content.split(think_end_token)[0].rstrip('\n').split(think_start_token)[-1].lstrip('\n') %}

                {%- set content = content.split(think_end_token)[-1].lstrip('\n') %}

            {%- endif %}

        {%- endif %}

        {%- set reasoning_content = reasoning_content|trim %}

        {%- set show_think = false %}

        {%- if loop.index0 > ns.last_query_index and reasoning_content|length > 0 %}

            {%- set show_think = true %}

        {%- elif ns_flags.enable_thinking and preserve_thinking and reasoning_content|length > 0 %}

            {%- set show_think = true %}

        {%- endif %}

        {%- if show_think %}

            {{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content + '\n</think>\n\n' + content }}

        {%- else %}

            {{- '<|im_start|>' + message.role + '\n' + content }}

        {%- endif %}

        {%- if message.tool_calls and message.tool_calls is iterable and message.tool_calls is not mapping %}

            {%- for tool_call in message.tool_calls %}

                {%- if tool_call.function is defined %}

                    {%- set tool_call = tool_call.function %}

                {%- endif %}

                {%- if loop.first %}

                    {%- if content|trim %}

                        {{- '\n\n<tool_call>\n<function=' + tool_call.name + '>\n' }}

                    {%- else %}

                        {{- '<tool_call>\n<function=' + tool_call.name + '>\n' }}

                    {%- endif %}

                {%- else %}

                    {{- '\n<tool_call>\n<function=' + tool_call.name + '>\n' }}

                {%- endif %}

                {%- if tool_call.arguments is defined and tool_call.arguments is mapping %}

                    {%- if tool_call.arguments|length > 0 %}

                        {%- for args_name in tool_call.arguments %}

                            {%- set args_value = tool_call.arguments[args_name] %}

                            {{- '<parameter=' + args_name + '>\n' }}

                            {%- set args_value = args_value | string if args_value is string else args_value | tojson %}

                            {{- args_value }}

                            {{- '\n</parameter>\n' }}

                        {%- endfor %}

                    {%- endif %}

                {%- elif tool_call.arguments is defined and tool_call.arguments is string %}

                    {%- if tool_call.arguments|trim|length > 0 %}

                        {#- Note: raw JSON string arguments are emitted as-is and will not match

                            the XML parameter format in the tool instructions. Normalize arguments

                            to a dict in your serving layer before applying this template. -#}

                        {{- tool_call.arguments }}

                        {{- '\n' }}

                    {%- endif %}

                {%- endif %}

                {{- '</function>\n</tool_call>' }}

            {%- endfor %}

        {%- endif %}

        {%- if not (loop.last and continue_final_message is defined and continue_final_message is true) %}

            {{- '<|im_end|>\n' }}

        {%- endif %}

    {%- elif message.role == "tool" %}

        {%- if not loop.previtem or (loop.previtem.role != "tool" and loop.previtem.role != "assistant") %}

            {{- raise_exception('A tool message must follow an assistant or tool message.') }}

        {%- endif %}

        {%- if loop.previtem and loop.previtem.role != "tool" %}

            {{- '<|im_start|>user' }}

        {%- endif %}

        {{- '\n<tool_response>\n' }}

        {{- content }}

        {{- '\n</tool_response>' }}

        {%- if not loop.last and loop.nextitem.role != "tool" %}

            {{- '<|im_end|>\n' }}

        {%- elif loop.last %}

            {{- '<|im_end|>\n' }}

        {%- endif %}

    {%- else %}

        {{- raise_exception('Unexpected message role.') }}

    {%- endif %}

{%- endfor %}

{%- if add_generation_prompt %}

    {{- '<|im_start|>assistant\n' }}

    {%- if ns_flags.enable_thinking is false %}

        {{- '<think>\n\n</think>\n\n' }}

    {%- else %}

        {{- '<think>\n' }}

    {%- endif %}

{%- endif %}