




"""simple docstring"""

import argparse
import logging
from collections import namedtuple

import torch
from model_bertabs import BertAbsSummarizer
from models.model_builder import AbsSummarizer  # The authors' implementation

from transformers import BertTokenizer


logging.basicConfig(level=logging.INFO)
_lowerCamelCase  :			Any        =       logging.getLogger(__name__)


_lowerCamelCase  :			Dict        =       'Hello world! cécé herlolip'


_lowerCamelCase  :			Optional[Any]        =       namedtuple(
    'BertAbsConfig',
    [
        'temp_dir',
        'large',
        'use_bert_emb',
        'finetune_bert',
        'encoder',
        'share_emb',
        'max_pos',
        'enc_layers',
        'enc_hidden_size',
        'enc_heads',
        'enc_ff_size',
        'enc_dropout',
        'dec_layers',
        'dec_hidden_size',
        'dec_heads',
        'dec_ff_size',
        'dec_dropout',
    ],
)

def 		lowercase_      (		_UpperCAmelCase  ,      _UpperCAmelCase	):




	"""simple docstring"""






	A_  :				Union[str, Any]	   =		BertAbsConfig(
	    temp_dir='''.'''  ,      finetune_bert=_UpperCAmelCase  ,      large=_UpperCAmelCase  ,      share_emb=_UpperCAmelCase  ,      use_bert_emb=_UpperCAmelCase  ,      encoder='''bert'''  ,      max_pos=512  ,      enc_layers=6  ,      enc_hidden_size=512  ,      enc_heads=8  ,      enc_ff_size=512  ,      enc_dropout=0.2  ,      dec_layers=6  ,      dec_hidden_size=768  ,      dec_heads=8  ,      dec_ff_size=2048  ,      dec_dropout=0.2  ,      )
	A_  :				Tuple	   =		torch.load(_UpperCAmelCase  ,      lambda _UpperCAmelCase  ,      _UpperCAmelCase	: storage	)
	A_  :				Any	   =		AbsSummarizer(_UpperCAmelCase  ,      torch.device('''cpu'''	)  ,      _UpperCAmelCase	)
	original.eval()

	A_  :				Optional[int]	   =		BertAbsSummarizer(_UpperCAmelCase  ,      torch.device('''cpu'''	)	)
	new_model.eval()

	# -------------------
	# Convert the weights
	# -------------------

	logging.info('''convert the model'''	)
	new_model.bert.load_state_dict(original.bert.state_dict()	)
	new_model.decoder.load_state_dict(original.decoder.state_dict()	)
	new_model.generator.load_state_dict(original.generator.state_dict()	)

	# ----------------------------------
	# Make sure the outpus are identical
	# ----------------------------------

	logging.info('''Make sure that the models\' outputs are identical'''	)
	A_  :				List[str]	   =		BertTokenizer.from_pretrained('''bert-base-uncased'''	)

	# prepare the model inputs
	A_  :				Tuple	   =		tokenizer.encode('''This is sample éàalj\'-.'''	)
	encoder_input_ids.extend([tokenizer.pad_token_id] * (512 - len(_UpperCAmelCase	))	)
	A_  :				Tuple	   =		torch.tensor(_UpperCAmelCase	).unsqueeze(0	)
	A_  :				str	   =		tokenizer.encode('''This is sample 3 éàalj\'-.'''	)
	decoder_input_ids.extend([tokenizer.pad_token_id] * (512 - len(_UpperCAmelCase	))	)
	A_  :				Tuple	   =		torch.tensor(_UpperCAmelCase	).unsqueeze(0	)

	# failsafe to make sure the weights reset does not affect the
	# loaded weights.
	assert torch.max(torch.abs(original.generator[0].weight - new_model.generator[0].weight	)	) == 0

	# forward pass
	A_  :				Union[str, Any]	   =		encoder_input_ids
	A_  :				str	   =		decoder_input_ids
	A_  :				List[Any]	   =		None
	A_  :				Optional[int]	   =		None
	A_  :				Any	   =		None
	A_  :				List[Any]	   =		None
	A_  :				List[str]	   =		None

	# The original model does not apply the geneator layer immediatly but rather in
	# the beam search (where it combines softmax + linear layer). Since we already
	# apply the softmax in our generation process we only apply the linear layer here.
	# We make sure that the outputs of the full stack are identical
	A_  :				str	   =		original(_UpperCAmelCase  ,      _UpperCAmelCase  ,      _UpperCAmelCase  ,      _UpperCAmelCase  ,      _UpperCAmelCase  ,      _UpperCAmelCase  ,      _UpperCAmelCase	)[0]
	A_  :				List[str]	   =		original.generator(_UpperCAmelCase	)

	A_  :				int	   =		new_model(
	    _UpperCAmelCase  ,      _UpperCAmelCase  ,      _UpperCAmelCase  ,      _UpperCAmelCase  ,      _UpperCAmelCase	)[0]
	A_  :				Any	   =		new_model.generator(_UpperCAmelCase	)

	A_  :				Optional[Any]	   =		torch.max(torch.abs(output_converted_model - output_original_model	)	).item()
	print('''Maximum absolute difference beween weights: {:.2f}'''.format(_UpperCAmelCase	)	)
	A_  :				List[str]	   =		torch.max(torch.abs(output_converted_generator - output_original_generator	)	).item()
	print('''Maximum absolute difference beween weights: {:.2f}'''.format(_UpperCAmelCase	)	)

	A_  :				Any	   =		torch.allclose(_UpperCAmelCase  ,      _UpperCAmelCase  ,      atol=1E-3	)
	if are_identical:
		logging.info('''all weights are equal up to 1e-3'''	)
	else:
		raise ValueError('''the weights are different. The new model is likely different from the original one.'''	)

	# The model has been saved with torch.save(model) and this is bound to the exact
	# directory structure. We save the state_dict instead.
	logging.info('''saving the model\'s state dictionary'''	)
	torch.save(
	    new_model.state_dict()  ,      '''./bertabs-finetuned-cnndm-extractive-abstractive-summarization/pytorch_model.bin'''	)


if __name__ == "__main__":
		_lowerCamelCase  :			int        =       argparse.ArgumentParser()
		parser.add_argument(
		    '--bertabs_checkpoint_path',
		    default=None,
		    type=str,
		    required=True,
		    help='Path the official PyTorch dump.',
		)
		parser.add_argument(
		    '--pytorch_dump_folder_path',
		    default=None,
		    type=str,
		    required=True,
		    help='Path to the output PyTorch model.',
		)
		_lowerCamelCase  :			Any        =       parser.parse_args()

		convert_bertabs_checkpoints(
		    args.bertabs_checkpoint_path,
		    args.pytorch_dump_folder_path,
		)











"""simple docstring"""

from collections.abc import Generator
from math import sin

def 		lowercase_      (		_UpperCAmelCase	):




	"""simple docstring"""






	if len(_UpperCAmelCase	) != 32:
		raise ValueError('''Input must be of length 32'''	)

	A_  :				int	   =		b''''''
	for i in [3, 2, 1, 0]:
		little_endian += string_aa[8 * i : 8 * i + 8]
	return little_endian

def 		lowercase_      (		_UpperCAmelCase	):




	"""simple docstring"""






	if i < 0:
		raise ValueError('''Input must be non-negative'''	)

	A_  :				int	   =		format(_UpperCAmelCase  ,      '''08x'''	)[-8:]
	A_  :				Optional[Any]	   =		b''''''
	for i in [3, 2, 1, 0]:
		little_endian_hex += hex_rep[2 * i : 2 * i + 2].encode('''utf-8'''	)
	return little_endian_hex

def 		lowercase_      (		_UpperCAmelCase	):




	"""simple docstring"""






	A_  :				int	   =		b''''''
	for char in message:
		bit_string += format(_UpperCAmelCase  ,      '''08b'''	).encode('''utf-8'''	)
	A_  :				Optional[Any]	   =		format(len(_UpperCAmelCase	)  ,      '''064b'''	).encode('''utf-8'''	)

	# Pad bit_string to a multiple of 512 chars
	bit_string += b"1"
	while len(_UpperCAmelCase	) % 512 != 448:
		bit_string += b"0"
	bit_string += to_little_endian(start_len[32:]	) + to_little_endian(start_len[:32]	)

	return bit_string

def 		lowercase_      (		_UpperCAmelCase	):




	"""simple docstring"""






	if len(_UpperCAmelCase	) % 512 != 0:
		raise ValueError('''Input must have length that\'s a multiple of 512'''	)

	for pos in range(0  ,      len(_UpperCAmelCase	)  ,      512	):
		A_  :				Union[str, Any]	   =		bit_string[pos : pos + 512]
		A_  :				Optional[int]	   =		[]
		for i in range(0  ,      512  ,      32	):
			block_words.append(int(to_little_endian(block[i : i + 32]	)  ,      2	)	)
		yield block_words

def 		lowercase_      (		_UpperCAmelCase	):




	"""simple docstring"""






	if i < 0:
		raise ValueError('''Input must be non-negative'''	)

	A_  :				str	   =		format(_UpperCAmelCase  ,      '''032b'''	)
	A_  :				List[str]	   =		''''''
	for c in i_str:
		new_str += "1" if c == "0" else "0"
	return int(_UpperCAmelCase  ,      2	)

def 		lowercase_      (		_UpperCAmelCase  ,      _UpperCAmelCase	):




	"""simple docstring"""






	return (a + b) % 2**32

def 		lowercase_      (		_UpperCAmelCase  ,      _UpperCAmelCase	):




	"""simple docstring"""






	if i < 0:
		raise ValueError('''Input must be non-negative'''	)
	if shift < 0:
		raise ValueError('''Shift must be non-negative'''	)
	return ((i << shift) ^ (i >> (32 - shift))) % 2**32

def 		lowercase_      (		_UpperCAmelCase	):




	"""simple docstring"""






	A_  :				Any	   =		preprocess(_UpperCAmelCase	)

	A_  :				Any	   =		[int(2**32 * abs(sin(i + 1	)	)	) for i in range(64	)]

	# Starting states
	A_  :				List[str]	   =		0x6_7_4_5_2_3_0_1
	A_  :				str	   =		0xe_f_c_d_a_b_8_9
	A_  :				Union[str, Any]	   =		0x9_8_b_a_d_c_f_e
	A_  :				Dict	   =		0x1_0_3_2_5_4_7_6

	A_  :				int	   =		[
	    7,
	    12,
	    17,
	    22,
	    7,
	    12,
	    17,
	    22,
	    7,
	    12,
	    17,
	    22,
	    7,
	    12,
	    17,
	    22,
	    5,
	    9,
	    14,
	    20,
	    5,
	    9,
	    14,
	    20,
	    5,
	    9,
	    14,
	    20,
	    5,
	    9,
	    14,
	    20,
	    4,
	    11,
	    16,
	    23,
	    4,
	    11,
	    16,
	    23,
	    4,
	    11,
	    16,
	    23,
	    4,
	    11,
	    16,
	    23,
	    6,
	    10,
	    15,
	    21,
	    6,
	    10,
	    15,
	    21,
	    6,
	    10,
	    15,
	    21,
	    6,
	    10,
	    15,
	    21,
	]

	# Process bit string in chunks, each with 16 32-char words
	for block_words in get_block_words(_UpperCAmelCase	):
		A_  :				str	   =		aa
		A_  :				Tuple	   =		ba
		A_  :				Tuple	   =		ca
		A_  :				int	   =		da

		# Hash current chunk
		for i in range(64	):
			if i <= 15:
				# f = (b & c) | (not_32(b) & d)     # Alternate definition for f
				A_  :				str	   =		d ^ (b & (c ^ d))
				A_  :				int	   =		i
			elif i <= 31:
				# f = (d & b) | (not_32(d) & c)     # Alternate definition for f
				A_  :				List[Any]	   =		c ^ (d & (b ^ c))
				A_  :				Optional[int]	   =		(5 * i + 1) % 16
			elif i <= 47:
				A_  :				Optional[Any]	   =		b ^ c ^ d
				A_  :				List[Any]	   =		(3 * i + 5) % 16
			else:
				A_  :				Dict	   =		c ^ (b | not_aa(_UpperCAmelCase	))
				A_  :				Dict	   =		(7 * i) % 16
			A_  :				Optional[int]	   =		(f + a + added_consts[i] + block_words[g]) % 2**32
			A_  :				List[str]	   =		d
			A_  :				str	   =		c
			A_  :				Tuple	   =		b
			A_  :				Tuple	   =		sum_aa(_UpperCAmelCase  ,      left_rotate_aa(_UpperCAmelCase  ,      shift_amounts[i]	)	)

		# Add hashed chunk to running total
		A_  :				str	   =		sum_aa(_UpperCAmelCase  ,      _UpperCAmelCase	)
		A_  :				int	   =		sum_aa(_UpperCAmelCase  ,      _UpperCAmelCase	)
		A_  :				int	   =		sum_aa(_UpperCAmelCase  ,      _UpperCAmelCase	)
		A_  :				Optional[Any]	   =		sum_aa(_UpperCAmelCase  ,      _UpperCAmelCase	)

	A_  :				Dict	   =		reformat_hex(_UpperCAmelCase	) + reformat_hex(_UpperCAmelCase	) + reformat_hex(_UpperCAmelCase	) + reformat_hex(_UpperCAmelCase	)
	return digest


if __name__ == "__main__":
		import doctest

		doctest.testmod()





