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 				UpperCamelCase						(       __lowercase						: int						,__lowercase						: List[Any]						,__lowercase						: int						,__lowercase						: List[Any]=None						,__lowercase						: str=None	):
		'''simple docstring'''




		if "." in tensor_name:
				A_		:				Tuple     =      tensor_name.split('.'	)
				for split in splits[:-1]:
						A_		:				Union[str, Any]     =      getattr(a_						,a_	)
						if new_module is None:
								raise ValueError(f'''{module} has no attribute {split}.'''	)
						A_		:				Optional[Any]     =      new_module
				A_		:				List[str]     =      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}.'''	)
		A_		:				List[str]     =      tensor_name in module._buffers
		A_		:				Any     =      getattr(a_						,a_	)

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

		A_		:				Tuple     =      False
		A_		:				Dict     =      False
		if is_buffer or not is_bitsandbytes_available():
				A_		:				int     =      False
				A_		:				Dict     =      False
		else:
				A_		:				Union[str, Any]     =      hasattr(bnb.nn						,'Params4bit'	) and isinstance(module._parameters[tensor_name]						,bnb.nn.Paramsabit	)
				A_		:				Union[str, Any]     =      isinstance(module._parameters[tensor_name]						,bnb.nn.IntaParams	)

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

						A_		:				List[str]     =      old_value.__dict__
						if is_abit:
								A_		:				List[Any]     =      bnb.nn.IntaParams(a_						,requires_grad=a_						,**a_	).to(a_	)
						elif is_abit:
								A_		:				Tuple     =      bnb.nn.Paramsabit(a_						,requires_grad=a_						,**a_	).to(a_	)

						A_		:				Union[str, Any]     =      new_value
						if fpaa_statistics is not None:
								setattr(module.weight						,'SCB'						,fpaa_statistics.to(a_	)	)

		else:
				if value is None:
						A_		:				List[str]     =      old_value.to(a_	)
				elif isinstance(a_						,torch.Tensor	):
						A_		:				Tuple     =      value.to(a_	)
				else:
						A_		:				int     =      torch.tensor(a_						,device=a_	)

				if is_buffer:
						A_		:				Dict     =      new_value
				else:
						A_		:				Dict     =      nn.Parameter(a_						,requires_grad=old_value.requires_grad	)
						A_		:				int     =      new_value




def 				UpperCamelCase						(       __lowercase						: Union[str, Any]						,__lowercase						: str=None						,__lowercase						: int=None						,__lowercase						: int=None						,__lowercase						: List[str]=False	):
		'''simple docstring'''




		for name, module in model.named_children():
				if current_key_name is None:
						A_		:				Union[str, Any]     =      []
				current_key_name.append(a_	)

				if (isinstance(a_						,nn.Linear	) or isinstance(a_						,a_	)) 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(a_	) for key in modules_to_not_convert	):
								with init_empty_weights():
										if isinstance(a_						,a_	):
												A_   ,			A_		:				Union[str, Any]     =      module.weight.shape
										else:
												A_		:				List[str]     =      module.in_features
												A_		:				List[str]     =      module.out_features

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




def 				UpperCamelCase						(       __lowercase						: List[str]						,__lowercase						: int=None						,__lowercase						: Optional[Any]=None						,__lowercase						: Optional[Any]=None	):
		'''simple docstring'''




		A_		:				Optional[Any]     =      ['lm_head'] if modules_to_not_convert is None else modules_to_not_convert
		A_   ,			A_		:				Tuple     =      _replace_with_bnb_linear(
		    a_						,a_						,a_						,a_	)

		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 				UpperCamelCase						(       *__lowercase						: List[str]						,**__lowercase						: Dict	):
		'''simple docstring'''




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




def 				UpperCamelCase						(       *__lowercase						: List[str]						,**__lowercase						: Optional[Any]	):
		'''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'						,a_						,)
		return set_module_quantized_tensor_to_device(*a_						,**a_	)




def 				UpperCamelCase						(       __lowercase						: Union[str, Any]	):
		'''simple docstring'''




		A_		:				str     =      deepcopy(a_	)  # this has 0 cost since it is done inside `init_empty_weights` context manager`
		tied_model.tie_weights()

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

		# Check if it is a base model
		A_		:				Any     =      not hasattr(a_						,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
		A_		:				Dict     =      list(model.named_children()	)
		A_		:				int     =      [list_modules[-1][0]]

		# add last module together with tied weights
		A_		:				str     =      set(a_	) - set(a_	)
		A_		:				Union[str, Any]     =      list(set(a_	)	) + list(a_	)

		# remove ".weight" from the keys
		A_		:				List[str]     =      ['.weight', '.bias']
		A_		:				int     =      []
		for name in list_untouched:
				for name_to_remove in names_to_remove:
						if name_to_remove in name:
								A_		:				List[Any]     =      name.replace(a_						,''	)
				filtered_module_names.append(a_	)

		return filtered_module_names








from typing import TYPE_CHECKING

from ...utils import OptionalDependencyNotAvailable, _LazyModule, is_sentencepiece_available


SCREAMING_SNAKE_CASE							:List[Any]							 =				{}

try:
					if not is_sentencepiece_available():
										raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
					pass
else:
					SCREAMING_SNAKE_CASE							:List[str]							 =				['BartphoTokenizer']

if TYPE_CHECKING:
					try:
										if not is_sentencepiece_available():
															raise OptionalDependencyNotAvailable()
					except OptionalDependencyNotAvailable:
										pass
					else:
										from .tokenization_bartpho import BartphoTokenizer

else:
					import sys

					SCREAMING_SNAKE_CASE							:Union[str, Any]							 =				_LazyModule(__name__, globals()['__file__'], _import_structure, module_spec=__spec__)
