




import importlib.metadata
import warnings
from copy import deepcopy

from packaging import version

from ..utils import logging
from .import_utils import is_accelerate_available, is_bitsandbytes_available


if is_bitsandbytes_available():
     import bitsandbytes as bnb
     import torch
     import torch.nn as nn

     from ..pytorch_utils import ConvaD

if is_accelerate_available():
     from accelerate import init_empty_weights
     from accelerate.utils import find_tied_parameters

UpperCamelCase								=					logging.get_logger(__name__)



def 							_A       (						lowerCAmelCase_					: int       ,    lowerCAmelCase_					: List[str]       ,    lowerCAmelCase_					: str       ,    lowerCAmelCase_					: Union[str, Any]=None       ,    lowerCAmelCase_					: Optional[Any]=None      ):
     """simple docstring"""

     if "." in tensor_name:
          lowerCAmelCase__          =			tensor_name.split("."      )
          for split in splits[:-1]:
               lowerCAmelCase__          =			getattr(lowerCAmelCase_       ,    lowerCAmelCase_      )
               if new_module is None:
                    raise ValueError(F'{module} has no attribute {split}.'      )
               lowerCAmelCase__          =			new_module
          lowerCAmelCase__          =			splits[-1]

     if tensor_name not in module._parameters and tensor_name not in module._buffers:
          raise ValueError(F'{module} does not have a parameter or a buffer named {tensor_name}.'      )
     lowerCAmelCase__          =			tensor_name in module._buffers
     lowerCAmelCase__          =			getattr(lowerCAmelCase_       ,    lowerCAmelCase_      )

     if old_value.device == torch.device("meta"      ) and device not in ["meta", torch.device("meta"      )] and value is None:
          raise ValueError(F'{tensor_name} is on the meta device, we need a `value` to put in on {device}.'      )

     lowerCAmelCase__          =			False
     lowerCAmelCase__          =			False
     if is_buffer or not is_bitsandbytes_available():
          lowerCAmelCase__          =			False
          lowerCAmelCase__          =			False
     else:
          lowerCAmelCase__          =			hasattr(bnb.nn       ,    "Params4bit"      ) and isinstance(module._parameters[tensor_name]       ,    bnb.nn.Paramsabit      )
          lowerCAmelCase__          =			isinstance(module._parameters[tensor_name]       ,    bnb.nn.IntaParams      )

     if is_abit or is_abit:
          lowerCAmelCase__          =			module._parameters[tensor_name]
          if param.device.type != "cuda":
               if value is None:
                    lowerCAmelCase__          =			old_value.to(lowerCAmelCase_      )
               elif isinstance(lowerCAmelCase_       ,    torch.Tensor      ):
                    lowerCAmelCase__          =			value.to("cpu"      )
                    if value.dtype == torch.inta:
                         lowerCAmelCase__          =			version.parse(importlib.metadata.version("bitsandbytes"      )      ) > version.parse(
                             "0.37.2"      )
                         if not is_abit_serializable:
                              raise ValueError(
                                  "Detected int8 weights but the version of bitsandbytes is not compatible with int8 serialization. "
                                  "Make sure to download the latest `bitsandbytes` version. `pip install --upgrade bitsandbytes`."      )
               else:
                    lowerCAmelCase__          =			torch.tensor(lowerCAmelCase_       ,    device="cpu"      )

               # Support models using `Conv1D` in place of `nn.Linear` (e.g. gpt2) by transposing the weight matrix prior to quantization.
               # Since weights are saved in the correct "orientation", we skip transposing when loading.
               if issubclass(module.source_cls       ,    lowerCAmelCase_      ) and fpaa_statistics is None:
                    lowerCAmelCase__          =			new_value.T

               lowerCAmelCase__          =			old_value.__dict__
               if is_abit:
                    lowerCAmelCase__          =			bnb.nn.IntaParams(lowerCAmelCase_       ,    requires_grad=lowerCAmelCase_       ,    **lowerCAmelCase_      ).to(lowerCAmelCase_      )
               elif is_abit:
                    lowerCAmelCase__          =			bnb.nn.Paramsabit(lowerCAmelCase_       ,    requires_grad=lowerCAmelCase_       ,    **lowerCAmelCase_      ).to(lowerCAmelCase_      )

               lowerCAmelCase__          =			new_value
               if fpaa_statistics is not None:
                    setattr(module.weight       ,    "SCB"       ,    fpaa_statistics.to(lowerCAmelCase_      )      )

     else:
          if value is None:
               lowerCAmelCase__          =			old_value.to(lowerCAmelCase_      )
          elif isinstance(lowerCAmelCase_       ,    torch.Tensor      ):
               lowerCAmelCase__          =			value.to(lowerCAmelCase_      )
          else:
               lowerCAmelCase__          =			torch.tensor(lowerCAmelCase_       ,    device=lowerCAmelCase_      )

          if is_buffer:
               lowerCAmelCase__          =			new_value
          else:
               lowerCAmelCase__          =			nn.Parameter(lowerCAmelCase_       ,    requires_grad=old_value.requires_grad      )
               lowerCAmelCase__          =			new_value



def 							_A       (						lowerCAmelCase_					: str       ,    lowerCAmelCase_					: Tuple=None       ,    lowerCAmelCase_					: int=None       ,    lowerCAmelCase_					: Optional[int]=None       ,    lowerCAmelCase_					: Optional[int]=False      ):
     """simple docstring"""

     for name, module in model.named_children():
          if current_key_name is None:
               lowerCAmelCase__          =			[]
          current_key_name.append(lowerCAmelCase_      )

          if (isinstance(lowerCAmelCase_       ,    nn.Linear      ) or isinstance(lowerCAmelCase_       ,    lowerCAmelCase_      )) and name not in modules_to_not_convert:
               # Check if the current key is not in the `modules_to_not_convert`
               if not any(key in ".".join(lowerCAmelCase_      ) for key in modules_to_not_convert      ):
                    with init_empty_weights():
                         if isinstance(lowerCAmelCase_       ,    lowerCAmelCase_      ):
                              lowerCAmelCase__     ,		lowerCAmelCase__          =			module.weight.shape
                         else:
                              lowerCAmelCase__          =			module.in_features
                              lowerCAmelCase__          =			module.out_features

                         if quantization_config.quantization_method() == "llm_int8":
                              lowerCAmelCase__          =			bnb.nn.LinearabitLt(
                                  lowerCAmelCase_       ,    lowerCAmelCase_       ,    module.bias is not None       ,    has_fpaa_weights=quantization_config.llm_inta_has_fpaa_weight       ,    threshold=quantization_config.llm_inta_threshold       ,    )
                              lowerCAmelCase__          =			True
                         else:
                              if (
                                  quantization_config.llm_inta_skip_modules is not None
                                  and name in quantization_config.llm_inta_skip_modules
                              ):
                                   pass
                              else:
                                   lowerCAmelCase__          =			bnb.nn.Linearabit(
                                       lowerCAmelCase_       ,    lowerCAmelCase_       ,    module.bias is not None       ,    quantization_config.bnb_abit_compute_dtype       ,    compress_statistics=quantization_config.bnb_abit_use_double_quant       ,    quant_type=quantization_config.bnb_abit_quant_type       ,    )
                                   lowerCAmelCase__          =			True
                    # Store the module class in case we need to transpose the weight later
                         lowerCAmelCase__          =			type(lowerCAmelCase_      )
                         # Force requires grad to False to avoid unexpected errors
                         model._modules[name].requires_grad_(lowerCAmelCase_      )
          if len(list(module.children()      )      ) > 0:
               lowerCAmelCase__     ,		lowerCAmelCase__          =			_replace_with_bnb_linear(
                   lowerCAmelCase_       ,    lowerCAmelCase_       ,    lowerCAmelCase_       ,    lowerCAmelCase_       ,    has_been_replaced=lowerCAmelCase_       ,    )
          # Remove the last key for recursion
          current_key_name.pop(-1      )
     return model, has_been_replaced



def 							_A       (						lowerCAmelCase_					: str       ,    lowerCAmelCase_					: int=None       ,    lowerCAmelCase_					: Optional[int]=None       ,    lowerCAmelCase_					: List[str]=None      ):
     """simple docstring"""

     lowerCAmelCase__          =			["lm_head"] if modules_to_not_convert is None else modules_to_not_convert
     lowerCAmelCase__     ,		lowerCAmelCase__          =			_replace_with_bnb_linear(
         lowerCAmelCase_       ,    lowerCAmelCase_       ,    lowerCAmelCase_       ,    lowerCAmelCase_      )

     if not has_been_replaced:
          logger.warning(
              "You are loading your model in 8bit or 4bit but no linear modules were found in your model."
              " Please double check your model architecture, or submit an issue on github if you think this is"
              " a bug."      )

     return model



def 							_A       (						*lowerCAmelCase_					: Dict       ,    **lowerCAmelCase_					: Dict      ):
     """simple docstring"""

     warnings.warn(
         "`replace_8bit_linear` will be deprecated in a future version, please use `replace_with_bnb_linear` instead"       ,    lowerCAmelCase_       ,    )
     return replace_with_bnb_linear(*lowerCAmelCase_       ,    **lowerCAmelCase_      )



def 							_A       (						*lowerCAmelCase_					: str       ,    **lowerCAmelCase_					: Optional[int]      ):
     """simple docstring"""

     warnings.warn(
         "`set_module_8bit_tensor_to_device` will be deprecated in a future version, please use `set_module_quantized_tensor_to_device` instead"       ,    lowerCAmelCase_       ,    )
     return set_module_quantized_tensor_to_device(*lowerCAmelCase_       ,    **lowerCAmelCase_      )






def 							_A       (						lowerCAmelCase_					: Optional[Any]      ):
     """simple docstring"""

     lowerCAmelCase__          =			deepcopy(lowerCAmelCase_      )  # this has 0 cost since it is done inside `init_empty_weights` context manager`
     tied_model.tie_weights()

     lowerCAmelCase__          =			find_tied_parameters(lowerCAmelCase_      )
     # For compatibility with Accelerate < 0.18
     if isinstance(lowerCAmelCase_       ,    lowerCAmelCase_      ):
          lowerCAmelCase__          =			sum(list(tied_params.values()      )       ,    []      ) + list(tied_params.keys()      )
     else:
          lowerCAmelCase__          =			sum(lowerCAmelCase_       ,    []      )
     lowerCAmelCase__          =			len(lowerCAmelCase_      ) > 0

     # Check if it is a base model
     lowerCAmelCase__          =			not hasattr(lowerCAmelCase_       ,    model.base_model_prefix      )

     # Ignore this for base models (BertModel, GPT2Model, etc.)
     if (not has_tied_params) and is_base_model:
          return []

     # otherwise they have an attached head
     lowerCAmelCase__          =			list(model.named_children()      )
     lowerCAmelCase__          =			[list_modules[-1][0]]

     # add last module together with tied weights
     lowerCAmelCase__          =			set(lowerCAmelCase_      ) - set(lowerCAmelCase_      )
     lowerCAmelCase__          =			list(set(lowerCAmelCase_      )      ) + list(lowerCAmelCase_      )

     # remove ".weight" from the keys
     lowerCAmelCase__          =			[".weight", ".bias"]
     lowerCAmelCase__          =			[]
     for name in list_untouched:
          for name_to_remove in names_to_remove:
               if name_to_remove in name:
                    lowerCAmelCase__          =			name.replace(lowerCAmelCase_       ,    ""      )
          filtered_module_names.append(lowerCAmelCase_      )

     return filtered_module_names






import random



def 							_A       (						lowerCAmelCase_					: list       ,    lowerCAmelCase_					: List[str]      ):
     """simple docstring"""

     lowerCAmelCase__     ,		lowerCAmelCase__     ,		lowerCAmelCase__          =			[], [], []
     for element in data:
          if element < pivot:
               less.append(lowerCAmelCase_      )
          elif element > pivot:
               greater.append(lowerCAmelCase_      )
          else:
               equal.append(lowerCAmelCase_      )
     return less, equal, greater






def 							_A       (						lowerCAmelCase_					: list       ,    lowerCAmelCase_					: int      ):
     """simple docstring"""

     if index >= len(lowerCAmelCase_      ) or index < 0:
          return None

     lowerCAmelCase__          =			items[random.randint(0       ,    len(lowerCAmelCase_      ) - 1      )]
     lowerCAmelCase__          =			0
     lowerCAmelCase__     ,		lowerCAmelCase__     ,		lowerCAmelCase__          =			_partition(lowerCAmelCase_       ,    lowerCAmelCase_      )
     lowerCAmelCase__          =			len(lowerCAmelCase_      )
     lowerCAmelCase__          =			len(lowerCAmelCase_      )

     # index is the pivot
     if m <= index < m + count:
          return pivot
     # must be in smaller
     elif m > index:
          return quick_select(lowerCAmelCase_       ,    lowerCAmelCase_      )
     # must be in larger
     else:
          return quick_select(lowerCAmelCase_       ,    index - (m + count)      )
