





import logging
import math
from functools import partial
from typing import Any, Callable, Dict, Iterable, List, Optional, Sequence, Tuple, Union

import torch

from .tensor_utils import tensor_tree_map, tree_map






def 					SCREAMING_SNAKE_CASE__				(							UpperCamelCase__:				Union[dict, list, tuple, torch.Tensor]     ):
		SCREAMING_SNAKE_CASE__								=   []
		if isinstance(UpperCamelCase__       , UpperCamelCase__     ):
				for v in tree.values():
						shapes.extend(_fetch_dims(UpperCamelCase__     )     )
		elif isinstance(UpperCamelCase__       , (list, tuple)     ):
				for t in tree:
						shapes.extend(_fetch_dims(UpperCamelCase__     )     )
		elif isinstance(UpperCamelCase__       , torch.Tensor     ):
				shapes.append(tree.shape     )
		else:
				raise ValueError("""Not supported"""     )

		return shapes






@torch.jit.ignore
def 					SCREAMING_SNAKE_CASE__				(							UpperCamelCase__:				int       , UpperCamelCase__:				Tuple[int, ...]     ):
		SCREAMING_SNAKE_CASE__								=   []
		for d in reversed(UpperCamelCase__     ):
				idx.append(flat_idx % d     )
				SCREAMING_SNAKE_CASE__								=   flat_idx // d

		return tuple(reversed(UpperCamelCase__     )     )






@torch.jit.ignore
def 					SCREAMING_SNAKE_CASE__				(							UpperCamelCase__:				Sequence[int]       , UpperCamelCase__:				Sequence[int]       , UpperCamelCase__:				Sequence[int]       , UpperCamelCase__:				Optional[Sequence[bool]] = None       , UpperCamelCase__:				Optional[Sequence[bool]] = None       , ):

		# start_edges and end_edges both indicate whether, starting from any given
		# dimension, the start/end index is at the top/bottom edge of the
		# corresponding tensor, modeled as a tree
		def reduce_edge_list(UpperCamelCase__:				List[bool]     ) -> None:
				SCREAMING_SNAKE_CASE__								=   True
				for i in range(len(UpperCamelCase__     )     ):
						SCREAMING_SNAKE_CASE__								=   -1 * (i + 1)
						l[reversed_idx] &= tally
						SCREAMING_SNAKE_CASE__								=   l[reversed_idx]

		if start_edges is None:
				SCREAMING_SNAKE_CASE__								=   [s == 0 for s in start]
				reduce_edge_list(UpperCamelCase__     )
		if end_edges is None:
				SCREAMING_SNAKE_CASE__								=   [e == (d - 1) for e, d in zip(UpperCamelCase__       , UpperCamelCase__     )]
				reduce_edge_list(UpperCamelCase__     )

		# Base cases. Either start/end are empty and we're done, or the final,
		# one-dimensional tensor can be simply sliced
		if len(UpperCamelCase__     ) == 0:
				return [()]
		elif len(UpperCamelCase__     ) == 1:
				return [(slice(start[0]       , end[0] + 1     ),)]

		SCREAMING_SNAKE_CASE__								=   []
		SCREAMING_SNAKE_CASE__								=   []

		# Dimensions common to start and end can be selected directly
		for s, e in zip(UpperCamelCase__       , UpperCamelCase__     ):
				if s == e:
						path_list.append(slice(UpperCamelCase__       , s + 1     )     )
				else:
						break

		SCREAMING_SNAKE_CASE__								=   tuple(UpperCamelCase__     )
		SCREAMING_SNAKE_CASE__								=   len(UpperCamelCase__     )

		# start == end, and we're done
		if divergence_idx == len(UpperCamelCase__     ):
				return [path]

		def upper() -> Tuple[Tuple[slice, ...], ...]:
				assert start_edges is not None
				assert end_edges is not None

				SCREAMING_SNAKE_CASE__								=   start[divergence_idx]
				return tuple(
				    path + (slice(UpperCamelCase__       , sdi + 1     ),) + s
				    for s in _get_minimal_slice_set(
				        start[divergence_idx + 1 :]       , [d - 1 for d in dims[divergence_idx + 1 :]]       , dims[divergence_idx + 1 :]       , start_edges=start_edges[divergence_idx + 1 :]       , end_edges=[True for _ in end_edges[divergence_idx + 1 :]]       , )     )

		def lower() -> Tuple[Tuple[slice, ...], ...]:
				assert start_edges is not None
				assert end_edges is not None

				SCREAMING_SNAKE_CASE__								=   end[divergence_idx]
				return tuple(
				    path + (slice(UpperCamelCase__       , edi + 1     ),) + s
				    for s in _get_minimal_slice_set(
				        [0 for _ in start[divergence_idx + 1 :]]       , end[divergence_idx + 1 :]       , dims[divergence_idx + 1 :]       , start_edges=[True for _ in start_edges[divergence_idx + 1 :]]       , end_edges=end_edges[divergence_idx + 1 :]       , )     )

		# If both start and end are at the edges of the subtree rooted at
		# divergence_idx, we can just select the whole subtree at once
		if start_edges[divergence_idx] and end_edges[divergence_idx]:
				slices.append(path + (slice(start[divergence_idx]       , end[divergence_idx] + 1     ),)     )
		# If just start is at the edge, we can grab almost all of the subtree,
		# treating only the ragged bottom edge as an edge case
		elif start_edges[divergence_idx]:
				slices.append(path + (slice(start[divergence_idx]       , end[divergence_idx]     ),)     )
				slices.extend(lower()     )
		# Analogous to the previous case, but the top is ragged this time
		elif end_edges[divergence_idx]:
				slices.extend(upper()     )
				slices.append(path + (slice(start[divergence_idx] + 1       , end[divergence_idx] + 1     ),)     )
		# If both sides of the range are ragged, we need to handle both sides
		# separately. If there's contiguous meat in between them, we can index it
		# in one big chunk
		else:
				slices.extend(upper()     )
				SCREAMING_SNAKE_CASE__								=   end[divergence_idx] - start[divergence_idx]
				if middle_ground > 1:
						slices.append(path + (slice(start[divergence_idx] + 1       , end[divergence_idx]     ),)     )
				slices.extend(lower()     )

		return slices






@torch.jit.ignore
def 					SCREAMING_SNAKE_CASE__				(							UpperCamelCase__:				torch.Tensor       , UpperCamelCase__:				int       , UpperCamelCase__:				int       , UpperCamelCase__:				int     ):
		SCREAMING_SNAKE_CASE__								=   t.shape[:no_batch_dims]
		SCREAMING_SNAKE_CASE__								=   list(_flat_idx_to_idx(UpperCamelCase__       , UpperCamelCase__     )     )
		# _get_minimal_slice_set is inclusive
		SCREAMING_SNAKE_CASE__								=   list(_flat_idx_to_idx(flat_end - 1       , UpperCamelCase__     )     )

		# Get an ordered list of slices to perform
		SCREAMING_SNAKE_CASE__								=   _get_minimal_slice_set(
		    UpperCamelCase__       , UpperCamelCase__       , UpperCamelCase__       , )

		SCREAMING_SNAKE_CASE__								=   [t[s] for s in slices]

		return torch.cat([s.view((-1,) + t.shape[no_batch_dims:]     ) for s in sliced_tensors]     )






def 					SCREAMING_SNAKE_CASE__				(							UpperCamelCase__:				Callable       , UpperCamelCase__:				Dict[str, Any]       , UpperCamelCase__:				int       , UpperCamelCase__:				int       , UpperCamelCase__:				bool = False       , UpperCamelCase__:				Any = None       , UpperCamelCase__:				bool = False       , ):
		if not (len(UpperCamelCase__     ) > 0):
				raise ValueError("""Must provide at least one input"""     )

		SCREAMING_SNAKE_CASE__								=   [shape[:no_batch_dims] for shape in _fetch_dims(UpperCamelCase__     )]
		SCREAMING_SNAKE_CASE__								=   tuple([max(UpperCamelCase__     ) for s in zip(*UpperCamelCase__     )]     )

		def _prep_inputs(UpperCamelCase__:				torch.Tensor     ) -> torch.Tensor:
				if not low_mem:
						if not sum(t.shape[:no_batch_dims]     ) == no_batch_dims:
								SCREAMING_SNAKE_CASE__								=   t.expand(orig_batch_dims + t.shape[no_batch_dims:]     )
						SCREAMING_SNAKE_CASE__								=   t.reshape(-1       , *t.shape[no_batch_dims:]     )
				else:
						SCREAMING_SNAKE_CASE__								=   t.expand(orig_batch_dims + t.shape[no_batch_dims:]     )
				return t

		SCREAMING_SNAKE_CASE__								=   tensor_tree_map(_prep_inputs       , UpperCamelCase__     )
		SCREAMING_SNAKE_CASE__								=   None
		if _out is not None:
				SCREAMING_SNAKE_CASE__								=   tensor_tree_map(lambda UpperCamelCase__     : t.view([-1] + list(t.shape[no_batch_dims:]     )     )       , _out     )

		SCREAMING_SNAKE_CASE__								=   1
		for d in orig_batch_dims:
				flat_batch_dim *= d

		SCREAMING_SNAKE_CASE__								=   flat_batch_dim // chunk_size + (flat_batch_dim % chunk_size != 0)

		def _select_chunk(UpperCamelCase__:				torch.Tensor     ) -> torch.Tensor:
				return t[i : i + chunk_size] if t.shape[0] != 1 else t

		SCREAMING_SNAKE_CASE__								=   0
		SCREAMING_SNAKE_CASE__								=   prepped_outputs
		for _ in range(UpperCamelCase__     ):
				# Chunk the input
				if not low_mem:
						SCREAMING_SNAKE_CASE__								=   _select_chunk
				else:
						SCREAMING_SNAKE_CASE__								=   partial(
						    _chunk_slice       , flat_start=UpperCamelCase__       , flat_end=min(UpperCamelCase__       , i + chunk_size     )       , no_batch_dims=len(UpperCamelCase__     )       , )

				SCREAMING_SNAKE_CASE__								=   tensor_tree_map(UpperCamelCase__       , UpperCamelCase__     )

				# Run the layer on the chunk
				SCREAMING_SNAKE_CASE__								=   layer(**UpperCamelCase__     )

				# Allocate space for the output
				if out is None:
						SCREAMING_SNAKE_CASE__								=   tensor_tree_map(lambda UpperCamelCase__     : t.new_zeros((flat_batch_dim,) + t.shape[1:]     )       , UpperCamelCase__     )

				# Put the chunk in its pre-allocated space
				if isinstance(UpperCamelCase__       , UpperCamelCase__     ):

						def assign(UpperCamelCase__:				dict       , UpperCamelCase__:				dict     ) -> None:
								for k, v in da.items():
										if isinstance(UpperCamelCase__       , UpperCamelCase__     ):
												assign(UpperCamelCase__       , da[k]     )
										else:
												if _add_into_out:
														v[i : i + chunk_size] += da[k]
												else:
														SCREAMING_SNAKE_CASE__								=   da[k]

						assign(UpperCamelCase__       , UpperCamelCase__     )
				elif isinstance(UpperCamelCase__       , UpperCamelCase__     ):
						for xa, xa in zip(UpperCamelCase__       , UpperCamelCase__     ):
								if _add_into_out:
										xa[i : i + chunk_size] += xa
								else:
										SCREAMING_SNAKE_CASE__								=   xa
				elif isinstance(UpperCamelCase__       , torch.Tensor     ):
						if _add_into_out:
								out[i : i + chunk_size] += output_chunk
						else:
								SCREAMING_SNAKE_CASE__								=   output_chunk
				else:
						raise ValueError("""Not supported"""     )

				i += chunk_size

		SCREAMING_SNAKE_CASE__								=   tensor_tree_map(lambda UpperCamelCase__     : t.view(orig_batch_dims + t.shape[1:]     )       , UpperCamelCase__     )

		return out




class 	UpperCamelCase_							:


							def __init__(				self     :Optional[Any]				,					__A     :int = 512				,					) -> Tuple:



									"""simple docstring"""



									SCREAMING_SNAKE_CASE__								=   max_chunk_size
									SCREAMING_SNAKE_CASE__								=   None
									SCREAMING_SNAKE_CASE__								=   None


							def   _snake_case	(				self     :Dict				,					__A     :Callable				,					__A     :tuple				,					__A     :int		) -> int:



									"""simple docstring"""



									logging.info("""Tuning chunk size..."""		)

									if min_chunk_size >= self.max_chunk_size:
											return min_chunk_size

									SCREAMING_SNAKE_CASE__								=   [2**l for l in range(int(math.log(self.max_chunk_size				,					2		)		) + 1		)]
									SCREAMING_SNAKE_CASE__								=   [c for c in candidates if c > min_chunk_size]
									SCREAMING_SNAKE_CASE__								=   [min_chunk_size] + candidates
									candidates[-1] += 4

									def test_chunk_size(__A     :int		) -> bool:
											try:
													with torch.no_grad():
															fn(*__A				,					chunk_size=__A		)
													return True
											except RuntimeError:
													return False

									SCREAMING_SNAKE_CASE__								=   0
									SCREAMING_SNAKE_CASE__								=   len(__A		) - 1
									while i > min_viable_chunk_size_index:
											SCREAMING_SNAKE_CASE__								=   test_chunk_size(candidates[i]		)
											if not viable:
													SCREAMING_SNAKE_CASE__								=   (min_viable_chunk_size_index + i) // 2
											else:
													SCREAMING_SNAKE_CASE__								=   i
													SCREAMING_SNAKE_CASE__								=   (i + len(__A		) - 1) // 2

									return candidates[min_viable_chunk_size_index]


							def   _snake_case	(				self     :Dict				,					__A     :Iterable				,					__A     :Iterable		) -> bool:



									"""simple docstring"""



									SCREAMING_SNAKE_CASE__								=   True
									for aa, aa in zip(__A				,					__A		):
											assert type(__A		) == type(__A		)
											if isinstance(__A				,					(list, tuple)		):
													consistent &= self._compare_arg_caches(__A				,					__A		)
											elif isinstance(__A				,					__A		):
													SCREAMING_SNAKE_CASE__								=   [v for _, v in sorted(aa.items()				,					key=lambda __A		: x[0]		)]
													SCREAMING_SNAKE_CASE__								=   [v for _, v in sorted(aa.items()				,					key=lambda __A		: x[0]		)]
													consistent &= self._compare_arg_caches(__A				,					__A		)
											else:
													consistent &= aa == aa

									return consistent


							def   _snake_case	(				self     :int				,					__A     :Callable				,					__A     :tuple				,					__A     :int				,					) -> int:



									"""simple docstring"""



									SCREAMING_SNAKE_CASE__								=   True
									SCREAMING_SNAKE_CASE__								=   tree_map(lambda __A		: a.shape if isinstance(__A				,					torch.Tensor		) else a				,					__A				,					__A		)
									if self.cached_arg_data is not None:
											# If args have changed shape/value, we need to re-tune
											assert len(self.cached_arg_data		) == len(__A		)
											SCREAMING_SNAKE_CASE__								=   self._compare_arg_caches(self.cached_arg_data				,					__A		)
									else:
											# Otherwise, we can reuse the precomputed value
											SCREAMING_SNAKE_CASE__								=   False

									if not consistent:
											SCREAMING_SNAKE_CASE__								=   self._determine_favorable_chunk_size(
											    __A				,					__A				,					__A				,					)
											SCREAMING_SNAKE_CASE__								=   arg_data

									assert self.cached_chunk_size is not None

									return self.cached_chunk_size






import argparse

import torch
from datasets import load_dataset
from donut import DonutModel

from transformers import (
    DonutImageProcessor,
    DonutProcessor,
    DonutSwinConfig,
    DonutSwinModel,
    MBartConfig,
    MBartForCausalLM,
    VisionEncoderDecoderModel,
    XLMRobertaTokenizerFast,
)






def 					SCREAMING_SNAKE_CASE__				(							UpperCamelCase__:				str     ):
		SCREAMING_SNAKE_CASE__								=   model.config

		SCREAMING_SNAKE_CASE__								=   DonutSwinConfig(
		    image_size=original_config.input_size       , patch_size=4       , depths=original_config.encoder_layer       , num_heads=[4, 8, 16, 32]       , window_size=original_config.window_size       , embed_dim=128       , )
		SCREAMING_SNAKE_CASE__								=   MBartConfig(
		    is_decoder=UpperCamelCase__       , is_encoder_decoder=UpperCamelCase__       , add_cross_attention=UpperCamelCase__       , decoder_layers=original_config.decoder_layer       , max_position_embeddings=original_config.max_position_embeddings       , vocab_size=len(
		        model.decoder.tokenizer     )       , scale_embedding=UpperCamelCase__       , add_final_layer_norm=UpperCamelCase__       , )

		return encoder_config, decoder_config






def 					SCREAMING_SNAKE_CASE__				(							UpperCamelCase__:				List[str]     ):
		if "encoder.model" in name:
				SCREAMING_SNAKE_CASE__								=   name.replace("""encoder.model"""       , """encoder"""     )
		if "decoder.model" in name:
				SCREAMING_SNAKE_CASE__								=   name.replace("""decoder.model"""       , """decoder"""     )
		if "patch_embed.proj" in name:
				SCREAMING_SNAKE_CASE__								=   name.replace("""patch_embed.proj"""       , """embeddings.patch_embeddings.projection"""     )
		if "patch_embed.norm" in name:
				SCREAMING_SNAKE_CASE__								=   name.replace("""patch_embed.norm"""       , """embeddings.norm"""     )
		if name.startswith("""encoder"""     ):
				if "layers" in name:
						SCREAMING_SNAKE_CASE__								=   """encoder.""" + name
				if "attn.proj" in name:
						SCREAMING_SNAKE_CASE__								=   name.replace("""attn.proj"""       , """attention.output.dense"""     )
				if "attn" in name and "mask" not in name:
						SCREAMING_SNAKE_CASE__								=   name.replace("""attn"""       , """attention.self"""     )
				if "norm1" in name:
						SCREAMING_SNAKE_CASE__								=   name.replace("""norm1"""       , """layernorm_before"""     )
				if "norm2" in name:
						SCREAMING_SNAKE_CASE__								=   name.replace("""norm2"""       , """layernorm_after"""     )
				if "mlp.fc1" in name:
						SCREAMING_SNAKE_CASE__								=   name.replace("""mlp.fc1"""       , """intermediate.dense"""     )
				if "mlp.fc2" in name:
						SCREAMING_SNAKE_CASE__								=   name.replace("""mlp.fc2"""       , """output.dense"""     )

				if name == "encoder.norm.weight":
						SCREAMING_SNAKE_CASE__								=   """encoder.layernorm.weight"""
				if name == "encoder.norm.bias":
						SCREAMING_SNAKE_CASE__								=   """encoder.layernorm.bias"""

		return name






def 					SCREAMING_SNAKE_CASE__				(							UpperCamelCase__:				str       , UpperCamelCase__:				Optional[int]     ):
		for key in orig_state_dict.copy().keys():
				SCREAMING_SNAKE_CASE__								=   orig_state_dict.pop(UpperCamelCase__     )

				if "qkv" in key:
						SCREAMING_SNAKE_CASE__								=   key.split("""."""     )
						SCREAMING_SNAKE_CASE__								=   int(key_split[3]     )
						SCREAMING_SNAKE_CASE__								=   int(key_split[5]     )
						SCREAMING_SNAKE_CASE__								=   model.encoder.encoder.layers[layer_num].blocks[block_num].attention.self.all_head_size

						if "weight" in key:
								SCREAMING_SNAKE_CASE__								=   val[:dim, :]
								SCREAMING_SNAKE_CASE__								=   val[dim : dim * 2, :]
								SCREAMING_SNAKE_CASE__								=   val[-dim:, :]
						else:
								SCREAMING_SNAKE_CASE__								=   val[:dim]
								SCREAMING_SNAKE_CASE__								=   val[dim : dim * 2]
								SCREAMING_SNAKE_CASE__								=   val[-dim:]
				elif "attn_mask" in key or key in ["encoder.model.norm.weight", "encoder.model.norm.bias"]:
						# HuggingFace implementation doesn't use attn_mask buffer
						# and model doesn't use final LayerNorms for the encoder
						pass
				else:
						SCREAMING_SNAKE_CASE__								=   val

		return orig_state_dict






def 					SCREAMING_SNAKE_CASE__				(							UpperCamelCase__:				Union[str, Any]       , UpperCamelCase__:				int=None       , UpperCamelCase__:				str=False     ):
		# load original model
		SCREAMING_SNAKE_CASE__								=   DonutModel.from_pretrained(UpperCamelCase__     ).eval()

		# load HuggingFace model
		SCREAMING_SNAKE_CASE__						,    SCREAMING_SNAKE_CASE__								=   get_configs(UpperCamelCase__     )
		SCREAMING_SNAKE_CASE__								=   DonutSwinModel(UpperCamelCase__     )
		SCREAMING_SNAKE_CASE__								=   MBartForCausalLM(UpperCamelCase__     )
		SCREAMING_SNAKE_CASE__								=   VisionEncoderDecoderModel(encoder=UpperCamelCase__       , decoder=UpperCamelCase__     )
		model.eval()

		SCREAMING_SNAKE_CASE__								=   original_model.state_dict()
		SCREAMING_SNAKE_CASE__								=   convert_state_dict(UpperCamelCase__       , UpperCamelCase__     )
		model.load_state_dict(UpperCamelCase__     )

		# verify results on scanned document
		SCREAMING_SNAKE_CASE__								=   load_dataset("""hf-internal-testing/example-documents"""     )
		SCREAMING_SNAKE_CASE__								=   dataset["""test"""][0]["""image"""].convert("""RGB"""     )

		SCREAMING_SNAKE_CASE__								=   XLMRobertaTokenizerFast.from_pretrained(UpperCamelCase__       , from_slow=UpperCamelCase__     )
		SCREAMING_SNAKE_CASE__								=   DonutImageProcessor(
		    do_align_long_axis=original_model.config.align_long_axis       , size=original_model.config.input_size[::-1]     )
		SCREAMING_SNAKE_CASE__								=   DonutProcessor(UpperCamelCase__       , UpperCamelCase__     )
		SCREAMING_SNAKE_CASE__								=   processor(UpperCamelCase__       , return_tensors="""pt"""     ).pixel_values

		if model_name == "naver-clova-ix/donut-base-finetuned-docvqa":
				SCREAMING_SNAKE_CASE__								=   """<s_docvqa><s_question>{user_input}</s_question><s_answer>"""
				SCREAMING_SNAKE_CASE__								=   """When is the coffee break?"""
				SCREAMING_SNAKE_CASE__								=   task_prompt.replace("""{user_input}"""       , UpperCamelCase__     )
		elif model_name == "naver-clova-ix/donut-base-finetuned-rvlcdip":
				SCREAMING_SNAKE_CASE__								=   """<s_rvlcdip>"""
		elif model_name in [
		    "naver-clova-ix/donut-base-finetuned-cord-v1",
		    "naver-clova-ix/donut-base-finetuned-cord-v1-2560",
		]:
				SCREAMING_SNAKE_CASE__								=   """<s_cord>"""
		elif model_name == "naver-clova-ix/donut-base-finetuned-cord-v2":
				SCREAMING_SNAKE_CASE__								=   """s_cord-v2>"""
		elif model_name == "naver-clova-ix/donut-base-finetuned-zhtrainticket":
				SCREAMING_SNAKE_CASE__								=   """<s_zhtrainticket>"""
		elif model_name in ["naver-clova-ix/donut-proto", "naver-clova-ix/donut-base"]:
				# use a random prompt
				SCREAMING_SNAKE_CASE__								=   """hello world"""
		else:
				raise ValueError("""Model name not supported"""     )
		SCREAMING_SNAKE_CASE__								=   original_model.decoder.tokenizer(UpperCamelCase__       , add_special_tokens=UpperCamelCase__       , return_tensors="""pt"""     )[
		    """input_ids"""
		]

		SCREAMING_SNAKE_CASE__								=   original_model.encoder.model.patch_embed(UpperCamelCase__     )
		SCREAMING_SNAKE_CASE__						,    SCREAMING_SNAKE_CASE__								=   model.encoder.embeddings(UpperCamelCase__     )
		assert torch.allclose(UpperCamelCase__       , UpperCamelCase__       , atol=1e-3     )

		# verify encoder hidden states
		SCREAMING_SNAKE_CASE__								=   original_model.encoder(UpperCamelCase__     )
		SCREAMING_SNAKE_CASE__								=   model.encoder(UpperCamelCase__     ).last_hidden_state
		assert torch.allclose(UpperCamelCase__       , UpperCamelCase__       , atol=1e-2     )

		# verify decoder hidden states
		SCREAMING_SNAKE_CASE__								=   original_model(UpperCamelCase__       , UpperCamelCase__       , UpperCamelCase__     ).logits
		SCREAMING_SNAKE_CASE__								=   model(UpperCamelCase__       , decoder_input_ids=UpperCamelCase__     ).logits
		assert torch.allclose(UpperCamelCase__       , UpperCamelCase__       , atol=1e-3     )
		print("""Looks ok!"""     )

		if pytorch_dump_folder_path is not None:
				print(f'''Saving model and processor to {pytorch_dump_folder_path}'''     )
				model.save_pretrained(UpperCamelCase__     )
				processor.save_pretrained(UpperCamelCase__     )

		if push_to_hub:
				model.push_to_hub("""nielsr/""" + model_name.split("""/"""     )[-1]       , commit_message="""Update model"""     )
				processor.push_to_hub("""nielsr/""" + model_name.split("""/"""     )[-1]       , commit_message="""Update model"""     )


if __name__ == "__main__":
	_lowerCamelCase 					=      argparse.ArgumentParser()
	# Required parameters
	parser.add_argument(
	    '--model_name',
	    default='naver-clova-ix/donut-base-finetuned-docvqa',
	    required=False,
	    type=str,
	    help='Name of the original model you\'d like to convert.',
	)
	parser.add_argument(
	    '--pytorch_dump_folder_path',
	    default=None,
	    required=False,
	    type=str,
	    help='Path to the output PyTorch model directory.',
	)
	parser.add_argument(
	    '--push_to_hub',
	    action='store_true',
	    help='Whether or not to push the converted model and processor to the 🤗 hub.',
	)

	_lowerCamelCase 					=      parser.parse_args()
	convert_donut_checkpoint(args.model_name, args.pytorch_dump_folder_path, args.push_to_hub)