
"""simple docstring"""


import argparse

import requests
import torch

# pip3 install salesforce-lavis
# I'm actually installing a slightly modified version: pip3 install git+https://github.com/nielsrogge/LAVIS.git@fix_lavis
from lavis.models import load_model_and_preprocess
from PIL import Image

from transformers import (
    AutoTokenizer,
    BlipaConfig,
    BlipaForConditionalGeneration,
    BlipaProcessor,
    BlipaVisionConfig,
    BlipImageProcessor,
    OPTConfig,
    TaConfig,
)
from transformers.utils.constants import OPENAI_CLIP_MEAN, OPENAI_CLIP_STD






def    _snake_case					(		):
	A     = 'https://storage.googleapis.com/sfr-vision-language-research/LAVIS/assets/merlion.png'
	A     = Image.open(requests.get(snake_case__						,   stream=snake_case__  ).raw  ).convert('RGB'  )

	return image






def    _snake_case					(		snake_case__ :  Dict  ):
	A     = []
	# fmt: off

	# vision encoder
	rename_keys.append(('visual_encoder.cls_token', 'vision_model.embeddings.class_embedding')  )
	rename_keys.append(('visual_encoder.pos_embed', 'vision_model.embeddings.position_embedding')  )
	rename_keys.append(('visual_encoder.patch_embed.proj.weight', 'vision_model.embeddings.patch_embedding.weight')  )
	rename_keys.append(('visual_encoder.patch_embed.proj.bias', 'vision_model.embeddings.patch_embedding.bias')  )
	rename_keys.append(('ln_vision.weight', 'vision_model.post_layernorm.weight')  )
	rename_keys.append(('ln_vision.bias', 'vision_model.post_layernorm.bias')  )

	for i in range(config.vision_config.num_hidden_layers  ):
		rename_keys.append((F'visual_encoder.blocks.{i}.norm1.weight', F'vision_model.encoder.layers.{i}.layer_norm1.weight')  )
		rename_keys.append((F'visual_encoder.blocks.{i}.norm1.bias', F'vision_model.encoder.layers.{i}.layer_norm1.bias')  )
		rename_keys.append((F'visual_encoder.blocks.{i}.norm2.weight', F'vision_model.encoder.layers.{i}.layer_norm2.weight')  )
		rename_keys.append((F'visual_encoder.blocks.{i}.norm2.bias', F'vision_model.encoder.layers.{i}.layer_norm2.bias')  )
		rename_keys.append((F'visual_encoder.blocks.{i}.attn.qkv.weight', F'vision_model.encoder.layers.{i}.self_attn.qkv.weight')  )
		rename_keys.append((F'visual_encoder.blocks.{i}.attn.proj.weight', F'vision_model.encoder.layers.{i}.self_attn.projection.weight',)  )
		rename_keys.append((F'visual_encoder.blocks.{i}.attn.proj.bias', F'vision_model.encoder.layers.{i}.self_attn.projection.bias')  )
		rename_keys.append((F'visual_encoder.blocks.{i}.mlp.fc1.weight', F'vision_model.encoder.layers.{i}.mlp.fc1.weight')  )
		rename_keys.append((F'visual_encoder.blocks.{i}.mlp.fc1.bias', F'vision_model.encoder.layers.{i}.mlp.fc1.bias')  )
		rename_keys.append((F'visual_encoder.blocks.{i}.mlp.fc2.weight', F'vision_model.encoder.layers.{i}.mlp.fc2.weight')  )
		rename_keys.append((F'visual_encoder.blocks.{i}.mlp.fc2.bias', F'vision_model.encoder.layers.{i}.mlp.fc2.bias')  )

	# QFormer
	rename_keys.append(('Qformer.bert.embeddings.LayerNorm.weight', 'qformer.layernorm.weight')  )
	rename_keys.append(('Qformer.bert.embeddings.LayerNorm.bias', 'qformer.layernorm.bias')  )

	# fmt: on
	return rename_keys






def    _snake_case					(		snake_case__ :  Dict						,   snake_case__ :  int						,   snake_case__ :  str  ):
	A     = dct.pop(snake_case__  )
	A     = val






def    _snake_case					(		snake_case__ :  Optional[int]						,   snake_case__ :  Union[str, Any]  ):
	for i in range(config.vision_config.num_hidden_layers  ):
		# read in original q and v biases
		A     = state_dict.pop(F'visual_encoder.blocks.{i}.attn.q_bias'  )
		A     = state_dict.pop(F'visual_encoder.blocks.{i}.attn.v_bias'  )

		# next, set bias in the state dict
		A     = torch.cat((q_bias, torch.zeros_like(snake_case__						,   requires_grad=snake_case__  ), v_bias)  )
		A     = qkv_bias






def    _snake_case					(		snake_case__ :  Optional[int]						,   snake_case__ :  int  ):
	A     = 364 if 'coco' in model_name else 224
	A     = BlipaVisionConfig(image_size=snake_case__  ).to_dict()

	# make sure the models have proper bos_token_id and eos_token_id set (important for generation)
	# seems like flan-T5 models don't have bos_token_id properly set?
	if "opt-2.7b" in model_name:
		A     = OPTConfig.from_pretrained('facebook/opt-2.7b'						,   eos_token_id=snake_case__  ).to_dict()
	elif "opt-6.7b" in model_name:
		A     = OPTConfig.from_pretrained('facebook/opt-6.7b'						,   eos_token_id=snake_case__  ).to_dict()
	elif "t5-xl" in model_name:
		A     = TaConfig.from_pretrained('google/flan-t5-xl'						,   dense_act_fn='gelu'						,   bos_token_id=1  ).to_dict()
	elif "t5-xxl" in model_name:
		A     = TaConfig.from_pretrained('google/flan-t5-xxl'						,   dense_act_fn='gelu'						,   bos_token_id=1  ).to_dict()

	A     = BlipaConfig(vision_config=snake_case__						,   text_config=snake_case__  )

	return config, image_size






@torch.no_grad()
def    _snake_case					(		snake_case__ :  Optional[Any]						,   snake_case__ :  List[Any]=None						,   snake_case__ :  List[Any]=False  ):
	A     = (
	    AutoTokenizer.from_pretrained('facebook/opt-2.7b'  )
	    if 'opt' in model_name
	    else AutoTokenizer.from_pretrained('google/flan-t5-xl'  )
	)
	A     = tokenizer('\n'						,   add_special_tokens=snake_case__  ).input_ids[0]
	A ,   A     = get_blipa_config(snake_case__						,   eos_token_id=snake_case__  )

	A     = BlipaForConditionalGeneration(snake_case__  ).eval()

	A     = {
	    'blip2-opt-2.7b': ('blip2_opt', 'pretrain_opt2.7b'),
	    'blip2-opt-6.7b': ('blip2_opt', 'pretrain_opt6.7b'),
	    'blip2-opt-2.7b-coco': ('blip2_opt', 'caption_coco_opt2.7b'),
	    'blip2-opt-6.7b-coco': ('blip2_opt', 'caption_coco_opt6.7b'),
	    'blip2-flan-t5-xl': ('blip2_t5', 'pretrain_flant5xl'),
	    'blip2-flan-t5-xl-coco': ('blip2_t5', 'caption_coco_flant5xl'),
	    'blip2-flan-t5-xxl': ('blip2_t5', 'pretrain_flant5xxl'),
	}

	A ,   A     = model_name_to_original[model_name]

	# load original model
	print('Loading original model...'  )
	A     = 'cuda' if torch.cuda.is_available() else 'cpu'
	A ,   A ,   A     = load_model_and_preprocess(
	    name=snake_case__						,   model_type=snake_case__						,   is_eval=snake_case__						,   device=snake_case__  )
	original_model.eval()
	print('Done!'  )

	# update state dict keys
	A     = original_model.state_dict()
	A     = create_rename_keys(snake_case__  )
	for src, dest in rename_keys:
		rename_key(snake_case__						,   snake_case__						,   snake_case__  )

	# some keys can be renamed efficiently
	for key, val in state_dict.copy().items():
		A     = state_dict.pop(snake_case__  )
		if key.startswith('Qformer.bert'  ):
			A     = key.replace('Qformer.bert'						,   'qformer'  )
		if "attention.self" in key:
			A     = key.replace('self'						,   'attention'  )
		if "opt_proj" in key:
			A     = key.replace('opt_proj'						,   'language_projection'  )
		if "t5_proj" in key:
			A     = key.replace('t5_proj'						,   'language_projection'  )
		if key.startswith('opt'  ):
			A     = key.replace('opt'						,   'language'  )
		if key.startswith('t5'  ):
			A     = key.replace('t5'						,   'language'  )
		A     = val

	# read in qv biases
	read_in_q_v_bias(snake_case__						,   snake_case__  )

	A ,   A     = hf_model.load_state_dict(snake_case__						,   strict=snake_case__  )
	assert len(snake_case__  ) == 0
	assert unexpected_keys == ["qformer.embeddings.position_ids"]

	A     = load_demo_image()
	A     = vis_processors['eval'](snake_case__  ).unsqueeze(0  ).to(snake_case__  )
	A     = tokenizer(['\n']						,   return_tensors='pt'  ).input_ids.to(snake_case__  )

	# create processor
	A     = BlipImageProcessor(
	    size={'height': image_size, 'width': image_size}						,   image_mean=snake_case__						,   image_std=snake_case__  )
	A     = BlipaProcessor(image_processor=snake_case__						,   tokenizer=snake_case__  )
	A     = processor(images=snake_case__						,   return_tensors='pt'  ).pixel_values.to(snake_case__  )

	# make sure processor creates exact same pixel values
	assert torch.allclose(snake_case__						,   snake_case__  )

	original_model.to(snake_case__  )
	hf_model.to(snake_case__  )
	with torch.no_grad():
		if "opt" in model_name:
			A     = original_model({'image': original_pixel_values, 'text_input': ['']}  ).logits
			A     = hf_model(snake_case__						,   snake_case__  ).logits
		else:
			A     = original_model(
			    {'image': original_pixel_values, 'text_input': ['\n'], 'text_output': ['\n']}  ).logits
			A     = input_ids.masked_fill(input_ids == tokenizer.pad_token_id						,   -100  )
			A     = hf_model(snake_case__						,   snake_case__						,   labels=snake_case__  ).logits

	assert original_logits.shape == logits.shape
	print('First values of original logits:'						,   original_logits[0, :3, :3]  )
	print('First values of HF logits:'						,   logits[0, :3, :3]  )

	# assert values
	if model_name == "blip2-flan-t5-xl":
		A     = torch.tensor(
		    [[-41.5850, -4.4440, -8.9922], [-47.4322, -5.9143, -1.7340]]						,   device=snake_case__  )
		assert torch.allclose(logits[0, :3, :3]						,   snake_case__						,   atol=1e-4  )
	elif model_name == "blip2-flan-t5-xl-coco":
		A     = torch.tensor(
		    [[-57.0109, -9.8967, -12.6280], [-68.6578, -12.7191, -10.5065]]						,   device=snake_case__  )
	else:
		# cast to same type
		A     = logits.dtype
		assert torch.allclose(original_logits.to(snake_case__  )						,   snake_case__						,   atol=1e-2  )
	print('Looks ok!'  )

	print('Generating a caption...'  )
	A     = ''
	A     = tokenizer(snake_case__						,   return_tensors='pt'  ).input_ids.to(snake_case__  )

	A     = original_model.generate({'image': original_pixel_values}  )
	A     = hf_model.generate(
	    snake_case__						,   snake_case__						,   do_sample=snake_case__						,   num_beams=5						,   max_length=30						,   min_length=1						,   top_p=0.9						,   repetition_penalty=1.0						,   length_penalty=1.0						,   temperature=1						,   )
	print('Original generation:'						,   snake_case__  )
	A     = input_ids.shape[1]
	A     = processor.batch_decode(outputs[:, prompt_length:]						,   skip_special_tokens=snake_case__  )
	A     = [text.strip() for text in output_text]
	print('HF generation:'						,   snake_case__  )

	if pytorch_dump_folder_path is not None:
		processor.save_pretrained(snake_case__  )
		hf_model.save_pretrained(snake_case__  )

	if push_to_hub:
		processor.push_to_hub(F'nielsr/{model_name}'  )
		hf_model.push_to_hub(F'nielsr/{model_name}'  )


if __name__ == "__main__":
		_lowercase				 =					argparse.ArgumentParser()
		_lowercase				 =					[
		    '''blip2-opt-2.7b''',
		    '''blip2-opt-6.7b''',
		    '''blip2-opt-2.7b-coco''',
		    '''blip2-opt-6.7b-coco''',
		    '''blip2-flan-t5-xl''',
		    '''blip2-flan-t5-xl-coco''',
		    '''blip2-flan-t5-xxl''',
		]
		parser.add_argument(
		    '''--model_name''',
		    default='''blip2-opt-2.7b''',
		    choices=choices,
		    type=str,
		    help='''Path to hf config.json of model to convert''',
		)
		parser.add_argument('''--pytorch_dump_folder_path''', default=None, type=str, help='''Path to the output PyTorch model.''')
		parser.add_argument(
		    '''--push_to_hub''',
		    action='''store_true''',
		    help='''Whether to push the model and processor to the hub after converting''',
		)

		_lowercase				 =					parser.parse_args()

		convert_blipa_checkpoint(args.model_name, args.pytorch_dump_folder_path, args.push_to_hub)


"""simple docstring"""
import warnings
from typing import Dict, List, Optional, Tuple

from ...tokenization_utils import AddedToken, PreTrainedTokenizer
from ...utils import logging


_A							=  logging.get_logger(__name__)

class       lowerCamelCase	(       lowerCAmelCase__   ):


  '''simple docstring'''







  SCREAMING_SNAKE_CASE					      =  ['input_ids', 'attention_mask']



  def __init__(self							,       _lowerCamelCase="</s>"							,       _lowerCamelCase="<unk>"							,       _lowerCamelCase="<pad>"							,       _lowerCamelCase=125							,       _lowerCamelCase=None							,       **_lowerCamelCase							,       ):


        """simple docstring"""

        if extra_ids > 0 and additional_special_tokens is None:
              UpperCAmelCase__			:							List[str]							=    [F"""<extra_id_{i}>""" for i in range(_lowerCamelCase	)]
        elif extra_ids > 0 and additional_special_tokens is not None:
              # Check that we have the right number of extra_id special tokens
              UpperCAmelCase__			:							int							=    len(set(filter(lambda _lowerCamelCase	: bool("""extra_id""" in str(_lowerCamelCase	)	)							,       _lowerCamelCase	)	)	)
              if extra_tokens != extra_ids:
                    raise ValueError(
                        F"""Both extra_ids ({extra_ids}) and additional_special_tokens ({additional_special_tokens}) are"""
                        """ provided to ByT5Tokenizer. In this case the additional_special_tokens must include the"""
                        """ extra_ids tokens"""	)

        UpperCAmelCase__			:							List[str]							=    AddedToken(_lowerCamelCase							,       lstrip=_lowerCamelCase							,       rstrip=_lowerCamelCase	) if isinstance(_lowerCamelCase							,       _lowerCamelCase	) else pad_token
        UpperCAmelCase__			:							int							=    AddedToken(_lowerCamelCase							,       lstrip=_lowerCamelCase							,       rstrip=_lowerCamelCase	) if isinstance(_lowerCamelCase							,       _lowerCamelCase	) else eos_token
        UpperCAmelCase__			:							Optional[int]							=    AddedToken(_lowerCamelCase							,       lstrip=_lowerCamelCase							,       rstrip=_lowerCamelCase	) if isinstance(_lowerCamelCase							,       _lowerCamelCase	) else unk_token

        super().__init__(
            eos_token=_lowerCamelCase							,       unk_token=_lowerCamelCase							,       pad_token=_lowerCamelCase							,       extra_ids=_lowerCamelCase							,       additional_special_tokens=_lowerCamelCase							,       **_lowerCamelCase							,       )

        UpperCAmelCase__			:							int							=    extra_ids

        UpperCAmelCase__			:							List[str]							=    2**8  # utf is 8 bits

        # define special tokens dict
        UpperCAmelCase__			:							Dict[int, str]							=    {
            self.pad_token: 0,
            self.eos_token: 1,
            self.unk_token: 2,
        }
        UpperCAmelCase__			:							str							=    len(self.special_tokens_encoder	)
        UpperCAmelCase__			:							Union[str, Any]							=    len(_lowerCamelCase	)
        for i, token in enumerate(_lowerCamelCase	):
              UpperCAmelCase__			:							Optional[Any]							=    self.vocab_size + i - n
        UpperCAmelCase__			:							Dict[str, int]							=    {v: k for k, v in self.special_tokens_encoder.items()}



  @property
  def  _a      (self	):


        """simple docstring"""

        return self._utf_vocab_size + self._num_special_tokens + self._extra_ids



  def  _a      (self							,       _lowerCamelCase							,       _lowerCamelCase = None							,       _lowerCamelCase = False	):


        """simple docstring"""

        if already_has_special_tokens:
              return super().get_special_tokens_mask(
                  token_ids_a=_lowerCamelCase							,       token_ids_a=_lowerCamelCase							,       already_has_special_tokens=_lowerCamelCase	)

        # normal case: some special tokens
        if token_ids_a is None:
              return ([0] * len(_lowerCamelCase	)) + [1]
        return ([0] * len(_lowerCamelCase	)) + [1] + ([0] * len(_lowerCamelCase	)) + [1]



  def  _a      (self							,       _lowerCamelCase	):


        """simple docstring"""

        if len(_lowerCamelCase	) > 0 and token_ids[-1] == self.eos_token_id:
              warnings.warn(
                  F"""This sequence already has {self.eos_token}. In future versions this behavior may lead to duplicated"""
                  """ eos tokens being added."""	)
              return token_ids
        else:
              return token_ids + [self.eos_token_id]



  def  _a      (self							,       _lowerCamelCase							,       _lowerCamelCase = None	):


        """simple docstring"""

        UpperCAmelCase__			:							List[str]							=    [self.eos_token_id]

        if token_ids_a is None:
              return len(token_ids_a + eos	) * [0]
        return len(token_ids_a + eos + token_ids_a + eos	) * [0]



  def  _a      (self							,       _lowerCamelCase							,       _lowerCamelCase = None	):


        """simple docstring"""

        UpperCAmelCase__			:							Tuple							=    self._add_eos_if_not_present(_lowerCamelCase	)
        if token_ids_a is None:
              return token_ids_a
        else:
              UpperCAmelCase__			:							List[str]							=    self._add_eos_if_not_present(_lowerCamelCase	)
              return token_ids_a + token_ids_a



  def  _a      (self							,       _lowerCamelCase	):


        """simple docstring"""

        UpperCAmelCase__			:							Optional[Any]							=    [chr(_lowerCamelCase	) for i in text.encode("""utf-8"""	)]
        return tokens



  def  _a      (self							,       _lowerCamelCase	):


        """simple docstring"""

        if token in self.special_tokens_encoder:
              UpperCAmelCase__			:							List[str]							=    self.special_tokens_encoder[token]
        elif token in self.added_tokens_encoder:
              UpperCAmelCase__			:							Tuple							=    self.added_tokens_encoder[token]
        elif len(_lowerCamelCase	) != 1:
              UpperCAmelCase__			:							Dict							=    self.unk_token_id
        else:
              UpperCAmelCase__			:							Tuple							=    ord(_lowerCamelCase	) + self._num_special_tokens
        return token_id



  def  _a      (self							,       _lowerCamelCase	):


        """simple docstring"""

        if index in self.special_tokens_decoder:
              UpperCAmelCase__			:							Optional[Any]							=    self.special_tokens_decoder[index]
        else:
              UpperCAmelCase__			:							Dict							=    chr(index - self._num_special_tokens	)
        return token



  def  _a      (self							,       _lowerCamelCase	):


        """simple docstring"""

        UpperCAmelCase__			:							List[Any]							=    B""""""
        for token in tokens:
              if token in self.special_tokens_decoder:
                    UpperCAmelCase__			:							Tuple							=    self.special_tokens_decoder[token].encode("""utf-8"""	)
              elif token in self.added_tokens_decoder:
                    UpperCAmelCase__			:							Optional[Any]							=    self.special_tokens_decoder[token].encode("""utf-8"""	)
              elif token in self.special_tokens_encoder:
                    UpperCAmelCase__			:							str							=    token.encode("""utf-8"""	)
              elif token in self.added_tokens_encoder:
                    UpperCAmelCase__			:							List[Any]							=    token.encode("""utf-8"""	)
              else:
                    UpperCAmelCase__			:							Optional[int]							=    bytes([ord(_lowerCamelCase	)]	)
              bstring += tok_string
        UpperCAmelCase__			:							int							=    bstring.decode("""utf-8"""							,       errors="""ignore"""	)
        return string




  def  _a      (self							,       _lowerCamelCase							,       _lowerCamelCase = None	):


        """simple docstring"""

        return ()

