

import argparse
import os

import gluonnlp as nlp
import mxnet as mx
import numpy as np
import torch
from gluonnlp.base import get_home_dir
from gluonnlp.model.bert import BERTEncoder
from gluonnlp.model.utils import _load_vocab
from gluonnlp.vocab import Vocab
from packaging import version
from torch import nn

from transformers import BertConfig, BertForMaskedLM, BertModel, RobertaTokenizer
from transformers.models.bert.modeling_bert import (
    BertIntermediate,
    BertLayer,
    BertOutput,
    BertSelfAttention,
    BertSelfOutput,
)
from transformers.utils import logging


if version.parse(nlp.__version__) != version.parse('''0.8.3'''):
       raise Exception('''requires gluonnlp == 0.8.3''')

if version.parse(mx.__version__) != version.parse('''1.5.0'''):
       raise Exception('''requires mxnet == 1.5.0''')

logging.set_verbosity_info()
lowerCamelCase           =					logging.get_logger(__name__)

lowerCamelCase           =					'''The Nymphenburg Palace is a beautiful palace in Munich!'''




def 			UpperCAmelCase__				(			_A      : str	,      _A      : str							):





  '''simple docstring'''







  a__  ={
      """attention_cell""": """multi_head""",
      """num_layers""": 4,
      """units""": 10_24,
      """hidden_size""": 7_68,
      """max_length""": 5_12,
      """num_heads""": 8,
      """scaled""": True,
      """dropout""": 0.1,
      """use_residual""": True,
      """embed_size""": 10_24,
      """embed_dropout""": 0.1,
      """word_embed""": None,
      """layer_norm_eps""": 1E-5,
      """token_type_vocab_size""": 2,
  }

  a__  =bort_4_8_768_1024_hparams

  # Let's construct the original Bort model here
  # Taken from official BERT implementation, see:
  # https://github.com/alexa/bort/blob/master/bort/bort.py
  a__  =BERTEncoder(
      attention_cell=predefined_args['''attention_cell''']	,      num_layers=predefined_args['''num_layers''']	,      units=predefined_args['''units''']	,      hidden_size=predefined_args['''hidden_size''']	,      max_length=predefined_args['''max_length''']	,      num_heads=predefined_args['''num_heads''']	,      scaled=predefined_args['''scaled''']	,      dropout=predefined_args['''dropout''']	,      output_attention=lowerCAmelCase_	,      output_all_encodings=lowerCAmelCase_	,      use_residual=predefined_args['''use_residual''']	,      activation=predefined_args.get('''activation'''	,      '''gelu'''							)	,      layer_norm_eps=predefined_args.get('''layer_norm_eps'''	,      lowerCAmelCase_							)	,      )

  # Vocab information needs to be fetched first
  # It's the same as RoBERTa, so RobertaTokenizer can be used later
  a__  ="""openwebtext_ccnews_stories_books_cased"""

  # Specify download folder to Gluonnlp's vocab
  a__  =os.path.join(get_home_dir()	,      '''models'''							)
  a__  =_load_vocab(lowerCAmelCase_	,      lowerCAmelCase_	,      lowerCAmelCase_	,      cls=lowerCAmelCase_							)

  a__  =nlp.model.BERTModel(
      lowerCAmelCase_	,      len(lowerCAmelCase_							)	,      units=predefined_args['''units''']	,      embed_size=predefined_args['''embed_size''']	,      embed_dropout=predefined_args['''embed_dropout''']	,      word_embed=predefined_args['''word_embed''']	,      use_pooler=lowerCAmelCase_	,      use_token_type_embed=lowerCAmelCase_	,      token_type_vocab_size=predefined_args['''token_type_vocab_size''']	,      use_classifier=lowerCAmelCase_	,      use_decoder=lowerCAmelCase_	,      )

  original_bort.load_parameters(lowerCAmelCase_	,      cast_dtype=lowerCAmelCase_	,      ignore_extra=lowerCAmelCase_							)
  a__  =original_bort._collect_params_with_prefix()

  # Build our config 🤗
  a__  ={
      """architectures""": ["""BertForMaskedLM"""],
      """attention_probs_dropout_prob""": predefined_args["""dropout"""],
      """hidden_act""": """gelu""",
      """hidden_dropout_prob""": predefined_args["""dropout"""],
      """hidden_size""": predefined_args["""embed_size"""],
      """initializer_range""": 0.02,
      """intermediate_size""": predefined_args["""hidden_size"""],
      """layer_norm_eps""": predefined_args["""layer_norm_eps"""],
      """max_position_embeddings""": predefined_args["""max_length"""],
      """model_type""": """bort""",
      """num_attention_heads""": predefined_args["""num_heads"""],
      """num_hidden_layers""": predefined_args["""num_layers"""],
      """pad_token_id""": 1,  # 2 = BERT, 1 = RoBERTa
      """type_vocab_size""": 1,  # 2 = BERT, 1 = RoBERTa
      """vocab_size""": len(lowerCAmelCase_							),
  }

  a__  =BertConfig.from_dict(lowerCAmelCase_							)
  a__  =BertForMaskedLM(lowerCAmelCase_							)
  hf_bort_model.eval()

  # Parameter mapping table (Gluonnlp to Transformers)
  # * denotes layer index
  #
  # | Gluon Parameter                                                | Transformers Parameter
  # | -------------------------------------------------------------- | ----------------------
  # | `encoder.layer_norm.beta`                                      | `bert.embeddings.LayerNorm.bias`
  # | `encoder.layer_norm.gamma`                                     | `bert.embeddings.LayerNorm.weight`
  # | `encoder.position_weight`                                      | `bert.embeddings.position_embeddings.weight`
  # | `word_embed.0.weight`                                          | `bert.embeddings.word_embeddings.weight`
  # | `encoder.transformer_cells.*.attention_cell.proj_key.bias`     | `bert.encoder.layer.*.attention.self.key.bias`
  # | `encoder.transformer_cells.*.attention_cell.proj_key.weight`   | `bert.encoder.layer.*.attention.self.key.weight`
  # | `encoder.transformer_cells.*.attention_cell.proj_query.bias`   | `bert.encoder.layer.*.attention.self.query.bias`
  # | `encoder.transformer_cells.*.attention_cell.proj_query.weight` | `bert.encoder.layer.*.attention.self.query.weight`
  # | `encoder.transformer_cells.*.attention_cell.proj_value.bias`   | `bert.encoder.layer.*.attention.self.value.bias`
  # | `encoder.transformer_cells.*.attention_cell.proj_value.weight` | `bert.encoder.layer.*.attention.self.value.weight`
  # | `encoder.transformer_cells.*.ffn.ffn_2.bias`                   | `bert.encoder.layer.*.attention.output.dense.bias`
  # | `encoder.transformer_cells.*.ffn.ffn_2.weight`                 | `bert.encoder.layer.*.attention.output.dense.weight`
  # | `encoder.transformer_cells.*.layer_norm.beta`                  | `bert.encoder.layer.*.attention.output.LayerNorm.bias`
  # | `encoder.transformer_cells.*.layer_norm.gamma`                 | `bert.encoder.layer.*.attention.output.LayerNorm.weight`
  # | `encoder.transformer_cells.*.ffn.ffn_1.bias`                   | `bert.encoder.layer.*.intermediate.dense.bias`
  # | `encoder.transformer_cells.*.ffn.ffn_1.weight`                 | `bert.encoder.layer.*.intermediate.dense.weight`
  # | `encoder.transformer_cells.*.ffn.layer_norm.beta`              | `bert.encoder.layer.*.output.LayerNorm.bias`
  # | `encoder.transformer_cells.*.ffn.layer_norm.gamma`             | `bert.encoder.layer.*.output.LayerNorm.weight`
  # | `encoder.transformer_cells.*.proj.bias`                        | `bert.encoder.layer.*.output.dense.bias`
  # | `encoder.transformer_cells.*.proj.weight`                      | `bert.encoder.layer.*.output.dense.weight`

  # Helper function to convert MXNET Arrays to PyTorch
  def to_torch(_A      : int							) -> nn.Parameter:
    return nn.Parameter(torch.FloatTensor(mx_array.data().asnumpy()							)							)

  # Check param shapes and map new HF param back
  def check_and_map_params(_A      : str	,      _A      : Optional[Any]							):
    a__  =hf_param.shape

    a__  =to_torch(params[gluon_param]							)
    a__  =gluon_param.shape

    assert (
        shape_hf == shape_gluon
    ), F"""The gluon parameter {gluon_param} has shape {shape_gluon}, but expects shape {shape_hf} for Transformers"""

    return gluon_param

  a__  =check_and_map_params(
      hf_bort_model.bert.embeddings.word_embeddings.weight	,      '''word_embed.0.weight'''							)
  a__  =check_and_map_params(
      hf_bort_model.bert.embeddings.position_embeddings.weight	,      '''encoder.position_weight'''							)
  a__  =check_and_map_params(
      hf_bort_model.bert.embeddings.LayerNorm.bias	,      '''encoder.layer_norm.beta'''							)
  a__  =check_and_map_params(
      hf_bort_model.bert.embeddings.LayerNorm.weight	,      '''encoder.layer_norm.gamma'''							)

  # Inspired by RoBERTa conversion script, we just zero them out (Bort does not use them)
  a__  =torch.zeros_like(
      hf_bort_model.bert.embeddings.token_type_embeddings.weight.data							)

  for i in range(hf_bort_config.num_hidden_layers							):
    a__  =hf_bort_model.bert.encoder.layer[i]

    # self attention
    a__  =layer.attention.self

    a__  =check_and_map_params(
        self_attn.key.bias.data	,      F"""encoder.transformer_cells.{i}.attention_cell.proj_key.bias"""							)

    a__  =check_and_map_params(
        self_attn.key.weight.data	,      F"""encoder.transformer_cells.{i}.attention_cell.proj_key.weight"""							)
    a__  =check_and_map_params(
        self_attn.query.bias.data	,      F"""encoder.transformer_cells.{i}.attention_cell.proj_query.bias"""							)
    a__  =check_and_map_params(
        self_attn.query.weight.data	,      F"""encoder.transformer_cells.{i}.attention_cell.proj_query.weight"""							)
    a__  =check_and_map_params(
        self_attn.value.bias.data	,      F"""encoder.transformer_cells.{i}.attention_cell.proj_value.bias"""							)
    a__  =check_and_map_params(
        self_attn.value.weight.data	,      F"""encoder.transformer_cells.{i}.attention_cell.proj_value.weight"""							)

    # self attention output
    a__  =layer.attention.output

    a__  =check_and_map_params(
        self_output.dense.bias	,      F"""encoder.transformer_cells.{i}.proj.bias"""							)
    a__  =check_and_map_params(
        self_output.dense.weight	,      F"""encoder.transformer_cells.{i}.proj.weight"""							)
    a__  =check_and_map_params(
        self_output.LayerNorm.bias	,      F"""encoder.transformer_cells.{i}.layer_norm.beta"""							)
    a__  =check_and_map_params(
        self_output.LayerNorm.weight	,      F"""encoder.transformer_cells.{i}.layer_norm.gamma"""							)

    # intermediate
    a__  =layer.intermediate

    a__  =check_and_map_params(
        intermediate.dense.bias	,      F"""encoder.transformer_cells.{i}.ffn.ffn_1.bias"""							)
    a__  =check_and_map_params(
        intermediate.dense.weight	,      F"""encoder.transformer_cells.{i}.ffn.ffn_1.weight"""							)

    # output
    a__  =layer.output

    a__  =check_and_map_params(
        bert_output.dense.bias	,      F"""encoder.transformer_cells.{i}.ffn.ffn_2.bias"""							)
    a__  =check_and_map_params(
        bert_output.dense.weight	,      F"""encoder.transformer_cells.{i}.ffn.ffn_2.weight"""							)
    a__  =check_and_map_params(
        bert_output.LayerNorm.bias	,      F"""encoder.transformer_cells.{i}.ffn.layer_norm.beta"""							)
    a__  =check_and_map_params(
        bert_output.LayerNorm.weight	,      F"""encoder.transformer_cells.{i}.ffn.layer_norm.gamma"""							)

  # Save space and energy 🎄
  hf_bort_model.half()

  # Compare output of both models
  a__  =RobertaTokenizer.from_pretrained('''roberta-base'''							)

  a__  =tokenizer.encode_plus(lowerCAmelCase_							)["""input_ids"""]

  # Get gluon output
  a__  =mx.nd.array([input_ids]							)
  a__  =original_bort(inputs=lowerCAmelCase_	,      token_types=[]							)

  # Get Transformer output (save and reload model again)
  hf_bort_model.save_pretrained(lowerCAmelCase_							)
  a__  =BertModel.from_pretrained(lowerCAmelCase_							)
  hf_bort_model.eval()

  a__  =tokenizer.encode_plus(lowerCAmelCase_	,      return_tensors='''pt'''							)
  a__  =hf_bort_model(**lowerCAmelCase_							)[0]

  a__  =output_gluon[0].asnumpy()
  a__  =output_hf[0].detach().numpy()

  a__  =np.max(np.abs(hf_layer - gluon_layer							)							).item()
  a__  =np.allclose(lowerCAmelCase_	,      lowerCAmelCase_	,      atol=1E-3							)

  if success:
    print('''✔️ Both model do output the same tensors'''							)
  else:
    print('''❌ Both model do **NOT** output the same tensors'''							)
    print('''Absolute difference is:'''	,      lowerCAmelCase_							)


if __name__ == "__main__":
       lowerCamelCase           =					argparse.ArgumentParser()
       # Required parameters
       parser.add_argument(
           '''--bort_checkpoint_path''', default=None, type=str, required=True, help='''Path the official Bort params file.'''
       )
       parser.add_argument(
           '''--pytorch_dump_folder_path''', default=None, type=str, required=True, help='''Path to the output PyTorch model.'''
       )
       lowerCamelCase           =					parser.parse_args()
       convert_bort_checkpoint_to_pytorch(args.bort_checkpoint_path, args.pytorch_dump_folder_path)








# 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 re

from ..models.auto import AutoProcessor
from ..models.vision_encoder_decoder import VisionEncoderDecoderModel
from ..utils import is_vision_available
from .base import PipelineTool


if is_vision_available():
	from PIL import Image

class 						lowerCAmelCase   (       __a	):

					'''simple docstring'''

					_A  :	List[str]     =					'''naver-clova-ix/donut-base-finetuned-docvqa'''
					_A  :	Any     =					(
					    '''This is a tool that answers a question about an document (pdf). It takes an input named `document` which '''
					    '''should be the document containing the information, as well as a `question` that is the question about the '''
					    '''document. It returns a text that contains the answer to the question.'''
					)
					_A  :	Tuple     =					'''document_qa'''
					_A  :	Dict     =					AutoProcessor
					_A  :	Tuple     =					VisionEncoderDecoderModel

					_A  :	Optional[int]     =					['''image''', '''text''']
					_A  :	Optional[int]     =					['''text''']



					def __init__(     self :		Any						,   *__a :		List[str]						,   **__a :		Any							)	->     Optional[Any]:


												"""simple docstring"""

												if not is_vision_available():
																			raise ValueError("""Pillow must be installed to use the DocumentQuestionAnsweringTool."""							)

												super().__init__(*__a						,   **__a							)



					def 					lowerCAmelCase (     self :		List[Any]						,   __a :		"Image"						,   __a :		str							)	->     List[str]:


												"""simple docstring"""

												__lowercase					:							int			=   """<s_docvqa><s_question>{user_input}</s_question><s_answer>"""
												__lowercase					:							str			=   task_prompt.replace("""{user_input}"""						,   __a							)
												__lowercase					:							Union[str, Any]			=   self.pre_processor.tokenizer(
												    __a						,   add_special_tokens=__a						,   return_tensors="""pt"""							).input_ids
												__lowercase					:							int			=   self.pre_processor(__a						,   return_tensors="""pt"""							).pixel_values

												return {"decoder_input_ids": decoder_input_ids, "pixel_values": pixel_values}



					def 					lowerCAmelCase (     self :		Optional[int]						,   __a :		int							)	->     int:


												"""simple docstring"""

												return self.model.generate(
												    inputs["""pixel_values"""].to(self.device							)						,   decoder_input_ids=inputs["""decoder_input_ids"""].to(self.device							)						,   max_length=self.model.decoder.config.max_position_embeddings						,   early_stopping=__a						,   pad_token_id=self.pre_processor.tokenizer.pad_token_id						,   eos_token_id=self.pre_processor.tokenizer.eos_token_id						,   use_cache=__a						,   num_beams=1						,   bad_words_ids=[[self.pre_processor.tokenizer.unk_token_id]]						,   return_dict_in_generate=__a						,   ).sequences



					def 					lowerCAmelCase (     self :		Union[str, Any]						,   __a :		Union[str, Any]							)	->     Union[str, Any]:


												"""simple docstring"""

												__lowercase					:							Tuple			=   self.pre_processor.batch_decode(__a							)[0]
												__lowercase					:							int			=   sequence.replace(self.pre_processor.tokenizer.eos_token						,   """"""							)
												__lowercase					:							Union[str, Any]			=   sequence.replace(self.pre_processor.tokenizer.pad_token						,   """"""							)
												__lowercase					:							Optional[Any]			=   re.sub(r"""<.*?>"""						,   """"""						,   __a						,   count=1							).strip()  # remove first task start token
												__lowercase					:							Dict			=   self.pre_processor.tokenajson(__a							)

												return sequence["answer"]