From e53e1852a8fe989ae4881107474ef5b64f9b0fa3 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Tue, 9 Dec 2025 01:02:26 -0800 Subject: [PATCH 01/41] 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/41] [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/41] [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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] [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/41] 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`" From 554021220c993dc9c424e7bd3e4fa9bb0e3c2445 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Tue, 16 Dec 2025 19:48:41 -0800 Subject: [PATCH 21/41] Update import_fixes.py --- unsloth/import_fixes.py | 67 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/unsloth/import_fixes.py b/unsloth/import_fixes.py index 3da82c8eb6..458221cf18 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -422,3 +422,70 @@ def fix_openenv_no_vllm(): ) except Exception as e: logger.info(f"Unsloth: Failed patching TRL OpenEnv with error = {str(e)}") + + +# Fix Exeuctorch needing get_mapped_key +def fix_executorch(): + if importlib.util.find_spec("executorch") is None: + print(1) + executorch_location = importlib.util.find_spec("executorch").origin + if executorch_location is None: + executorch_location = importlib.util.find_spec("executorch").submodule_search_locations[0] + else: + executorch_location = os.path.split(executorch_location)[0] + executorch = Path(executorch_location) / "examples" / "models" / "__init__.py" + if not executorch.exists(): + return + + try: + what = r''' + import sys + import types + import re + from typing import Any, Optional + def get_mapped_key(key: str, mapping_dict: dict[str, str]) -> str: + try: + # Checks if there is a layer # in the key + if any(k.isdigit() for k in key.split(".")): + # Replace layer number with "{}" to create key for lookup + abstract_key = re.sub(r"(\.\d+)", ".{}", key) + layer_num = re.search(r"\d+", key).group(0) + new_key = mapping_dict[abstract_key] + new_key = new_key.format(layer_num) + else: + new_key = mapping_dict[key] + except KeyError as e: + raise Exception( + f'Error converting the state dict. Found unexpected key: "{key}". ' + "Please make sure you're loading a checkpoint with the right format. " + ) from e + + return new_key + + torchtune = types.ModuleType("torchtune") + torchtune.__path__ = [] + models = types.ModuleType("torchtune.models") + models.__path__ = [] + convert_weights = types.ModuleType("torchtune.models.convert_weights") + convert_weights.get_mapped_key = get_mapped_key + torchtune.models = models + models.convert_weights = convert_weights + sys.modules["torchtune"] = torchtune + sys.modules["torchtune.models"] = models + sys.modules["torchtune.models.convert_weights"] = convert_weights + ''' + what = textwrap.dedent(what) + + with open(executorch, "r+", encoding = "utf-8") as f: + text = f.read() + bad = "from enum import Enum\n" + if bad in text: + text = text.replace(bad + "\n", bad + "\n" + what) + f.seek(0) + f.write(text) + f.truncate() + logger.info( + "Unsloth: Patching Executorch to fix get_mapped_key" + ) + except Exception as e: + logger.info(f"Unsloth: Failed Executorch with error = {str(e)}") From 4c80b034af13c04fad72c2a5e7e746d13fa04b99 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Tue, 16 Dec 2025 19:49:19 -0800 Subject: [PATCH 22/41] Update __init__.py --- unsloth/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/unsloth/__init__.py b/unsloth/__init__.py index 007b952200..bf3de82dc0 100644 --- a/unsloth/__init__.py +++ b/unsloth/__init__.py @@ -126,6 +126,7 @@ patch_datasets, patch_enable_input_require_grads, fix_openenv_no_vllm, + fix_executorch, ) fix_xformers_performance_issue() @@ -137,6 +138,7 @@ patch_datasets() patch_enable_input_require_grads() fix_openenv_no_vllm() +fix_executorch() del fix_xformers_performance_issue del fix_vllm_aimv2_issue @@ -147,6 +149,7 @@ del patch_datasets del patch_enable_input_require_grads del fix_openenv_no_vllm +del fix_executorch # Torch 2.4 has including_emulation if DEVICE_TYPE == "cuda": From e57edc2694c3f8929182d31e5c166275930fbf9d Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Tue, 16 Dec 2025 19:51:10 -0800 Subject: [PATCH 23/41] Update import_fixes.py --- unsloth/import_fixes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unsloth/import_fixes.py b/unsloth/import_fixes.py index 458221cf18..1577a8384e 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -427,7 +427,7 @@ def fix_openenv_no_vllm(): # Fix Exeuctorch needing get_mapped_key def fix_executorch(): if importlib.util.find_spec("executorch") is None: - print(1) + return executorch_location = importlib.util.find_spec("executorch").origin if executorch_location is None: executorch_location = importlib.util.find_spec("executorch").submodule_search_locations[0] From 9bc1567a17e54b4313f55dda9109e06e30b55a38 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Tue, 16 Dec 2025 19:59:04 -0800 Subject: [PATCH 24/41] Update import_fixes.py --- unsloth/import_fixes.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/unsloth/import_fixes.py b/unsloth/import_fixes.py index 1577a8384e..09c8637992 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -115,8 +115,11 @@ def fix_xformers_performance_issue(): return xformers_version = importlib_version("xformers") if Version(xformers_version) < Version("0.0.29"): - xformers_location = importlib.util.find_spec("xformers").origin - xformers_location = os.path.split(xformers_location)[0] + xformers_location = importlib.util.find_spec("xformers") + if xformers_location is None: + xformers_location = importlib.util.find_spec("xformers").submodule_search_locations[0] + else: + xformers_location = os.path.split(xformers_location.origin)[0] cutlass = Path(xformers_location) / "ops" / "fmha" / "cutlass.py" try: if cutlass.exists(): @@ -144,8 +147,11 @@ def fix_vllm_aimv2_issue(): return vllm_version = importlib_version("vllm") if Version(vllm_version) < Version("0.10.1"): - vllm_version = importlib.util.find_spec("vllm").origin - vllm_version = os.path.split(vllm_version)[0] + vllm_version = importlib.util.find_spec("vllm") + if vllm_version is None: + vllm_version = importlib.util.find_spec("vllm").submodule_search_locations[0] + else: + vllm_version = os.path.split(vllm_version.origin)[0] ovis_config = Path(vllm_version) / "transformers_utils" / "configs" / "ovis.py" try: if ovis_config.exists(): @@ -388,8 +394,11 @@ def torchvision_compatibility_check(): 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] + trl_location = importlib.util.find_spec("trl") + if trl_location is None: + trl_location = importlib.util.find_spec("trl").submodule_search_locations[0] + else: + trl_location = os.path.split(trl_location.origin)[0] openenv = Path(trl_location) / "experimental" / "openenv" / "utils.py" if not openenv.exists(): return @@ -428,11 +437,11 @@ def fix_openenv_no_vllm(): def fix_executorch(): if importlib.util.find_spec("executorch") is None: return - executorch_location = importlib.util.find_spec("executorch").origin + executorch_location = importlib.util.find_spec("executorch") if executorch_location is None: executorch_location = importlib.util.find_spec("executorch").submodule_search_locations[0] else: - executorch_location = os.path.split(executorch_location)[0] + executorch_location = os.path.split(executorch_location.origin)[0] executorch = Path(executorch_location) / "examples" / "models" / "__init__.py" if not executorch.exists(): return From c22fbb7383bc917e39f2242f72488da5896b377e Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Tue, 16 Dec 2025 20:06:12 -0800 Subject: [PATCH 25/41] Update import_fixes.py --- unsloth/import_fixes.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/unsloth/import_fixes.py b/unsloth/import_fixes.py index 09c8637992..23bb4789ca 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -115,11 +115,11 @@ def fix_xformers_performance_issue(): return xformers_version = importlib_version("xformers") if Version(xformers_version) < Version("0.0.29"): - xformers_location = importlib.util.find_spec("xformers") + xformers_location = importlib.util.find_spec("xformers").origin if xformers_location is None: xformers_location = importlib.util.find_spec("xformers").submodule_search_locations[0] else: - xformers_location = os.path.split(xformers_location.origin)[0] + xformers_location = os.path.split(xformers_location)[0] cutlass = Path(xformers_location) / "ops" / "fmha" / "cutlass.py" try: if cutlass.exists(): @@ -147,11 +147,11 @@ def fix_vllm_aimv2_issue(): return vllm_version = importlib_version("vllm") if Version(vllm_version) < Version("0.10.1"): - vllm_version = importlib.util.find_spec("vllm") + vllm_version = importlib.util.find_spec("vllm").origin if vllm_version is None: vllm_version = importlib.util.find_spec("vllm").submodule_search_locations[0] else: - vllm_version = os.path.split(vllm_version.origin)[0] + vllm_version = os.path.split(vllm_version)[0] ovis_config = Path(vllm_version) / "transformers_utils" / "configs" / "ovis.py" try: if ovis_config.exists(): @@ -394,11 +394,11 @@ def torchvision_compatibility_check(): def fix_openenv_no_vllm(): if importlib.util.find_spec("trl") is None: return - trl_location = importlib.util.find_spec("trl") + trl_location = importlib.util.find_spec("trl").origin if trl_location is None: trl_location = importlib.util.find_spec("trl").submodule_search_locations[0] else: - trl_location = os.path.split(trl_location.origin)[0] + trl_location = os.path.split(trl_location)[0] openenv = Path(trl_location) / "experimental" / "openenv" / "utils.py" if not openenv.exists(): return @@ -437,11 +437,11 @@ def fix_openenv_no_vllm(): def fix_executorch(): if importlib.util.find_spec("executorch") is None: return - executorch_location = importlib.util.find_spec("executorch") + executorch_location = importlib.util.find_spec("executorch").origin if executorch_location is None: executorch_location = importlib.util.find_spec("executorch").submodule_search_locations[0] else: - executorch_location = os.path.split(executorch_location.origin)[0] + executorch_location = os.path.split(executorch_location)[0] executorch = Path(executorch_location) / "examples" / "models" / "__init__.py" if not executorch.exists(): return From d7482e8b2345e8d066def3a58354741335c804f3 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Tue, 16 Dec 2025 20:15:22 -0800 Subject: [PATCH 26/41] 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 23bb4789ca..3b10ec26fb 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -19,6 +19,7 @@ from packaging.version import Version as TrueVersion import re import logging +import textwrap # We cannot do from unsloth_zoo.log import logger since FBGEMM might cause seg faults. UNSLOTH_ENABLE_LOGGING = os.environ.get("UNSLOTH_ENABLE_LOGGING", "0") in ("1", "True", "true",) From ca7779872febbb98a02f6c37baa4bcb1f3501f04 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 04:26:02 +0000 Subject: [PATCH 27/41] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- unsloth/import_fixes.py | 38 +++++++++++++++++++++++++------------- unsloth/models/rl.py | 2 +- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/unsloth/import_fixes.py b/unsloth/import_fixes.py index 3b10ec26fb..a93a6c917f 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -22,14 +22,22 @@ import textwrap # We cannot do from unsloth_zoo.log import logger since FBGEMM might cause seg faults. -UNSLOTH_ENABLE_LOGGING = os.environ.get("UNSLOTH_ENABLE_LOGGING", "0") in ("1", "True", "true",) +UNSLOTH_ENABLE_LOGGING = os.environ.get("UNSLOTH_ENABLE_LOGGING", "0") in ( + "1", + "True", + "true", +) logger = logging.getLogger(__name__) if UNSLOTH_ENABLE_LOGGING: - logging.basicConfig(level = logging.INFO, format = '[%(name)s|%(levelname)s]%(message)s') + logging.basicConfig( + level = logging.INFO, format = "[%(name)s|%(levelname)s]%(message)s" + ) logger.setLevel(logging.INFO) else: - logging.basicConfig(level = logging.WARNING, format = '[%(name)s|%(levelname)s]%(message)s') - logger.setLevel(logging.WARNING) + logging.basicConfig( + level = logging.WARNING, format = "[%(name)s|%(levelname)s]%(message)s" + ) + logger.setLevel(logging.WARNING) def Version(version): @@ -118,7 +126,9 @@ def fix_xformers_performance_issue(): if Version(xformers_version) < Version("0.0.29"): xformers_location = importlib.util.find_spec("xformers").origin if xformers_location is None: - xformers_location = importlib.util.find_spec("xformers").submodule_search_locations[0] + xformers_location = importlib.util.find_spec( + "xformers" + ).submodule_search_locations[0] else: xformers_location = os.path.split(xformers_location)[0] cutlass = Path(xformers_location) / "ops" / "fmha" / "cutlass.py" @@ -150,7 +160,9 @@ def fix_vllm_aimv2_issue(): if Version(vllm_version) < Version("0.10.1"): vllm_version = importlib.util.find_spec("vllm").origin if vllm_version is None: - vllm_version = importlib.util.find_spec("vllm").submodule_search_locations[0] + vllm_version = importlib.util.find_spec("vllm").submodule_search_locations[ + 0 + ] else: vllm_version = os.path.split(vllm_version)[0] ovis_config = Path(vllm_version) / "transformers_utils" / "configs" / "ovis.py" @@ -440,7 +452,9 @@ def fix_executorch(): return executorch_location = importlib.util.find_spec("executorch").origin if executorch_location is None: - executorch_location = importlib.util.find_spec("executorch").submodule_search_locations[0] + executorch_location = importlib.util.find_spec( + "executorch" + ).submodule_search_locations[0] else: executorch_location = os.path.split(executorch_location)[0] executorch = Path(executorch_location) / "examples" / "models" / "__init__.py" @@ -448,7 +462,7 @@ def fix_executorch(): return try: - what = r''' + what = r""" import sys import types import re @@ -483,9 +497,9 @@ def get_mapped_key(key: str, mapping_dict: dict[str, str]) -> str: sys.modules["torchtune"] = torchtune sys.modules["torchtune.models"] = models sys.modules["torchtune.models.convert_weights"] = convert_weights - ''' + """ what = textwrap.dedent(what) - + with open(executorch, "r+", encoding = "utf-8") as f: text = f.read() bad = "from enum import Enum\n" @@ -494,8 +508,6 @@ def get_mapped_key(key: str, mapping_dict: dict[str, str]) -> str: f.seek(0) f.write(text) f.truncate() - logger.info( - "Unsloth: Patching Executorch to fix get_mapped_key" - ) + logger.info("Unsloth: Patching Executorch to fix get_mapped_key") except Exception as e: logger.info(f"Unsloth: Failed Executorch with error = {str(e)}") diff --git a/unsloth/models/rl.py b/unsloth/models/rl.py index 3fd180bb27..31316e45b7 100644 --- a/unsloth/models/rl.py +++ b/unsloth/models/rl.py @@ -741,7 +741,7 @@ def _patch_trl_rl_trainers(trainer_file = "grpo_trainer"): "generation_kwargs": {}, "bf16": False, "fp16": False, - "report_to" : "none", + "report_to": "none", "include_tokens_per_second": False, "include_num_input_tokens_seen": False, "auto_find_batch_size": False, # Auto /2 batch size - too many people complained so removing From 71c5938e49927a38c335e2f8f83769ae2065a660 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Tue, 16 Dec 2025 20:34:34 -0800 Subject: [PATCH 28/41] Update import_fixes.py --- unsloth/import_fixes.py | 51 +++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/unsloth/import_fixes.py b/unsloth/import_fixes.py index 3b10ec26fb..afbc6f5a96 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -112,13 +112,14 @@ def GetPrototype(self, descriptor): # Fix Xformers performance issues since 0.0.25 def fix_xformers_performance_issue(): - if importlib.util.find_spec("xformers") is None: + spec = importlib.util.find_spec("xformers") + if spec is None: return xformers_version = importlib_version("xformers") if Version(xformers_version) < Version("0.0.29"): - xformers_location = importlib.util.find_spec("xformers").origin + xformers_location = spec.origin if xformers_location is None: - xformers_location = importlib.util.find_spec("xformers").submodule_search_locations[0] + xformers_location = spec.submodule_search_locations[0] else: xformers_location = os.path.split(xformers_location)[0] cutlass = Path(xformers_location) / "ops" / "fmha" / "cutlass.py" @@ -144,13 +145,14 @@ def fix_xformers_performance_issue(): # ValueError: 'aimv2' is already used by a Transformers config, pick another name. def fix_vllm_aimv2_issue(): - if importlib.util.find_spec("vllm") is None: + spec = importlib.util.find_spec("vllm") + if spec is None: return vllm_version = importlib_version("vllm") if Version(vllm_version) < Version("0.10.1"): - vllm_version = importlib.util.find_spec("vllm").origin + vllm_version = spec.origin if vllm_version is None: - vllm_version = importlib.util.find_spec("vllm").submodule_search_locations[0] + vllm_version = spec.submodule_search_locations[0] else: vllm_version = os.path.split(vllm_version)[0] ovis_config = Path(vllm_version) / "transformers_utils" / "configs" / "ovis.py" @@ -393,11 +395,12 @@ def torchvision_compatibility_check(): # Fix TRL OpenEnv 0.26 NameError: name 'SamplingParams' is not defined def fix_openenv_no_vllm(): - if importlib.util.find_spec("trl") is None: + spec = importlib.util.find_spec("trl") + if spec is None: return - trl_location = importlib.util.find_spec("trl").origin + trl_location = spec.origin if trl_location is None: - trl_location = importlib.util.find_spec("trl").submodule_search_locations[0] + trl_location = spec.submodule_search_locations[0] else: trl_location = os.path.split(trl_location)[0] openenv = Path(trl_location) / "experimental" / "openenv" / "utils.py" @@ -412,18 +415,15 @@ def fix_openenv_no_vllm(): " 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" - ), - ) + replace_with = bad + ( + "else:\n" + " from typing import Any\n" + " SamplingParams = Any\n" + " GuidedDecodingParams = Any\n" + "\n" + ) + if bad + "\n" + "\n" in text and replace_with not in text: + text = text.replace(bad + "\n" + "\n", replace_with) f.seek(0) f.write(text) f.truncate() @@ -436,11 +436,12 @@ def fix_openenv_no_vllm(): # Fix Exeuctorch needing get_mapped_key def fix_executorch(): - if importlib.util.find_spec("executorch") is None: + spec = importlib.util.find_spec("executorch") + if spec is None: return - executorch_location = importlib.util.find_spec("executorch").origin + executorch_location = spec.origin if executorch_location is None: - executorch_location = importlib.util.find_spec("executorch").submodule_search_locations[0] + executorch_location = spec.submodule_search_locations[0] else: executorch_location = os.path.split(executorch_location)[0] executorch = Path(executorch_location) / "examples" / "models" / "__init__.py" @@ -489,7 +490,7 @@ def get_mapped_key(key: str, mapping_dict: dict[str, str]) -> str: with open(executorch, "r+", encoding = "utf-8") as f: text = f.read() bad = "from enum import Enum\n" - if bad in text: + if bad in text and what not in text: text = text.replace(bad + "\n", bad + "\n" + what) f.seek(0) f.write(text) From 7c101954bbc062199460ca3b1849e3908c7c6082 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Tue, 16 Dec 2025 20:52:09 -0800 Subject: [PATCH 29/41] Update unsloth/import_fixes.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- unsloth/import_fixes.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/unsloth/import_fixes.py b/unsloth/import_fixes.py index cffbb8ef3a..2c4dbcffb0 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -158,12 +158,12 @@ def fix_vllm_aimv2_issue(): return vllm_version = importlib_version("vllm") if Version(vllm_version) < Version("0.10.1"): - vllm_version = spec.origin - if vllm_version is None: - vllm_version = spec.submodule_search_locations[0] + vllm_location = spec.origin + if vllm_location is None: + vllm_location = spec.submodule_search_locations[0] else: - vllm_version = os.path.split(vllm_version)[0] - ovis_config = Path(vllm_version) / "transformers_utils" / "configs" / "ovis.py" + vllm_location = os.path.split(vllm_location)[0] + ovis_config = Path(vllm_location) / "transformers_utils" / "configs" / "ovis.py" try: if ovis_config.exists(): with open(ovis_config, "r+", encoding = "utf-8") as f: From 3738db73a8445a3cd858d1409290152198c0d9fb Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Tue, 16 Dec 2025 23:15:31 -0800 Subject: [PATCH 30/41] Update save.py --- unsloth/save.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/unsloth/save.py b/unsloth/save.py index 01887321cf..640a7ffe14 100644 --- a/unsloth/save.py +++ b/unsloth/save.py @@ -3037,7 +3037,9 @@ def patch_saving_functions(model, vision = False): model.save_pretrained_merged = types.MethodType( unsloth_generic_save_pretrained_merged, model ) - model.push_to_hub_gguf = types.MethodType(unsloth_push_to_hub_gguf, model) + model.push_to_hub_gguf = types.MethodType( + unsloth_push_to_hub_gguf, model + ) model.save_pretrained_gguf = types.MethodType( unsloth_save_pretrained_gguf, model ) @@ -3058,7 +3060,9 @@ def patch_saving_functions(model, vision = False): model.save_pretrained_merged = types.MethodType( unsloth_generic_save_pretrained_merged, model ) - model.push_to_hub_gguf = types.MethodType(unsloth_push_to_hub_gguf, model) + model.push_to_hub_gguf = types.MethodType( + unsloth_push_to_hub_gguf, model + ) model.save_pretrained_gguf = types.MethodType( unsloth_save_pretrained_gguf, model ) From fbaacce52013adc8bbb5d16455bfa7c69b79ada1 Mon Sep 17 00:00:00 2001 From: Datta Nimmaturi Date: Wed, 17 Dec 2025 14:37:21 +0530 Subject: [PATCH 31/41] [fbgemm] Silence tma fbgemm (#3735) * Silence fbgemm TMA print Also safer .push_to_hub * [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> --- unsloth/import_fixes.py | 30 ++++++++++++++++++++++++++++++ unsloth/save.py | 6 +++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/unsloth/import_fixes.py b/unsloth/import_fixes.py index 2c4dbcffb0..308bd92db7 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -71,6 +71,36 @@ def filter(self, x): return not (self.text in x.getMessage()) +class HidePrintMessage: + __slots__ = ("_original_stream", "_hidden_texts") + + def __init__(self, original_stream): + self._original_stream = original_stream + self._hidden_texts = [] + + def add_filter(self, text): + self._hidden_texts.append(text) + + def write(self, message): + if not any(text in message for text in self._hidden_texts): + self._original_stream.write(message) + + def flush(self): + self._original_stream.flush() + + def __getattr__(self, name): + return getattr(self._original_stream, name) + + +if os.environ.get("UNSLOTH_ENABLE_LOGGING", "0") != "1": + import sys + + # Apply to stderr for FBGEMM + sys.stderr = HidePrintMessage(sys.stderr) + # https://github.com/pytorch/FBGEMM/blob/d99cd96490ec4aabac2ee95b1e76ea4dcfcfa628/fbgemm_gpu/experimental/gemm/triton_gemm/utils.py#L43-L52 + sys.stderr.add_filter("TMA benchmarks will be running") + + # Fix up AttributeError: 'MessageFactory' object has no attribute 'GetPrototype' # MUST do this at the start primarily due to tensorflow causing issues def fix_message_factory_issue(): diff --git a/unsloth/save.py b/unsloth/save.py index 01887321cf..d3b20f117c 100644 --- a/unsloth/save.py +++ b/unsloth/save.py @@ -3010,7 +3010,11 @@ def patch_saving_functions(model, vision = False): original_model = model while True: - if original_model.push_to_hub.__name__ != "unsloth_push_to_hub": + # Check if push_to_hub exists before accessing its __name__ + if ( + hasattr(original_model, "push_to_hub") + and original_model.push_to_hub.__name__ != "unsloth_push_to_hub" + ): original_model.original_push_to_hub = original_model.push_to_hub original_model.push_to_hub = types.MethodType( unsloth_push_to_hub, original_model From 3e6cfb5f27eb0830e49d1cd24eff780d3838f131 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Wed, 17 Dec 2025 01:51:29 -0800 Subject: [PATCH 32/41] Update loader.py --- unsloth/models/loader.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/unsloth/models/loader.py b/unsloth/models/loader.py index e1c13315f7..bfa94d86d7 100644 --- a/unsloth/models/loader.py +++ b/unsloth/models/loader.py @@ -739,6 +739,8 @@ def from_pretrained( "compatible with `full_finetuning=True`. If you wish to use QAT with LoRA, " "please pass in `qat_scheme` in `FastLanguageModel.get_peft_model(...)` instead." ) + if qat_scheme == "phone-deployment": + qat_scheme = "int8-int4" # Check if 4bit is allowed specifically for AMD if not ALLOW_BITSANDBYTES and not use_exact_model_name: if load_in_4bit or load_in_8bit or model_name.lower().endswith("-bnb-4bit"): From 30a454cc5518e1101134d8a62187987495404389 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Wed, 17 Dec 2025 02:21:47 -0800 Subject: [PATCH 33/41] Update save.py --- unsloth/save.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/unsloth/save.py b/unsloth/save.py index f5ea8d7d8f..5fa2df7b18 100644 --- a/unsloth/save.py +++ b/unsloth/save.py @@ -2745,6 +2745,17 @@ def _unsloth_save_torchao_with_attached_config( """Save a QAT-trained model by converting fake-quantized weights to real quantized weights.""" # Convert QAT fake-quantized weights to real quantized weights _convert_torchao_model(model) + # PEFT models also might come here, so parse it + if isinstance(model, PeftModelForCausalLM): + _unsloth_save_torchao_with_given_config( + model = model, + save_directory = save_directory, + tokenizer = tokenizer, + torchao_config = model.config.quantization_config, + push_to_hub = push_to_hub, + token = token, + ) + return # TorchAO does not support safe_serialization reliably safe_serialization = False @@ -2897,7 +2908,7 @@ def unsloth_save_pretrained_torchao( ) if torchao_config is not None: - # PTQ path: user provided a config, model must NOT have QAT config + # PTQ path: user provided a config, model must NOT have QAT config unless PEFT assert not has_qat_config, ( "Unsloth: You passed `torchao_config` but this model was trained with `qat_scheme`. " "For QAT models, do not pass `torchao_config` - the quantization config is already " From b58663ae421218bbee207b1d918938b8278d26d2 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Wed, 17 Dec 2025 02:28:03 -0800 Subject: [PATCH 34/41] Update save.py --- unsloth/save.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/unsloth/save.py b/unsloth/save.py index 5fa2df7b18..c5099a5891 100644 --- a/unsloth/save.py +++ b/unsloth/save.py @@ -2817,7 +2817,10 @@ def _unsloth_save_torchao_with_given_config( ) from torchao import quantize_ - quantization_config = TorchAoConfig(quant_type = torchao_config) + if isinstance(torchao_config, TorchAoConfig): + quantization_config = torchao_config + else: + quantization_config = TorchAoConfig(quant_type = torchao_config) # Determine if this is a VLM is_vlm = False From 7b613759e9e652b4c88c2c6f90e4441917e341da Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Wed, 17 Dec 2025 02:38:05 -0800 Subject: [PATCH 35/41] Update _utils.py --- unsloth/models/_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unsloth/models/_utils.py b/unsloth/models/_utils.py index 653b539b20..5b2cc681b0 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.5" +__version__ = "2025.12.6" __all__ = [ "SUPPORTS_BFLOAT16", From a2b5def55ac411634bcf9915141f0618aaac5548 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Wed, 17 Dec 2025 02:54:15 -0800 Subject: [PATCH 36/41] Update _utils.py --- unsloth/models/_utils.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/unsloth/models/_utils.py b/unsloth/models/_utils.py index 5b2cc681b0..6f6d693b4f 100644 --- a/unsloth/models/_utils.py +++ b/unsloth/models/_utils.py @@ -413,16 +413,6 @@ 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 59a1fa57714ed8a3e6ddbf8abb2ad31d1b2456f0 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Wed, 17 Dec 2025 03:25:40 -0800 Subject: [PATCH 37/41] Diffusers warnings --- unsloth/__init__.py | 3 +++ unsloth/import_fixes.py | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/unsloth/__init__.py b/unsloth/__init__.py index bf3de82dc0..d10a0f8030 100644 --- a/unsloth/__init__.py +++ b/unsloth/__init__.py @@ -29,14 +29,17 @@ fix_message_factory_issue, check_fbgemm_gpu_version, torchvision_compatibility_check, + fix_diffusers_warnings, ) fix_message_factory_issue() check_fbgemm_gpu_version() torchvision_compatibility_check() +fix_diffusers_warnings() del fix_message_factory_issue del check_fbgemm_gpu_version del torchvision_compatibility_check +del fix_diffusers_warnings # This check is critical because Unsloth optimizes these libraries by modifying # their code at import time. If they're imported first, the original (slower, diff --git a/unsloth/import_fixes.py b/unsloth/import_fixes.py index 308bd92db7..f3aae7f523 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -536,3 +536,8 @@ def get_mapped_key(key: str, mapping_dict: dict[str, str]) -> str: logger.info("Unsloth: Patching Executorch to fix get_mapped_key") except Exception as e: logger.info(f"Unsloth: Failed Executorch with error = {str(e)}") + + +def fix_diffusers_warnings(): + # Silence Flax classes are deprecated and will be removed in Diffusers v1.0.0. + os.environ["DIFFUSERS_VERBOSITY"] = "error" From 5e33a07b50265ff947404084af2bb71458e39782 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Wed, 17 Dec 2025 03:26:19 -0800 Subject: [PATCH 38/41] Update pyproject.toml --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c6e19b014e..cb3f8f3fa4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,7 +60,7 @@ huggingfacenotorch = [ ] huggingface = [ "unsloth[huggingfacenotorch]", - "unsloth_zoo>=2025.12.4", + "unsloth_zoo>=2025.12.5", "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.4", + "unsloth_zoo>=2025.12.5", "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", From 1f1bf49a588233e9e6ea3285e20c89e5d49e734a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 11:29:39 +0000 Subject: [PATCH 39/41] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- unsloth/save.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/unsloth/save.py b/unsloth/save.py index c5099a5891..24303aba52 100644 --- a/unsloth/save.py +++ b/unsloth/save.py @@ -3055,9 +3055,7 @@ def patch_saving_functions(model, vision = False): model.save_pretrained_merged = types.MethodType( unsloth_generic_save_pretrained_merged, model ) - model.push_to_hub_gguf = types.MethodType( - unsloth_push_to_hub_gguf, model - ) + model.push_to_hub_gguf = types.MethodType(unsloth_push_to_hub_gguf, model) model.save_pretrained_gguf = types.MethodType( unsloth_save_pretrained_gguf, model ) @@ -3078,9 +3076,7 @@ def patch_saving_functions(model, vision = False): model.save_pretrained_merged = types.MethodType( unsloth_generic_save_pretrained_merged, model ) - model.push_to_hub_gguf = types.MethodType( - unsloth_push_to_hub_gguf, model - ) + model.push_to_hub_gguf = types.MethodType(unsloth_push_to_hub_gguf, model) model.save_pretrained_gguf = types.MethodType( unsloth_save_pretrained_gguf, model ) From 5d0286d6c5ecbf0b652a24f124c6abdd5db39d0a Mon Sep 17 00:00:00 2001 From: Datta Nimmaturi Date: Thu, 18 Dec 2025 17:37:12 +0530 Subject: [PATCH 40/41] [hf_hub] Token login (#3739) * login on token * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * cleanup old code * safer imports * cleanup * Return token after login * correct return types * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Apply suggestion from @danielhanchen * add back imports * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * finish return token --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Daniel Han --- unsloth/models/_utils.py | 21 +++++++++++++++++++++ unsloth/models/llama.py | 3 +-- unsloth/models/loader.py | 23 +++-------------------- unsloth/models/vision.py | 3 +-- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/unsloth/models/_utils.py b/unsloth/models/_utils.py index 6f6d693b4f..0d0f90cf40 100644 --- a/unsloth/models/_utils.py +++ b/unsloth/models/_utils.py @@ -72,6 +72,7 @@ "patch_hf_quantizer", "verify_fp8_support_if_applicable", "_get_inference_mode_context_manager", + "hf_login", ] import torch @@ -2344,3 +2345,23 @@ def _get_inference_mode_context_manager(model: torch.nn.Module): return torch.no_grad() else: return torch.inference_mode() + + +def hf_login(token: Optional[str] = None) -> Optional[str]: + if token is None: + try: + from huggingface_hub import get_token + + token = get_token() + if token is None: + return None + except: + return None + try: + from huggingface_hub import login + + login(token = token) + return token + except Exception as e: + logger.info(f"Failed to login to huggingface using token with error: {e}") + return token diff --git a/unsloth/models/llama.py b/unsloth/models/llama.py index 4c9337ccf9..1d7695b9aa 100644 --- a/unsloth/models/llama.py +++ b/unsloth/models/llama.py @@ -2130,8 +2130,7 @@ def from_pretrained( "Unsloth: `unsloth_vllm_standby` is True, but environment variable `UNSLOTH_VLLM_STANDBY` is not set to 1!" ) - if token is None: - token = get_token() + token = hf_login(token) if model_patcher is None: model_patcher = FastLlamaModel SUPPORTS_BFLOAT16 = is_bfloat16_supported() diff --git a/unsloth/models/loader.py b/unsloth/models/loader.py index bfa94d86d7..b13775076c 100644 --- a/unsloth/models/loader.py +++ b/unsloth/models/loader.py @@ -20,6 +20,7 @@ HAS_FLASH_ATTENTION_SOFTCAPPING, USE_MODELSCOPE, get_transformers_model_type, + hf_login, ) from .granite import FastGraniteModel from .llama import FastLlamaModel, logger @@ -151,15 +152,7 @@ def from_pretrained( **kwargs, ): # Login to allow private models - if token is None: - token = get_token() - if token is not None: - try: - from huggingface_hub import login - - login(token = token) - except: - pass + token = hf_login(token) if load_in_8bit or full_finetuning or qat_scheme is not None: return FastModel.from_pretrained( model_name = model_name, @@ -195,8 +188,6 @@ def from_pretrained( **kwargs, ) - if token is None: - token = get_token() if isinstance(dtype, str) and dtype in ["float16", "bfloat16"]: dtype = getattr(torch, dtype) assert ( @@ -682,16 +673,8 @@ def from_pretrained( *args, **kwargs, ): - if token is None: - token = get_token() # Login to allow private models - if token is not None: - try: - from huggingface_hub import login - - login(token = token) - except: - pass + token = hf_login(token) if whisper_language is not None: assert type(whisper_language) is str if whisper_task is not None: diff --git a/unsloth/models/vision.py b/unsloth/models/vision.py index ed19f587cf..a10d65f3fb 100644 --- a/unsloth/models/vision.py +++ b/unsloth/models/vision.py @@ -390,8 +390,7 @@ def from_pretrained( "Unsloth: WARNING `trust_remote_code` is True.\n" "Are you certain you want to do remote code execution?" ) - if token is None: - token = get_token() + token = hf_login(token) SUPPORTS_BFLOAT16 = is_bfloat16_supported() if DEVICE_TYPE == "cuda": From 1de77bfadcb30e51f73c58d28ef3db9861f76f69 Mon Sep 17 00:00:00 2001 From: Datta Nimmaturi Date: Sat, 20 Dec 2025 08:38:28 +0530 Subject: [PATCH 41/41] Do not overwrite slots (#3752) * Do not overwrite slots * [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> --- unsloth/import_fixes.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/unsloth/import_fixes.py b/unsloth/import_fixes.py index f3aae7f523..efc7a7f4cd 100644 --- a/unsloth/import_fixes.py +++ b/unsloth/import_fixes.py @@ -72,8 +72,6 @@ def filter(self, x): class HidePrintMessage: - __slots__ = ("_original_stream", "_hidden_texts") - def __init__(self, original_stream): self._original_stream = original_stream self._hidden_texts = []