diff --git a/src/axolotl/utils/chat_templates/templates/exaone4.jinja b/src/axolotl/utils/chat_templates/templates/exaone4.jinja new file mode 100644 index 000000000..8bfb0651b --- /dev/null +++ b/src/axolotl/utils/chat_templates/templates/exaone4.jinja @@ -0,0 +1,126 @@ +{%- if not skip_think is defined %} + {%- set skip_think = true %} +{%- endif %} +{%- set role_indicators = { + 'user': '[|user|]\n', + 'assistant': '[|assistant|]\n', + 'system': '[|system|]\n', + 'tool': '[|tool|]\n' +} %} +{%- set end_of_turn = '[|endofturn|]\n' %} +{%- macro available_tools(tools) %} + {{- "# Available Tools" }} + {{- "\nYou can use none, one, or multiple of the following tools by calling them as functions to help with the user’s query." }} + {{- "\nHere are the tools available to you in JSON format within and tags:\n" }} + {%- for tool in tools %} + {{- "" }} + {{- tool | tojson(ensure_ascii=False) | safe }} + {{- "\n" }} + {%- endfor %} + {{- "\nFor each function call you want to make, return a JSON object with function name and arguments within and tags, like:" }} + {{- "\n{\"name\": function_1_name, \"arguments\": {argument_1_name: argument_1_value, argument_2_name: argument_2_value}}" }} + {{- "\n{\"name\": function_2_name, \"arguments\": {...}}\n..." }} + {{- "\nNote that if no argument name is specified for a tool, you can just print the argument value directly, without the argument name or JSON formatting." }} +{%- endmacro %} +{%- set ns = namespace(last_query_index = messages|length - 1) %} +{%- for message in messages %} + {%- if message.role == "user" and message.content is string %} + {%- set ns.last_query_index = loop.index0 -%} + {%- endif %} +{%- endfor %} +{%- for i in range(messages | length) %} + {%- set msg = messages[i] %} + {%- set role = msg.role %} + {%- if role not in role_indicators %} + {{- raise_exception('Unknown role: ' ~ role) }} + {%- endif %} + {# ---- Case A: If the first message is "system", handle it here alone (without continue) ---- #} + {%- if i == 0 and role == 'system' %} + {{- role_indicators['system'] }} + {{- msg.content }} + {%- if tools is defined and tools %} + {{- "\n\n" }}{{- available_tools(tools) }} + {%- endif %} + {{- end_of_turn -}} + {%- else %} + {# ---- Case B: If the first message is tools instead of system, inject the system tools preamble ---- #} + {%- if i == 0 and tools is defined and tools %} + {{- role_indicators['system'] }} + {{- available_tools(tools) }} + {{- end_of_turn -}} + {%- endif %} + {%- endif %} + {%- if role == 'assistant' %} + {{- role_indicators['assistant'] }} + {%- if msg.content %} + {%- if "" in msg.content %} + {%- set content = msg.content.split('')[-1].strip() %} + {%- set reasoning_content = msg.content.split('')[0].strip() %} + {%- if reasoning_content.startswith("") %} + {%- set reasoning_content = reasoning_content[7:].strip() %} + {%- endif %} + {%- else %} + {%- set content = msg.content %} + {%- endif %} + {%- if msg.reasoning_content %} + {%- set reasoning_content = msg.reasoning_content %} + {%- endif %} + {%- if (not skip_think and loop.last) and reasoning_content is defined %} + {{- "\n" }} + {{- reasoning_content}} + {{- "\n\n\n" }} + {%- else %} + {{- "\n\n\n\n" }} + {%- endif %} + {{- content }} + {%- endif %} + {%- if msg.tool_calls %} + {%- if msg.content %} + {{- "\n" }} + {%- else %} + {{- "\n\n\n\n" }} + {%- endif %} + {%- for tool_call in msg.tool_calls %} + {%- if tool_call.function is defined %} + {%- set tool_call = tool_call.function %} + {%- endif %} + {%- if tool_call.arguments is defined %} + {%- set arguments = tool_call.arguments %} + {%- elif tool_call.parameters is defined %} + {%- set arguments = tool_call.parameters %} + {%- else %} + {{- raise_exception('arguments or parameters are mandatory: ' ~ tool_call) }} + {%- endif %} + {{- "" }}{"name": "{{- tool_call.name }}", "arguments": {{ arguments | tojson(ensure_ascii=False) | safe }}}{{- "" }} + {%- if not loop.last %} + {{- "\n" }} + {%- endif %} + {%- endfor %} + {%- endif %} + {{- end_of_turn -}} + {%- elif role == "tool" %} + {%- if i == 0 or messages[i - 1].role != "tool" %} + {{- role_indicators['tool'] }} + {%- endif %} + {%- if msg.content is defined %} + {{- "" }}{"result": {{ msg.content | tojson(ensure_ascii=False) | safe }}}{{- "" }} + {%- endif %} + {%- if loop.last or messages[i + 1].role != "tool" %} + {{- end_of_turn -}} + {%- else %} + {{- "\n" }} + {%- endif %} + {%- else %} + {{- role_indicators[role] }} + {{- msg.content }} + {{- end_of_turn -}} + {%- endif %} +{% endfor %} +{%- if add_generation_prompt %} + {{- role_indicators['assistant'] }} + {%- if enable_thinking is defined and enable_thinking is true %} + {{- "\n" }} + {%- else %} + {{- "\n\n\n\n" }} + {%- endif %} +{%- endif %} diff --git a/src/axolotl/utils/schemas/enums.py b/src/axolotl/utils/schemas/enums.py index bcd03e1a2..f86d1a191 100644 --- a/src/axolotl/utils/schemas/enums.py +++ b/src/axolotl/utils/schemas/enums.py @@ -58,6 +58,7 @@ class ChatTemplate(str, Enum): falcon_h1 = "falcon_h1" tokenizer_default = "tokenizer_default" exaone = "exaone" + exaone4 = "exaone4" metharme = "metharme" pixtral = "pixtral" llava = "llava"