






import argparse

import torch
from clip import load

from transformers import CLIPConfig, CLIPModel

def 					UpperCamelCase		( _A,					_A				):






						"""simple docstring"""







						__magic_name__    :     List[Any]     		=      pt_attn_layer.in_proj_weight.chunk(3,					dim=0				)
						__magic_name__    :     Dict     		=      pt_attn_layer.in_proj_bias.chunk(3,					dim=0				)

						__magic_name__    :     Optional[Any]     		=      pt_attn_layer.out_proj.weight
						__magic_name__    :     Union[str, Any]     		=      pt_attn_layer.out_proj.bias

						__magic_name__    :     List[str]     		=      q_proj
						__magic_name__    :     int     		=      q_proj_bias

						__magic_name__    :     Dict     		=      k_proj
						__magic_name__    :     Optional[Any]     		=      k_proj_bias

						__magic_name__    :     List[str]     		=      v_proj
						__magic_name__    :     Any     		=      v_proj_bias

						__magic_name__    :     Any     		=      out_proj_weights
						__magic_name__    :     List[str]     		=      out_proj_bias

def 					UpperCamelCase		( _A,					_A				):






						"""simple docstring"""







						copy_linear(hf_mlp.fca,					pt_mlp.c_fc				)
						copy_linear(hf_mlp.fca,					pt_mlp.c_proj				)

def 					UpperCamelCase		( _A,					_A				):






						"""simple docstring"""







						__magic_name__    :     Optional[Any]     		=      pt_linear.weight
						__magic_name__    :     Tuple     		=      pt_linear.bias

def 					UpperCamelCase		( _A,					_A				):






						"""simple docstring"""







						copy_linear(hf_layer.layer_norma,					pt_layer.ln_a				)
						copy_linear(hf_layer.layer_norma,					pt_layer.ln_a				)

						# copy MLP
						copy_mlp(hf_layer.mlp,					pt_layer.mlp				)

						# copy attn
						copy_attn_layer(hf_layer.self_attn,					pt_layer.attn				)

def 					UpperCamelCase		( _A,					_A				):






						"""simple docstring"""







						for hf_layer, pt_layer in zip(_A,					_A				):
												copy_layer(_A,					_A				)

def 					UpperCamelCase		( _A,					_A				):






						"""simple docstring"""







						__magic_name__    :     Optional[Any]     		=      pt_model.token_embedding.weight
						__magic_name__    :     Dict     		=      pt_model.positional_embedding

						# copy layer norm
						copy_linear(hf_encoder.final_layer_norm,					pt_model.ln_final				)

						# copy hidden layers
						copy_layers(hf_encoder.encoder.layers,					pt_model.transformer.resblocks				)

def 					UpperCamelCase		( _A,					_A				):






						"""simple docstring"""







						__magic_name__    :     Optional[Any]     		=      pt_model.text_projection.data.T

						# copy text encoder
						copy_encoder(hf_model.text_model,					_A				)

def 					UpperCamelCase		( _A,					_A				):






						"""simple docstring"""







						__magic_name__    :     List[str]     		=      pt_model.visual.proj.data.T

						# copy layer norms
						copy_linear(hf_model.vision_model.pre_layrnorm,					pt_model.visual.ln_pre				)
						copy_linear(hf_model.vision_model.post_layernorm,					pt_model.visual.ln_post				)

						# copy embeds
						__magic_name__    :     Optional[Any]     		=      pt_model.visual.conva.weight.data
						__magic_name__    :     Optional[Any]     		=      pt_model.visual.class_embedding
						__magic_name__    :     Dict     		=      pt_model.visual.positional_embedding.data

						# copy encoder
						copy_layers(hf_model.vision_model.encoder.layers,					pt_model.visual.transformer.resblocks				)

@torch.no_grad()
def 					UpperCamelCase		( _A,					_A,					_A=None				):






						"""simple docstring"""







						if config_path is not None:
												__magic_name__    :     str     		=      CLIPConfig.from_pretrained(_A				)
						else:
												__magic_name__    :     Any     		=      CLIPConfig(projection_dim=512,					text_config={},					vision_config={}				)

						__magic_name__    :     str     		=      CLIPModel(_A				).eval()

						__magic_name__    :     Union[str, Any]     		=      load(_A,					device="""cpu""",					jit=_A				)
						__magic_name__    :     Union[str, Any]     		=      pt_model.eval()

						copy_text_model_and_projection(_A,					_A				)
						copy_vison_model_and_projection(_A,					_A				)
						__magic_name__    :     Tuple     		=      pt_model.logit_scale

						__magic_name__    :     Union[str, Any]     		=      torch.arange(0,					77				).unsqueeze(0				)
						__magic_name__    :     List[Any]     		=      torch.randn(1,					3,					224,					224				)

						__magic_name__    :     Any     		=      hf_model(input_ids=_A,					pixel_values=_A,					return_dict=_A				)
						__magic_name__    :     List[Any]     		=      hf_outputs.logits_per_image
						__magic_name__    :     Optional[int]     		=      hf_outputs.logits_per_text
						__magic_name__    :     List[str]     		=      pt_model(_A,					_A				)

						assert torch.allclose(_A,					_A,					atol=1e-3				)
						assert torch.allclose(_A,					_A,					atol=1e-3				)

						hf_model.save_pretrained(_A				)


if __name__ == "__main__":
		__magic_name__:  Any  	=			argparse.ArgumentParser()
		parser.add_argument("--pytorch_dump_folder_path", default=None, type=str, help="Path to the output PyTorch model.")
		parser.add_argument("--checkpoint_path", default=None, type=str, help="Path to fairseq checkpoint")
		parser.add_argument("--config_path", default=None, type=str, help="Path to hf config.json of model to convert")
		__magic_name__:  Optional[Any]  	=			parser.parse_args()

		convert_clip_checkpoint(args.checkpoint_path, args.pytorch_dump_folder_path, args.config_path)








class  snake_case__      :
	def __init__(       self				)							->   None:
							# numbermap keys are the number and its values are lists of indexes sorted
							# in ascending order
							__magic_name__    :     dict[int, list[int]]     		=      {}
							# indexmap keys are an index and it's values are the number at that index
							__magic_name__    :     dict[int, int]     		=      {}
	def     __magic_name__       (       self    ,     lowerCAmelCase__    ,     lowerCAmelCase__				)							->   list[int]:
							if isinstance(lowerCAmelCase__    ,     (range, str)				):
													__magic_name__    :     int     		=      list(lowerCAmelCase__				)
							elif not isinstance(lowerCAmelCase__    ,     lowerCAmelCase__				):
													raise TypeError(
													    """binary_search_delete() only accepts either a list, range or str"""				)

							__magic_name__    :     str     		=      0
							__magic_name__    :     int     		=      len(lowerCAmelCase__				) - 1

							while low <= high:
													__magic_name__    :     List[str]     		=      (low + high) // 2
													if array[mid] == item:
																			array.pop(lowerCAmelCase__				)
																			return array
													elif array[mid] < item:
																			__magic_name__    :     Tuple     		=      mid + 1
													else:
																			__magic_name__    :     Dict     		=      mid - 1
							raise ValueError(
							    """Either the item is not in the array or the array was unsorted"""				)
	def     __magic_name__       (       self    ,     lowerCAmelCase__    ,     lowerCAmelCase__				)							->   list[int]:
							if isinstance(lowerCAmelCase__    ,     (range, str)				):
													__magic_name__    :     Tuple     		=      list(lowerCAmelCase__				)
							elif not isinstance(lowerCAmelCase__    ,     lowerCAmelCase__				):
													raise TypeError(
													    """binary_search_insert() only accepts either a list, range or str"""				)

							__magic_name__    :     List[str]     		=      0
							__magic_name__    :     Tuple     		=      len(lowerCAmelCase__				) - 1

							while low <= high:
													__magic_name__    :     Dict     		=      (low + high) // 2
													if array[mid] == index:
																			# If the item already exists in the array,
																			# insert it after the existing item
																			array.insert(mid + 1    ,     lowerCAmelCase__				)
																			return array
													elif array[mid] < index:
																			__magic_name__    :     int     		=      mid + 1
													else:
																			__magic_name__    :     Tuple     		=      mid - 1

        # If the item doesn't exist in the array, insert it at the appropriate position
							array.insert(lowerCAmelCase__    ,     lowerCAmelCase__				)
							return array
	def     __magic_name__       (       self    ,     lowerCAmelCase__    ,     lowerCAmelCase__				)							->   None:
							# Remove previous index
							if index in self.indexmap:
													__magic_name__    :     int     		=      self.indexmap[index]
													if len(self.numbermap[n]				) == 1:
																			del self.numbermap[n]
													else:
																			__magic_name__    :     Union[str, Any]     		=      self.binary_search_delete(self.numbermap[n]    ,     lowerCAmelCase__				)

        # Set new index
							__magic_name__    :     List[Any]     		=      number

							# Number not seen before or empty so insert number value
							if number not in self.numbermap:
													__magic_name__    :     Any     		=      [index]

							# Here we need to perform a binary search insertion in order to insert
							# The item in the correct place
							else:
													__magic_name__    :     Optional[Any]     		=      self.binary_search_insert(
													    self.numbermap[number]    ,     lowerCAmelCase__				)







	def     __magic_name__       (       self    ,     lowerCAmelCase__				)							->   int:
							return self.numbermap.get(lowerCAmelCase__    ,     [-1]				)[0]


if __name__ == "__main__":
		import doctest

		doctest.testmod()
