Bug fixes (#306)

* Approx gelu

* Update llama.py

* Update __init__.py

* Update __init__.py

* Update _utils.py

* Update geglu.py

* Update gemma.py

* Update rms_layernorm.py

* Update rms_layernorm.py

* Update rms_layernorm.py

* Update gemma.py

* Update gemma.py

* Update gemma.py

* Update gemma.py

* Update gemma.py

* Fix Gemma merging

* Update rms_layernorm.py

* Update gemma.py

* Update pyproject.toml

* Layernorms

* Gemma precision

* Update gemma.py

* sqrt

* Update gemma.py

* Update save.py

* RoPE and Gemma precision

* Update rms_layernorm.py

* Fix warning

* Update chat_templates.py

* Update chat_templates.py

* Update save.py

* Update save.py

* Update save.py

* Update chat_templates.py

* Update llama.py

* model_name

* Update loader.py

* Tokenizer overwritten

* Update llama.py

* Update llama.py

* Update llama.py

* Update save.py

* Accuracy

* Revert

* Update save.py

* Update fast_lora.py

* Update fast_lora.py

* Update fast_lora.py

* Update fast_lora.py

* Update fast_lora.py

* Update chat_templates.py

* Update save.py

* Update save.py

* Update llama.py

* Update llama.py

* Account for DoRA

* Update llama.py

* Update save.py

* GGUF incorrect

* Update save.py

* Update pyproject.toml

* kaggle new

* Update pyproject.toml

* Update pyproject.toml

* upcasting

* Fix Colab

* Update pyproject.toml

* Update pyproject.toml

* Update pyproject.toml

* Update pyproject.toml

* Update pyproject.toml

* Update pyproject.toml

* Update pyproject.toml

* Update pyproject.toml

* Update chat_templates.py

* Update chat_templates.py

* Update chat_templates.py

* Update chat_templates.py

* Update chat_templates.py

* Update pyproject.toml

* Update pyproject.toml

* Update pyproject.toml

* Update rope_embedding.py

* Update rope_embedding.py

* Fix bugs

* Update fast_lora.py

* Update fast_lora.py

* Update README.md

* Update README.md

* GGUF

* Update save.py

* Update save.py

* Update save.py

* Update save.py

* Update README.md

* Update README.md

* Bugs

* Update fast_lora.py

* Update pyproject.toml

* Update fast_lora.py

* Update __init__.py

* Update fast_lora.py

* dtype

* Update llama.py

* Update llama.py

* Update llama.py

* dtype

* Update mistral.py

* trust_remote_code

* lm_head

* Update llama.py

* save_pretrained_settings

* Update save.py

* Update save.py

* Update save.py

* Update save.py

* Update save.py

* Update save.py

* Update save.py

* Update save.py

* Update save.py

* Update save.py

* Update save.py

* Update save.py

* state_dict

* Update save.py

* whoami

* Update llama.py

* Update save.py

* Update llama.py

* Patch tokenizer

* Update chat_templates.py

* Heal tokenizers

* Update chat_templates.py

* Update mapper.py

* Update tokenizer_utils.py

* Update tokenizer_utils.py

* Update tokenizer_utils.py

* Update tokenizer_utils.py

* Update tokenizer_utils.py

* Update chat_templates.py

* tokenizer patching

* patch_tokenizer

* Update chat_templates.py

* Update tokenizer_utils.py

* Update chat_templates.py

* Update chat_templates.py

* Update chat_templates.py

* Update tokenizer_utils.py

* Edit

* Update mistral.py

* Update mistral.py

* Stats

* Update mistral.py

* attention_mask

* Update llama.py

* Update llama.py

* batch

* Temp fix batch inference

* Update llama.py

* Update gemma.py

* Fix inference

* swiglu

* Update llama.py

* Update llama.py

* Update llama.py

* Update llama.py

* Update mistral.py

* Update llama.py

* fast inference

* model

* Update llama.py

* Update llama.py

* Update llama.py

* Update llama.py

* Update llama.py

* Update llama.py

* Update llama.py

* Update llama.py

* Update llama.py

* Update llama.py

* Update llama.py

* Update llama.py

* Update llama.py

* Update utils.py

* Update llama.py

* Update utils.py

* inference

* Update llama.py

* Update llama.py

* Update llama.py

* overhead

* Update llama.py

* Update llama.py

* compile

* Update gemma.py

* Update llama.py

* Update llama.py

* Update llama.py

* Update llama.py

* Update utils.py

* Update utils.py

* lora mamtul

* Update llama.py

* Update llama.py

* Update llama.py

* offloaded checkpointing

* Update llama.py

* Update llama.py

* Update _utils.py

* Update _utils.py

* Update _utils.py

* Update llama.py

* Update llama.py

* Update gemma.py

* Revert "Update gemma.py"

This reverts commit e3c3c5f3fa3d04a87f854056f6b547ced610d712.

* Update _utils.py

* Update _utils.py

* Update _utils.py

* Saving

* sentencepiece_model_pb2

* Update llama.py

* Update save.py

* Update llama.py

* padding side
This commit is contained in:
Daniel Han 2024-04-06 04:31:24 +11:00 committed by GitHub
commit 4290c8a278
5 changed files with 140 additions and 42 deletions

View file

@ -30,7 +30,7 @@ import numpy as np
import os
import psutil
__version__ = "2024.3"
__version__ = "2024.4"
# Get Flash Attention v2 if Ampere (RTX 30xx, A100)
major_version, minor_version = torch.cuda.get_device_capability()
@ -70,12 +70,13 @@ __all__ = [
"platform_system",
"patch_tokenizer",
"get_statistics",
"Offloaded_Gradient_Checkpointer",
]
def prepare_model_for_kbit_training(
model : Any,
use_gradient_checkpointing : bool = True,
use_gradient_checkpointing : Optional = True,
use_reentrant : Optional[bool] = True,
) -> Any:
"""
@ -101,9 +102,23 @@ def prepare_model_for_kbit_training(
param.requires_grad_(False)
pass
if use_gradient_checkpointing:
# Gradient checkpointing!
if use_gradient_checkpointing == "offloaded":
# Saves VRAM!
original_model = model
while hasattr(original_model, "model"):
original_model._offloaded_gradient_checkpointing = True
original_model = original_model.model
pass
original_model._offloaded_gradient_checkpointing = True
model.gradient_checkpointing_enable()
elif use_gradient_checkpointing == True:
model.gradient_checkpointing_enable()
pass
# If use_reentrant = True which is the Pytorch default, we just make the input requires_grad.
if use_reentrant:
if hasattr(model, "enable_input_require_grads"):
@ -179,6 +194,7 @@ def get_statistics():
try:
from huggingface_hub import hf_hub_download
from huggingface_hub.utils import disable_progress_bars, enable_progress_bars, are_progress_bars_disabled
import psutil
n_cpus = psutil.cpu_count(logical = False)
keynames = "\n" + "\n".join(os.environ.keys())
@ -291,3 +307,35 @@ def prepare_n_gradient_checkpoints(
_model._gradient_checkpointing_boundaries = boundaries
_model._gradient_checkpointing_use_reentrant = use_reentrant
pass
class Offloaded_Gradient_Checkpointer(torch.autograd.Function):
"""
Saves VRAM by smartly offloading to RAM.
Tiny hit to performance, since we mask the movement via non blocking calls.
[TODO] Load the backward pass earlier
"""
@staticmethod
@torch.cuda.amp.custom_fwd
def forward(ctx, forward_function, hidden_states, *args):
saved_hidden_states = hidden_states.to("cpu", non_blocking = True)
with torch.no_grad():
(output,) = forward_function(hidden_states, *args)
ctx.save_for_backward(saved_hidden_states)
ctx.forward_function = forward_function
ctx.args = args
return output
pass
@staticmethod
@torch.cuda.amp.custom_bwd
def backward(ctx, dY):
(hidden_states,) = ctx.saved_tensors
hidden_states = hidden_states.to("cuda", non_blocking = True).detach()
hidden_states.requires_grad = True
with torch.enable_grad():
(output,) = ctx.forward_function(hidden_states, *ctx.args)
torch.autograd.backward(output, dY)
return (None, hidden_states.grad,) + (None,)*len(ctx.args)
pass
pass

View file

@ -628,19 +628,42 @@ def LlamaModel_fast_forward(
boundaries = None
pass
# Check checkpointing method
gradient_checkpointing = False
offloaded_gradient_checkpointing = False
if (self.gradient_checkpointing and self.training and not use_cache):
gradient_checkpointing = True
if output_attentions is False and hasattr(self, "_offloaded_gradient_checkpointing"):
offloaded_gradient_checkpointing = True
pass
# Go through every layer!
for idx, decoder_layer in enumerate(self.layers):
if output_hidden_states: all_hidden_states += (hidden_states,)
past_key_value = past_key_values[idx] if past_key_values is not None else None
if self.gradient_checkpointing and self.training:
if offloaded_gradient_checkpointing:
hidden_states = Offloaded_Gradient_Checkpointer.apply(
decoder_layer,
hidden_states,
causal_mask,
attention_mask,
position_ids,
past_key_values,
output_attentions,
use_cache,
)
elif gradient_checkpointing:
def create_custom_forward(module):
def custom_forward(*inputs):
# None for past_key_value
return module(*inputs, past_key_value, output_attentions, padding_mask=padding_mask)
return module(*inputs, past_key_value, output_attentions, padding_mask = padding_mask)
return custom_forward
pass
layer_outputs = torch.utils.checkpoint.checkpoint(
create_custom_forward(decoder_layer),
@ -648,9 +671,11 @@ def LlamaModel_fast_forward(
causal_mask,
attention_mask,
position_ids,
use_reentrant=True,
preserve_rng_state=False,
use_reentrant = True,
preserve_rng_state = False,
)
hidden_states = layer_outputs[0]
else:
layer_outputs = decoder_layer(
hidden_states,
@ -662,9 +687,9 @@ def LlamaModel_fast_forward(
use_cache=use_cache,
padding_mask=padding_mask,
)
hidden_states = layer_outputs[0]
pass
hidden_states = layer_outputs[0]
if use_cache: next_decoder_cache += (layer_outputs[2 if output_attentions else 1],)
if output_attentions: all_self_attns += (layer_outputs[1],)
pass
@ -801,12 +826,12 @@ def CausalLM_fast_forward(fast_forward_inference):
hidden_states = outputs[0]
bsz, q_len, hd = hidden_states.shape
lm_head = self.lm_head.weight
if bsz == 1 and q_len == 1:
lm_head = self.lm_head.weight
logits = torch.mv(lm_head, hidden_states.ravel().to(lm_head.dtype))
logits = logits.unsqueeze(0).unsqueeze(0)
else:
logits = self.lm_head(hidden_states)
logits = self.lm_head(hidden_states.to(lm_head.dtype))
pass
logits = logits.to(self.config.torch_dtype)
@ -1402,6 +1427,8 @@ class FastLlamaModel:
"We shall do it for you!"
)
train_lm_head = True
if modules_to_save is None: modules_to_save = ["lm_head"]
else: modules_to_save.append("lm_head")
elif module == "embed_tokens":
logger.warning_once(
@ -1409,6 +1436,8 @@ class FastLlamaModel:
"We shall do it for you!"
)
train_embed_tokens = True
if modules_to_save is None: modules_to_save = ["embed_tokens"]
else: modules_to_save.append("embed_tokens")
else:
assert(module in accepted_modules)

View file

@ -225,12 +225,12 @@ def MistralForCausalLM_fast_forward(
hidden_states = outputs[0]
bsz, q_len, hd = hidden_states.shape
lm_head = self.lm_head.weight
if bsz == 1 and q_len == 1:
lm_head = self.lm_head.weight
logits = torch.mv(lm_head, hidden_states.ravel().to(lm_head.dtype))
logits = logits.unsqueeze(0).unsqueeze(0)
else:
logits = self.lm_head(hidden_states)
logits = self.lm_head(hidden_states.to(lm_head.dtype))
pass
logits = logits.to(self.config.torch_dtype)

View file

@ -33,9 +33,13 @@ __all__ = [
"patch_saving_functions",
]
# Check Kaggle
IS_A_KAGGLE_ENVIRONMENT = "KAGGLE_CONTAINER_NAME" in os.environ
# Check environments
keynames = "\n" + "\n".join(os.environ.keys())
IS_COLAB_ENVIRONMENT = "\nCOLAB_" in keynames
IS_KAGGLE_ENVIRONMENT = "\nKAGGLE_" in keynames
del keynames
# Weights
LLAMA_WEIGHTS = (
"self_attn.q_proj", "self_attn.k_proj", "self_attn.v_proj", "self_attn.o_proj",
"mlp.gate_proj", "mlp.up_proj", "mlp.down_proj",
@ -177,6 +181,9 @@ def unsloth_save_model(
temporary_location : str = "_unsloth_temporary_saved_buffers",
maximum_memory_usage : float = 0.9,
):
if token is None and "HF_TOKEN" in os.environ:
token = os.environ["HF_TOKEN"]
if commit_message is None: commit_message = ""
if "Unsloth" not in commit_message:
commit_message += " (Trained with Unsloth)"
@ -291,6 +298,10 @@ def unsloth_save_model(
tags = tags,
)
if tokenizer is not None:
# Set padding side to left for inference
old_padding_side = tokenizer.padding_side
tokenizer.padding_side = "left"
getattr(tokenizer, "original_push_to_hub", tokenizer.push_to_hub)\
(
repo_id = save_directory,
@ -305,6 +316,9 @@ def unsloth_save_model(
commit_description = commit_description,
tags = tags,
)
# Revert back padding side
tokenizer.padding_side = old_padding_side
pass
if hasattr(model, "config"):
@ -361,7 +375,16 @@ def unsloth_save_model(
if tokenizer is not None:
print("Unsloth: Saving tokenizer...", end = "")
# Set padding side to left for inference
old_padding_side = tokenizer.padding_side
tokenizer.padding_side = "left"
tokenizer.save_pretrained(**tokenizer_save_settings)
# Revert back padding side
tokenizer.padding_side = old_padding_side
print(" Done.")
else:
print()
@ -449,12 +472,12 @@ def unsloth_save_model(
os.makedirs(temporary_location)
pass
# Check if Kaggle, since only 20GB of Disk space allowed.
if IS_A_KAGGLE_ENVIRONMENT:
# Check if Kaggle or Colab, since only 20GB of Disk space allowed.
if IS_KAGGLE_ENVIRONMENT or IS_COLAB_ENVIRONMENT:
# We free up 4GB of space
logger.warning_once(
"Unsloth: Kaggle only allows 20GB of disk space. We need to delete the downloaded\n"\
"model which will save 4GB of disk space, allowing you to save on Kaggle."
"Unsloth: Kaggle/Colab has limited disk space. We need to delete the downloaded\n"\
"model which will save 4-16GB of disk space, allowing you to save on Kaggle/Colab."
)
_free_cached_model(internal_model)
pass
@ -462,7 +485,10 @@ def unsloth_save_model(
# HF also uses a OrderedDict
from collections import OrderedDict
state_dict = OrderedDict()
state_dict["model.embed_tokens.weight"] = internal_model.model.embed_tokens.weight.data
torch_dtype = model.config.torch_dtype
# Check modules to save float32 dtype
state_dict["model.embed_tokens.weight"] = internal_model.model.embed_tokens.weight.data.to(torch_dtype)
max_vram = int(torch.cuda.get_device_properties(0).total_memory * maximum_memory_usage)
@ -495,7 +521,8 @@ def unsloth_save_model(
pass
state_dict["model.norm.weight"] = internal_model.model.norm.weight.data
state_dict["lm_head.weight"] = internal_model.lm_head.weight.data
# Check for modules_to_save float32 dtype
state_dict["lm_head.weight"] = internal_model.lm_head.weight.data.to(torch_dtype)
# All tensors MUST be type torch.Tensor and not torch.nn.parameter.Parameter
for key, value in state_dict.items():
@ -552,7 +579,16 @@ def unsloth_save_model(
# Save tokenizer
if tokenizer is not None:
print("Unsloth: Saving tokenizer...", end = "")
# Set padding side to left for inference
old_padding_side = tokenizer.padding_side
tokenizer.padding_side = "left"
tokenizer.save_pretrained(**tokenizer_save_settings)
# Revert back padding side
tokenizer.padding_side = old_padding_side
print(" Done.")
else:
print()
@ -1216,7 +1252,7 @@ def unsloth_save_pretrained_gguf(
# Non blocking install GGUF first
if not os.path.exists("llama.cpp"):
if IS_A_KAGGLE_ENVIRONMENT:
if IS_KAGGLE_ENVIRONMENT:
# Kaggle is weird - no blocking installs, and no CUDA?
python_install = install_python_non_blocking(["gguf", "protobuf"])
python_install.wait()
@ -1237,7 +1273,7 @@ def unsloth_save_pretrained_gguf(
makefile = None
except:
# Retry by recloning llama.cpp
if IS_A_KAGGLE_ENVIRONMENT:
if IS_KAGGLE_ENVIRONMENT:
# Kaggle is weird - no blocking installs, and no CUDA?
python_install = install_python_non_blocking(["gguf", "protobuf"])
python_install.wait()
@ -1336,7 +1372,7 @@ def unsloth_push_to_hub_gguf(
# Non blocking install GGUF first
if not os.path.exists("llama.cpp"):
if IS_A_KAGGLE_ENVIRONMENT:
if IS_KAGGLE_ENVIRONMENT:
# Kaggle is weird - no blocking installs, and no CUDA?
python_install = install_python_non_blocking(["gguf", "protobuf"])
python_install.wait()
@ -1357,7 +1393,7 @@ def unsloth_push_to_hub_gguf(
makefile = None
except:
# Retry by recloning llama.cpp
if IS_A_KAGGLE_ENVIRONMENT:
if IS_KAGGLE_ENVIRONMENT:
# Kaggle is weird - no blocking installs, and no CUDA?
python_install = install_python_non_blocking(["gguf", "protobuf"])
python_install.wait()

View file

@ -186,9 +186,6 @@ def assert_same_tokenization(slow_tokenizer, fast_tokenizer):
pass
global sentencepiece_model_pb2
sentencepiece_model_pb2 = None
def fix_sentencepiece_tokenizer(
old_tokenizer,
new_tokenizer,
@ -197,19 +194,7 @@ def fix_sentencepiece_tokenizer(
):
# From https://github.com/google/sentencepiece/issues/121
# We need to manually edit the sentencepiece tokenizer!
global sentencepiece_model_pb2
if sentencepiece_model_pb2 is None:
try:
import sentencepiece.sentencepiece_model_pb2 as _sentencepiece_model_pb2
sentencepiece_model_pb2 = _sentencepiece_model_pb2
except:
if not os.path.exists(temporary_location):
os.system(f"git clone https://github.com/google/sentencepiece.git {temporary_location}")
os.system(f"cd {temporary_location}/src && protoc --python_out=. sentencepiece_model.proto")
pass
import sentencepiece.sentencepiece_model_pb2 as _sentencepiece_model_pb2
sentencepiece_model_pb2 = _sentencepiece_model_pb2
pass
from transformers.utils import sentencepiece_model_pb2
if not os.path.exists(temporary_location):
os.makedirs(temporary_location)