diff --git a/unsloth/__init__.py b/unsloth/__init__.py index abee9c9e04..458c2696bc 100644 --- a/unsloth/__init__.py +++ b/unsloth/__init__.py @@ -62,9 +62,13 @@ os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "expandable_segments:True" try: import torch -except: - raise ImportError("Pytorch is not installed. Go to https://pytorch.org/.\n"\ - "We have some installation instructions on our Github page.") +except ModuleNotFoundError: + raise ImportError( + "Unsloth: Pytorch is not installed. Go to https://pytorch.org/.\n"\ + "We have some installation instructions on our Github page." + ) +except Exception as exception: + raise exception pass # Hugging Face Hub faster downloads (only enable during Colab and Kaggle sessions) diff --git a/unsloth/models/_utils.py b/unsloth/models/_utils.py index 2214ff80d4..bf5216b228 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__ = "2024.10.5" +__version__ = "2024.10.6" __all__ = [ "prepare_model_for_kbit_training", @@ -1172,10 +1172,10 @@ pass def patch_gradient_accumulation_fix(Trainer): # Fixes gradient accumulation + import inspect if hasattr(Trainer, "get_batch_samples"): - from inspect import getsource if \ - not getsource(Trainer.get_batch_samples).strip()\ + not inspect.getsource(Trainer.get_batch_samples).strip()\ .endswith("return batch_samples, num_items_in_batch"): raise NotImplementedError("Unsloth: Please make a Github issue immediately!!") @@ -1198,4 +1198,33 @@ def patch_gradient_accumulation_fix(Trainer): '`pip install --upgrade --no-cache-dir unsloth git+https://github.com/huggingface/transformers.git git+https://github.com/huggingface/trl.git`' ) pass + + # Also fix up loss scaling ie negate loss *= self.args.gradient_accumulation_steps + if "num_items_in_batch" not in inspect.signature(Trainer.training_step).parameters: return + + function = inspect.getsource(Trainer.training_step) + where = function.find("def") + function = function.split("\n") + function = "\n".join(x[where:] for x in function) + + # Import all variables that need importing + import transformers.trainer + items_in_trainer = dir(transformers.trainer) + good_items = [] + for item in items_in_trainer: + # TODO: Support Deepspeed + if item.startswith(("deepspeed", "xm", "met", "smp")): continue + if item in function: good_items.append(item) + pass + exec("from transformers.trainer import (" + ", ".join(x for x in good_items) + ")", globals()) + + # Accelerate does / self.args.gradient_accumulation_steps internally, so if we already + # summed it up and did the division before hand, we have to negate it. + function = function.replace( + "loss *= self.args.gradient_accumulation_steps", + "if num_items_in_batch is not None: loss *= self.args.gradient_accumulation_steps", + ) + function = function.replace("def training_step", "def _unsloth_training_step", 1) + exec(function, globals()) + Trainer.training_step = _unsloth_training_step pass diff --git a/unsloth/save.py b/unsloth/save.py index ab30e0fea5..ccda79aeee 100644 --- a/unsloth/save.py +++ b/unsloth/save.py @@ -145,7 +145,7 @@ pass def _merge_lora(layer, name): - bias = None + bias = getattr(layer, "bias", None) if isinstance(layer, (Bnb_Linear4bit, Peft_Linear4bit, Peft_Linear)): # Is LoRA so we need to merge! W, quant_state, A, B, s, bias = get_lora_parameters_bias(layer) diff --git a/unsloth/tokenizer_utils.py b/unsloth/tokenizer_utils.py index 4b9fd5e133..8806f1e743 100644 --- a/unsloth/tokenizer_utils.py +++ b/unsloth/tokenizer_utils.py @@ -914,7 +914,9 @@ def patch_sft_trainer_tokenizer(): check_text = \ "\n"\ - "if 'tokenizer' not in locals(): tokenizer = processing_class\n"\ + "if 'tokenizer' not in locals(): tokenizer = processing_class\n"\ + "if 'formatting_func' not in locals(): raise RuntimeError('Unsloth: Please file a bug report - `formatting_func` does not exist!')\n"\ + "if 'dataset_text_field' not in locals(): raise RuntimeError('Unsloth: Please file a bug report - `dataset_text_field` does not exist!')\n"\ "test_text = dataset[0][dataset_text_field] if (formatting_func is None and dataset_text_field is not None) else formatting_func(dataset[0])[0]\n"\ "chat_template = getattr(tokenizer, 'chat_template', None)\n"\ "chat_template = '' if chat_template is None else chat_template\n"\ @@ -1017,7 +1019,10 @@ pass for trainer_name in ("SFTTrainer", "DPOTrainer", "KTOTrainer"): trainer_text = patch_trl_tokenizer_processing_class(trainer_name) if trainer_text is None: continue - exec(trainer_text, globals()) + try: + exec(trainer_text, globals()) + except: + raise RuntimeError(f"Unsloth: Please file a bug report! Error patching {trainer_name}") exec(f"trl.trainer.{trainer_name} = Unsloth{trainer_name}", globals()) pass