From e53e1852a8fe989ae4881107474ef5b64f9b0fa3 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Tue, 9 Dec 2025 01:02:26 -0800 Subject: [PATCH 01/20] Update _utils.py --- unsloth/models/_utils.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/unsloth/models/_utils.py b/unsloth/models/_utils.py index f0db65fdbf..e3814163ef 100644 --- a/unsloth/models/_utils.py +++ b/unsloth/models/_utils.py @@ -85,6 +85,7 @@ from dataclasses import dataclass, field import functools import textwrap +import logging import warnings, subprocess, inspect, psutil, os, math from unsloth_zoo.utils import Version, get_quant_type from importlib.metadata import version as importlib_version @@ -167,9 +168,9 @@ ) warnings.filterwarnings(action = "ignore", category = RuntimeWarning, module = "multiprocess") warnings.filterwarnings(action = "ignore", category = UserWarning, module = "triton") -# Stop "Special tokens have been added in the vocabulary, ..." -import logging +warnings.filterwarnings(action = "ignore", category = UserWarning, module = "bitsandbytes") +# Stop "Special tokens have been added in the vocabulary, ..." logging.getLogger("transformers.tokenization_utils_base").setLevel(logging.CRITICAL + 1) From 30ade5241694e6a25142fc8475572a013e0c6507 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 12:12:49 +0000 Subject: [PATCH 02/20] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- unsloth/import_fixes.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/unsloth/import_fixes.py b/unsloth/import_fixes.py index 67d9bf286d..858e910c20 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -22,6 +22,7 @@ UNSLOTH_ENABLE_LOGGING = os.environ.get("UNSLOTH_ENABLE_LOGGING", "0") == "1" + def Version(version): try: new_version = str(version) @@ -30,13 +31,14 @@ def Version(version): raise Exception(str(e)) new_version = new_version.group(0).rstrip(".") if new_version != version: - new_version += ".1" # Add .1 for dev / alpha / beta / rc + new_version += ".1" # Add .1 for dev / alpha / beta / rc return TrueVersion(new_version) except: from inspect import getframeinfo, stack + caller = getframeinfo(stack()[1][0]) raise RuntimeError( - f"Unsloth: Could not get version for `{version}`\n"\ + f"Unsloth: Could not get version for `{version}`\n" f"File name = [{caller.filename}] Line number = [{caller.lineno}]" ) From cde2d42caf053565ba66988807c3774269bab45c Mon Sep 17 00:00:00 2001 From: Datta Nimmaturi Date: Fri, 12 Dec 2025 17:03:39 +0530 Subject: [PATCH 03/20] [FIX] [Transformers] VLM input embeds fix for gradients (#3715) * Fix get_input_embeds call for VLMs * patch input_require_grads instead * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * cleanup old patch * cleanup old patch * cleanup * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Apply suggestion from @danielhanchen * use logger instead of prints * Move unsloth present set * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Daniel Han --- unsloth/__init__.py | 8 ++- unsloth/import_fixes.py | 105 ++++++++++++++++++++++++++++++---------- 2 files changed, 85 insertions(+), 28 deletions(-) diff --git a/unsloth/__init__.py b/unsloth/__init__.py index 47739fad15..5df43d3117 100644 --- a/unsloth/__init__.py +++ b/unsloth/__init__.py @@ -17,6 +17,9 @@ import os, re, subprocess, inspect, functools import numpy as np +# Log Unsloth is being used +# We want logger in import_fixes and hence setting it here for zoo to be importable +os.environ["UNSLOTH_IS_PRESENT"] = "1" # Fix some issues before importing other packages from .import_fixes import ( fix_message_factory_issue, @@ -63,8 +66,6 @@ # "pinned_use_cuda_host_register:True,"\ # "pinned_num_register_threads:8" -# Log Unsloth is being used -os.environ["UNSLOTH_IS_PRESENT"] = "1" from importlib.metadata import version as importlib_version from importlib.metadata import PackageNotFoundError @@ -123,6 +124,7 @@ patch_ipykernel_hf_xet, patch_trackio, patch_datasets, + patch_enable_input_require_grads, ) fix_xformers_performance_issue() @@ -132,6 +134,7 @@ patch_ipykernel_hf_xet() patch_trackio() patch_datasets() +patch_enable_input_require_grads() del fix_xformers_performance_issue del fix_vllm_aimv2_issue @@ -140,6 +143,7 @@ del patch_ipykernel_hf_xet del patch_trackio del patch_datasets +del patch_enable_input_require_grads # Torch 2.4 has including_emulation if DEVICE_TYPE == "cuda": diff --git a/unsloth/import_fixes.py b/unsloth/import_fixes.py index 858e910c20..a43be23194 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -19,8 +19,7 @@ from packaging.version import Version as TrueVersion import re import logging - -UNSLOTH_ENABLE_LOGGING = os.environ.get("UNSLOTH_ENABLE_LOGGING", "0") == "1" +from unsloth_zoo.log import logger def Version(version): @@ -71,8 +70,7 @@ def GetPrototype(self, *args, **kwargs): return if not hasattr(google.protobuf.message_factory, "MessageFactory"): - if UNSLOTH_ENABLE_LOGGING: - print("Unsloth: Patching protobuf.MessageFactory as it doesn't exist") + logger.info("Unsloth: Patching protobuf.MessageFactory as it doesn't exist") google.protobuf.message_factory.MessageFactory = MessageFactory elif ( hasattr(google.protobuf.message_factory, "MessageFactory") @@ -82,8 +80,7 @@ def GetPrototype(self, *args, **kwargs): and not hasattr(google.protobuf.message_factory, "GetMessageClass") ): google.protobuf.message_factory.MessageFactory = MessageFactory - if UNSLOTH_ENABLE_LOGGING: - print("Unsloth: Patching protobuf.MessageFactory as it doesn't exist") + logger.info("Unsloth: Patching protobuf.MessageFactory as it doesn't exist") elif ( hasattr(google.protobuf.message_factory, "MessageFactory") and not hasattr( @@ -97,8 +94,7 @@ def GetPrototype(self, descriptor): return GetMessageClass(descriptor) google.protobuf.message_factory.MessageFactory.GetPrototype = GetPrototype - if UNSLOTH_ENABLE_LOGGING: - print("Unsloth: Patching protobuf.MessageFactory.GetPrototype") + logger.info("Unsloth: Patching protobuf.MessageFactory.GetPrototype") pass except: pass @@ -126,13 +122,11 @@ def fix_xformers_performance_issue(): f.seek(0) f.write(text) f.truncate() - if UNSLOTH_ENABLE_LOGGING: - print( - "Unsloth: Patching Xformers to fix some performance issues." - ) + logger.info( + "Unsloth: Patching Xformers to fix some performance issues." + ) except Exception as e: - if UNSLOTH_ENABLE_LOGGING: - print(f"Unsloth: Failed patching Xformers with error = {str(e)}") + logger.info(f"Unsloth: Failed patching Xformers with error = {str(e)}") # ValueError: 'aimv2' is already used by a Transformers config, pick another name. @@ -167,13 +161,11 @@ def fix_vllm_aimv2_issue(): f.seek(0) f.write(text) f.truncate() - if UNSLOTH_ENABLE_LOGGING: - print( - "Unsloth: Patching vLLM to fix `'aimv2' is already used by a Transformers config, pick another name.`" - ) + logger.info( + "Unsloth: Patching vLLM to fix `'aimv2' is already used by a Transformers config, pick another name.`" + ) except Exception as e: - if UNSLOTH_ENABLE_LOGGING: - print(f"Unsloth: Failed patching vLLM with error = {str(e)}") + logger.info(f"Unsloth: Failed patching vLLM with error = {str(e)}") def fix_vllm_guided_decoding_params(): @@ -274,8 +266,70 @@ def check_fbgemm_gpu_version(): raise ImportError( f"Unsloth: fbgemm_gpu_genai=={fbgemm_gpu_version} detected. It might cause unexpected issues like segmentation faults. Please uninstall the current one by doing `pip uninstall fbgemm-gpu` && `pip install fbgemm-gpu` to install fbgemm-gpu 1.4.0 or newer!" ) - elif UNSLOTH_ENABLE_LOGGING: - print(f"Unsloth: fbgemm_gpu_genai=={fbgemm_gpu_version} detected.") + logger.info(f"Unsloth: fbgemm_gpu_genai=={fbgemm_gpu_version} detected.") + + +def patch_enable_input_require_grads(): + """ + Patch transformers PreTrainedModel.enable_input_require_grads to handle vision models + that raise NotImplementedError from get_input_embeddings(). + + """ + import inspect + from transformers import PreTrainedModel + + # Check if the original function iterates over self.modules() instead of just returning the enable_input_require_grads + # Ref: https://github.com/huggingface/transformers/pull/41993/files#diff-6b72b98c4c2dcfc6cc606843917733f5d858374fbc22a735ff483bbc0c1e63eaL1979-R1996 + try: + original_source = inspect.getsource(PreTrainedModel.enable_input_require_grads) + except (OSError, TypeError): + return + + # Only patch if the new pattern exists (iterating over self.modules()) + if "for module in self.modules()" not in original_source: + return + + def _patched_enable_input_require_grads(self): + def make_inputs_require_grads(module, input, output): + output.requires_grad_(True) + + hooks = [] + seen_modules = set() + + for module in self.modules(): + if not ( + isinstance(module, PreTrainedModel) + and hasattr(module, "get_input_embeddings") + ): + continue + + try: + input_embeddings = module.get_input_embeddings() + except NotImplementedError: + # Vision models may not implement get_input_embeddings - skip them + # For GLM V4.6 for example, this skips only `self.visual` + continue + + if input_embeddings is None: + continue + + embedding_id = id(input_embeddings) + if embedding_id in seen_modules: + continue + + seen_modules.add(embedding_id) + hooks.append( + input_embeddings.register_forward_hook(make_inputs_require_grads) + ) + + self._require_grads_hooks = hooks + if hooks: + self._require_grads_hook = hooks[0] + + PreTrainedModel.enable_input_require_grads = _patched_enable_input_require_grads + logger.info( + "Unsloth: Patched enable_input_require_grads for vision model compatibility" + ) def torchvision_compatibility_check(): @@ -313,7 +367,6 @@ def torchvision_compatibility_check(): f"but found torchvision=={torchvision_version}. " f"Please refer to https://pytorch.org/get-started/previous-versions/ for more information." ) - elif UNSLOTH_ENABLE_LOGGING: - print( - f"Unsloth: torch=={torch_version} and torchvision=={torchvision_version} are compatible." - ) + logger.info( + f"Unsloth: torch=={torch_version} and torchvision=={torchvision_version} are compatible." + ) From 2c22ce662f883cd757cc58efb5c308a2008b2046 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 12 Dec 2025 03:41:09 -0800 Subject: [PATCH 04/20] Update rope_embedding.py --- unsloth/kernels/rope_embedding.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/unsloth/kernels/rope_embedding.py b/unsloth/kernels/rope_embedding.py index e93cbd1544..2adc9ecc5a 100644 --- a/unsloth/kernels/rope_embedding.py +++ b/unsloth/kernels/rope_embedding.py @@ -20,13 +20,6 @@ from .utils import calculate_settings, torch_gpu_device, torch_device_stream -@triton.heuristics( - { - "BACKWARD_PASS": lambda args: bool(args["BACKWARD_PASS"]), - "HAS_ROPE_INDICES": lambda args: bool(args["HAS_ROPE_INDICES"]), - } -) -@triton.jit def _rope_embedding_QK( Q, Q_batch_stride, @@ -104,9 +97,17 @@ def _rope_embedding_QK( tl.store(k_ptr + half_head_dim + col_offsets, k1 * cos1 + k0 * sin1, mask = mask) -ROPE_GROUP_SIZE: int = 4 +_rope_embedding_QK = triton.jit(_rope_embedding_QK) +_rope_embedding_QK = triton.heuristics( + { + "BACKWARD_PASS": lambda args: bool(args["BACKWARD_PASS"]), + "HAS_ROPE_INDICES": lambda args: bool(args["HAS_ROPE_INDICES"]), + } +)(_rope_embedding_QK) +ROPE_GROUP_SIZE: int = 4 + def _rope_embedding( Q, Q_row_stride: tl.constexpr, From b5f1a77482a7615a748d8783837ee59da3e89e00 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 12 Dec 2025 04:58:43 -0800 Subject: [PATCH 05/20] Fixes --- unsloth/import_fixes.py | 2 +- unsloth/models/rl_replacements.py | 8 +++++++- unsloth/trainer.py | 5 +++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/unsloth/import_fixes.py b/unsloth/import_fixes.py index a43be23194..4cbe57cd95 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -282,7 +282,7 @@ def patch_enable_input_require_grads(): # Ref: https://github.com/huggingface/transformers/pull/41993/files#diff-6b72b98c4c2dcfc6cc606843917733f5d858374fbc22a735ff483bbc0c1e63eaL1979-R1996 try: original_source = inspect.getsource(PreTrainedModel.enable_input_require_grads) - except (OSError, TypeError): + except: return # Only patch if the new pattern exists (iterating over self.modules()) diff --git a/unsloth/models/rl_replacements.py b/unsloth/models/rl_replacements.py index 2cf3527c9b..7dab0d7307 100644 --- a/unsloth/models/rl_replacements.py +++ b/unsloth/models/rl_replacements.py @@ -26,7 +26,9 @@ import inspect from collections import defaultdict from unsloth_zoo.rl_replacements import RL_REPLACEMENTS, left_pack_padding +from unsloth_zoo.utils import Version from unsloth_zoo.log import logger +import importlib.util from ..device_type import ( is_hip, get_device_type, @@ -942,11 +944,15 @@ def openenv_vllm_reload_weights(): # # The fix: Use wake_up() with no tags, which wakes everything. Unsloth's patched # CuMemAllocator.wake_up skips weights anyway, so this is safe. + if importlib.util.find_spec("trl") is None: + return + if Version(importlib_version("trl")) < Version("0.26.0"): + return try: import trl.experimental.openenv.utils as openenv_utils import trl.experimental.openenv as openenv except ImportError as e: - logger.warning(f"Unsloth: Failed to import trl openenv: {e}") + logger.info(f"Unsloth: Failed to import trl openenv: {e}") return src = inspect.getsource(openenv_utils.generate_rollout_completions) diff --git a/unsloth/trainer.py b/unsloth/trainer.py index 339af63f33..5cd1bfd08d 100644 --- a/unsloth/trainer.py +++ b/unsloth/trainer.py @@ -36,7 +36,7 @@ UnslothVisionDataCollator, ) from unsloth_zoo.hf_utils import get_transformers_model_type -from packaging.version import Version +from unsloth_zoo.utils import Version import dataclasses __all__ = [ @@ -315,10 +315,11 @@ def new_init(self, *args, **kwargs): # We also disable vision language models for padding free collators blocked = ( - data_collator is not None + (data_collator is not None) or isinstance(processing_class, ProcessorMixin) or is_vlm or is_unsupported_model + or (os.environ.get("UNSLOTH_RETURN_LOGITS", "0") == "1") # Disable padding free on forced logits ) requested_pack = bool(getattr(config_arg, "packing", False)) if blocked: From c94f59513fb2353b40628f9620c6657eaccbff7e Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 12 Dec 2025 05:01:43 -0800 Subject: [PATCH 06/20] Update _utils.py --- unsloth/models/_utils.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/unsloth/models/_utils.py b/unsloth/models/_utils.py index bdb8f38a50..0377127860 100644 --- a/unsloth/models/_utils.py +++ b/unsloth/models/_utils.py @@ -413,6 +413,16 @@ def filter(self, x): except: pass +# Flax classes are deprecated and will be removed in Diffusers v1.0.0. +try: + from diffusers.utils import logger as diffusers_logger + + diffusers_logger.addFilter(HideLoggingMessage("are deprecated")) + del diffusers_logger +except: + pass + + # Errors out on # Some weights of Gemma3nForConditionalGeneration were not initialized from the model checkpoint from transformers.modeling_utils import logger as transformers_logger From 01319d3681289e46e9c9f7166888b923418d3bc4 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 12 Dec 2025 05:10:45 -0800 Subject: [PATCH 07/20] Update import_fixes.py --- unsloth/import_fixes.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/unsloth/import_fixes.py b/unsloth/import_fixes.py index 4cbe57cd95..63bfd6e1e1 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -370,3 +370,41 @@ def torchvision_compatibility_check(): logger.info( f"Unsloth: torch=={torch_version} and torchvision=={torchvision_version} are compatible." ) + + +# Fix TRL OpenEnv 0.26 NameError: name 'SamplingParams' is not defined +def fix_openenv_no_vllm(): + if importlib.util.find_spec("trl") is None: + return + trl_location = importlib.util.find_spec("trl").origin + trl_location = os.path.split(trl_location)[0] + openenv = Path(trl_location) / "experimental" / "openenv" / "utils.py" + if not openenv.exists(): + return + try: + with open(openenv, "r+", encoding = "utf-8") as f: + text = f.read() + bad = ( + "if is_vllm_available():\n" + "from vllm import SamplingParams\n" + "from vllm.sampling_params import GuidedDecodingParams\n" + ) + if bad + "\n" + "\n" in text: + text = text.replace( + bad + "\n" + "\n", + bad + ( + "else:\n" + " from typing import Any\n"\ + " SamplingParams = Any\n"\ + " GuidedDecodingParams = Any\n" + "\n" + ) + ) + f.seek(0) + f.write(text) + f.truncate() + logger.info( + "Unsloth: Patching TRL OpenEnv to fix SamplingParams not defined" + ) + except Exception as e: + logger.info(f"Unsloth: Failed patching TRL OpenEnv with error = {str(e)}") From 696a540c1ef5f2f6da5cf9d67e36994d29aee434 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 12 Dec 2025 05:11:12 -0800 Subject: [PATCH 08/20] Update rl_replacements.py --- unsloth/models/rl_replacements.py | 1 + 1 file changed, 1 insertion(+) diff --git a/unsloth/models/rl_replacements.py b/unsloth/models/rl_replacements.py index 7dab0d7307..7d4d520c1f 100644 --- a/unsloth/models/rl_replacements.py +++ b/unsloth/models/rl_replacements.py @@ -27,6 +27,7 @@ from collections import defaultdict from unsloth_zoo.rl_replacements import RL_REPLACEMENTS, left_pack_padding from unsloth_zoo.utils import Version +from importlib.metadata import version as importlib_version from unsloth_zoo.log import logger import importlib.util from ..device_type import ( From ac54d6e1c8ad3c7615037a49dfd5fed8883e41c3 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 12 Dec 2025 05:20:09 -0800 Subject: [PATCH 09/20] fix_openenv_no_vllm --- pyproject.toml | 4 ++-- unsloth/__init__.py | 3 +++ unsloth/models/_utils.py | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8d91ff621d..c6e19b014e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,7 +60,7 @@ huggingfacenotorch = [ ] huggingface = [ "unsloth[huggingfacenotorch]", - "unsloth_zoo>=2025.12.3", + "unsloth_zoo>=2025.12.4", "torchvision", "unsloth[triton]", ] @@ -523,7 +523,7 @@ colab-ampere-torch220 = [ "flash-attn>=2.6.3 ; ('linux' in sys_platform)", ] colab-new = [ - "unsloth_zoo>=2025.12.3", + "unsloth_zoo>=2025.12.4", "packaging", "tyro", "transformers>=4.51.3,!=4.52.0,!=4.52.1,!=4.52.2,!=4.52.3,!=4.53.0,!=4.54.0,!=4.55.0,!=4.55.1,!=4.57.0,<=4.57.3", diff --git a/unsloth/__init__.py b/unsloth/__init__.py index 5df43d3117..e389074a1b 100644 --- a/unsloth/__init__.py +++ b/unsloth/__init__.py @@ -125,6 +125,7 @@ patch_trackio, patch_datasets, patch_enable_input_require_grads, + fix_openenv_no_vllm, ) fix_xformers_performance_issue() @@ -135,6 +136,7 @@ patch_trackio() patch_datasets() patch_enable_input_require_grads() +fix_openenv_no_vllm() del fix_xformers_performance_issue del fix_vllm_aimv2_issue @@ -144,6 +146,7 @@ del patch_trackio del patch_datasets del patch_enable_input_require_grads +del fix_openenv_no_vllm # Torch 2.4 has including_emulation if DEVICE_TYPE == "cuda": diff --git a/unsloth/models/_utils.py b/unsloth/models/_utils.py index 0377127860..653b539b20 100644 --- a/unsloth/models/_utils.py +++ b/unsloth/models/_utils.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "2025.12.4" +__version__ = "2025.12.5" __all__ = [ "SUPPORTS_BFLOAT16", From 9a9813942d89cf8d122b1a544aa5d552d8e72d70 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 12 Dec 2025 05:27:42 -0800 Subject: [PATCH 10/20] Fix --- unsloth/__init__.py | 4 ++-- unsloth/import_fixes.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/unsloth/__init__.py b/unsloth/__init__.py index e389074a1b..30bfae35bb 100644 --- a/unsloth/__init__.py +++ b/unsloth/__init__.py @@ -124,7 +124,7 @@ patch_ipykernel_hf_xet, patch_trackio, patch_datasets, - patch_enable_input_require_grads, + # patch_enable_input_require_grads, fix_openenv_no_vllm, ) @@ -135,7 +135,7 @@ patch_ipykernel_hf_xet() patch_trackio() patch_datasets() -patch_enable_input_require_grads() +# patch_enable_input_require_grads() fix_openenv_no_vllm() del fix_xformers_performance_issue diff --git a/unsloth/import_fixes.py b/unsloth/import_fixes.py index 63bfd6e1e1..79fba855f5 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -386,8 +386,8 @@ def fix_openenv_no_vllm(): text = f.read() bad = ( "if is_vllm_available():\n" - "from vllm import SamplingParams\n" - "from vllm.sampling_params import GuidedDecodingParams\n" + " from vllm import SamplingParams\n" + " from vllm.sampling_params import GuidedDecodingParams\n" ) if bad + "\n" + "\n" in text: text = text.replace( From 680f19f156952cf687ce0f776fa7f73555c8724c Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 12 Dec 2025 05:29:25 -0800 Subject: [PATCH 11/20] Update __init__.py --- unsloth/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unsloth/__init__.py b/unsloth/__init__.py index 30bfae35bb..e389074a1b 100644 --- a/unsloth/__init__.py +++ b/unsloth/__init__.py @@ -124,7 +124,7 @@ patch_ipykernel_hf_xet, patch_trackio, patch_datasets, - # patch_enable_input_require_grads, + patch_enable_input_require_grads, fix_openenv_no_vllm, ) @@ -135,7 +135,7 @@ patch_ipykernel_hf_xet() patch_trackio() patch_datasets() -# patch_enable_input_require_grads() +patch_enable_input_require_grads() fix_openenv_no_vllm() del fix_xformers_performance_issue From fb763f34ec280e83f935a7ad383c30f92a0a05be Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 12 Dec 2025 05:31:36 -0800 Subject: [PATCH 12/20] Update __init__.py --- unsloth/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unsloth/__init__.py b/unsloth/__init__.py index e389074a1b..72d53f572e 100644 --- a/unsloth/__init__.py +++ b/unsloth/__init__.py @@ -18,8 +18,8 @@ import numpy as np # Log Unsloth is being used -# We want logger in import_fixes and hence setting it here for zoo to be importable os.environ["UNSLOTH_IS_PRESENT"] = "1" + # Fix some issues before importing other packages from .import_fixes import ( fix_message_factory_issue, @@ -46,7 +46,7 @@ # stacklevel=2 makes warning point to user's import line rather than this library code, # showing them exactly where to fix the import order in their script warnings.warn( - f"WARNING: Unsloth should be imported before {', '.join(already_imported)} " + f"WARNING: Unsloth should be imported before [{', '.join(already_imported)}] " f"to ensure all optimizations are applied. Your code may run slower or encounter " f"memory issues without these optimizations.\n\n" f"Please restructure your imports with 'import unsloth' at the top of your file.", From f4f2a7f907f4923bbd1c70257683b09001202c03 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 12 Dec 2025 05:34:29 -0800 Subject: [PATCH 13/20] Update __init__.py --- unsloth/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/unsloth/__init__.py b/unsloth/__init__.py index 72d53f572e..9dd7b08b56 100644 --- a/unsloth/__init__.py +++ b/unsloth/__init__.py @@ -16,6 +16,7 @@ from packaging.version import Version import os, re, subprocess, inspect, functools import numpy as np +print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) # Log Unsloth is being used os.environ["UNSLOTH_IS_PRESENT"] = "1" @@ -26,6 +27,7 @@ check_fbgemm_gpu_version, torchvision_compatibility_check, ) +print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) fix_message_factory_issue() check_fbgemm_gpu_version() From e17b62f76e0c2c8da6728aabaae9267e6b2bf00c Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 12 Dec 2025 05:36:40 -0800 Subject: [PATCH 14/20] Update import_fixes.py --- unsloth/import_fixes.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/unsloth/import_fixes.py b/unsloth/import_fixes.py index 79fba855f5..3ba79c2162 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -268,6 +268,7 @@ def check_fbgemm_gpu_version(): ) logger.info(f"Unsloth: fbgemm_gpu_genai=={fbgemm_gpu_version} detected.") +print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) def patch_enable_input_require_grads(): """ @@ -331,6 +332,7 @@ def make_inputs_require_grads(module, input, output): "Unsloth: Patched enable_input_require_grads for vision model compatibility" ) +print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) def torchvision_compatibility_check(): if importlib.util.find_spec("torch") is None: From f34eb0abb6bfcfb28d0e8bfb00b87bdd3f652da9 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 12 Dec 2025 05:38:24 -0800 Subject: [PATCH 15/20] Update import_fixes.py --- unsloth/import_fixes.py | 1 + 1 file changed, 1 insertion(+) diff --git a/unsloth/import_fixes.py b/unsloth/import_fixes.py index 3ba79c2162..75dc12f5a1 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -13,6 +13,7 @@ # limitations under the License. import os +import sys import importlib.util from pathlib import Path from importlib.metadata import version as importlib_version From 04ad21cdb0b77602412adfe58e9b86e08a1d37e8 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 12 Dec 2025 05:40:56 -0800 Subject: [PATCH 16/20] Update import_fixes.py --- unsloth/import_fixes.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/unsloth/import_fixes.py b/unsloth/import_fixes.py index 75dc12f5a1..aa848a91b8 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -20,8 +20,9 @@ from packaging.version import Version as TrueVersion import re import logging +print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) from unsloth_zoo.log import logger - +print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) def Version(version): try: @@ -41,7 +42,7 @@ def Version(version): f"Unsloth: Could not get version for `{version}`\n" f"File name = [{caller.filename}] Line number = [{caller.lineno}]" ) - +print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) # Ignore logging messages class HideLoggingMessage(logging.Filter): @@ -52,7 +53,7 @@ def __init__(self, text): def filter(self, x): return not (self.text in x.getMessage()) - +print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) # Fix up AttributeError: 'MessageFactory' object has no attribute 'GetPrototype' # MUST do this at the start primarily due to tensorflow causing issues @@ -99,7 +100,7 @@ def GetPrototype(self, descriptor): pass except: pass - +print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) # Fix Xformers performance issues since 0.0.25 def fix_xformers_performance_issue(): @@ -128,7 +129,7 @@ def fix_xformers_performance_issue(): ) except Exception as e: logger.info(f"Unsloth: Failed patching Xformers with error = {str(e)}") - +print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) # ValueError: 'aimv2' is already used by a Transformers config, pick another name. def fix_vllm_aimv2_issue(): @@ -167,7 +168,7 @@ def fix_vllm_aimv2_issue(): ) except Exception as e: logger.info(f"Unsloth: Failed patching vLLM with error = {str(e)}") - +print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) def fix_vllm_guided_decoding_params(): if importlib.util.find_spec("vllm") is None: @@ -183,7 +184,7 @@ def fix_vllm_guided_decoding_params(): vllm.sampling_params.GuidedDecodingParams = ( vllm.sampling_params.StructuredOutputsParams ) - +print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) def ignore_logger_messages(): # Ignore Environment variable `HF_TOKEN` is set @@ -194,7 +195,7 @@ def ignore_logger_messages(): del huggingface_hub_logger except: pass - +print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) def patch_ipykernel_hf_xet(): # HF-XET == 1.1.10 and ipykernel == 7.0.0 / 7.0.1 causes issues @@ -226,7 +227,7 @@ def patch_ipykernel_hf_xet(): from huggingface_hub.utils import disable_progress_bars disable_progress_bars() - +print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) def patch_trackio(): # Set some environment variables to customize the Trackio dashboard for experiment tracking @@ -238,7 +239,7 @@ def patch_trackio(): "https://raw.githubusercontent.com/unslothai/unsloth/main/images/unsloth%20logo%20white%20text.png" ) os.environ["TRACKIO_PLOT_ORDER"] = "train/reward" - +print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) def patch_datasets(): # Datasets 4.4.0 and 4.4.1 weirdly have some weird `_thread.RLock_recursion_count` issues @@ -253,7 +254,7 @@ def patch_datasets(): f"#### Unsloth: Using `datasets = {str(datasets_version)}` will cause recursion errors.\n" "Please downgrade datasets to `datasets==4.3.0" ) - +print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) def check_fbgemm_gpu_version(): if importlib.util.find_spec("fbgemm_gpu") is None: From 32b52a00028bd497ac11bd853ca8f08fd979562e Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 12 Dec 2025 05:44:38 -0800 Subject: [PATCH 17/20] logger --- unsloth/__init__.py | 2 -- unsloth/import_fixes.py | 36 ++++++++++++++++++++---------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/unsloth/__init__.py b/unsloth/__init__.py index 9dd7b08b56..72d53f572e 100644 --- a/unsloth/__init__.py +++ b/unsloth/__init__.py @@ -16,7 +16,6 @@ from packaging.version import Version import os, re, subprocess, inspect, functools import numpy as np -print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) # Log Unsloth is being used os.environ["UNSLOTH_IS_PRESENT"] = "1" @@ -27,7 +26,6 @@ check_fbgemm_gpu_version, torchvision_compatibility_check, ) -print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) fix_message_factory_issue() check_fbgemm_gpu_version() diff --git a/unsloth/import_fixes.py b/unsloth/import_fixes.py index aa848a91b8..d90c9a8a07 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -13,16 +13,15 @@ # limitations under the License. import os -import sys import importlib.util from pathlib import Path from importlib.metadata import version as importlib_version from packaging.version import Version as TrueVersion import re import logging -print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) -from unsloth_zoo.log import logger -print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) +# Cannot import logger here since it'll import transformers +# from unsloth_zoo.log import logger + def Version(version): try: @@ -42,7 +41,7 @@ def Version(version): f"Unsloth: Could not get version for `{version}`\n" f"File name = [{caller.filename}] Line number = [{caller.lineno}]" ) -print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) + # Ignore logging messages class HideLoggingMessage(logging.Filter): @@ -53,7 +52,7 @@ def __init__(self, text): def filter(self, x): return not (self.text in x.getMessage()) -print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) + # Fix up AttributeError: 'MessageFactory' object has no attribute 'GetPrototype' # MUST do this at the start primarily due to tensorflow causing issues @@ -71,6 +70,7 @@ def GetMessages(self, *args, **kwargs): def GetPrototype(self, *args, **kwargs): return + from unsloth_zoo.log import logger if not hasattr(google.protobuf.message_factory, "MessageFactory"): logger.info("Unsloth: Patching protobuf.MessageFactory as it doesn't exist") google.protobuf.message_factory.MessageFactory = MessageFactory @@ -100,7 +100,7 @@ def GetPrototype(self, descriptor): pass except: pass -print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) + # Fix Xformers performance issues since 0.0.25 def fix_xformers_performance_issue(): @@ -108,6 +108,7 @@ def fix_xformers_performance_issue(): return xformers_version = importlib_version("xformers") if Version(xformers_version) < Version("0.0.29"): + from unsloth_zoo.log import logger xformers_location = importlib.util.find_spec("xformers").origin xformers_location = os.path.split(xformers_location)[0] cutlass = Path(xformers_location) / "ops" / "fmha" / "cutlass.py" @@ -129,7 +130,7 @@ def fix_xformers_performance_issue(): ) except Exception as e: logger.info(f"Unsloth: Failed patching Xformers with error = {str(e)}") -print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) + # ValueError: 'aimv2' is already used by a Transformers config, pick another name. def fix_vllm_aimv2_issue(): @@ -137,6 +138,7 @@ def fix_vllm_aimv2_issue(): return vllm_version = importlib_version("vllm") if Version(vllm_version) < Version("0.10.1"): + from unsloth_zoo.log import logger vllm_version = importlib.util.find_spec("vllm").origin vllm_version = os.path.split(vllm_version)[0] ovis_config = Path(vllm_version) / "transformers_utils" / "configs" / "ovis.py" @@ -168,7 +170,7 @@ def fix_vllm_aimv2_issue(): ) except Exception as e: logger.info(f"Unsloth: Failed patching vLLM with error = {str(e)}") -print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) + def fix_vllm_guided_decoding_params(): if importlib.util.find_spec("vllm") is None: @@ -184,7 +186,7 @@ def fix_vllm_guided_decoding_params(): vllm.sampling_params.GuidedDecodingParams = ( vllm.sampling_params.StructuredOutputsParams ) -print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) + def ignore_logger_messages(): # Ignore Environment variable `HF_TOKEN` is set @@ -195,7 +197,7 @@ def ignore_logger_messages(): del huggingface_hub_logger except: pass -print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) + def patch_ipykernel_hf_xet(): # HF-XET == 1.1.10 and ipykernel == 7.0.0 / 7.0.1 causes issues @@ -227,7 +229,7 @@ def patch_ipykernel_hf_xet(): from huggingface_hub.utils import disable_progress_bars disable_progress_bars() -print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) + def patch_trackio(): # Set some environment variables to customize the Trackio dashboard for experiment tracking @@ -239,7 +241,7 @@ def patch_trackio(): "https://raw.githubusercontent.com/unslothai/unsloth/main/images/unsloth%20logo%20white%20text.png" ) os.environ["TRACKIO_PLOT_ORDER"] = "train/reward" -print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) + def patch_datasets(): # Datasets 4.4.0 and 4.4.1 weirdly have some weird `_thread.RLock_recursion_count` issues @@ -254,7 +256,7 @@ def patch_datasets(): f"#### Unsloth: Using `datasets = {str(datasets_version)}` will cause recursion errors.\n" "Please downgrade datasets to `datasets==4.3.0" ) -print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) + def check_fbgemm_gpu_version(): if importlib.util.find_spec("fbgemm_gpu") is None: @@ -268,9 +270,9 @@ def check_fbgemm_gpu_version(): raise ImportError( f"Unsloth: fbgemm_gpu_genai=={fbgemm_gpu_version} detected. It might cause unexpected issues like segmentation faults. Please uninstall the current one by doing `pip uninstall fbgemm-gpu` && `pip install fbgemm-gpu` to install fbgemm-gpu 1.4.0 or newer!" ) + from unsloth_zoo.log import logger logger.info(f"Unsloth: fbgemm_gpu_genai=={fbgemm_gpu_version} detected.") -print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) def patch_enable_input_require_grads(): """ @@ -330,11 +332,11 @@ def make_inputs_require_grads(module, input, output): self._require_grads_hook = hooks[0] PreTrainedModel.enable_input_require_grads = _patched_enable_input_require_grads + from unsloth_zoo.log import logger logger.info( "Unsloth: Patched enable_input_require_grads for vision model compatibility" ) -print([mod for mod in ["trl", "transformers", "peft"] if mod in sys.modules]) def torchvision_compatibility_check(): if importlib.util.find_spec("torch") is None: @@ -371,6 +373,7 @@ def torchvision_compatibility_check(): f"but found torchvision=={torchvision_version}. " f"Please refer to https://pytorch.org/get-started/previous-versions/ for more information." ) + from unsloth_zoo.log import logger logger.info( f"Unsloth: torch=={torch_version} and torchvision=={torchvision_version} are compatible." ) @@ -385,6 +388,7 @@ def fix_openenv_no_vllm(): openenv = Path(trl_location) / "experimental" / "openenv" / "utils.py" if not openenv.exists(): return + from unsloth_zoo.log import logger try: with open(openenv, "r+", encoding = "utf-8") as f: text = f.read() From 0c9288f311dfe59e4496da999ba29427f66d2a27 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 12 Dec 2025 05:46:50 -0800 Subject: [PATCH 18/20] Update __init__.py --- unsloth/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/unsloth/__init__.py b/unsloth/__init__.py index 72d53f572e..a0ca276cde 100644 --- a/unsloth/__init__.py +++ b/unsloth/__init__.py @@ -20,6 +20,10 @@ # Log Unsloth is being used os.environ["UNSLOTH_IS_PRESENT"] = "1" +# Check if modules that need patching are already imported +critical_modules = ["trl", "transformers", "peft"] +already_imported = [mod for mod in critical_modules if mod in sys.modules] + # Fix some issues before importing other packages from .import_fixes import ( fix_message_factory_issue, @@ -34,10 +38,6 @@ del check_fbgemm_gpu_version del torchvision_compatibility_check -# Check if modules that need patching are already imported -critical_modules = ["trl", "transformers", "peft"] -already_imported = [mod for mod in critical_modules if mod in sys.modules] - # This check is critical because Unsloth optimizes these libraries by modifying # their code at import time. If they're imported first, the original (slower, # more memory-intensive) implementations will be used instead of Unsloth's From b5b57b3378b5d74948372995f7f9c290d8370502 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 12 Dec 2025 13:48:24 +0000 Subject: [PATCH 19/20] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- unsloth/import_fixes.py | 16 ++++++++++++---- unsloth/kernels/rope_embedding.py | 1 + unsloth/trainer.py | 4 +++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/unsloth/import_fixes.py b/unsloth/import_fixes.py index d90c9a8a07..a78b5451ea 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -71,6 +71,7 @@ def GetPrototype(self, *args, **kwargs): return from unsloth_zoo.log import logger + if not hasattr(google.protobuf.message_factory, "MessageFactory"): logger.info("Unsloth: Patching protobuf.MessageFactory as it doesn't exist") google.protobuf.message_factory.MessageFactory = MessageFactory @@ -109,6 +110,7 @@ def fix_xformers_performance_issue(): xformers_version = importlib_version("xformers") if Version(xformers_version) < Version("0.0.29"): from unsloth_zoo.log import logger + xformers_location = importlib.util.find_spec("xformers").origin xformers_location = os.path.split(xformers_location)[0] cutlass = Path(xformers_location) / "ops" / "fmha" / "cutlass.py" @@ -139,6 +141,7 @@ def fix_vllm_aimv2_issue(): vllm_version = importlib_version("vllm") if Version(vllm_version) < Version("0.10.1"): from unsloth_zoo.log import logger + vllm_version = importlib.util.find_spec("vllm").origin vllm_version = os.path.split(vllm_version)[0] ovis_config = Path(vllm_version) / "transformers_utils" / "configs" / "ovis.py" @@ -271,6 +274,7 @@ def check_fbgemm_gpu_version(): f"Unsloth: fbgemm_gpu_genai=={fbgemm_gpu_version} detected. It might cause unexpected issues like segmentation faults. Please uninstall the current one by doing `pip uninstall fbgemm-gpu` && `pip install fbgemm-gpu` to install fbgemm-gpu 1.4.0 or newer!" ) from unsloth_zoo.log import logger + logger.info(f"Unsloth: fbgemm_gpu_genai=={fbgemm_gpu_version} detected.") @@ -333,6 +337,7 @@ def make_inputs_require_grads(module, input, output): PreTrainedModel.enable_input_require_grads = _patched_enable_input_require_grads from unsloth_zoo.log import logger + logger.info( "Unsloth: Patched enable_input_require_grads for vision model compatibility" ) @@ -374,6 +379,7 @@ def torchvision_compatibility_check(): f"Please refer to https://pytorch.org/get-started/previous-versions/ for more information." ) from unsloth_zoo.log import logger + logger.info( f"Unsloth: torch=={torch_version} and torchvision=={torchvision_version} are compatible." ) @@ -389,6 +395,7 @@ def fix_openenv_no_vllm(): if not openenv.exists(): return from unsloth_zoo.log import logger + try: with open(openenv, "r+", encoding = "utf-8") as f: text = f.read() @@ -400,13 +407,14 @@ def fix_openenv_no_vllm(): if bad + "\n" + "\n" in text: text = text.replace( bad + "\n" + "\n", - bad + ( + bad + + ( "else:\n" - " from typing import Any\n"\ - " SamplingParams = Any\n"\ + " from typing import Any\n" + " SamplingParams = Any\n" " GuidedDecodingParams = Any\n" "\n" - ) + ), ) f.seek(0) f.write(text) diff --git a/unsloth/kernels/rope_embedding.py b/unsloth/kernels/rope_embedding.py index 2adc9ecc5a..a032e0f7fc 100644 --- a/unsloth/kernels/rope_embedding.py +++ b/unsloth/kernels/rope_embedding.py @@ -108,6 +108,7 @@ def _rope_embedding_QK( ROPE_GROUP_SIZE: int = 4 + def _rope_embedding( Q, Q_row_stride: tl.constexpr, diff --git a/unsloth/trainer.py b/unsloth/trainer.py index 5cd1bfd08d..c0b2dd03b6 100644 --- a/unsloth/trainer.py +++ b/unsloth/trainer.py @@ -319,7 +319,9 @@ def new_init(self, *args, **kwargs): or isinstance(processing_class, ProcessorMixin) or is_vlm or is_unsupported_model - or (os.environ.get("UNSLOTH_RETURN_LOGITS", "0") == "1") # Disable padding free on forced logits + or ( + os.environ.get("UNSLOTH_RETURN_LOGITS", "0") == "1" + ) # Disable padding free on forced logits ) requested_pack = bool(getattr(config_arg, "packing", False)) if blocked: From efb5801a74a695fcae41653652baadc0bcd78d41 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 12 Dec 2025 05:51:31 -0800 Subject: [PATCH 20/20] Update __init__.py --- unsloth/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unsloth/__init__.py b/unsloth/__init__.py index a0ca276cde..007b952200 100644 --- a/unsloth/__init__.py +++ b/unsloth/__init__.py @@ -73,7 +73,7 @@ # Check for unsloth_zoo try: unsloth_zoo_version = importlib_version("unsloth_zoo") - if Version(unsloth_zoo_version) < Version("2025.12.3"): + if Version(unsloth_zoo_version) < Version("2025.12.4"): print( "Unsloth: Please update Unsloth and Unsloth-Zoo to the latest version!\n" "Do this via `pip install --upgrade --force-reinstall --no-cache-dir --no-deps unsloth unsloth_zoo`"