



# Copyright 2023 The HuggingFace Inc. team. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import copy
import importlib.metadata
import json
import os
from dataclasses import dataclass
from typing import Any, Dict, Union

from packaging import version

from ..utils import is_torch_available, logging


if is_torch_available():
	import torch


snake_case__					:     str    		=   logging.get_logger(__name__)

@dataclass
class   _A   :


						'''simple docstring'''





						def __init__(	self	:							Tuple							,      lowerCamelCase	:							Dict=False							,      lowerCamelCase	:							Optional[Any]=False							,      lowerCamelCase	:							List[Any]=6.0							,      lowerCamelCase	:							str=None							,      lowerCamelCase	:							int=False							,      lowerCamelCase	:							Union[str, Any]=False							,      lowerCamelCase	:							Optional[Any]=None							,      lowerCamelCase	:							Optional[Any]="fp4"							,      lowerCamelCase	:							str=False							,      **lowerCamelCase	:							Union[str, Any]							,      ):






							'''simple docstring'''



							__lowercase		       =			load_in_abit
							__lowercase		       =			load_in_abit
							__lowercase		       =			llm_inta_threshold
							__lowercase		       =			llm_inta_skip_modules
							__lowercase		       =			llm_inta_enable_fpaa_cpu_offload
							__lowercase		       =			llm_inta_has_fpaa_weight
							__lowercase		       =			bnb_abit_quant_type
							__lowercase		       =			bnb_abit_use_double_quant

							if bnb_abit_compute_dtype is None:
								__lowercase		       =			torch.floataa
							elif isinstance(lowerCamelCase							,      lowerCamelCase	):
								__lowercase		       =			getattr(lowerCamelCase							,      lowerCamelCase	)
							elif isinstance(lowerCamelCase							,      torch.dtype	):
								__lowercase		       =			bnb_abit_compute_dtype
							else:
								raise ValueError("bnb_4bit_compute_dtype must be a string or a torch.dtype"	)

							self.post_init()



						def     _snake_case	(	self	:							List[str]	):






							'''simple docstring'''



							if not isinstance(self.llm_inta_threshold							,      lowerCamelCase	):
								raise ValueError("llm_int8_threshold must be a float"	)

							if self.llm_inta_skip_modules is not None and not isinstance(self.llm_inta_skip_modules							,      lowerCamelCase	):
								raise ValueError("llm_int8_skip_modules must be a list of strings"	)
							if not isinstance(self.llm_inta_enable_fpaa_cpu_offload							,      lowerCamelCase	):
								raise ValueError("llm_int8_enable_fp32_cpu_offload must be a boolean"	)

							if not isinstance(self.llm_inta_has_fpaa_weight							,      lowerCamelCase	):
								raise ValueError("llm_int8_has_fp16_weight must be a boolean"	)

							if self.bnb_abit_compute_dtype is not None and not isinstance(self.bnb_abit_compute_dtype							,      torch.dtype	):
								raise ValueError("bnb_4bit_compute_dtype must be torch.dtype"	)

							if not isinstance(self.bnb_abit_quant_type							,      lowerCamelCase	):
								raise ValueError("bnb_4bit_quant_type must be a string"	)

							if not isinstance(self.bnb_abit_use_double_quant							,      lowerCamelCase	):
								raise ValueError("bnb_4bit_use_double_quant must be a boolean"	)

							if self.load_in_abit and not version.parse(importlib.metadata.version("bitsandbytes"	)	) >= version.parse(
							    "0.39.0"	):
								raise ValueError(
								    "4 bit quantization requires bitsandbytes>=0.39.0 - please upgrade your bitsandbytes version"	)



						def     _snake_case	(	self	:							Union[str, Any]	):






							'''simple docstring'''



							return self.load_in_abit or self.load_in_abit



						def     _snake_case	(	self	:							str	):






							'''simple docstring'''



							if self.load_in_abit:
								return "llm_int8"
							elif self.load_in_abit and self.bnb_abit_quant_type == "fp4":
								return "fp4"
							elif self.load_in_abit and self.bnb_abit_quant_type == "nf4":
								return "nf4"
							else:
								return None



						@classmethod
						def     _snake_case	(	cls	:							Optional[Any]							,      lowerCamelCase	:							int							,      lowerCamelCase	:							Optional[int]							,      **lowerCamelCase	:							Optional[int]	):






							'''simple docstring'''



							__lowercase		       =			cls(**lowerCamelCase	)

							__lowercase		       =			[]
							for key, value in kwargs.items():
								if hasattr(lowerCamelCase							,      lowerCamelCase	):
									setattr(lowerCamelCase							,      lowerCamelCase							,      lowerCamelCase	)
									to_remove.append(lowerCamelCase	)
							for key in to_remove:
								kwargs.pop(lowerCamelCase							,      lowerCamelCase	)

							if return_unused_kwargs:
								return config, kwargs
							else:
								return config



						def     _snake_case	(	self	:							Any							,      lowerCamelCase	:							Union[str, os.PathLike]	):






							'''simple docstring'''



							with open(lowerCamelCase							,      "w"							,      encoding="utf-8"	) as writer:
								__lowercase		       =			self.to_dict()
								__lowercase		       =			json.dumps(lowerCamelCase							,      indent=2							,      sort_keys=lowerCamelCase	) + "\n"

								writer.write(lowerCamelCase	)



						def     _snake_case	(	self	:							int	):






							'''simple docstring'''



							__lowercase		       =			copy.deepcopy(self.__dict__	)
							__lowercase		       =			str(output["bnb_4bit_compute_dtype"]	).split("."	)[1]

							return output



						def __repr__(	self	:							List[str]	):






							'''simple docstring'''



							return f"""{self.__class__.__name__} {self.to_json_string()}"""



						def     _snake_case	(	self	:							int							,      lowerCamelCase	:							bool = True	):






							'''simple docstring'''



							if use_diff is True:
								__lowercase		       =			self.to_diff_dict()
							else:
								__lowercase		       =			self.to_dict()
							return json.dumps(lowerCamelCase							,      indent=2							,      sort_keys=lowerCamelCase	) + "\n"



						def     _snake_case	(	self	:							Tuple	):






							'''simple docstring'''



							__lowercase		       =			self.to_dict()

							# get the default config dict
							__lowercase		       =			BitsAndBytesConfig().to_dict()

							__lowercase		       =			{}

							# only serialize values that differ from the default config
							for key, value in config_dict.items():
								if value != default_config_dict[key]:
									__lowercase		       =			value

							return serializable_config_dict








from __future__ import annotations

from collections.abc import Callable
from typing import Generic, TypeVar

snake_case__					:     Union[str, Any]    		=   TypeVar("""T""")
snake_case__					:     Optional[int]    		=   TypeVar("""U""")

class   _A   ( Generic[T, U]	):


						'''simple docstring'''





						def __init__(	self	:							Optional[int]							,      lowerCamelCase	:							T | None							,      lowerCamelCase	:							U | None	):






							'''simple docstring'''



							__lowercase		       =			key
							__lowercase		       =			val
							__lowercase		       =			None
							__lowercase		       =			None



						def __repr__(	self	:							Any	):






							'''simple docstring'''



							return (
							    f"""Node: key: {self.key}, val: {self.val}, """
							    f"""has next: {bool(self.next	)}, has prev: {bool(self.prev	)}"""
							)

class   _A   ( Generic[T, U]	):


						'''simple docstring'''





						def __init__(	self	:							Dict	):






							'''simple docstring'''



							__lowercase		       =			DoubleLinkedListNode(lowerCamelCase							,      lowerCamelCase	)
							__lowercase		       =			DoubleLinkedListNode(lowerCamelCase							,      lowerCamelCase	)
							__lowercase       ,    __lowercase		       =			self.rear, self.head



						def __repr__(	self	:							Optional[Any]	):






							'''simple docstring'''



							__lowercase		       =			["DoubleLinkedList"]
							__lowercase		       =			self.head
							while node.next is not None:
								rep.append(str(lowerCamelCase	)	)
								__lowercase		       =			node.next
							rep.append(str(self.rear	)	)
							return ",\n    ".join(lowerCamelCase	)



						def     _snake_case	(	self	:							Union[str, Any]							,      lowerCamelCase	:							DoubleLinkedListNode[T, U]	):






							'''simple docstring'''



							__lowercase		       =			self.rear.prev

							# All nodes other than self.head are guaranteed to have non-None previous
							assert previous is not None

							__lowercase		       =			node
							__lowercase		       =			previous
							__lowercase		       =			node
							__lowercase		       =			self.rear



						def     _snake_case	(	self	:							Optional[int]							,      lowerCamelCase	:							DoubleLinkedListNode[T, U]	):






							'''simple docstring'''



							if node.prev is None or node.next is None:
								return None

							__lowercase		       =			node.next
							__lowercase		       =			node.prev
							__lowercase		       =			None
							__lowercase		       =			None
							return node

class   _A   ( Generic[T, U]	):


						'''simple docstring'''





						_snake_case			:     dict[Callable[[T], U], LRUCache[T, U]]      							=      {}



						def __init__(	self	:							List[Any]							,      lowerCamelCase	:							int	):






							'''simple docstring'''



							__lowercase		       =			DoubleLinkedList()
							__lowercase		       =			capacity
							__lowercase		       =			0
							__lowercase		       =			0
							__lowercase		       =			0
							__lowercase		       =			{}



						def __repr__(	self	:							Optional[Any]	):






							'''simple docstring'''



							return (
							    f"""CacheInfo(hits={self.hits}, misses={self.miss}, """
							    f"""capacity={self.capacity}, current size={self.num_keys})"""
							)



						def __contains__(	self	:							Dict							,      lowerCamelCase	:							T	):






							'''simple docstring'''



							return key in self.cache



						def     _snake_case	(	self	:							List[Any]							,      lowerCamelCase	:							T	):






							'''simple docstring'''



							if key in self.cache:
								self.hits += 1
								__lowercase		       =			self.cache[key]
								__lowercase		       =			self.list.remove(self.cache[key]	)
								assert node == value_node

								# node is guaranteed not None because it is in self.cache
								assert node is not None
								self.list.add(lowerCamelCase	)
								return node.val
							self.miss += 1
							return None



						def     _snake_case	(	self	:							Union[str, Any]							,      lowerCamelCase	:							T							,      lowerCamelCase	:							U	):






							'''simple docstring'''



							if key not in self.cache:
								if self.num_keys >= self.capacity:
									# delete first node (oldest) when over capacity
									__lowercase		       =			self.list.head.next

									# guaranteed to have a non-None first node when num_keys > 0
									# explain to type checker via assertions
									assert first_node is not None
									assert first_node.key is not None
									assert (
									    self.list.remove(lowerCamelCase	) is not None
									)  # node guaranteed to be in list assert node.key is not None

									del self.cache[first_node.key]
									self.num_keys -= 1
								__lowercase		       =			DoubleLinkedListNode(lowerCamelCase							,      lowerCamelCase	)
								self.list.add(self.cache[key]	)
								self.num_keys += 1

							else:
								# bump node to the end of the list, update value
								__lowercase		       =			self.list.remove(self.cache[key]	)
								assert node is not None  # node guaranteed to be in list
								__lowercase		       =			value
								self.list.add(lowerCamelCase	)



						@classmethod
						def     _snake_case	(	cls	:							Union[str, Any]							,      lowerCamelCase	:							int = 128	):






							'''simple docstring'''



							def cache_decorator_inner(lowerCamelCase	:							Callable[[T], U]	) -> Callable[..., U]:
								def cache_decorator_wrapper(*lowerCamelCase	:							T	) -> U:
									if func not in cls.decorator_function_to_instance_map:
										__lowercase		       =			LRUCache(lowerCamelCase	)

									__lowercase		       =			cls.decorator_function_to_instance_map[func].get(args[0]	)
									if result is None:
										__lowercase		       =			func(*lowerCamelCase	)
										cls.decorator_function_to_instance_map[func].put(args[0]							,      lowerCamelCase	)
									return result

								def cache_info() -> LRUCache[T, U]:
									return cls.decorator_function_to_instance_map[func]

								setattr(lowerCamelCase							,      "cache_info"							,      lowerCamelCase	)  # noqa: B010

								return cache_decorator_wrapper

							return cache_decorator_inner


if __name__ == "__main__":
	import doctest

	doctest.testmod()



