1
+ {% - macro render_typescript_type (param_spec , required_params , is_nullable =false ) -%}
2
+ {% - if param_spec .type == "array" -%}
3
+ {% - if param_spec ['items' ] -%}
4
+ {% - if param_spec ['items' ]['type' ] == "string" -%}
5
+ {{- "string[] " }}
6
+ {% - elif param_spec ['items' ]['type' ] == "number" -%}
7
+ {{- "number[] " }}
8
+ {% - elif param_spec ['items' ]['type' ] == "integer" -%}
9
+ {{- "number[] " }}
10
+ {% - elif param_spec ['items' ]['type' ] == "boolean" -%}
11
+ {{- "boolean[] " }}
12
+ {% - else -%}
13
+ {% - set inner_type = render_typescript_type (param_spec ['items' ], required_params ) -%}
14
+ {% - if inner_type == "object | object" or inner_type |length > 50 -%}
15
+ {{- "any[] " }}
16
+ {% - else -%}
17
+ {{- inner_type + "[] " }}
18
+ {% - endif -%}
19
+ {% - endif -%}
20
+ {% - if param_spec .nullable -%}
21
+ {{- " | null" }}
22
+ {% - endif -%}
23
+ {% - else -%}
24
+ {{- "any[] " }}
25
+ {% - if param_spec .nullable -%}
26
+ {{- " | null" }}
27
+ {% - endif -%}
28
+ {% - endif -%}
29
+ {% - elif param_spec .type is defined and param_spec .type is iterable and param_spec .type is not string and param_spec .type is not mapping and param_spec .type [0] is defined -%}
30
+ {#- Handle array of types like ["object", "object"] from Union[dict, list] #}
31
+ {% - if param_spec .type | length > 1 -%}
32
+ {{- param_spec.type | join(" | ") }}
33
+ {% - else -%}
34
+ {{- param_spec.type[0] }}
35
+ {% - endif -%}
36
+ {% - elif param_spec .oneOf -%}
37
+ {#- Handle oneOf schemas - check for complex unions and fallback to any #}
38
+ {% - set has_object_variants = false -%}
39
+ {% - for variant in param_spec .oneOf -%}
40
+ {% - if variant .type == "object" -%}
41
+ {% - set has_object_variants = true -%}
42
+ {% - endif -%}
43
+ {% - endfor -%}
44
+ {% - if has_object_variants and param_spec .oneOf |length > 1 -%}
45
+ {{- "any" }}
46
+ {% - else -%}
47
+ {% - for variant in param_spec .oneOf -%}
48
+ {{- render_typescript_type(variant, required_params) -}}
49
+ {% - if variant .description %}
50
+ {{- "// " + variant.description }}
51
+ {% - endif -%}
52
+ {% - if variant .default is defined %}
53
+ {{ "// default: " + variant.default|tojson }}
54
+ {% - endif -%}
55
+ {% - if not loop .last %}
56
+ {{- " | " }}
57
+ {% endif -%}
58
+ {% - endfor -%}
59
+ {% - endif -%}
60
+ {% - elif param_spec .type == "string" -%}
61
+ {% - if param_spec .enum -%}
62
+ {{- '"' + param_spec.enum|join('" | "') + '"' -}}
63
+ {% - else -%}
64
+ {{- "string" }}
65
+ {% - if param_spec .nullable %}
66
+ {{- " | null" }}
67
+ {% - endif -%}
68
+ {% - endif -%}
69
+ {% - elif param_spec .type == "number" -%}
70
+ {{- "number" }}
71
+ {% - elif param_spec .type == "integer" -%}
72
+ {{- "number" }}
73
+ {% - elif param_spec .type == "boolean" -%}
74
+ {{- "boolean" }}
75
+ {% - elif param_spec .type == "object" -%}
76
+ {% - if param_spec .properties -%}
77
+ {{- "{\n" }}
78
+ {% - for prop_name , prop_spec in param_spec .properties .items () -%}
79
+ {{- prop_name -}}
80
+ {% - if prop_name not in (param_spec .required or []) -%}
81
+ {{- "?" }}
82
+ {% - endif -%}
83
+ {{- ": " }}
84
+ {{ render_typescript_type(prop_spec, param_spec.required or [] ) }}
85
+ {% - if not loop .last -%}
86
+ {{-", " }}
87
+ {% - endif -%}
88
+ {% - endfor -%}
89
+ {{- "}" }}
90
+ {% - else -%}
91
+ {{- "object" }}
92
+ {% - endif -%}
93
+ {% - else -%}
94
+ {{- "any" }}
95
+ {% - endif -%}
96
+ {% - endmacro -%}
97
+
98
+ {% - macro render_tools (tools ) -%}
99
+ {% - for tool in tools %}
100
+ {% - if tool .function is defined -%}
101
+ {#- Chat Completions format: {"type": "function", "function": {...}} #}
102
+ {% - set func = tool .function -%}
103
+ {% - if func .description is defined -%}
104
+ {{- "// " + func.description + "\n" }}
105
+ {% - endif -%}
106
+ {{- "type "+ func.name + " = " }}
107
+ {% - if func .parameters and func .parameters .properties %}
108
+ {{- "(_: {\n" }}
109
+ {% - for param_name , param_spec in func .parameters .properties .items () %}
110
+ {% - if param_spec .description is defined %}
111
+ {{- "// " + param_spec.description + "\n" }}
112
+ {% - endif %}
113
+ {{- param_name }}
114
+ {% - if param_name not in (func .parameters .required or []) -%}
115
+ {{- "?" }}
116
+ {% - endif -%}
117
+ {{- ": " }}
118
+ {{- render_typescript_type(param_spec, func.parameters.required or [] ) }}
119
+ {% - if param_spec .default is defined -%}
120
+ {% - if param_spec .enum %}
121
+ {{- ", // default: " + param_spec.default }}
122
+ {% - elif param_spec .oneOf %}
123
+ {{- "// default: " + param_spec.default }}
124
+ {% - else %}
125
+ {{- ", // default: " + param_spec.default|tojson }}
126
+ {% - endif -%}
127
+ {% - endif -%}
128
+ {% - if not loop .last %}
129
+ {{- ",\n" }}
130
+ {% - else %}
131
+ {{- "\n" }}
132
+ {% - endif -%}
133
+ {% - endfor %}
134
+ {{- "}) => any;" }}
135
+ {% - else -%}
136
+ {{- "() => any;" }}
137
+ {% - endif -%}
138
+ {% - else -%}
139
+ {#- Responses format: {"type": "function", "name": "...", ...} #}
140
+ {% - if tool .description is defined -%}
141
+ {{- "// " + tool.description + "\n" }}
142
+ {% - endif -%}
143
+ {{- "type "+ tool.name + " = " }}
144
+ {% - if tool .parameters and tool .parameters .properties %}
145
+ {{- "(_: {\n" }}
146
+ {% - for param_name , param_spec in tool .parameters .properties .items () %}
147
+ {% - if param_spec .description is defined %}
148
+ {{- "// " + param_spec.description + "\n" }}
149
+ {% - endif %}
150
+ {{- param_name }}
151
+ {% - if param_name not in (tool .parameters .required or []) -%}
152
+ {{- "?" }}
153
+ {% - endif -%}
154
+ {{- ": " }}
155
+ {{- render_typescript_type(param_spec, tool.parameters.required or [] ) }}
156
+ {% - if param_spec .default is defined -%}
157
+ {% - if param_spec .enum %}
158
+ {{- ", // default: " + param_spec.default }}
159
+ {% - elif param_spec .oneOf %}
160
+ {{- "// default: " + param_spec.default }}
161
+ {% - else %}
162
+ {{- ", // default: " + param_spec.default|tojson }}
163
+ {% - endif -%}
164
+ {% - endif -%}
165
+ {% - if not loop .last %}
166
+ {{- ",\n" }}
167
+ {% - else %}
168
+ {{- "\n" }}
169
+ {% - endif -%}
170
+ {% - endfor %}
171
+ {{- "}) => any;" }}
172
+ {% - else -%}
173
+ {{- "() => any;" }}
174
+ {% - endif -%}
175
+ {% - endif -%}
176
+ {% - if not loop .last -%}
177
+ {{- "\n" }}
178
+ {% - endif -%}
179
+ {% - endfor %}
180
+ {% - endmacro -%}
181
+
182
+ {{ bos_token }}
183
+
184
+ {% - set system_token = '<|system_start|>' -%}
185
+ {% - set end_system_token = '<|system_end|>' -%}
186
+ {% - set developer_token = '<|developer_start|>' -%}
187
+ {% - set end_developer_token = '<|developer_end|>' -%}
188
+ {% - set user_token = '<|user_start|>' -%}
189
+ {% - set end_user_token = '<|user_end|>' -%}
190
+ {% - set assistant_token = '<|assistant_start|>' -%}
191
+ {% - set end_assistant_token = '<|assistant_end|>' -%}
192
+ {% - set inner_token = '<|inner_prefix|>' -%}
193
+ {% - set outer_token = '<|inner_suffix|>' -%}
194
+ {% - set tool_calls_token = '<|tools_prefix|>' -%}
195
+ {% - set end_tool_calls_token = '<|tools_suffix|>' -%}
196
+
197
+ {% - set ns = namespace (in_assistant =false , in_tool =false , in_inner =false , assistant_format =none ) -%}
198
+
199
+ {% - if messages and messages [0].role == 'system' -%}
200
+ {% - if "content" in messages [0] -%}
201
+ {% - if messages [0].content is string -%}
202
+ {{ system_token + messages[0] .content + end_system_token }}
203
+ {% - elif messages [0].content is mapping and "text" in messages [0].content -%}
204
+ {{ system_token + messages[0] .content.text + end_system_token }}
205
+ {% - else -%}
206
+ {{- raise_exception("Invalid system message") -}}
207
+ {% - endif -%}
208
+ {% - else -%}
209
+ {{- raise_exception("Invalid system message") -}}
210
+ {% - endif -%}
211
+ {% - set loop_messages = messages [1:] -%}
212
+ {% - else -%}
213
+ {{ system_token + 'You are Apertus, a helpful assistant created by the SwissAI initiative.\nKnowledge cutoff: 2024-04\nCurrent date: ' + strftime_now('%Y-%m-%d') + end_system_token }}
214
+ {% - set loop_messages = messages -%}
215
+ {% - endif -%}
216
+
217
+ {{ developer_token + 'Deliberation: ' }}
218
+ {% - if enable_thinking is defined and enable_thinking -%}
219
+ {{ 'enabled\n' }}
220
+ {% - else -%}
221
+ {{ 'disabled\n' }}
222
+ {% - endif -%}
223
+ {% - if tools is defined and tools -%}
224
+ {{ 'Tool Capabilities:\n' + render_tools(tools) }}
225
+ {% - else -%}
226
+ {{ 'Tool Capabilities: disabled' }}
227
+ {% - endif -%}
228
+ {{ end_developer_token }}
229
+
230
+ {% - for message in loop_messages -%}
231
+ {% - if message .role == 'user' -%}
232
+ {% - set ns .in_inner = false -%}
233
+ {% - if ns .in_tool -%}
234
+ {{ '] ' }}
235
+ {% - set ns .in_tool = false -%}
236
+ {% - endif -%}
237
+ {% - if ns .in_assistant -%}
238
+ {{ end_assistant_token }}
239
+ {% - set ns .in_assistant = false -%}
240
+ {% - endif -%}
241
+ {% - if "content" in message -%}
242
+ {{ user_token }}
243
+ {% - if message .content is string -%}
244
+ {{ message.content }}
245
+ {% - elif message .content is mapping and "parts" in message .content -%}
246
+ {% - set parts = message .content .parts -%}
247
+ {% - for part in parts -%}
248
+ {% - if part .type == "text" -%}
249
+ {{ part.text }}
250
+ {% - else -%}
251
+ {{- raise_exception("Invalid user part: " + part.type) -}}
252
+ {% - endif -%}
253
+ {% - endfor -%}
254
+ {% - else -%}
255
+ {{- raise_exception("Invalid user message: " + message.role) -}}
256
+ {% - endif -%}
257
+ {{ end_user_token }}
258
+ {% - endif -%}
259
+ {% - elif message .role == 'assistant' -%}
260
+ {% - if not ns .in_assistant -%}
261
+ {{ assistant_token }}
262
+ {% - set ns .in_assistant = true -%}
263
+ {% - endif -%}
264
+ {% - if "content" in message -%}
265
+ {% - if message .content is string and (ns .assistant_format is none or ns .assistant_format == "string" ) -%}
266
+ {% - if ns .in_tool -%}
267
+ {{ '] ' }}
268
+ {% - set ns .in_tool = false -%}
269
+ {% - endif -%}
270
+ {% - set ns .assistant_format = "string" -%}
271
+ {{ message.content }}
272
+ {% - elif message .content is mapping and "blocks" in message .content and (ns .assistant_format is none or ns .assistant_format == "mapping" ) -%}
273
+ {% - set ns .assistant_format = "mapping" -%}
274
+ {% - set blocks = message .content .blocks -%}
275
+ {% - for block in blocks -%}
276
+ {% - if block .type == 'thoughts' -%}
277
+ {% - if ns .in_tool -%}
278
+ {{ '] ' }}
279
+ {% - set ns .in_tool = false -%}
280
+ {% - endif -%}
281
+ {% - if not ns .in_inner -%}
282
+ {% - set ns .in_inner = true -%}
283
+ {{ inner_token }}
284
+ {% - endif -%}
285
+ {{ block.text }}
286
+ {% - elif block .type == 'tool_calls' -%}
287
+ {% - if ns .in_tool -%}
288
+ {{ '] ' }}
289
+ {% - set ns .in_tool = false -%}
290
+ {% - endif -%}
291
+ {% - if ns .in_inner and not loop .first and block .calls |length == 1 and block .calls [0].name == 'display_answers' -%}
292
+ {% - set ns .in_inner = false -%}
293
+ {{ outer_token }}
294
+ {% - endif -%}
295
+ {{ tool_calls_token + '[' }}
296
+ {% - for tool_call in block .calls -%}
297
+ {{- '{"' + tool_call.name + '": ' + tool_call.arguments + '}' }}
298
+ {% - if not loop .last -%}
299
+ {{- ", " }}
300
+ {% - endif -%}
301
+ {% - endfor -%}
302
+ {{ '] ' + end_tool_calls_token }}
303
+ {% - elif block .type == 'tool_outputs' -%}
304
+ {% - if ns .in_tool -%}
305
+ {{- raise_exception("Cannot have both tool outputs as separate messages and tool outputs as blocks") -}}
306
+ {% - endif -%}
307
+ {{ '[' }}
308
+ {% - for tool_output in block .outputs -%}
309
+ {{- tool_output.output }}
310
+ {% - if not loop .last -%}
311
+ {{- ", " }}
312
+ {% - endif -%}
313
+ {% - endfor -%}
314
+ {{- '] ' }}
315
+ {% - elif block .type == 'response' -%}
316
+ {% - if ns .in_tool -%}
317
+ {{ '] ' }}
318
+ {% - set ns .in_tool = false -%}
319
+ {% - endif -%}
320
+ {% - if (not loop .first and ns .in_inner ) or (ns .in_assistant and ns .in_inner ) -%}
321
+ {% - set ns .in_inner = false -%}
322
+ {{ outer_token }}
323
+ {% - endif -%}
324
+ {{ block.text }}
325
+ {% - else -%}
326
+ {{- raise_exception("Invalid assistant block type: " + block.type) -}}
327
+ {% - endif -%}
328
+ {% - endfor -%}
329
+ {% - else -%}
330
+ {{- raise_exception("Invalid assistant content") -}}
331
+ {% - endif -%}
332
+ {% - else -%}
333
+ {{- raise_exception("Invalid assistant message") -}}
334
+ {% - endif -%}
335
+ {% - if "tool_calls" in message and message .tool_calls -%}
336
+ {{ tool_calls_token + '[' }}
337
+ {% - for tool_call in message .tool_calls -%}
338
+ {% - if tool_call .type == 'function' -%}
339
+ {% - set function = tool_call .function -%}
340
+ {{- '{"' + function.name + '": ' + function.arguments + '}' }}
341
+ {% - if not loop .last -%}
342
+ {{- ", " }}
343
+ {% - endif -%}
344
+ {% - else -%}
345
+ {{- raise_exception("Invalid tool call type: " + tool_call.type) -}}
346
+ {% - endif -%}
347
+ {% - endfor -%}
348
+ {{ '] ' + end_tool_calls_token }}
349
+ {% - endif -%}
350
+ {% - elif message .role == 'tool' -%}
351
+ {% - if not ns .in_assistant -%}
352
+ {{- raise_exception("Tool message outside of assistant") -}}
353
+ {% - endif -%}
354
+ {% - if not ns .in_tool -%}
355
+ {{ '[' }}
356
+ {% - set ns .in_tool = true -%}
357
+ {% - else -%}
358
+ {{ ", "}}
359
+ {% - endif -%}
360
+ {{ message.content }}
361
+ {% - else -%}
362
+ {{- raise_exception("Invalid message role") -}}
363
+ {% - endif -%}
364
+ {% - endfor -%}
365
+ {% - if ns .in_tool -%}
366
+ {{ '] ' }}
367
+ {% - endif -%}
368
+ {% - if add_generation_prompt -%}
369
+ {{ assistant_token }}
370
+ {% - endif -%}
0 commit comments