
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_float32 (there's also the fix_lavis branch)
# also note: to convert Vicuna checkpoints, we had to include /home/niels/python_projects/checkpoints/FastChat/vicuna-7b in lavis/configs/models/blip2/blip2_instruct_vicuna7b.yaml
# same for Vicuna-13b
from lavis.models import load_model_and_preprocess
from PIL import Image

from transformers import (
    AutoTokenizer,
    BlipImageProcessor,
    InstructBlipConfig,
    InstructBlipForConditionalGeneration,
    InstructBlipProcessor,
    InstructBlipQFormerConfig,
    InstructBlipVisionConfig,
    LlamaConfig,
    LlamaTokenizerFast,
    TaConfig,
    TaTokenizerFast,
)
from transformers.utils.constants import OPENAI_CLIP_MEAN, OPENAI_CLIP_STD
def 							SCREAMING_SNAKE_CASE_	(					)			->						Dict:
       SCREAMING_SNAKE_CASE_							:				Optional[int]		='''https://raw.githubusercontent.com/salesforce/LAVIS/main/docs/_static/Confusing-Pictures.jpg'''
       SCREAMING_SNAKE_CASE_							:				List[str]		=Image.open(requests.get(UpperCAmelCase_			,							stream=UpperCAmelCase_				).raw				).convert('''RGB'''				)

       return image
def 							SCREAMING_SNAKE_CASE_	(					UpperCAmelCase_	:     int				)			->						List[str]:
       SCREAMING_SNAKE_CASE_							:				List[Any]		=[]
       # 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.embeddings.layernorm.weight''')				)
       rename_keys.append(('''Qformer.bert.embeddings.LayerNorm.bias''', '''qformer.embeddings.layernorm.bias''')				)

       # fmt: on
       return rename_keys
def 							SCREAMING_SNAKE_CASE_	(					UpperCAmelCase_	:     str			,							UpperCAmelCase_	:     Optional[int]			,							UpperCAmelCase_	:     int				)			->						Tuple:
       SCREAMING_SNAKE_CASE_							:				Dict		=dct.pop(UpperCAmelCase_				)
       SCREAMING_SNAKE_CASE_							:				Any		=val
def 							SCREAMING_SNAKE_CASE_	(					UpperCAmelCase_	:     Optional[Any]			,							UpperCAmelCase_	:     str				)			->						Any:
       for i in range(config.vision_config.num_hidden_layers				):
              # read in original q and v biases
              SCREAMING_SNAKE_CASE_							:				str		=state_dict.pop(f'visual_encoder.blocks.{i}.attn.q_bias'				)
              SCREAMING_SNAKE_CASE_							:				List[str]		=state_dict.pop(f'visual_encoder.blocks.{i}.attn.v_bias'				)

              # next, set bias in the state dict
              SCREAMING_SNAKE_CASE_							:				Optional[int]		=torch.cat((q_bias, torch.zeros_like(UpperCAmelCase_			,							requires_grad=UpperCAmelCase_				), v_bias)				)
              SCREAMING_SNAKE_CASE_							:				str		=qkv_bias
def 							SCREAMING_SNAKE_CASE_	(					UpperCAmelCase_	:     Any				)			->						int:
       SCREAMING_SNAKE_CASE_							:				List[Any]		=3_6_4 if '''coco''' in model_name else 2_2_4
       SCREAMING_SNAKE_CASE_							:				str		=InstructBlipVisionConfig(image_size=UpperCAmelCase_				).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 "t5-xl" in model_name:
              SCREAMING_SNAKE_CASE_							:				Dict		=TaConfig.from_pretrained('''google/flan-t5-xl'''			,							dense_act_fn='''gelu'''			,							bos_token_id=1				).to_dict()
       elif "t5-xxl" in model_name:
              SCREAMING_SNAKE_CASE_							:				Optional[int]		=TaConfig.from_pretrained('''google/flan-t5-xxl'''			,							dense_act_fn='''gelu'''			,							bos_token_id=1				).to_dict()
       elif "vicuna-7b" in model_name:
              SCREAMING_SNAKE_CASE_							:				Any		=LlamaConfig.from_pretrained('''decapoda-research/llama-7b-hf'''			,							vocab_size=3_2_0_0_1				).to_dict()
       elif "vicuna-13b" in model_name:
              SCREAMING_SNAKE_CASE_							:				Tuple		=LlamaConfig.from_pretrained('''decapoda-research/llama-13b-hf'''			,							vocab_size=3_2_0_0_1				).to_dict()
       else:
              raise ValueError('''Model name not supported'''				)

       # the authors add one special "[DEC]" token to the vocab of Q-Former, hence vocab size = 30522 + 1
       SCREAMING_SNAKE_CASE_							:				Optional[int]		=InstructBlipQFormerConfig(vocab_size=3_0_5_2_3				).to_dict()
       SCREAMING_SNAKE_CASE_							:				int		=InstructBlipConfig(vision_config=UpperCAmelCase_			,							text_config=UpperCAmelCase_			,							qformer_config=UpperCAmelCase_				)

       return config, image_size
@torch.no_grad()
def 							SCREAMING_SNAKE_CASE_	(					UpperCAmelCase_	:     Union[str, Any]			,							UpperCAmelCase_	:     Tuple=None			,							UpperCAmelCase_	:     int=False				)			->						List[str]:
       SCREAMING_SNAKE_CASE_							:				str		=AutoTokenizer.from_pretrained('''bert-base-uncased'''			,							truncation_side='''left'''				)
       qformer_tokenizer.add_special_tokens({'''bos_token''': '''[DEC]'''}				)

       if "t5" in model_name:
              SCREAMING_SNAKE_CASE_							:				Tuple		=TaTokenizerFast.from_pretrained('''google/flan-t5-xl'''			,							truncation_side='''left'''				)
       elif "vicuna" in model_name:
              # the following was used in the original implementation:
              # tokenizer = LlamaTokenizer.from_pretrained("huggyllama/llama-7b", use_fast=False, truncation_side="left")
              # tokenizer.add_special_tokens({"pad_token": "[PAD]"})
              # tokenizer.add_special_tokens({"bos_token": "</s>"})
              # tokenizer.add_special_tokens({"eos_token": "</s>"})
              # tokenizer.add_special_tokens({"unk_token": "</s>"})
              SCREAMING_SNAKE_CASE_							:				List[Any]		=LlamaTokenizerFast.from_pretrained(
                  '''huggyllama/llama-7b'''			,							truncation_side='''left'''			,							bos_token='''</s>'''			,							unk_token='''</s>'''				)
              tokenizer.add_special_tokens({'''pad_token''': '''[PAD]'''}				)

       SCREAMING_SNAKE_CASE_	,     SCREAMING_SNAKE_CASE_							:				Optional[Any]		=get_blipa_config(UpperCAmelCase_				)
       SCREAMING_SNAKE_CASE_							:				Tuple		=InstructBlipForConditionalGeneration(UpperCAmelCase_				).eval()

       SCREAMING_SNAKE_CASE_							:				Dict		={
           '''instructblip-vicuna-7b''': ('''blip2_vicuna_instruct''', '''vicuna7b'''),
           '''instructblip-vicuna-13b''': ('''blip2_vicuna_instruct''', '''vicuna13b'''),
           '''instructblip-flan-t5-xl''': ('''blip2_t5_instruct''', '''flant5xl'''),
           '''instructblip-flan-t5-xxl''': ('''blip2_t5_instruct''', '''flant5xxl'''),
       }

       SCREAMING_SNAKE_CASE_	,     SCREAMING_SNAKE_CASE_							:				str		=model_name_to_original[model_name]

       # load original model
       print('''Loading original model...'''				)
       SCREAMING_SNAKE_CASE_							:				int		='''cuda:1''' if torch.cuda.is_available() else '''cpu'''
       SCREAMING_SNAKE_CASE_							:				str		='''cuda:2''' if torch.cuda.is_available() else '''cpu'''
       SCREAMING_SNAKE_CASE_	,     SCREAMING_SNAKE_CASE_	,     SCREAMING_SNAKE_CASE_							:				Optional[int]		=load_model_and_preprocess(
           name=UpperCAmelCase_			,							model_type=UpperCAmelCase_			,							is_eval=UpperCAmelCase_			,							device=UpperCAmelCase_				)
       original_model.eval()
       print('''Done!'''				)

       # update state dict keys
       SCREAMING_SNAKE_CASE_							:				List[str]		=original_model.state_dict()
       SCREAMING_SNAKE_CASE_							:				Dict		=create_rename_keys(UpperCAmelCase_				)
       for src, dest in rename_keys:
              rename_key(UpperCAmelCase_			,							UpperCAmelCase_			,							UpperCAmelCase_				)

       # some keys can be renamed efficiently
       for key, val in state_dict.copy().items():
              SCREAMING_SNAKE_CASE_							:				Tuple		=state_dict.pop(UpperCAmelCase_				)
              if key.startswith('''Qformer.bert'''				):
                     SCREAMING_SNAKE_CASE_							:				str		=key.replace('''Qformer.bert'''			,							'''qformer'''				)
              if "attention.self" in key:
                     SCREAMING_SNAKE_CASE_							:				Dict		=key.replace('''self'''			,							'''attention'''				)
              if "llm_proj" in key:
                     SCREAMING_SNAKE_CASE_							:				Dict		=key.replace('''llm_proj'''			,							'''language_projection'''				)
              if "t5_proj" in key:
                     SCREAMING_SNAKE_CASE_							:				str		=key.replace('''t5_proj'''			,							'''language_projection'''				)
              if key.startswith('''llm_model'''				):
                     SCREAMING_SNAKE_CASE_							:				Union[str, Any]		=key.replace('''llm_model'''			,							'''language_model'''				)
              if key.startswith('''t5'''				):
                     SCREAMING_SNAKE_CASE_							:				Tuple		=key.replace('''t5'''			,							'''language'''				)
              SCREAMING_SNAKE_CASE_							:				List[Any]		=val

       # read in qv biases
       read_in_q_v_bias(UpperCAmelCase_			,							UpperCAmelCase_				)

       # note: weights get loaded in torch.float32 by default
       hf_model.load_state_dict(UpperCAmelCase_			,							strict=UpperCAmelCase_				)

       SCREAMING_SNAKE_CASE_							:				Any		=load_demo_image()
       SCREAMING_SNAKE_CASE_							:				int		='''What is unusual about this image?'''

       # create processor
       SCREAMING_SNAKE_CASE_							:				List[Any]		=BlipImageProcessor(
           size={'''height''': image_size, '''width''': image_size}			,							image_mean=UpperCAmelCase_			,							image_std=UpperCAmelCase_				)
       SCREAMING_SNAKE_CASE_							:				Tuple		=InstructBlipProcessor(
           image_processor=UpperCAmelCase_			,							tokenizer=UpperCAmelCase_			,							qformer_tokenizer=UpperCAmelCase_			,							)
       SCREAMING_SNAKE_CASE_							:				Any		=processor(images=UpperCAmelCase_			,							text=UpperCAmelCase_			,							return_tensors='''pt'''				).to(UpperCAmelCase_				)

       # make sure processor creates exact same pixel values
       SCREAMING_SNAKE_CASE_							:				Tuple		=vis_processors['''eval'''](UpperCAmelCase_				).unsqueeze(0				).to(UpperCAmelCase_				)
       SCREAMING_SNAKE_CASE_							:				Tuple		=inputs.pixel_values
       assert torch.allclose(original_pixel_values.to(pixel_values.device				)			,							UpperCAmelCase_				)

       original_model.to(UpperCAmelCase_				)
       hf_model.to(UpperCAmelCase_				)
       with torch.no_grad():
              if "vicuna" in model_name:
                     SCREAMING_SNAKE_CASE_							:				Union[str, Any]		=original_model({'''image''': original_pixel_values, '''text_input''': [prompt]}				).logits
                     SCREAMING_SNAKE_CASE_							:				Optional[int]		=hf_model(**UpperCAmelCase_				).logits
              else:
                     SCREAMING_SNAKE_CASE_							:				List[Any]		=original_model(
                         {'''image''': original_pixel_values, '''text_input''': [prompt], '''text_output''': ['''\n''']}				).logits
                     SCREAMING_SNAKE_CASE_							:				List[str]		=tokenizer('''\n'''			,							return_tensors='''pt'''				).input_ids.to(UpperCAmelCase_				)
                     SCREAMING_SNAKE_CASE_							:				Dict		=label_input_ids.masked_fill(label_input_ids == tokenizer.pad_token_id			,							-1_0_0				)
                     SCREAMING_SNAKE_CASE_							:				str		=hf_model(**UpperCAmelCase_			,							labels=UpperCAmelCase_				).logits

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

       # assert values
       assert original_logits.shape == logits.shape
       SCREAMING_SNAKE_CASE_							:				str		=1E-4 if '''vicuna''' in model_name else 1E-5
       assert torch.allclose(original_logits.to(logits.device				)			,							UpperCAmelCase_			,							atol=UpperCAmelCase_				)
       print('''Looks ok!'''				)

       print('''Generating with original model...'''				)
       SCREAMING_SNAKE_CASE_							:				str		=original_model.generate({'''image''': original_pixel_values, '''prompt''': prompt}			,							num_beams=5				)

       # important: we need to cast the weights of the HF model to the appropriate type
       print('''Generating with HF model...'''				)
       SCREAMING_SNAKE_CASE_							:				List[str]		=hf_model.generate(
           **UpperCAmelCase_			,							do_sample=UpperCAmelCase_			,							num_beams=5			,							max_length=2_5_6			,							min_length=1			,							top_p=0.9			,							repetition_penalty=1.5			,							length_penalty=1.0			,							temperature=1			,							)
       if "vicuna" in model_name:
              # convert output id 0 to 2 (eos_token_id)
              # TODO add this in the generate method?
              SCREAMING_SNAKE_CASE_							:				Optional[Any]		=2
       print('''Original generation:'''			,							UpperCAmelCase_				)
       SCREAMING_SNAKE_CASE_							:				Tuple		=processor.batch_decode(UpperCAmelCase_			,							skip_special_tokens=UpperCAmelCase_				)
       SCREAMING_SNAKE_CASE_							:				List[str]		=[text.strip() for text in output_text]
       print('''HF generation:'''			,							UpperCAmelCase_				)

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

       if push_to_hub:
              processor.push_to_hub(f'Salesforce/{model_name}'				)
              hf_model.push_to_hub(f'Salesforce/{model_name}'				)


if __name__ == "__main__":
 _lowercase											=    argparse.ArgumentParser()
 _lowercase											=    [
     """instructblip-vicuna-7b""",
     """instructblip-vicuna-13b""",
     """instructblip-flan-t5-xl""",
     """instructblip-flan-t5-xxl""",
 ]
 parser.add_argument(
     """--model_name""",
     default="""instructblip-flan-t5-xl""",
     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)


def 							SCREAMING_SNAKE_CASE_	(					UpperCAmelCase_	:     int | float | str				)			->						tuple[int, int]:
       try:
              SCREAMING_SNAKE_CASE_							:				int		=float(UpperCAmelCase_				)
       except ValueError:
              raise ValueError('''Please enter a valid number'''				)
       SCREAMING_SNAKE_CASE_							:				Any		=decimal - int(UpperCAmelCase_				)
       if fractional_part == 0:
              return int(UpperCAmelCase_				), 1
       else:
              SCREAMING_SNAKE_CASE_							:				Any		=len(str(UpperCAmelCase_				).split('''.'''				)[1]				)
              SCREAMING_SNAKE_CASE_							:				str		=int(decimal * (1_0**number_of_frac_digits)				)
              SCREAMING_SNAKE_CASE_							:				Any		=1_0**number_of_frac_digits
              SCREAMING_SNAKE_CASE_	,     SCREAMING_SNAKE_CASE_							:				Tuple		=denominator, numerator
              while True:
                     SCREAMING_SNAKE_CASE_							:				Any		=dividend % divisor
                     if remainder == 0:
                            break
                     SCREAMING_SNAKE_CASE_	,     SCREAMING_SNAKE_CASE_							:				Optional[int]		=divisor, remainder
              SCREAMING_SNAKE_CASE_	,     SCREAMING_SNAKE_CASE_							:				Optional[int]		=numerator / divisor, denominator / divisor
              return int(UpperCAmelCase_				), int(UpperCAmelCase_				)


if __name__ == "__main__":
 print(F"{decimal_to_fraction(2) = }")
 print(F"{decimal_to_fraction(89.0) = }")
 print(F"{decimal_to_fraction('67') = }")
 print(F"{decimal_to_fraction('45.0') = }")
 print(F"{decimal_to_fraction(1.5) = }")
 print(F"{decimal_to_fraction('6.25') = }")
 print(F"{decimal_to_fraction('78td') = }")
