File size: 7,194 Bytes
de94349
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
{#- Begin-of-sequence token to start the model prompt -#}
{{ bos_token }}
{#- Extracts the system message. Gemma does not support system messages so it will be prepended to first user message. -#}
{%- if messages[0]['role'] == 'system' -%}
    {%- if messages[0]['content'] is string -%}
        {%- set first_user_prefix = messages[0]['content'] -%}
    {%- else -%}
        {%- set first_user_prefix = messages[0]['content'][0]['text'] -%}
    {%- endif -%}
    {%- set loop_messages = messages[1:] -%}
{%- else -%}
    {%- set first_user_prefix = "You are a helpful assistant named Typhoon created by SCB 10X to be helpful, harmless, and honest." -%}
    {%- set loop_messages = messages -%}
{%- endif -%}
{%- if enable_thinking is defined and enable_thinking is true %}
    {%- set first_user_prefix = first_user_prefix + " First, think through the reasoning internally, then present the reasoning within <think>...</think>. After thinking, clearly state a response that addresses the user's request and aligns with their preferences, not just providing a direct answer." -%}
{%- endif %}
{%- set first_user_prefix = first_user_prefix + '\n\n' -%}
{#- Set tools to none if not defined for this ChatCompletion request (helps avoid errors later) -#}
{%- if not tools is defined %}
    {%- set tools = none %}
{%- endif %}

{#- If given only system message -#}
{%- if loop_messages|length == 0 -%}
    {{ '<start_of_turn>user\n' -}}
    {{ first_user_prefix }}
    {#- Append system message with tool information if using tools in message request. -#}
    {%- if tools is not none -%}
        {{- "Tools (functions) are available. If you decide to invoke one or more of the tools, you must respond with a python list of the function calls.\n" -}}
        {{- "Example Format: [func_name1(params_name1=params_value1, params_name2=params_value2...), func_name2(params)] \n" -}}
        {{- "Do not use variables. DO NOT USE MARKDOWN SYNTAX. You SHOULD NOT include any other text in the response if you call a function. If none of the functions can be used, point it out. If you lack the parameters required by the function, also point it out.\n" -}}
        {{- "Here is a list of functions in JSON format that you can invoke.\n" -}}
        {{- tools | tojson(indent=4) -}}
        {{- "\n\n" -}}
    {%- endif -%}
{%- endif %}

{#- Main loop over all messages in the conversation history -#}
{%- for message in loop_messages -%}
    {#- Normalize roles for model prompt formatting -#}
    {%- if (message['role'] == 'assistant') -%}
        {%- set role = "model" -%}
    {%- elif (message['role'] == 'tool') -%}
        {%- set role = "user" -%}
    {%- else -%}
        {%- set role = message['role'] -%}
    {%- endif -%}
    {#- Mark the start of a message block with the appropriate role -#}
    {{ '<start_of_turn>' + role + '\n' -}}

    {#- Insert system message content (if present) at the beginning of the first message. -#}
    {%- if loop.first -%}
        {{ first_user_prefix }}
        {#- Append system message with tool information if using tools in message request. -#}
        {%- if tools is not none -%}
            {{- "Tools (functions) are available. If you decide to invoke one or more of the tools, you must respond with a python list of the function calls.\n" -}}
            {{- "Example Format: [func_name1(params_name1=params_value1, params_name2=params_value2...), func_name2(params)] \n" -}}
            {{- "Do not use variables. DO NOT USE MARKDOWN SYNTAX. You SHOULD NOT include any other text in the response if you call a function. If none of the functions can be used, point it out. If you lack the parameters required by the function, also point it out.\n" -}}
            {{- "Here is a list of functions in JSON format that you can invoke.\n" -}}
            {{- tools | tojson(indent=4) -}}
            {{- "\n\n" -}}
        {%- endif -%}
    {%- endif -%}

    {#- Format model tool calls (turns where model indicates they want to call a tool) -#}
    {%- if 'tool_calls' in message -%}
        {#- Opening bracket for tool call list. -#}
        {{- '[' -}}
        {#- For each tool call -#}
        {%- for tool_call in message.tool_calls -%}
            {#- Function name & opening parenthesis. -#}
            {%- if tool_call.function is defined -%}
                {%- set tool_call = tool_call.function -%}
            {%- endif -%}
            {{- tool_call.name + '(' -}}

            {#-- Handle arguments as list (positional) or dict (named) --#}
            {#-- Named arguments (dict) --#}
            {%- if tool_call.arguments is iterable and tool_call.arguments is mapping -%}
                {%- set first = true -%}
                {%- for key, val in tool_call.arguments.items() -%}
                    {%- if not first %}, {% endif -%}
                    {{ key }}={{ val | tojson }}
                    {%- set first = false -%}
                {%- endfor -%}
            {#-- Positional arguments (list) --#}
            {%- elif tool_call.arguments is iterable -%}
                {{- tool_call.arguments | map('tojson') | join(', ') -}}
            {#-- Fallback: single positional value --#}
            {%- else -%}
                {{- tool_call.arguments | tojson -}}
            {#-- Closing parenthesis. --#}
            {%- endif -%}
                {{- ')' -}}
            {#-- If more than one tool call, place comma and move to formatting next tool call --#}
            {%- if not loop.last -%}, {% endif -%}
        {%- endfor -%}
        {#- Closing bracket for tool call list. -#}
        {{- ']' -}}
    {%- endif -%}
    
    {#- Tool response start tag (for messages from a tool) -#}
    {%- if (message['role'] == 'tool') -%}
        {{ '<tool_response>\n' -}}
    {%- endif -%}

    {#- Render the message content: handle plain string or multimodal content like image/text -#}
    {%- if message['content'] is string -%}
        {%- set content = message['content'] -%}
        {%- if '</think>' in content -%}
            {%- set content = content.split('</think>')[-1] -%}
        {%- endif -%}
        {{ content | trim }}
    {%- elif message['content'] is iterable -%}
        {%- for item in message['content'] -%}
            {%- if item['type'] == 'image' -%}
                {{ '<start_of_image>' }}
            {%- elif item['type'] == 'text' -%}
                {%- set content = item['text'] -%}
                {%- if '</think>' in content -%}
                    {%- set content = content.split('</think>')[-1] -%}
                {%- endif -%}
                {{ content | trim }}
            {%- endif -%}
        {%- endfor -%}
    {%- else -%}
        {{ raise_exception("Invalid content type") }}
    {%- endif -%}

    {#- Tool response end tag -#}
    {%- if (message['role'] == 'tool') -%}
        {{ '</tool_response>' -}}
    {%- endif -%}

    {#- Mark end of a single turn -#}
    {{ '<end_of_turn>\n' }}
{%- endfor -%}

{#- If generation is to be triggered, add model prompt prefix -#}
{%- if add_generation_prompt -%}
    {{'<start_of_turn>model\n'}}
    {%- if enable_thinking is defined and enable_thinking is true -%}
        {{- '<think>' -}}
    {%- endif %}
{%- endif -%}