main
jinja 123 lines 5.53 KB
Raw
1 {#- Begin-of-sequence token to start the model prompt -#}
2 {{ bos_token }}
3 {#- Extracts the system message. Gemma does not support system messages so it will be prepended to first user message. -#}
4 {%- if messages[0]['role'] == 'system' -%}
5 {%- if messages[0]['content'] is string -%}
6 {%- set first_user_prefix = messages[0]['content'] + '\n\n' -%}
7 {%- else -%}
8 {%- set first_user_prefix = messages[0]['content'][0]['text'] + '\n\n' -%}
9 {%- endif -%}
10 {%- set loop_messages = messages[1:] -%}
11 {%- else -%}
12 {%- set first_user_prefix = "" -%}
13 {%- set loop_messages = messages -%}
14 {%- endif -%}
15 {#- Set tools to none if not defined for this ChatCompletion request (helps avoid errors later) -#}
16 {%- if not tools is defined %}
17 {%- set tools = none %}
18 {%- endif %}
19 {#- Validate alternating user/assistant messages (excluding 'tool' messages and ones with tool_calls) -#}
20 {%- for message in loop_messages | rejectattr("role", "equalto", "tool") | selectattr("tool_calls", "undefined") -%}
21 {%- if (message['role'] == 'user') != (loop.index0 % 2 == 0) %}
22 {{ raise_exception("Conversation roles must alternate user/assistant/user/assistant/...") }}
23 {%- endif -%}
24 {%- endfor -%}
25
26 {#- Main loop over all messages in the conversation history -#}
27 {%- for message in loop_messages -%}
28 {#- Normalize roles for model prompt formatting -#}
29 {%- if (message['role'] == 'assistant') -%}
30 {%- set role = "model" -%}
31 {%- elif (message['role'] == 'tool') -%}
32 {%- set role = "user" -%}
33 {%- else -%}
34 {%- set role = message['role'] -%}
35 {%- endif -%}
36 {#- Mark the start of a message block with the appropriate role -#}
37 {{ '<start_of_turn>' + role + '\n' -}}
38
39 {#- Insert system message content (if present) at the beginning of the first message. -#}
40 {%- if loop.first -%}
41 {{ first_user_prefix }}
42 {#- Append system message with tool information if using tools in message request. -#}
43 {%- if tools is not none -%}
44 {{- "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" -}}
45 {{- "Example Format: [func_name1(params_name1=params_value1, params_name2=params_value2...), func_name2(params)] \n" -}}
46 {{- "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" -}}
47 {{- "Here is a list of functions in JSON format that you can invoke.\n" -}}
48 {{- tools | tojson(indent=4) -}}
49 {{- "\n\n" -}}
50 {%- endif -%}
51 {%- endif -%}
52
53 {#- Format model tool calls (turns where model indicates they want to call a tool) -#}
54 {%- if 'tool_calls' in message -%}
55 {#- Opening bracket for tool call list. -#}
56 {{- '[' -}}
57 {#- For each tool call -#}
58 {%- for tool_call in message.tool_calls -%}
59 {#- Get tool call function. -#}
60 {%- if tool_call.function is defined -%}
61 {%- set tool_call = tool_call.function -%}
62 {%- endif -%}
63 {#- Function name & opening parenthesis. -#}
64 {{- tool_call.name + '(' -}}
65
66 {#-- Handle arguments as list (positional) or dict (named) --#}
67 {#-- Named arguments (dict) --#}
68 {%- if tool_call.arguments is iterable and tool_call.arguments is mapping -%}
69 {%- set first = true -%}
70 {%- for key, val in tool_call.arguments.items() -%}
71 {%- if not first %}, {% endif -%}
72 {{ key }}={{ val | tojson }}
73 {%- set first = false -%}
74 {%- endfor -%}
75 {#-- Positional arguments (list) --#}
76 {%- elif tool_call.arguments is iterable -%}
77 {{- tool_call.arguments | map('tojson') | join(', ') -}}
78 {#-- Fallback: single positional value --#}
79 {%- else -%}
80 {{- tool_call.arguments | tojson -}}
81 {#-- Closing parenthesis. --#}
82 {%- endif -%}
83 {{- ')' -}}
84 {#-- If more than one tool call, place comma and move to formatting next tool call --#}
85 {%- if not loop.last -%}, {% endif -%}
86 {%- endfor -%}
87 {#- Closing bracket for tool call list. -#}
88 {{- ']' -}}
89 {%- endif -%}
90
91 {#- Tool response start tag (for messages from a tool) -#}
92 {%- if (message['role'] == 'tool') -%}
93 {{ '<tool_response>\n' -}}
94 {%- endif -%}
95
96 {#- Render the message content: handle plain string or multimodal content like image/text -#}
97 {%- if message['content'] is string -%}
98 {{ message['content'] | trim }}
99 {%- elif message['content'] is iterable -%}
100 {%- for item in message['content'] -%}
101 {%- if item['type'] == 'image' -%}
102 {{ '<start_of_image>' }}
103 {%- elif item['type'] == 'text' -%}
104 {{ item['text'] | trim }}
105 {%- endif -%}
106 {%- endfor -%}
107 {%- else -%}
108 {{ raise_exception("Invalid content type") }}
109 {%- endif -%}
110
111 {#- Tool response end tag -#}
112 {%- if (message['role'] == 'tool') -%}
113 {{ '</tool_response>' -}}
114 {%- endif -%}
115
116 {#- Mark end of a single turn -#}
117 {{ '<end_of_turn>\n' }}
118 {%- endfor -%}
119
120 {#- If generation is to be triggered, add model prompt prefix -#}
121 {%- if add_generation_prompt -%}
122 {{'<start_of_turn>model\n'}}
123 {%- endif -%}