






"""simple docstring"""




import logging
import os

import quant_trainer
import torch
from torch.utils.data import DataLoader

from transformers import Trainer, is_torch_tpu_available
from transformers.trainer_utils import PredictionOutput


UpperCamelCase							       =    logging.getLogger(__name__)

if is_torch_tpu_available(check_device=False):
     import torch_xla.core.xla_model as xm
     import torch_xla.debug.metrics as met




class    lowercase_    (_UpperCAmelCase     ):






      def __init__(    self     ,     *a_     ,     a_=None     ,     a_=None     ,     a_=None     ,     **a_	)	->Tuple:







        '''simple docstring'''


        super().__init__(*UpperCAmelCase__     ,     **UpperCAmelCase__	)
        _a							=							eval_examples
        _a							=							post_process_function
        _a							=							quant_trainer_args
        _a							=							1_2_8  # default number of calibration samples






      def 			lowerCamelCase__    (    self     ,     a_=None	)	->Union[str, Any]:







        '''simple docstring'''


        if calib_dataset is None and self.calib_dataset is None:
          raise ValueError("Trainer: calibration requires an calib_dataset."	)
        _a							=							calib_dataset if calib_dataset is not None else self.calib_dataset

        _a							=							self._remove_unused_columns(UpperCAmelCase__     ,     description="Calibration"	)

        return DataLoader(
            UpperCAmelCase__     ,     batch_size=self.args.eval_batch_size     ,     collate_fn=self.data_collator     ,     drop_last=self.args.dataloader_drop_last     ,     num_workers=self.args.dataloader_num_workers     ,     pin_memory=self.args.dataloader_pin_memory     ,     shuffle=UpperCAmelCase__     ,     )






      def 			lowerCamelCase__    (    self     ,     a_=None	)	->Any:







        '''simple docstring'''


        _a							=							self.train_dataset if calib_dataset is None else calib_dataset
        _a							=							self.get_calib_dataloader(UpperCAmelCase__	)

        _a							=							self.model
        quant_trainer.configure_model(UpperCAmelCase__     ,     self.quant_trainer_args     ,     calib=UpperCAmelCase__	)
        model.eval()
        quant_trainer.enable_calibration(UpperCAmelCase__	)

        logger.info("***** Running calibration *****"	)
        logger.info(f'''  Num examples = {self.calib_num}'''	)
        logger.info(f'''  Batch size = {calib_dataloader.batch_size}'''	)

        for step, inputs in enumerate(UpperCAmelCase__	):
          # Prediction step
          _a			,	_a			,	_a							=							self.prediction_step(UpperCAmelCase__     ,     UpperCAmelCase__     ,     prediction_loss_only=UpperCAmelCase__	)
          if (step + 1) * calib_dataloader.batch_size >= self.calib_num:
            break

        quant_trainer.finish_calibration(UpperCAmelCase__     ,     self.quant_trainer_args	)
        _a							=							model






      def 			lowerCamelCase__    (    self     ,     a_=None     ,     a_=None     ,     a_=None     ,     a_ = "eval"	)	->List[str]:







        '''simple docstring'''


        _a							=							self.eval_dataset if eval_dataset is None else eval_dataset
        _a							=							self.get_eval_dataloader(UpperCAmelCase__	)
        _a							=							self.eval_examples if eval_examples is None else eval_examples

        # Temporarily disable metric computation, we will do it in the loop here.
        _a							=							self.compute_metrics
        _a							=							None
        _a							=							self.prediction_loop if self.args.use_legacy_prediction_loop else self.evaluation_loop
        try:
          _a							=							eval_loop(
              UpperCAmelCase__     ,     description="Evaluation"     ,     prediction_loss_only=True if compute_metrics is None else None     ,     ignore_keys=UpperCAmelCase__     ,     )
        finally:
          _a							=							compute_metrics

        if self.post_process_function is not None and self.compute_metrics is not None:
          _a							=							self.post_process_function(UpperCAmelCase__     ,     UpperCAmelCase__     ,     output.predictions	)
          _a							=							self.compute_metrics(UpperCAmelCase__	)

          # Prefix all keys with metric_key_prefix + '_'
          for key in list(metrics.keys()	):
            if not key.startswith(f'''{metric_key_prefix}_'''	):
              _a							=							metrics.pop(UpperCAmelCase__	)

          self.log(UpperCAmelCase__	)
        else:
          _a							=							{}

        if self.args.tpu_metrics_debug or self.args.debug:
          # tpu-comment: Logging debug metrics for PyTorch/XLA (compile, execute times, ops, etc.)
          xm.master_print(met.metrics_report()	)

        _a							=							self.callback_handler.on_evaluate(self.args     ,     self.state     ,     self.control     ,     UpperCAmelCase__	)
        return metrics






      def 			lowerCamelCase__    (    self     ,     a_     ,     a_     ,     a_=None     ,     a_ = "test"	)	->Dict:







        '''simple docstring'''


        _a							=							self.get_test_dataloader(UpperCAmelCase__	)

        # Temporarily disable metric computation, we will do it in the loop here.
        _a							=							self.compute_metrics
        _a							=							None
        _a							=							self.prediction_loop if self.args.use_legacy_prediction_loop else self.evaluation_loop
        try:
          _a							=							eval_loop(
              UpperCAmelCase__     ,     description="Prediction"     ,     prediction_loss_only=True if compute_metrics is None else None     ,     ignore_keys=UpperCAmelCase__     ,     )
        finally:
          _a							=							compute_metrics

        if self.post_process_function is None or self.compute_metrics is None:
          return output

        _a							=							self.post_process_function(UpperCAmelCase__     ,     UpperCAmelCase__     ,     output.predictions     ,     "predict"	)
        _a							=							self.compute_metrics(UpperCAmelCase__	)

        # Prefix all keys with metric_key_prefix + '_'
        for key in list(metrics.keys()	):
          if not key.startswith(f'''{metric_key_prefix}_'''	):
            _a							=							metrics.pop(UpperCAmelCase__	)

        return PredictionOutput(predictions=predictions.predictions     ,     label_ids=predictions.label_ids     ,     metrics=UpperCAmelCase__	)






      def 			lowerCamelCase__    (    self     ,     a_="./"	)	->List[str]:







        '''simple docstring'''


        _a							=							self.eval_dataset
        _a							=							self.get_eval_dataloader(UpperCAmelCase__	)

        _a							=							next(iter(UpperCAmelCase__	)	)

        # saving device - to make it consistent
        _a							=							torch.device("cuda" if torch.cuda.is_available() else "cpu"	)

        # convert to tuple
        _a							=							tuple(v.to(UpperCAmelCase__	) for k, v in batch.items()	)

        logger.info("Converting model to be onnx compatible"	)
        from pytorch_quantization.nn import TensorQuantizer

        _a							=							True

        _a							=							self.model.to(UpperCAmelCase__	)

        model.eval()
        model.float()

        _a							=							model.module if hasattr(UpperCAmelCase__     ,     "module"	) else model
        quant_trainer.configure_model(UpperCAmelCase__     ,     self.quant_trainer_args	)

        _a							=							os.path.join(UpperCAmelCase__     ,     "model.onnx"	)
        logger.info(f'''exporting model to {output_model_file}'''	)

        _a							=							{0: "batch_size", 1: "seq_len"}

        torch.onnx.export(
            UpperCAmelCase__     ,     UpperCAmelCase__     ,     UpperCAmelCase__     ,     export_params=UpperCAmelCase__     ,     opset_version=1_3     ,     do_constant_folding=UpperCAmelCase__     ,     input_names=["input_ids", "attention_mask", "token_type_ids"]     ,     output_names=["output_start_logits", "output_end_logits"]     ,     dynamic_axes={
                "input_ids": axes,
                "attention_mask": axes,
                "token_type_ids": axes,
                "output_start_logits": axes,
                "output_end_logits": axes,
            }     ,     verbose=UpperCAmelCase__     ,     )
        logger.info("onnx export finished"	)










"""simple docstring"""




import argparse
import json
import os
from collections import OrderedDict

import numpy as np
import tensorflow as tf
import torch






def        lowerCAmelCase (      UpperCamelCase_:							Dict					)       ->							Any:







  '''simple docstring'''







  _a							=	os.path.join(args.tf_model_dir     , "parameters.json"					)
  _a							=	json.loads(open(UpperCamelCase_					).read()					)
  if not params:
    raise ValueError(
        f'''It seems that the json file at {parameter_file} is empty. Make sure you have a correct json file.'''					)
  if not args.output.endswith(".pt"					):
    _a							=	args.output + ".pt"
  _a							=	OrderedDict()
  with tf.device("/CPU:0"					):
    _a							=	tf.train.load_checkpoint(args.tf_model_dir					)
    _a							=	reader.get_variable_to_shape_map()
    for key_name in shapes.keys():
      _a							=	reader.get_tensor(UpperCamelCase_					).astype(np.floataa					)
      if key_name.endswith("/adam_m"					) or key_name.endswith("/adam_v"					):
        continue
      if key_name.startswith("pasts/"					):
        if key_name.startswith("pasts/mlp"					):
          _a							=	int(key_name[9]					)
        elif key_name.startswith("pasts/out"					):
          _a							=	8
        _a							=	"model.sqout.%d.weight" % (player * 2)  # enter to nn.Sequencial with Tanh, so 2 at a time
        _a							=	vnp.transpose([1, 0]					).copy()  # Mesh-Tensorflow is a diagonal matrix
        _a							=	torch.tensor(UpperCamelCase_					)
      elif key_name.startswith("model/moe"					):
        _a							=	int(key_name[9:].split("/"					)[0]					)
        if key_name.endswith("/switch_gating/kernel"					):
          _a							=	"model.blocks.%d.feed_forward.mlp.router.classifier.weight" % player
          _a							=	vnp.transpose([1, 0]					).copy()  # Mesh-Tensorflow is a diagonal matrix
          _a							=	torch.tensor(UpperCamelCase_					)
        elif key_name.endswith("/softmlp/kernel"					):
          _a							=	"model.blocks.%d.feed_forward.soft_bypass_mlp.weight" % player
          _a							=	vnp.transpose([1, 0]					).copy()  # Mesh-Tensorflow is a diagonal matrix
          _a							=	torch.tensor(UpperCamelCase_					)
        elif key_name.endswith("/wo/kernel"					) or key_name.endswith("/wi/kernel"					):
          _a							=	key_name[-9:-7]
          for i in range(16					):
            _a							=	"model.blocks.%d.feed_forward.mlp.experts.expert_%d.%s.weight" % (player, i, nlayer)
            _a							=	(
                vnp[i].transpose([1, 0]					).copy()
            )  # In Mesh-Tensorflow, it is one array, so it is divided
            _a							=	torch.tensor(UpperCamelCase_					)
      elif key_name.startswith("model/mlp"					):
        _a							=	int(key_name[9:].split("/"					)[0]					)
        if key_name.endswith("/p1/kernel"					):
          _a							=	"model.blocks.%d.feed_forward.mlp.wi.weight" % player
          _a							=	vnp.transpose([1, 0]					).copy()  # Mesh-Tensorflow is a diagonal matrix
          _a							=	torch.tensor(UpperCamelCase_					)
        elif key_name.endswith("/p1/bias"					):
          _a							=	"model.blocks.%d.feed_forward.mlp.wi.bias" % player
          _a							=	vnp.copy()  # same because it is one dimensional
          _a							=	torch.tensor(UpperCamelCase_					)
        elif key_name.endswith("/p2/kernel"					):
          _a							=	"model.blocks.%d.feed_forward.mlp.wo.weight" % player
          _a							=	vnp.transpose([1, 0]					).copy()  # Mesh-Tensorflow is a diagonal matrix
          _a							=	torch.tensor(UpperCamelCase_					)
        elif key_name.endswith("/p2/bias"					):
          _a							=	"model.blocks.%d.feed_forward.mlp.wo.bias" % player
          _a							=	vnp.copy()  # same because it is one dimensional
          _a							=	torch.tensor(UpperCamelCase_					)
      elif key_name.startswith("model/ln"					):
        _a							=	int(key_name[8:].split("/"					)[0]					)
        if key_name.endswith("/b"					):
          _a							=	"model.blocks.%d.feed_forward.norm.bias" % player
          _a							=	vnp.copy()  # same because it is one dimensional
          _a							=	torch.tensor(UpperCamelCase_					)
        elif key_name.endswith("/g"					):
          _a							=	"model.blocks.%d.feed_forward.norm.weight" % player
          _a							=	vnp.copy()  # same because it is one dimensional
          _a							=	torch.tensor(UpperCamelCase_					)
      elif key_name.startswith("model/att"					):
        _a							=	int(key_name[9:].split("/"					)[0]					)
        if key_name.endswith("/qkv/kernel"					):
          _a							=	vnp.copy()  # Compute same dimension as Mesh-tensorflow using einsum
          _a							=	state[:, 0, :, :]
          _a							=	state[:, 1, :, :]
          _a							=	state[:, 2, :, :]
          _a							=	(
              state_q.reshape([state_q.shape[0], state_q.shape[1] * state_q.shape[2]]					)
              .transpose([1, 0]					)
              .copy()
          )  # Mesh-Tensorflow is a diagonal matrix
          _a							=	(
              state_k.reshape([state_k.shape[0], state_k.shape[1] * state_k.shape[2]]					)
              .transpose([1, 0]					)
              .copy()
          )  # Mesh-Tensorflow is a diagonal matrix
          _a							=	(
              state_v.reshape([state_v.shape[0], state_v.shape[1] * state_v.shape[2]]					)
              .transpose([1, 0]					)
              .copy()
          )  # Mesh-Tensorflow is a diagonal matrix
          _a							=	"model.blocks.%d.self_attn.self_attn.q_proj.weight" % player
          _a							=	torch.tensor(UpperCamelCase_					)
          _a							=	"model.blocks.%d.self_attn.self_attn.k_proj.weight" % player
          _a							=	torch.tensor(UpperCamelCase_					)
          _a							=	"model.blocks.%d.self_attn.self_attn.v_proj.weight" % player
          _a							=	torch.tensor(UpperCamelCase_					)
        elif key_name.endswith("/o/kernel"					):
          _a							=	"model.blocks.%d.self_attn.self_attn.out_proj.weight" % player
          _a							=	(
              vnp.reshape([vnp.shape[0] * vnp.shape[1], vnp.shape[2]]					).transpose([1, 0]					).copy()
          )  # Mesh-Tensorflow is a diagonal matrix
          _a							=	torch.tensor(UpperCamelCase_					)
      elif key_name.startswith("model/an"					):
        _a							=	int(key_name[8:].split("/"					)[0]					)
        if key_name.endswith("/b"					):
          _a							=	"model.blocks.%d.self_attn.norm.bias" % player
          _a							=	vnp.copy()  # same because it is one dimensional
          _a							=	torch.tensor(UpperCamelCase_					)
        elif key_name.endswith("/g"					):
          _a							=	"model.blocks.%d.self_attn.norm.weight" % player
          _a							=	vnp.copy()  # same because it is one dimensional
          _a							=	torch.tensor(UpperCamelCase_					)
      elif (
          key_name.startswith("model/wte"					)
          or key_name.startswith("model/wpe"					)
          or key_name.startswith("model/ete"					)
      ):
        _a							=	{"wte": "embed_tokens", "wpe": "position_embeddings", "ete": "extra_position_embeddings"}[
            key_name[-3:]
        ]
        _a							=	"model.%s.weight" % nlayer
        _a							=	vnp.copy()  # same in embedded
        _a							=	torch.tensor(UpperCamelCase_					)
        if key_name.startswith("model/wte"					):
          _a							=	"lm_head.weight"
          _a							=	vnp.copy()  # same in embedded
          _a							=	torch.tensor(UpperCamelCase_					)
      elif key_name.startswith("model/wob"					):
        _a							=	"final_logits_bias"
        _a							=	vnp.copy()  # same in embedded
        _a							=	state.reshape((1, -1)					)
        _a							=	torch.tensor(UpperCamelCase_					)
      elif key_name == "model/dense/kernel":
        _a							=	"model.last_project.weight"
        _a							=	vnp.transpose([1, 0]					).copy()  # Mesh-Tensorflow is a diagonal matrix
        _a							=	torch.tensor(UpperCamelCase_					)
      elif key_name == "model/dense_1/bias":
        _a							=	"model.last_project.bias"
        _a							=	vnp.copy()  # same because it is one dimensional
        _a							=	torch.tensor(UpperCamelCase_					)
  torch.save(UpperCamelCase_     , args.output					)


if __name__ == "__main__":
     UpperCamelCase							       =    argparse.ArgumentParser(
         description="""model converter.""", formatter_class=argparse.ArgumentDefaultsHelpFormatter
     )
     parser.add_argument("""--tf_model_dir""", metavar="""PATH""", type=str, required=True, help="""import model""")
     parser.add_argument("""--output""", metavar="""PATH""", type=str, required=True, help="""output model""")
     UpperCamelCase							       =    parser.parse_args()
     convert_tf_gptsan_to_pt(args)


