
import logging
import re

import pytorch_quantization
import pytorch_quantization.nn as quant_nn
import torch
from pytorch_quantization import calib
from pytorch_quantization.tensor_quant import QuantDescriptor


lowercase__       =logging.getLogger(__name__)

lowercase__       =50  # max width of layer names
lowercase__       =70  # max width of quantizer names




def    __UpperCamelCase     (				lowerCAmelCase__							:				Optional[int]  ):
 __a :  Union[str, Any]						=  parser.add_argument_group('''quant_trainer arguments'''  )
 group.add_argument('''--wprec'''  ,   type=lowerCAmelCase__  ,   default=8  ,   help='''weight precision'''  )
 group.add_argument('''--aprec'''  ,   type=lowerCAmelCase__  ,   default=8  ,   help='''activation precision'''  )
 group.add_argument('''--quant-per-tensor'''  ,   action='''store_true'''  ,   help='''per tensor weight scaling'''  )
 group.add_argument('''--quant-disable'''  ,   action='''store_true'''  ,   help='''disable all quantizers'''  )
 group.add_argument('''--quant-disable-embeddings'''  ,   action='''store_true'''  ,   help='''disable all embeddings quantizers'''  )
 group.add_argument('''--quant-disable-keyword'''  ,   type=lowerCAmelCase__  ,   nargs='''+'''  ,   help='''disable quantizers by keyword'''  )
 group.add_argument('''--quant-disable-layer-module'''  ,   type=lowerCAmelCase__  ,   help='''disable quantizers by keyword under layer.'''  )
 group.add_argument('''--quant-enable-layer-module'''  ,   type=lowerCAmelCase__  ,   help='''enable quantizers by keyword under layer'''  )
 group.add_argument('''--calibrator'''  ,   default='''max'''  ,   help='''which quantization range calibrator to use'''  )
 group.add_argument('''--percentile'''  ,   default=lowerCAmelCase__  ,   type=lowerCAmelCase__  ,   help='''percentile for PercentileCalibrator'''  )
 group.add_argument('''--fuse-qkv'''  ,   action='''store_true'''  ,   help='''use the same scale factor for qkv'''  )
 group.add_argument('''--clip-gelu'''  ,   metavar='''N'''  ,   type=lowerCAmelCase__  ,   help='''clip gelu output maximum value to N'''  )
 group.add_argument(
     '''--recalibrate-weights'''  ,   action='''store_true'''  ,   help=(
         '''recalibrate weight amaxes by taking the max of the weights.'''
         ''' amaxes will be computed with the current quantization granularity (axis).'''
     )  ,   )




def    __UpperCamelCase     (				lowerCAmelCase__							:				List[Any]  ):



 if args.calibrator == "max":
  __a :  str						=  '''max'''
 elif args.calibrator == "percentile":
  if args.percentile is None:
   raise ValueError('''Specify --percentile when using percentile calibrator'''  )
  __a :  List[Any]						=  '''histogram'''
 elif args.calibrator == "mse":
  __a :  List[str]						=  '''histogram'''
 else:
  raise ValueError(f"Invalid calibrator {args.calibrator}"  )

 __a :  Optional[int]						=  QuantDescriptor(num_bits=args.aprec  ,   calib_method=lowerCAmelCase__  )
 __a :  Dict						=  QuantDescriptor(num_bits=args.wprec  ,   axis=(None if args.quant_per_tensor else (0,))  )
 quant_nn.QuantLinear.set_default_quant_desc_input(lowerCAmelCase__  )
 quant_nn.QuantLinear.set_default_quant_desc_weight(lowerCAmelCase__  )




def    __UpperCamelCase     (				lowerCAmelCase__							:				Optional[int]  ,   lowerCAmelCase__							:				Tuple  ,   lowerCAmelCase__							:				List[str]=False  ,   lowerCAmelCase__							:				Optional[int]=False  ):
 logger.info('''Configuring Model for Quantization'''  )
 logger.info(f"using quantization package {pytorch_quantization.__file__}"  )

 if not calib:
  if args.quant_disable_embeddings:
   set_quantizer_by_name(lowerCAmelCase__  ,   ['''embeddings''']  ,   which='''weight'''  ,   _disabled=lowerCAmelCase__  )

  if args.quant_disable:
   set_quantizer_by_name(lowerCAmelCase__  ,   ['''''']  ,   _disabled=lowerCAmelCase__  )

  if args.quant_disable_keyword:
   set_quantizer_by_name(lowerCAmelCase__  ,   args.quant_disable_keyword  ,   _disabled=lowerCAmelCase__  )

  if args.quant_disable_layer_module:
   set_quantizer_by_name(lowerCAmelCase__  ,   [R'''layer.\d+.''' + args.quant_disable_layer_module]  ,   _disabled=lowerCAmelCase__  )

  if args.quant_enable_layer_module:
   set_quantizer_by_name(lowerCAmelCase__  ,   [R'''layer.\d+.''' + args.quant_enable_layer_module]  ,   _disabled=lowerCAmelCase__  )

  if args.recalibrate_weights:
   recalibrate_weights(lowerCAmelCase__  )

  if args.fuse_qkv:
   fuse_qkv(lowerCAmelCase__  ,   lowerCAmelCase__  )

 if args.clip_gelu:
  clip_gelu(lowerCAmelCase__  ,   args.clip_gelu  )

 # if args.local_rank in [-1, 0] and not calib:
 print_quant_summary(lowerCAmelCase__  )




def    __UpperCamelCase     (				lowerCAmelCase__							:				int  ):
 logger.info('''Enabling Calibration'''  )
 for name, module in model.named_modules():
  if name.endswith('''_quantizer'''  ):
   if module._calibrator is not None:
    module.disable_quant()
    module.enable_calib()
   else:
    module.disable()
   logger.info(f"{name:80}: {module}"  )




def    __UpperCamelCase     (				lowerCAmelCase__							:				List[Any]  ,   lowerCAmelCase__							:				List[str]  ):
 logger.info('''Loading calibrated amax'''  )
 for name, module in model.named_modules():
  if name.endswith('''_quantizer'''  ):
   if module._calibrator is not None:
    if isinstance(module._calibrator  ,   calib.MaxCalibrator  ):
     module.load_calib_amax()
    else:
     module.load_calib_amax('''percentile'''  ,   percentile=args.percentile  )
    module.enable_quant()
    module.disable_calib()
   else:
    module.enable()
 model.cuda()
 print_quant_summary(lowerCAmelCase__  )




def    __UpperCamelCase     (				lowerCAmelCase__							:				str  ,   lowerCAmelCase__							:				Optional[int]  ):



 def fusea(lowerCAmelCase__							:				Union[str, Any]  ,   lowerCAmelCase__							:				Optional[int]  ,   lowerCAmelCase__							:				List[Any]  ):
  for mod in [qq, qk, qv]:
   if not hasattr(lowerCAmelCase__  ,   '''_amax'''  ):
    print('''          WARNING: NO AMAX BUFFER'''  )
    return
  __a :  int						=  qq._amax.detach().item()
  __a :  Dict						=  qk._amax.detach().item()
  __a :  str						=  qv._amax.detach().item()

  __a :  List[Any]						=  max(lowerCAmelCase__  ,   lowerCAmelCase__  ,   lowerCAmelCase__  )
  qq._amax.fill_(lowerCAmelCase__  )
  qk._amax.fill_(lowerCAmelCase__  )
  qv._amax.fill_(lowerCAmelCase__  )
  logger.info(f"          q={q:5.2f} k={k:5.2f} v={v:5.2f} -> {amax:5.2f}"  )

 for name, mod in model.named_modules():
  if name.endswith('''.attention.self'''  ):
   logger.info(f"FUSE_QKV: {name:{name_width}}"  )
   fusea(mod.matmul_q_input_quantizer  ,   mod.matmul_k_input_quantizer  ,   mod.matmul_v_input_quantizer  )
   if args.quant_per_tensor:
    fusea(mod.query._weight_quantizer  ,   mod.key._weight_quantizer  ,   mod.value._weight_quantizer  )




def    __UpperCamelCase     (				lowerCAmelCase__							:				Any  ,   lowerCAmelCase__							:				str  ):



 for name, mod in model.named_modules():
  if name.endswith('''.output.dense'''  ) and not name.endswith('''attention.output.dense'''  ):
   __a :  List[Any]						=  mod._input_quantizer._amax.data.detach().item()
   mod._input_quantizer._amax.data.detach().clamp_(max=lowerCAmelCase__  )
   __a :  List[str]						=  mod._input_quantizer._amax.data.detach().item()
   logger.info(f"CLIP_GELU: {name:{name_width}} amax: {amax_init:5.2f} -> {amax:5.2f}"  )




def    __UpperCamelCase     (				lowerCAmelCase__							:				Optional[int]  ):



 for name, mod in model.named_modules():
  if hasattr(lowerCAmelCase__  ,   '''_weight_quantizer'''  ) and mod._weight_quantizer.axis is not None:
   __a :  Tuple						=  mod.weight.shape[0]
   __a :  Any						=  mod._weight_quantizer._amax.detach()
   __a :  int						=  torch.ones(lowerCAmelCase__  ,   dtype=amax.dtype  ,   device=amax.device  ) * amax
   print(f"expanding {name} {amax} -> {mod._weight_quantizer._amax}"  )




def    __UpperCamelCase     (				lowerCAmelCase__							:				List[Any]  ):



 for name, mod in model.named_modules():
  if hasattr(lowerCAmelCase__  ,   '''_weight_quantizer'''  ):
   if not hasattr(mod.weight_quantizer  ,   '''_amax'''  ):
    print('''RECALIB: {name:{name_width}} WARNING: NO AMAX BUFFER'''  )
    continue

   # determine which axes to reduce across
   # e.g. a 4D tensor quantized per axis 0 should reduce over (1,2,3)
   __a :  Union[str, Any]						=  set() if mod._weight_quantizer.axis is None else set(mod._weight_quantizer.axis  )
   __a :  Union[str, Any]						=  set(range(len(mod.weight.size()  )  )  ) - axis_set
   __a :  Tuple						=  pytorch_quantization.utils.reduce_amax(mod.weight  ,   axis=lowerCAmelCase__  ,   keepdims=lowerCAmelCase__  ).detach()
   logger.info(f"RECALIB: {name:{name_width}} {mod._weight_quantizer._amax.flatten()} -> {amax.flatten()}"  )
   __a :  Union[str, Any]						=  amax




def    __UpperCamelCase     (				lowerCAmelCase__							:				List[Any]  ,   lowerCAmelCase__							:				List[Any]=2_5  ,   lowerCAmelCase__							:				List[str]=1_8_0  ,   lowerCAmelCase__							:				Optional[int]=None  ):



 if ignore is None:
  __a :  Dict						=  []
 elif not isinstance(lowerCAmelCase__  ,   lowerCAmelCase__  ):
  __a :  List[Any]						=  [ignore]

 __a :  Optional[int]						=  0
 for name, mod in model.named_modules():
  if not hasattr(lowerCAmelCase__  ,   '''weight'''  ):
   continue
  __a :  Optional[Any]						=  max(lowerCAmelCase__  ,   len(lowerCAmelCase__  )  )

 for name, mod in model.named_modules():
  __a :  Optional[int]						=  getattr(lowerCAmelCase__  ,   '''_input_quantizer'''  ,   lowerCAmelCase__  )
  __a :  List[Any]						=  getattr(lowerCAmelCase__  ,   '''_weight_quantizer'''  ,   lowerCAmelCase__  )
  if not hasattr(lowerCAmelCase__  ,   '''weight'''  ):
   continue
  if type(lowerCAmelCase__  ) in ignore:
   continue
  if [True for s in ignore if type(lowerCAmelCase__  ) is str and s in name]:
   continue
  __a :  str						=  f"Act:{input_q.extra_repr()}"
  __a :  str						=  f"Wgt:{weight_q.extra_repr()}"
  __a :  Optional[int]						=  f"{name:{name_width}} {act_str} {wgt_str}"
  if len(lowerCAmelCase__  ) <= line_width:
   logger.info(lowerCAmelCase__  )
  else:
   logger.info(f"{name:{name_width}} {act_str}"  )
   logger.info(f"{'  ':{name_width}} {wgt_str}"  )




def    __UpperCamelCase     (				lowerCAmelCase__							:				Tuple  ):
 __a :  Union[str, Any]						=  0
 for name, mod in model.named_modules():
  if isinstance(lowerCAmelCase__  ,   pytorch_quantization.nn.TensorQuantizer  ):
   print(f"{name:80} {mod}"  )
   count += 1
 print(f"{count} TensorQuantizers found in model"  )




def    __UpperCamelCase     (				lowerCAmelCase__							:				int  ,   lowerCAmelCase__							:				Tuple  ,   lowerCAmelCase__							:				Optional[Any]  ,   lowerCAmelCase__							:				Optional[Any]  ,   lowerCAmelCase__							:				Optional[int]  ):
 __a :  Optional[Any]						=  getattr(lowerCAmelCase__  ,   lowerCAmelCase__  ,   lowerCAmelCase__  )
 if quantizer_mod is not None:
  assert hasattr(lowerCAmelCase__  ,   lowerCAmelCase__  )
  setattr(lowerCAmelCase__  ,   lowerCAmelCase__  ,   lowerCAmelCase__  )
 else:
  logger.warning(f"{name} has no {quantizer}"  )




def    __UpperCamelCase     (				lowerCAmelCase__							:				Dict  ,   lowerCAmelCase__							:				Union[str, Any]  ,   lowerCAmelCase__							:				Any="both"  ,   **lowerCAmelCase__							:				Any  ):
 __a :  int						=  f"Warning: changing {which} quantizers of {name:{qname_width}}"
 for k, v in kwargs.items():
  s += f" {k}={v}"
  if which in ["input", "both"]:
   set_quantizer(lowerCAmelCase__  ,   lowerCAmelCase__  ,   '''_input_quantizer'''  ,   lowerCAmelCase__  ,   lowerCAmelCase__  )
  if which in ["weight", "both"]:
   set_quantizer(lowerCAmelCase__  ,   lowerCAmelCase__  ,   '''_weight_quantizer'''  ,   lowerCAmelCase__  ,   lowerCAmelCase__  )
 logger.info(lowerCAmelCase__  )




def    __UpperCamelCase     (				lowerCAmelCase__							:				Tuple  ,   lowerCAmelCase__							:				int  ,   **lowerCAmelCase__							:				List[Any]  ):



 for name, mod in model.named_modules():
  if hasattr(lowerCAmelCase__  ,   '''_input_quantizer'''  ) or hasattr(lowerCAmelCase__  ,   '''_weight_quantizer'''  ):
   for n in names:
    if re.search(lowerCAmelCase__  ,   lowerCAmelCase__  ):
     set_quantizers(lowerCAmelCase__  ,   lowerCAmelCase__  ,   **lowerCAmelCase__  )
  elif name.endswith('''_quantizer'''  ):
   for n in names:
    if re.search(lowerCAmelCase__  ,   lowerCAmelCase__  ):
     __a :  Tuple						=  f"Warning: changing {name:{name_width}}"
     for k, v in kwargs.items():
      s += f" {k}={v}"
      setattr(lowerCAmelCase__  ,   lowerCAmelCase__  ,   lowerCAmelCase__  )
     logger.info(lowerCAmelCase__  )






from typing import TYPE_CHECKING

from ...utils import (
    OptionalDependencyNotAvailable,
    _LazyModule,
    is_flax_available,
    is_tf_available,
    is_tokenizers_available,
    is_torch_available,
)


lowerCamelCase				:		Optional[Any]     =   {
    "configuration_whisper": ["WHISPER_PRETRAINED_CONFIG_ARCHIVE_MAP", "WhisperConfig", "WhisperOnnxConfig"],
    "feature_extraction_whisper": ["WhisperFeatureExtractor"],
    "processing_whisper": ["WhisperProcessor"],
    "tokenization_whisper": ["WhisperTokenizer"],
}

try:
 if not is_tokenizers_available():
  raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
 pass
else:
 lowerCamelCase				:		Tuple     =   ["WhisperTokenizerFast"]

try:
 if not is_torch_available():
  raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
 pass
else:
 lowerCamelCase				:		str     =   [
     "WHISPER_PRETRAINED_MODEL_ARCHIVE_LIST",
     "WhisperForConditionalGeneration",
     "WhisperModel",
     "WhisperPreTrainedModel",
     "WhisperForAudioClassification",
 ]

try:
 if not is_tf_available():
  raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
 pass
else:
 lowerCamelCase				:		List[str]     =   [
     "TF_WHISPER_PRETRAINED_MODEL_ARCHIVE_LIST",
     "TFWhisperForConditionalGeneration",
     "TFWhisperModel",
     "TFWhisperPreTrainedModel",
 ]

try:
 if not is_flax_available():
  raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
 pass
else:
 lowerCamelCase				:		str     =   [
     "FlaxWhisperForConditionalGeneration",
     "FlaxWhisperModel",
     "FlaxWhisperPreTrainedModel",
     "FlaxWhisperForAudioClassification",
 ]


if TYPE_CHECKING:
 from .configuration_whisper import WHISPER_PRETRAINED_CONFIG_ARCHIVE_MAP, WhisperConfig, WhisperOnnxConfig
 from .feature_extraction_whisper import WhisperFeatureExtractor
 from .processing_whisper import WhisperProcessor
 from .tokenization_whisper import WhisperTokenizer

 try:
  if not is_tokenizers_available():
   raise OptionalDependencyNotAvailable()
 except OptionalDependencyNotAvailable:
  pass
 else:
  from .tokenization_whisper_fast import WhisperTokenizerFast

 try:
  if not is_torch_available():
   raise OptionalDependencyNotAvailable()
 except OptionalDependencyNotAvailable:
  pass
 else:
  from .modeling_whisper import (
      WHISPER_PRETRAINED_MODEL_ARCHIVE_LIST,
      WhisperForAudioClassification,
      WhisperForConditionalGeneration,
      WhisperModel,
      WhisperPreTrainedModel,
  )

 try:
  if not is_tf_available():
   raise OptionalDependencyNotAvailable()
 except OptionalDependencyNotAvailable:
  pass
 else:
  from .modeling_tf_whisper import (
      TF_WHISPER_PRETRAINED_MODEL_ARCHIVE_LIST,
      TFWhisperForConditionalGeneration,
      TFWhisperModel,
      TFWhisperPreTrainedModel,
  )

 try:
  if not is_flax_available():
   raise OptionalDependencyNotAvailable()
 except OptionalDependencyNotAvailable:
  pass
 else:
  from .modeling_flax_whisper import (
      FlaxWhisperForAudioClassification,
      FlaxWhisperForConditionalGeneration,
      FlaxWhisperModel,
      FlaxWhisperPreTrainedModel,
  )

else:
 import sys

 lowerCamelCase				:		Tuple     =   _LazyModule(__name__, globals()["__file__"], _import_structure, module_spec=__spec__)



