diff --git a/tests/utils/test_packing.py b/tests/utils/test_packing.py index 70c80b7321..098f6a3667 100644 --- a/tests/utils/test_packing.py +++ b/tests/utils/test_packing.py @@ -178,13 +178,29 @@ class _DummyModel(torch.nn.Module): class _DummyTrainer: def __init__(self): self.args = SimpleNamespace(remove_unused_columns = True) - self.data_collator = DataCollatorForLanguageModeling( - pad_token_id = 0, - completion_only_loss = False, - padding_free = True, - return_position_ids = False, - return_tensors = "pt", - ) + collator_args = { + "pad_token_id": 0, + "completion_only_loss": False, + "return_tensors": "pt", + } + optional_flags = [ + {"padding_free": True, "return_position_ids": False}, + {"padding_free": True}, + {}, + ] + for extra in optional_flags: + try: + self.data_collator = DataCollatorForLanguageModeling( + **collator_args, **extra + ) + break + except TypeError: + continue + # Ensure attributes exist even if the constructor did not accept them + if not hasattr(self.data_collator, "padding_free"): + self.data_collator.padding_free = True + if not hasattr(self.data_collator, "return_position_ids"): + self.data_collator.return_position_ids = False class _PaddingFreeCollator: diff --git a/unsloth/chat_templates.py b/unsloth/chat_templates.py index 63d310af8e..a17a6f6299 100644 --- a/unsloth/chat_templates.py +++ b/unsloth/chat_templates.py @@ -36,6 +36,7 @@ import shutil from .tokenizer_utils import * from .models._utils import patch_tokenizer import re +from .ollama_template_mappers import OLLAMA_TEMPLATES from unsloth_zoo.dataset_utils import ( train_on_responses_only, standardize_data_formats, @@ -43,6 +44,8 @@ from unsloth_zoo.dataset_utils import ( standardize_sharegpt = standardize_data_formats CHAT_TEMPLATES = {} DEFAULT_SYSTEM_MESSAGE = {} +def _ollama_template(name: str): + return OLLAMA_TEMPLATES[name] # =========================================== Unsloth # Unsloth efficient template leverages from Zephyr @@ -68,18 +71,7 @@ unsloth_template = \ "{{ '>>> Assistant: ' }}"\ "{% endif %}" -unsloth_ollama = \ -''' -FROM {__FILE_LOCATION__} -TEMPLATE """{{ if .System }}{{ .System }} -{{ end }}{{ if .Prompt }}>>> User: {{ .Prompt }} -{{ end }}>>> Assistant: {{ .Response }}{__EOS_TOKEN__} -""" -PARAMETER stop "{__EOS_TOKEN__}" -PARAMETER temperature 1.5 -PARAMETER min_p 0.1 -SYSTEM """You are a helpful assistant to the user""" -''' +unsloth_ollama = _ollama_template("unsloth") unsloth_eos_token = "eos_token" CHAT_TEMPLATES["unsloth"] = (unsloth_template, unsloth_eos_token, False, unsloth_ollama,) @@ -101,20 +93,7 @@ zephyr_template = \ "{{ '<|assistant|>\n' }}"\ "{% endif %}" -zephyr_ollama = \ -''' -FROM {__FILE_LOCATION__} -TEMPLATE """{{ if .System }}<|system|> -{{ .System }}{__EOS_TOKEN__} -{{ end }}{{ if .Prompt }}<|user|> -{{ .Prompt }}{__EOS_TOKEN__} -{{ end }}<|assistant|> -{{ .Response }}{__EOS_TOKEN__} -""" -PARAMETER stop "{__EOS_TOKEN__}" -PARAMETER temperature 1.5 -PARAMETER min_p 0.1 -''' +zephyr_ollama = _ollama_template("zephyr") zephyr_eos_token = "eos_token" CHAT_TEMPLATES["zephyr"] = (zephyr_template, zephyr_eos_token, False, zephyr_ollama,) @@ -136,21 +115,7 @@ chatml_template = \ "{{ '<|im_start|>assistant\n' }}"\ "{% endif %}" -chatml_ollama = \ -''' -FROM {__FILE_LOCATION__} -TEMPLATE """{{ if .System }}<|im_start|>system -{{ .System }}<|im_end|> -{{ end }}{{ if .Prompt }}<|im_start|>user -{{ .Prompt }}<|im_end|> -{{ end }}<|im_start|>assistant -{{ .Response }}<|im_end|> -""" -PARAMETER stop "<|im_start|>" -PARAMETER stop "<|im_end|>" -PARAMETER temperature 1.5 -PARAMETER min_p 0.1 -''' +chatml_ollama = _ollama_template("chatml") chatml_eos_token = "<|im_end|>" CHAT_TEMPLATES["chatml"] = (chatml_template, chatml_eos_token, True, chatml_ollama,) @@ -182,14 +147,7 @@ mistral_template = \ "{% endfor %}" # Ollama from https://www.ollama.com/library/mistral -mistral_ollama = \ -''' -FROM {__FILE_LOCATION__} -TEMPLATE """[INST] {{ if .System }}{{ .System }} {{ end }}{{ .Prompt }} [/INST]""" -PARAMETER stop "{__EOS_TOKEN__}" -PARAMETER temperature 1.5 -PARAMETER min_p 0.1 -''' +mistral_ollama = _ollama_template("mistral") mistral_eos_token = "eos_token" CHAT_TEMPLATES["mistral"] = (mistral_template, mistral_eos_token, False, mistral_ollama,) @@ -220,16 +178,7 @@ llama_template = \ "{% endfor %}" # Ollama from https://www.ollama.com/library/llama3 -llama_ollama = \ -''' -FROM {__FILE_LOCATION__} -TEMPLATE """[INST] <>{{ .System }}<> - -{{ .Prompt }} [/INST]""" -PARAMETER stop "{__EOS_TOKEN__}" -PARAMETER temperature 1.5 -PARAMETER min_p 0.1 -''' +llama_ollama = _ollama_template("llama") llama_eos_token = "eos_token" CHAT_TEMPLATES["llama"] = (llama_template, llama_eos_token, False, llama_ollama,) @@ -260,14 +209,7 @@ vicuna_template = \ "{% endif %}" # Ollama from https://www.ollama.com/library/vicuna -vicuna_ollama = \ -''' -FROM {__FILE_LOCATION__} -TEMPLATE """{{ if .System }}{{ .System }} {{ end }}{{ if .Prompt }}USER: {{ .Prompt }} {{ end }}ASSISTANT: {{ .Response }} {__EOS_TOKEN__}""" -PARAMETER stop "{__EOS_TOKEN__}" -PARAMETER temperature 1.5 -PARAMETER min_p 0.1 -''' +vicuna_ollama = _ollama_template("vicuna") vicuna_eos_token = "eos_token" CHAT_TEMPLATES["vicuna"] = (vicuna_template, vicuna_eos_token, False, vicuna_ollama,) @@ -297,18 +239,7 @@ vicuna_old_template = \ "{{ '### Assistant:' }}"\ "{% endif %}" -vicuna_old_ollama = \ -''' -FROM {__FILE_LOCATION__} -TEMPLATE """{{ if .System }}{{ .System }} -{{ end }}{{ if .Prompt }}### Human: {{ .Prompt }} -{{ end }}### Assistant: {{ .Response }}{__EOS_TOKEN__} -""" -PARAMETER stop "{__EOS_TOKEN__}" -PARAMETER temperature 1.5 -PARAMETER min_p 0.1 -SYSTEM """A chat between a curious human and an artificial intelligence assistant. The assistant gives helpful, detailed, and polite answers to the human's questions.""" -''' +vicuna_old_ollama = _ollama_template("vicuna_old") vicuna_old_eos_token = "eos_token" CHAT_TEMPLATES["vicuna_old"] = (vicuna_old_template, vicuna_old_eos_token, False, vicuna_old_ollama,) @@ -341,23 +272,7 @@ alpaca_template = \ "{{ '### Response:\n' }}"\ "{% endif %}" -alpaca_ollama = \ -''' -FROM {__FILE_LOCATION__} -TEMPLATE """{{ if .System }}{{ .System }} - -{{ end }}{{ if .Prompt }}### Instruction: -{{ .Prompt }}{{ end }} - -### Response: -{{ .Response }}{__EOS_TOKEN__} - -""" -PARAMETER stop "{__EOS_TOKEN__}" -PARAMETER temperature 1.5 -PARAMETER min_p 0.1 -SYSTEM """Below are some instructions that describe some tasks. Write responses that appropriately complete each request.""" -''' +alpaca_ollama = _ollama_template("alpaca") alpaca_eos_token = "eos_token" CHAT_TEMPLATES["alpaca"] = (alpaca_template, alpaca_eos_token, False, alpaca_ollama,) @@ -387,21 +302,7 @@ gemma_template = \ "{% endif %}" # Ollama from https://www.ollama.com/library/gemma -gemma_ollama = \ -''' -FROM {__FILE_LOCATION__} -TEMPLATE """user -{{ if .System }}{{ .System }} {{ end }}{{ .Prompt }} -model -{{ .Response }} -""" -PARAMETER repeat_penalty 1 -PARAMETER stop "" -PARAMETER stop "" -PARAMETER penalize_newline false -PARAMETER temperature 1.5 -PARAMETER min_p 0.1 -''' +gemma_ollama = _ollama_template("gemma") gemma_eos_token = "" CHAT_TEMPLATES["gemma"] = (gemma_template, gemma_eos_token, True, gemma_ollama,) @@ -411,23 +312,7 @@ DEFAULT_SYSTEM_MESSAGE["gemma"] = None # No system message in Gemma # We find using is still more appropriate! gemma_chatml_template = "{{ bos_token }}" + chatml_template -gemma_chatml_ollama = \ -''' -FROM {__FILE_LOCATION__} -TEMPLATE """{{ if .System }}<|im_start|>system -{{ .System }}<|im_end|> -{{ end }}{{ if .Prompt }}<|im_start|>user -{{ .Prompt }}<|im_end|> -{{ end }}<|im_start|>assistant -{{ .Response }}<|im_end|> -""" -PARAMETER repeat_penalty 1 -PARAMETER stop "<|im_start|>" -PARAMETER stop "<|im_end|>" -PARAMETER penalize_newline false -PARAMETER temperature 1.5 -PARAMETER min_p 0.1 -''' +gemma_chatml_ollama = _ollama_template("gemma_chatml") gemma_chatml_eos_token = ( {"" : "<|im_start|>", "" : "<|im_end|>"}, @@ -440,14 +325,14 @@ DEFAULT_SYSTEM_MESSAGE["gemma_chatml"] = None # No system message in Gemma # Same as Gemma 1, but with sliding window attention! # https://ollama.com/library/gemma2/blobs/6522ca797f47 gemma2_template = gemma_template -gemma2_ollama = gemma_ollama + "PARAMETER num_ctx 4096\n" +gemma2_ollama = _ollama_template("gemma2") gemma2_eos_token = "" CHAT_TEMPLATES["gemma2"] = (gemma2_template, gemma2_eos_token, True, gemma2_ollama,) DEFAULT_SYSTEM_MESSAGE["gemma2"] = None # No system message in Gemma 2 # =========================================== Gemma 2 with ChatML instead gemma2_chatml_template = gemma_chatml_template -gemma2_chatml_ollama = gemma_chatml_ollama + "PARAMETER num_ctx 4096\n" +gemma2_chatml_ollama = _ollama_template("gemma2_chatml") gemma2_chatml_eos_token = gemma_chatml_eos_token CHAT_TEMPLATES["gemma2_chatml"] = (gemma2_chatml_template, gemma2_chatml_eos_token, True, gemma2_chatml_ollama,) DEFAULT_SYSTEM_MESSAGE["gemma2_chatml"] = None # No system message in Gemma 2 @@ -470,22 +355,7 @@ llama3_template = \ "{% endif %}" # Ollama from https://www.ollama.com/library/llama3 -llama3_ollama = \ -''' -FROM {__FILE_LOCATION__} -TEMPLATE """{{ if .System }}<|start_header_id|>system<|end_header_id|> - -{{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|> - -{{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|> - -{{ .Response }}<|eot_id|>""" -PARAMETER stop "<|start_header_id|>" -PARAMETER stop "<|end_header_id|>" -PARAMETER stop "<|eot_id|>" -PARAMETER temperature 1.5 -PARAMETER min_p 0.1 -''' +llama3_ollama = _ollama_template("llama-3") llama3_template_eos_token = "eos_token" @@ -513,22 +383,7 @@ phi3_template = \ "{% endif %}" # Ollama from https://www.ollama.com/library/phi3 -phi3_ollama = \ -''' -FROM {__FILE_LOCATION__} -TEMPLATE """{{ if .System }}<|system|> -{{ .System }}<|end|> -{{ end }}{{ if .Prompt }}<|user|> -{{ .Prompt }}<|end|> -{{ end }}<|assistant|> -{{ .Response }}<|end|> -""" -PARAMETER stop "<|end|>" -PARAMETER stop "<|user|>" -PARAMETER stop "<|assistant|>" -PARAMETER temperature 1.5 -PARAMETER min_p 0.1 -''' +phi3_ollama = _ollama_template("phi-3") phi3_template_eos_token = "<|end|>" CHAT_TEMPLATES["phi-3"] = (phi3_template, phi3_template_eos_token, False, phi3_ollama,) @@ -670,65 +525,7 @@ llama31_template = \ """ # Ollama from https://ollama.com/library/llama3.1 (needs updating!) -llama31_ollama = \ -''' -FROM {__FILE_LOCATION__} -TEMPLATE """{{ if .Messages }} -{{- if or .System .Tools }}<|start_header_id|>system<|end_header_id|> -{{- if .System }} - -{{ .System }} -{{- end }} -{{- if .Tools }} - -You are a helpful assistant with tool calling capabilities. When you receive a tool call response, use the output to format an answer to the original use question. -{{- end }} -{{- end }}<|eot_id|> -{{- range $i, $_ := .Messages }} -{{- $last := eq (len (slice $.Messages $i)) 1 }} -{{- if eq .Role "user" }}<|start_header_id|>user<|end_header_id|> -{{- if and $.Tools $last }} - -Given the following functions, please respond with a JSON for a function call with its proper arguments that best answers the given prompt. - -Respond in the format {"name": function name, "parameters": dictionary of argument name and its value}. Do not use variables. - -{{ $.Tools }} -{{- end }} - -{{ .Content }}<|eot_id|>{{ if $last }}<|start_header_id|>assistant<|end_header_id|> - -{{ end }} -{{- else if eq .Role "assistant" }}<|start_header_id|>assistant<|end_header_id|> -{{- if .ToolCalls }} - -{{- range .ToolCalls }}{"name": "{{ .Function.Name }}", "parameters": {{ .Function.Arguments }}}{{ end }} -{{- else }} - -{{ .Content }}{{ if not $last }}<|eot_id|>{{ end }} -{{- end }} -{{- else if eq .Role "tool" }}<|start_header_id|>ipython<|end_header_id|> - -{{ .Content }}<|eot_id|>{{ if $last }}<|start_header_id|>assistant<|end_header_id|> - -{{ end }} -{{- end }} -{{- end }} -{{- else }} -{{- if .System }}<|start_header_id|>system<|end_header_id|> - -{{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|> - -{{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|> - -{{ end }}{{ .Response }}{{ if .Response }}<|eot_id|>{{ end }}""" -PARAMETER stop "<|start_header_id|>" -PARAMETER stop "<|end_header_id|>" -PARAMETER stop "<|eot_id|>" -PARAMETER stop "<|eom_id|>" -PARAMETER temperature 1.5 -PARAMETER min_p 0.1 -''' +llama31_ollama = _ollama_template("llama-3.1") llama31_template_eos_token = "eos_token" CHAT_TEMPLATES["llama-3.1"] = (llama31_template, llama31_template_eos_token, False, llama31_ollama,) @@ -796,64 +593,7 @@ qwen25_template = \ # Ollama from https://ollama.com/library/qwen2.5/blobs/eb4402837c78 -qwen25_ollama = \ -''' -FROM {__FILE_LOCATION__} -TEMPLATE """{{- if .Messages }} -{{- if or .System .Tools }}<|im_start|>system -{{- if .System }} -{{ .System }} -{{- end }} -{{- if .Tools }} - -# Tools - -You may call one or more functions to assist with the user query. - -You are provided with function signatures within XML tags: - -{{- range .Tools }} -{"type": "function", "function": {{ .Function }}} -{{- end }} - - -For each function call, return a json object with function name and arguments within XML tags: - -{"name": , "arguments": } - -{{- end }}<|im_end|> -{{ end }} -{{- range $i, $_ := .Messages }} -{{- $last := eq (len (slice $.Messages $i)) 1 -}} -{{- if eq .Role "user" }}<|im_start|>user -{{ .Content }}<|im_end|> -{{ else if eq .Role "assistant" }}<|im_start|>assistant -{{ if .Content }}{{ .Content }} -{{- else if .ToolCalls }} -{{ range .ToolCalls }}{"name": "{{ .Function.Name }}", "arguments": {{ .Function.Arguments }}} -{{ end }} -{{- end }}{{ if not $last }}<|im_end|> -{{ end }} -{{- else if eq .Role "tool" }}<|im_start|>user - -{{ .Content }} -<|im_end|> -{{ end }} -{{- if and (ne .Role "assistant") $last }}<|im_start|>assistant -{{ end }} -{{- end }} -{{- else }} -{{- if .System }}<|im_start|>system -{{ .System }}<|im_end|> -{{ end }}{{ if .Prompt }}<|im_start|>user -{{ .Prompt }}<|im_end|> -{{ end }}<|im_start|>assistant -{{ end }}{{ .Response }}{{ if .Response }}<|im_end|>{{ end }}""" -PARAMETER stop "<|im_end|>" -PARAMETER stop "<|endoftext|>" -PARAMETER temperature 1.5 -PARAMETER min_p 0.1 -''' +qwen25_ollama = _ollama_template("qwen-2.5") qwen25_template_eos_token = "eos_token" qwen25_default_system_message = "You are Qwen, created by Alibaba Cloud. You are a helpful assistant." @@ -891,16 +631,7 @@ _phi4_ollama_template = \ "<|im_start|><|assistant|><|im_sep|>{{ .Response }}<|im_end|>" # Ollama from https://www.ollama.com/library/phi4 is different -phi4_ollama = \ -f''' -FROM {{__FILE_LOCATION__}} -TEMPLATE """{_phi4_ollama_template}""" -PARAMETER stop "<|im_end|>" -PARAMETER stop "<|im_start|>" -PARAMETER stop "<|im_sep|>" -PARAMETER temperature 1.5 -PARAMETER min_p 0.1 -''' +phi4_ollama = _ollama_template("phi-4") phi4_template_eos_token = "<|im_end|>" CHAT_TEMPLATES["phi-4"] = (phi4_template, phi4_template_eos_token, False, phi4_ollama,) @@ -954,28 +685,7 @@ gemma3_template = \ """ # Ollama from https://ollama.com/library/gemma3/blobs/e0a42594d802 -gemma3_ollama = \ -''' -FROM {__FILE_LOCATION__} -TEMPLATE """{{- range $i, $_ := .Messages }} -{{- $last := eq (len (slice $.Messages $i)) 1 }} -{{- if or (eq .Role "user") (eq .Role "system") }}user -{{ .Content }} -{{ if $last }}model -{{ end }} -{{- else if eq .Role "assistant" }}model -{{ .Content }}{{ if not $last }} -{{ end }} -{{- end }} -{{- end }}""" -PARAMETER stop "" -PARAMETER stop "" -PARAMETER temperature 0.1 -PARAMETER min_p 0.0 -PARAMETER top_k 64 -PARAMETER top_p 0.95 -PARAMETER num_predict 32768 -''' +gemma3_ollama = _ollama_template("gemma-3") gemma3_template_eos_token = "" CHAT_TEMPLATES["gemma-3"] = (gemma3_template, gemma3_template_eos_token, False, gemma3_ollama,) @@ -1088,69 +798,7 @@ qwen3_template = \ {%- endif %} """ -# Ollama template for Qwen-3 (see https://ollama.com/library/qwen3/blobs/eb4402837c78) -qwen3_ollama = \ -''' -FROM {__FILE_LOCATION__} -TEMPLATE """{{- if .Messages }} -{{- if or .System .Tools }}<|im_start|>system -{{- if .System }} -{{ .System }} -{{- end }} -{{- if .Tools }} - -# Tools - -You may call one or more functions to assist with the user query. - -You are provided with function signatures within XML tags: - -{{- range .Tools }} -{"type": "function", "function": {{ .Function }}} -{{- end }} - - -For each function call, return a json object with function name and arguments within XML tags: - -{"name": , "arguments": } - -{{- end }}<|im_end|> -{{ end }} -{{- range $i, $_ := .Messages }} -{{- $last := eq (len (slice $.Messages $i)) 1 -}} -{{- if eq .Role "user" }}<|im_start|>user -{{ .Content }}<|im_end|> -{{ else if eq .Role "assistant" }}<|im_start|>assistant -{{ if .Content }}{{ .Content }} -{{- else if .ToolCalls }} -{{ range .ToolCalls }}{"name": "{{ .Function.Name }}", "arguments": {{ .Function.Arguments }}} -{{ end }} -{{- end }}{{ if not $last }}<|im_end|> -{{ end }} -{{- else if eq .Role "tool" }}<|im_start|>user - -{{ .Content }} -<|im_end|> -{{ end }} -{{- if and (ne .Role "assistant") $last }}<|im_start|>assistant -{{ end }} -{{- end }} -{{- else }} -{{- if .System }}<|im_start|>system -{{ .System }}<|im_end|> -{{ end }}{{ if .Prompt }}<|im_start|>user -{{ .Prompt }}<|im_end|> -{{ end }}<|im_start|>assistant -{{ end }}{{ .Response }}{{ if .Response }}<|im_end|>{{ end }}""" -PARAMETER stop "<|im_end|>" -PARAMETER stop "<|im_start|>" -PARAMETER temperature 0.6 -PARAMETER min_p 0.0 -PARAMETER top_k 20 -PARAMETER top_p 0.95 -PARAMETER repeat_penalty 1 -''' - +qwen3_ollama = _ollama_template("qwen-3") qwen3_template_eos_token = "<|im_end|>" CHAT_TEMPLATES["qwen-3"] = (qwen3_template, qwen3_template_eos_token, False, qwen3_ollama,) DEFAULT_SYSTEM_MESSAGE["qwen-3"] = None # No default system message for Qwen-3 @@ -1207,22 +855,7 @@ gemma3n_template = \ """ # Ollama from https://ollama.com/library/gemma3n/blobs/e0a42594d802 -gemma3n_ollama = \ -''' -FROM {__FILE_LOCATION__} -TEMPLATE """{{- range $i, $_ := .Messages }} -{{- $last := eq (len (slice $.Messages $i)) 1 }} -{{- if or (eq .Role "user") (eq .Role "system") }}user -{{ .Content }} -{{ if $last }}model -{{ end }} -{{- else if eq .Role "assistant" }}model -{{ .Content }}{{ if not $last }} -{{ end }} -{{- end }} -{{- end }}""" -''' - +gemma3n_ollama = _ollama_template("gemma-3n") gemma3n_template_eos_token = "" CHAT_TEMPLATES["gemma-3n"] = (gemma3n_template, gemma3n_template_eos_token, False, gemma3n_ollama,) DEFAULT_SYSTEM_MESSAGE["gemma-3n"] = None # No system message in Gemma-3n @@ -1583,7 +1216,7 @@ gptoss_template = \ <|start|>assistant {%- endif -%}""" -# Ollama from https://ollama.com/library/gemma3n/blobs/e0a42594d802 +# Ollama from https://ollama.com/library/gpt-oss gptoss_ollama = \ ''' FROM {__FILE_LOCATION__} @@ -1861,66 +1494,8 @@ qwen3_instruct_template = \ {{- '<|im_start|>assistant\\n' }} {%- endif %}''' -# Ollama from https://ollama.com/library/qwen3/blobs/53e4ea15e8f5 -qwen3_ollama = \ -''' -FROM {__FILE_LOCATION__} -TEMPLATE """ -{{- $lastUserIdx := -1 -}} -{{- range $idx, $msg := .Messages -}} -{{- if eq $msg.Role "user" }}{{ $lastUserIdx = $idx }}{{ end -}} -{{- end }} -{{- if or .System .Tools }}<|im_start|>system -{{ if .System }} -{{ .System }} -{{- end }} -{{- if .Tools }} - -# Tools - -You may call one or more functions to assist with the user query. - -You are provided with function signatures within XML tags: - -{{- range .Tools }} -{"type": "function", "function": {{ .Function }}} -{{- end }} - - -For each function call, return a json object with function name and arguments within XML tags: - -{"name": , "arguments": } - -{{- end -}} -<|im_end|> -{{ end }} -{{- range $i, $_ := .Messages }} -{{- $last := eq (len (slice $.Messages $i)) 1 -}} -{{- if eq .Role "user" }}<|im_start|>user -{{ .Content }}<|im_end|> -{{ else if eq .Role "assistant" }}<|im_start|>assistant -{{ if (and $.IsThinkSet (and .Thinking (or $last (gt $i $lastUserIdx)))) -}} -{{ .Thinking }} -{{ end -}} -{{ if .Content }}{{ .Content }} -{{- else if .ToolCalls }} -{{ range .ToolCalls }}{"name": "{{ .Function.Name }}", "arguments": {{ .Function.Arguments }}} -{{ end }} -{{- end }}{{ if not $last }}<|im_end|> -{{ end }} -{{- else if eq .Role "tool" }}<|im_start|>user - -{{ .Content }} -<|im_end|> -{{ end }} -{{- if and (ne .Role "assistant") $last }}<|im_start|>assistant -{{ end }} -{{- end }} -""" -''' - qwen3_template_eos_token = "<|im_end|>" -CHAT_TEMPLATES["qwen3-instruct"] = (qwen3_instruct_template, qwen3_template_eos_token, False, qwen3_ollama,) +CHAT_TEMPLATES["qwen3-instruct"] = (qwen3_instruct_template, qwen3_template_eos_token, False, _ollama_template("qwen3-instruct"),) DEFAULT_SYSTEM_MESSAGE["qwen3-instruct"] = None # No system message in Qwen3 @@ -2013,7 +1588,12 @@ qwen3_thinking_template = \ {{- '<|im_start|>assistant\n\n' }} {%- endif %}''' -CHAT_TEMPLATES["qwen3-thinking"] = (qwen3_thinking_template, qwen3_template_eos_token, False, qwen3_ollama,) +CHAT_TEMPLATES["qwen3-thinking"] = ( + qwen3_thinking_template, + qwen3_template_eos_token, + False, + _ollama_template("qwen3-thinking"), +) DEFAULT_SYSTEM_MESSAGE["qwen3-thinking"] = None # No system message in Qwen3 @@ -2042,19 +1622,7 @@ starling_template = \ {%- endif %}""" # Ollama from https://ollama.com/library/starling-lm:7b/blobs/4b21bfc435b4 -starling_ollama = \ -''' -FROM {__FILE_LOCATION__} -TEMPLATE """{{ if .System }}GPT4 Correct System: {{ .System }}<|end_of_turn|> -{{ end }}{{ if .Prompt }}GPT4 Correct User: {{ .Prompt }}<|end_of_turn|> -{{ end }}GPT4 Correct Assistant: {{ .Response }}<|end_of_turn|>""" -PARAMETER stop "<|end_of_turn|>" -PARAMETER stop "GPT4 Correct User:" -PARAMETER stop "GPT4 Correct Assistant:" -PARAMETER stop "GPT4 Correct System:" -PARAMETER temperature 1.5 -PARAMETER min_p 0.1 -''' +starling_ollama = _ollama_template("starling") starling_template_eos_token = "<|end_of_turn|>" CHAT_TEMPLATES["starling"] = (starling_template, starling_template_eos_token, False, starling_ollama) @@ -2072,16 +1640,7 @@ yi_chat_template = \ """ # Ollama from https://ollama.com/library/yi:34b-chat/blobs/62fbfd9ed093 -yi_chat_ollama = \ -''' -FROM {__FILE_LOCATION__} -TEMPLATE """{{ if .System }}<|im_start|>system -{{ .System }}<|im_end|> -{{ end }}{{ if .Prompt }}<|im_start|>user -{{ .Prompt }}<|im_end|> -{{ end }}<|im_start|>assistant -{{ .Response }}<|im_end|>""" -''' +yi_chat_ollama = _ollama_template("yi-chat") yi_chat_template_eos_token = "<|endoftext|>" CHAT_TEMPLATES["yi-chat"] = (yi_chat_template, yi_chat_template_eos_token, False, yi_chat_ollama) diff --git a/unsloth/ollama_template_mappers.py b/unsloth/ollama_template_mappers.py index ea1882e117..1bf77461d9 100644 --- a/unsloth/ollama_template_mappers.py +++ b/unsloth/ollama_template_mappers.py @@ -806,7 +806,7 @@ TEMPLATE """<|system|> PARAMETER stop "<|system|>" PARAMETER stop "<|user|>" PARAMETER stop "<|assistant|>" -PARAMETER "" +PARAMETER stop "" SYSTEM """You are a helpful AI assistant.""" ''' @@ -974,6 +974,7 @@ TEMPLATE """{{- range $i, $_ := .Messages }} OLLAMA_TEMPLATES["qwen-25"] = qwen25_ollama +OLLAMA_TEMPLATES["qwen-2.5"] = qwen25_ollama OLLAMA_TEMPLATES["qwen-25-coder"] = qwen_25_coder_ollama OLLAMA_TEMPLATES["qwen-25-vl"] = qwen_25_vl_ollama OLLAMA_TEMPLATES["openthinker"] = openthinker_ollama diff --git a/unsloth/utils/packing.py b/unsloth/utils/packing.py index 81b721a29b..63a57c04da 100644 --- a/unsloth/utils/packing.py +++ b/unsloth/utils/packing.py @@ -107,12 +107,14 @@ def configure_sample_packing(config): _ensure_trl_warning_filter() setattr(config, "packing", True) setattr(config, "padding_free", True) + setattr(config, "remove_unused_columns", False) def configure_padding_free(config): """Mutate an ``SFTConfig`` so TRL enables padding-free batching without packing.""" _ensure_trl_warning_filter() setattr(config, "padding_free", True) + setattr(config, "remove_unused_columns", False) def enable_sample_packing( @@ -151,6 +153,12 @@ def enable_sample_packing( lengths = example.get(sequence_lengths_key) if isinstance(lengths, Iterable): seq_lengths.extend(int(length) for length in lengths) + # Fallback: infer lengths from tokenized inputs when metadata is absent + if not seq_lengths: + for example in examples: + ids = example.get("input_ids") + if isinstance(ids, Iterable): + seq_lengths.append(len(ids)) if seq_lengths: batch["packed_seq_lengths"] = torch.tensor( seq_lengths, dtype = torch.int32 @@ -176,6 +184,8 @@ def enable_padding_free_metadata(model, trainer): mark_allow_overlength(model) if hasattr(collator, "return_position_ids"): collator.return_position_ids = True + if hasattr(trainer, "args") and hasattr(trainer.args, "remove_unused_columns"): + trainer.args.remove_unused_columns = False original_torch_call = collator.torch_call