





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

snake_case								=							logging.get_logger(__name__)

def 				SCREAMING_SNAKE_CASE__							(	snake_case__	:Union[str, Any]      ,				snake_case__	:Optional[int]      ,				snake_case__	:Any      ,				snake_case__	:Union[str, Any]=None      ,				snake_case__	:str=None  )   ->    Optional[Any]:
  # Recurse if needed
  if "." in tensor_name:
    _lowercase						    =			tensor_name.split('.'  )
    for split in splits[:-1]:
      _lowercase						    =			getattr(snake_case__      ,				snake_case__  )
      if new_module is None:
        raise ValueError(F"""{module} has no attribute {split}."""  )
      _lowercase						    =			new_module
    _lowercase						    =			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}."""  )
  _lowercase						    =			tensor_name in module._buffers
  _lowercase						    =			getattr(snake_case__      ,				snake_case__  )

  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}."""  )

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

  if is_abit or is_abit:
    _lowercase						    =			module._parameters[tensor_name]
    if param.device.type != "cuda":
      if value is None:
        _lowercase						    =			old_value.to(snake_case__  )
      elif isinstance(snake_case__      ,				torch.Tensor  ):
        _lowercase						    =			value.to('cpu'  )
        if value.dtype == torch.inta:
          _lowercase						    =			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:
        _lowercase						    =			torch.tensor(snake_case__      ,				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      ,				snake_case__  ) and fpaa_statistics is None:
        _lowercase						    =			new_value.T

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

      _lowercase						    =			new_value
      if fpaa_statistics is not None:
        setattr(module.weight      ,				'SCB'      ,				fpaa_statistics.to(snake_case__  )  )

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

    if is_buffer:
      _lowercase						    =			new_value
    else:
      _lowercase						    =			nn.Parameter(snake_case__      ,				requires_grad=old_value.requires_grad  )
      _lowercase						    =			new_value

def 				SCREAMING_SNAKE_CASE__							(	snake_case__	:Union[str, Any]      ,				snake_case__	:Any=None      ,				snake_case__	:Union[str, Any]=None      ,				snake_case__	:Optional[Any]=None      ,				snake_case__	:str=False  )   ->    Optional[int]:
  for name, module in model.named_children():
    if current_key_name is None:
      _lowercase						    =			[]
    current_key_name.append(snake_case__  )

    if (isinstance(snake_case__      ,				nn.Linear  ) or isinstance(snake_case__      ,				snake_case__  )) 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(snake_case__  ) for key in modules_to_not_convert  ):
        with init_empty_weights():
          if isinstance(snake_case__      ,				snake_case__  ):
            _lowercase    ,		_lowercase						    =			module.weight.shape
          else:
            _lowercase						    =			module.in_features
            _lowercase						    =			module.out_features

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

def 				SCREAMING_SNAKE_CASE__							(	snake_case__	:int      ,				snake_case__	:Union[str, Any]=None      ,				snake_case__	:Union[str, Any]=None      ,				snake_case__	:Union[str, Any]=None  )   ->    Optional[Any]:
  _lowercase						    =			['lm_head'] if modules_to_not_convert is None else modules_to_not_convert
  _lowercase    ,		_lowercase						    =			_replace_with_bnb_linear(
      snake_case__      ,				snake_case__      ,				snake_case__      ,				snake_case__  )

  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 				SCREAMING_SNAKE_CASE__							(	*snake_case__	:Optional[Any]      ,				**snake_case__	:Optional[int]  )   ->    str:
  warnings.warn(
      '`replace_8bit_linear` will be deprecated in a future version, please use `replace_with_bnb_linear` instead'      ,				snake_case__      ,				)
  return replace_with_bnb_linear(*snake_case__      ,				**snake_case__  )

def 				SCREAMING_SNAKE_CASE__							(	*snake_case__	:Dict      ,				**snake_case__	:List[str]  )   ->    Tuple:
  warnings.warn(
      '`set_module_8bit_tensor_to_device` will be deprecated in a future version, please use `set_module_quantized_tensor_to_device` instead'      ,				snake_case__      ,				)
  return set_module_quantized_tensor_to_device(*snake_case__      ,				**snake_case__  )







def 				SCREAMING_SNAKE_CASE__							(	snake_case__	:int  )   ->    Any:
  _lowercase						    =			deepcopy(snake_case__  )  # this has 0 cost since it is done inside `init_empty_weights` context manager`
  tied_model.tie_weights()

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

  # Check if it is a base model
  _lowercase						    =			not hasattr(snake_case__      ,				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
  _lowercase						    =			list(model.named_children()  )
  _lowercase						    =			[list_modules[-1][0]]

  # add last module together with tied weights
  _lowercase						    =			set(snake_case__  ) - set(snake_case__  )
  _lowercase						    =			list(set(snake_case__  )  ) + list(snake_case__  )

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

  return filtered_module_names




from .configuration_bert_masked import MaskedBertConfig
from .modeling_bert_masked import (
    MaskedBertForMultipleChoice,
    MaskedBertForQuestionAnswering,
    MaskedBertForSequenceClassification,
    MaskedBertForTokenClassification,
    MaskedBertModel,
)
from .modules import *



