
import json
import multiprocessing
import os
import re
from collections import defaultdict

import torch
from accelerate import Accelerator
from accelerate.utils import set_seed
from arguments import HumanEvalArguments
from datasets import load_dataset, load_metric
from torch.utils.data import IterableDataset
from torch.utils.data.dataloader import DataLoader
from tqdm import tqdm

import transformers
from transformers import AutoModelForCausalLM, AutoTokenizer, HfArgumentParser, StoppingCriteria, StoppingCriteriaList


lowerCamelCase__	=							["\nclass", "\ndef", "\n#", "\n@", "\nprint", "\nif"]







class        lowerCAmelCase__      (   __lowercase	):

						def __init__(			self       ,							a       ,							a       ,							a=None       ,							a=1				)					->      List[str]:


								'''simple docstring'''

								_UpperCamelCase						    =	tokenizer
								_UpperCamelCase						    =	dataset
								_UpperCamelCase						    =	len(a				) if n_tasks is None else n_tasks
								_UpperCamelCase						    =	n_copies







						def __iter__(			self				)					->      str:


								'''simple docstring'''

								_UpperCamelCase						    =	[]
								for task in range(self.n_tasks				):
										# without strip, the model generate commented codes ...
										prompts.append(self.tokenizer.eos_token + self.dataset[task]["""prompt"""].strip()				)
								_UpperCamelCase						    =	self.tokenizer(a       ,							padding=a       ,							return_tensors="""pt"""				)
								for task in range(self.n_tasks				):
										for _ in range(self.n_copies				):
												yield {
												    "ids": outputs.input_ids[task],
												    "task_id": task,
												    "input_len": outputs.attention_mask[task].sum(),
												}







class        lowerCAmelCase__      (   __lowercase	):

						def __init__(			self       ,							a       ,							a       ,							a				)					->      Union[str, Any]:


								'''simple docstring'''

								_UpperCamelCase						    =	start_length
								_UpperCamelCase						    =	eof_strings
								_UpperCamelCase						    =	tokenizer







						def __call__(			self       ,							a       ,							a       ,							**a				)					->      List[Any]:


								'''simple docstring'''

								_UpperCamelCase						    =	self.tokenizer.batch_decode(input_ids[:, self.start_length :]				)
								_UpperCamelCase						    =	[]
								for decoded_generation in decoded_generations:
										done.append(any(stop_string in decoded_generation for stop_string in self.eof_strings				)				)
								return all(a				)




def 							__A(lowerCAmelCase )		->				List[Any]:

		"""simple docstring"""






		_UpperCamelCase						    =	re.split("""(%s)""" % """|""".join(lowerCAmelCase )						,  lowerCAmelCase )
		# last string should be ""
		return "".join(string_list[:-2] )


def 							__A(lowerCAmelCase						,  lowerCAmelCase						,  lowerCAmelCase						,  lowerCAmelCase						,  lowerCAmelCase						,  lowerCAmelCase=2_0						,  **lowerCAmelCase )		->				List[str]:

		"""simple docstring"""






		_UpperCamelCase						    =	defaultdict(lowerCAmelCase )  # dict of list of generated tokens
		for step, batch in tqdm(enumerate(lowerCAmelCase ) ):
				with torch.no_grad():
						_UpperCamelCase						    =	batch["""ids"""].shape[-1]
						_UpperCamelCase						    =	accelerator.unwrap_model(lowerCAmelCase ).generate(
						    input_ids=batch["""ids"""][:, : batch["""input_len"""]]						,  num_return_sequences=lowerCAmelCase						,  **lowerCAmelCase )
						# each task is generated batch_size times
						_UpperCamelCase						    =	batch["""task_id"""].repeat(lowerCAmelCase )
						_UpperCamelCase						    =	accelerator.pad_across_processes(
						    lowerCAmelCase						,  dim=1						,  pad_index=tokenizer.pad_token_id )

						_UpperCamelCase    ,	_UpperCamelCase						    =	accelerator.gather((generated_tokens, generated_tasks) )
						_UpperCamelCase						    =	generated_tokens.cpu().numpy()
						_UpperCamelCase						    =	generated_tasks.cpu().numpy()

						for task, generated_tokens in zip(lowerCAmelCase						,  lowerCAmelCase ):
								gen_token_dict[task].append(lowerCAmelCase )

		_UpperCamelCase						    =	[[] for _ in range(lowerCAmelCase )]
		for task, generated_tokens in gen_token_dict.items():
				for s in generated_tokens:
						_UpperCamelCase						    =	tokenizer.decode(lowerCAmelCase						,  skip_special_tokens=lowerCAmelCase						,  clean_up_tokenization_spaces=lowerCAmelCase )
						code_gens[task].append(remove_last_block(lowerCAmelCase ) )
		return code_gens


def 							__A()		->				List[Any]:

		"""simple docstring"""






		_UpperCamelCase						    =	HfArgumentParser(lowerCAmelCase )
		_UpperCamelCase						    =	parser.parse_args()

		transformers.logging.set_verbosity_error()
		# enables code execution in code_eval metric
		_UpperCamelCase						    =	args.HF_ALLOW_CODE_EVAL
		# make sure tokenizer plays nice with multiprocessing
		_UpperCamelCase						    =	"""false"""

		if args.num_workers is None:
				_UpperCamelCase						    =	multiprocessing.cpu_count()

		# Use dataset load to feed to accelerate
		_UpperCamelCase						    =	Accelerator()
		set_seed(args.seed						,  device_specific=lowerCAmelCase )

		# Load model and tokenizer
		_UpperCamelCase						    =	AutoTokenizer.from_pretrained(args.model_ckpt )
		_UpperCamelCase						    =	tokenizer.eos_token
		_UpperCamelCase						    =	AutoModelForCausalLM.from_pretrained(args.model_ckpt )

		# Generation settings
		_UpperCamelCase						    =	{
		    """do_sample""": args.do_sample,
		    """temperature""": args.temperature,
		    """max_new_tokens""": args.max_new_tokens,
		    """top_p""": args.top_p,
		    """top_k""": args.top_k,
		    """stopping_criteria""": StoppingCriteriaList([EndOfFunctionCriteria(0						,  lowerCAmelCase						,  lowerCAmelCase )] ),
		}

		# Load evaluation dataset and metric
		_UpperCamelCase						    =	load_dataset("""openai_humaneval""" )
		_UpperCamelCase						    =	load_metric("""code_eval""" )

		_UpperCamelCase						    =	args.num_tasks if args.num_tasks is not None else len(human_eval["""test"""] )
		_UpperCamelCase						    =	args.n_samples // args.batch_size

		_UpperCamelCase						    =	TokenizedDataset(lowerCAmelCase						,  human_eval["""test"""]						,  n_copies=lowerCAmelCase						,  n_tasks=lowerCAmelCase )
		# do not confuse args.batch_size, which is actually the num_return_sequences
		_UpperCamelCase						    =	DataLoader(lowerCAmelCase						,  batch_size=1 )

		# Run a quick test to see if code evaluation is enabled
		try:
				_UpperCamelCase						    =	code_eval_metric.compute(references=[""""""]						,  predictions=[[""""""]] )
		except ValueError as exception:
				print(
				    """Code evaluation not enabled. Read the warning below carefully and then use `--HF_ALLOW_CODE_EVAL=\"1\"`"""
				    """ flag to enable code evaluation.""" )
				raise exception

		_UpperCamelCase    ,	_UpperCamelCase						    =	accelerator.prepare(lowerCAmelCase						,  lowerCAmelCase )

		_UpperCamelCase						    =	complete_code(
		    lowerCAmelCase						,  lowerCAmelCase						,  lowerCAmelCase						,  lowerCAmelCase						,  n_tasks=lowerCAmelCase						,  batch_size=args.batch_size						,  **lowerCAmelCase						,  )

		if accelerator.is_main_process:
				_UpperCamelCase						    =	[]

				for task in tqdm(range(lowerCAmelCase ) ):
						_UpperCamelCase						    =	human_eval["""test"""][task]["""test"""]
						_UpperCamelCase						    =	F'check({human_eval["test"][task]["entry_point"]})'
						references.append("""\n""" + test_func + """\n""" + entry_point )

				# Evaluate completions with "code_eval" metric
				_UpperCamelCase    ,	_UpperCamelCase						    =	code_eval_metric.compute(
				    references=lowerCAmelCase						,  predictions=lowerCAmelCase						,  num_workers=args.num_workers )
				print(F'Results: {pass_at_k}' )

				# Save results to json file
				with open(args.output_file						,  """w""" ) as fp:
						json.dump(lowerCAmelCase						,  lowerCAmelCase )


# For some reason the folliwng seems to be necessary sometimes for code_eval to work nice with multiprocessing
# https://stackoverflow.com/questions/60804599/python-multiprocessing-keeps-spawning-the-whole-script
if __name__ == "__main__":
		main()





import argparse

import torch

from transformers import YosoConfig, YosoForMaskedLM


def 							__A(lowerCAmelCase )		->				List[str]:

		"""simple docstring"""






		if "model" in orig_key:
				_UpperCamelCase						    =	orig_key.replace("""model."""						,  """""" )
		if "norm1" in orig_key:
				_UpperCamelCase						    =	orig_key.replace("""norm1"""						,  """attention.output.LayerNorm""" )
		if "norm2" in orig_key:
				_UpperCamelCase						    =	orig_key.replace("""norm2"""						,  """output.LayerNorm""" )
		if "norm" in orig_key:
				_UpperCamelCase						    =	orig_key.replace("""norm"""						,  """LayerNorm""" )
		if "transformer" in orig_key:
				_UpperCamelCase						    =	orig_key.split(""".""" )[0].split("""_""" )[-1]
				_UpperCamelCase						    =	orig_key.replace(F'transformer_{layer_num}'						,  F'encoder.layer.{layer_num}' )
		if "mha.attn" in orig_key:
				_UpperCamelCase						    =	orig_key.replace("""mha.attn"""						,  """attention.self""" )
		if "mha" in orig_key:
				_UpperCamelCase						    =	orig_key.replace("""mha"""						,  """attention""" )
		if "W_q" in orig_key:
				_UpperCamelCase						    =	orig_key.replace("""W_q"""						,  """self.query""" )
		if "W_k" in orig_key:
				_UpperCamelCase						    =	orig_key.replace("""W_k"""						,  """self.key""" )
		if "W_v" in orig_key:
				_UpperCamelCase						    =	orig_key.replace("""W_v"""						,  """self.value""" )
		if "ff1" in orig_key:
				_UpperCamelCase						    =	orig_key.replace("""ff1"""						,  """intermediate.dense""" )
		if "ff2" in orig_key:
				_UpperCamelCase						    =	orig_key.replace("""ff2"""						,  """output.dense""" )
		if "ff" in orig_key:
				_UpperCamelCase						    =	orig_key.replace("""ff"""						,  """output.dense""" )
		if "mlm_class" in orig_key:
				_UpperCamelCase						    =	orig_key.replace("""mlm.mlm_class"""						,  """cls.predictions.decoder""" )
		if "mlm" in orig_key:
				_UpperCamelCase						    =	orig_key.replace("""mlm"""						,  """cls.predictions.transform""" )
		if "cls" not in orig_key:
				_UpperCamelCase						    =	"""yoso.""" + orig_key

		return orig_key


def 							__A(lowerCAmelCase						,  lowerCAmelCase )		->				List[str]:

		"""simple docstring"""






		for key in orig_state_dict.copy().keys():
				_UpperCamelCase						    =	orig_state_dict.pop(lowerCAmelCase )

				if ("pooler" in key) or ("sen_class" in key):
						continue
				else:
						_UpperCamelCase						    =	val

		_UpperCamelCase						    =	orig_state_dict["""cls.predictions.decoder.bias"""]
		_UpperCamelCase						    =	torch.arange(lowerCAmelCase ).expand((1, -1) ) + 2

		return orig_state_dict


def 							__A(lowerCAmelCase						,  lowerCAmelCase						,  lowerCAmelCase )		->				Optional[int]:

		"""simple docstring"""






		_UpperCamelCase						    =	torch.load(lowerCAmelCase						,  map_location="""cpu""" )["""model_state_dict"""]
		_UpperCamelCase						    =	YosoConfig.from_json_file(lowerCAmelCase )
		_UpperCamelCase						    =	YosoForMaskedLM(lowerCAmelCase )

		_UpperCamelCase						    =	convert_checkpoint_helper(config.max_position_embeddings						,  lowerCAmelCase )

		print(model.load_state_dict(lowerCAmelCase ) )
		model.eval()
		model.save_pretrained(lowerCAmelCase )

		print(F'Checkpoint successfuly converted. Model saved at {pytorch_dump_path}' )


if __name__ == "__main__":
		lowerCamelCase__	=							argparse.ArgumentParser()
		# Required parameters
		parser.add_argument(
		    "--pytorch_model_path", default=None, type=str, required=True, help="Path to YOSO pytorch checkpoint."
		)
		parser.add_argument(
		    "--config_file",
		    default=None,
		    type=str,
		    required=True,
		    help="The json file for YOSO model config.",
		)
		parser.add_argument(
		    "--pytorch_dump_path", default=None, type=str, required=True, help="Path to the output PyTorch model."
		)
		lowerCamelCase__	=							parser.parse_args()
		convert_yoso_checkpoint(args.pytorch_model_path, args.config_file, args.pytorch_dump_path)



