





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 			__A       (      lowerCamelCase__  ):




      """simple docstring"""







      def __init__(		self      ,							a__      ,							a__      ,							a__=None      ,							a__=1):



             """simple docstring"""





             _lowerCamelCase							:     Optional[int]	=		tokenizer
             _lowerCamelCase							:     Union[str, Any]	=		dataset
             _lowerCamelCase							:     List[str]	=		len(a__) if n_tasks is None else n_tasks
             _lowerCamelCase							:     Dict	=		n_copies



      def __iter__(		self):



             """simple docstring"""





             _lowerCamelCase							:     List[str]	=		[]
             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())
             _lowerCamelCase							:     Optional[int]	=		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 			__A       (      lowerCamelCase__  ):




      """simple docstring"""







      def __init__(		self      ,							a__      ,							a__      ,							a__):



             """simple docstring"""





             _lowerCamelCase							:     Optional[Any]	=		start_length
             _lowerCamelCase							:     Tuple	=		eof_strings
             _lowerCamelCase							:     Tuple	=		tokenizer



      def __call__(		self      ,							a__      ,							a__      ,							**a__):



             """simple docstring"""





             _lowerCamelCase							:     Dict	=		self.tokenizer.batch_decode(input_ids[:, self.start_length :])
             _lowerCamelCase							:     Tuple	=		[]
             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    __UpperCAmelCase(      lowercase_      ):
       _lowerCamelCase							:     Any	=		re.split('''(%s)''' % '''|'''.join(lowercase_      ) ,    lowercase_      )
       # last string should be ""
       return "".join(string_list[:-2]      )




def    __UpperCAmelCase(      lowercase_ ,    lowercase_ ,    lowercase_ ,    lowercase_ ,    lowercase_ ,    lowercase_=20 ,    **lowercase_      ):
       _lowerCamelCase							:     Optional[int]	=		defaultdict(lowercase_      )  # dict of list of generated tokens
       for step, batch in tqdm(enumerate(lowercase_      )      ):
              with torch.no_grad():
                     _lowerCamelCase							:     str	=		batch['''ids'''].shape[-1]
                     _lowerCamelCase							:     List[str]	=		accelerator.unwrap_model(lowercase_      ).generate(
                         input_ids=batch['''ids'''][:, : batch['''input_len''']] ,    num_return_sequences=lowercase_ ,    **lowercase_      )
                     # each task is generated batch_size times
                     _lowerCamelCase							:     Dict	=		batch['''task_id'''].repeat(lowercase_      )
                     _lowerCamelCase							:     str	=		accelerator.pad_across_processes(
                         lowercase_ ,    dim=1 ,    pad_index=tokenizer.pad_token_id      )

                     _lowerCamelCase,  _lowerCamelCase							:     str	=		accelerator.gather((generated_tokens, generated_tasks)      )
                     _lowerCamelCase							:     Optional[int]	=		generated_tokens.cpu().numpy()
                     _lowerCamelCase							:     Dict	=		generated_tasks.cpu().numpy()

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

       _lowerCamelCase							:     List[str]	=		[[] for _ in range(lowercase_      )]
       for task, generated_tokens in gen_token_dict.items():
              for s in generated_tokens:
                     _lowerCamelCase							:     List[Any]	=		tokenizer.decode(lowercase_ ,    skip_special_tokens=lowercase_ ,    clean_up_tokenization_spaces=lowercase_      )
                     code_gens[task].append(remove_last_block(lowercase_      )      )
       return code_gens




def    __UpperCAmelCase(      ):
       # Setup configuration
       _lowerCamelCase							:     Union[str, Any]	=		HfArgumentParser(lowercase_      )
       _lowerCamelCase							:     int	=		parser.parse_args()

       transformers.logging.set_verbosity_error()
       # enables code execution in code_eval metric
       _lowerCamelCase							:     Any	=		args.HF_ALLOW_CODE_EVAL
       # make sure tokenizer plays nice with multiprocessing
       _lowerCamelCase							:     Union[str, Any]	=		'''false'''

       if args.num_workers is None:
              _lowerCamelCase							:     Optional[int]	=		multiprocessing.cpu_count()

       # Use dataset load to feed to accelerate
       _lowerCamelCase							:     Optional[int]	=		Accelerator()
       set_seed(args.seed ,    device_specific=lowercase_      )

       # Load model and tokenizer
       _lowerCamelCase							:     Any	=		AutoTokenizer.from_pretrained(args.model_ckpt      )
       _lowerCamelCase							:     List[str]	=		tokenizer.eos_token
       _lowerCamelCase							:     Optional[int]	=		AutoModelForCausalLM.from_pretrained(args.model_ckpt      )

       # Generation settings
       _lowerCamelCase							:     Optional[Any]	=		{
           '''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 ,    lowercase_ ,    lowercase_      )]      ),
       }

       # Load evaluation dataset and metric
       _lowerCamelCase							:     int	=		load_dataset('''openai_humaneval'''      )
       _lowerCamelCase							:     int	=		load_metric('''code_eval'''      )

       _lowerCamelCase							:     List[str]	=		args.num_tasks if args.num_tasks is not None else len(human_eval['''test''']      )
       _lowerCamelCase							:     Any	=		args.n_samples // args.batch_size

       _lowerCamelCase							:     Union[str, Any]	=		TokenizedDataset(lowercase_ ,    human_eval['''test'''] ,    n_copies=lowercase_ ,    n_tasks=lowercase_      )
       # do not confuse args.batch_size, which is actually the num_return_sequences
       _lowerCamelCase							:     Union[str, Any]	=		DataLoader(lowercase_ ,    batch_size=1      )

       # Run a quick test to see if code evaluation is enabled
       try:
              _lowerCamelCase							:     Tuple	=		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

       _lowerCamelCase,  _lowerCamelCase							:     Optional[Any]	=		accelerator.prepare(lowercase_ ,    lowercase_      )

       _lowerCamelCase							:     int	=		complete_code(
           lowercase_ ,    lowercase_ ,    lowercase_ ,    lowercase_ ,    n_tasks=lowercase_ ,    batch_size=args.batch_size ,    **lowercase_ ,    )

       if accelerator.is_main_process:
              _lowerCamelCase							:     Optional[int]	=		[]

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

              # Evaluate completions with "code_eval" metric
              _lowerCamelCase,  _lowerCamelCase							:     List[str]	=		code_eval_metric.compute(
                  references=lowercase_ ,    predictions=lowercase_ ,    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(lowercase_ ,    lowercase_      )


# 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()








_lowerCamelCase			       =      [4, 1, 7, 4, 2, 6, 4, 1, 5, 3, 7, 5]
_lowerCamelCase			       =      [3, 7, 7, 4, 2, 6, 4, 1, 5, 3, 7, 5]
_lowerCamelCase			       =      {
    0: 'Sunday',
    1: 'Monday',
    2: 'Tuesday',
    3: 'Wednesday',
    4: 'Thursday',
    5: 'Friday',
    6: 'Saturday',
}




def    __UpperCAmelCase(      lowercase_ ,    lowercase_ ,    lowercase_      ):
       assert len(str(lowercase_      )      ) > 2, "year should be in YYYY format"
       assert 1 <= month <= 12, "month should be between 1 to 12"
       assert 1 <= day <= 31, "day should be between 1 to 31"

       # Doomsday algorithm:
       _lowerCamelCase							:     List[Any]	=		year // 1_00
       _lowerCamelCase							:     Dict	=		(5 * (century % 4) + 2) % 7
       _lowerCamelCase							:     Tuple	=		year % 1_00
       _lowerCamelCase							:     int	=		centurian % 12
       _lowerCamelCase							:     List[Any]	=		(
           (centurian // 12) + centurian_m + (centurian_m // 4) + century_anchor
       ) % 7
       _lowerCamelCase							:     List[Any]	=		(
           DOOMSDAY_NOT_LEAP[month - 1]
           if (year % 4 != 0) or (centurian == 0 and (year % 4_00) == 0)
           else DOOMSDAY_LEAP[month - 1]
       )
       _lowerCamelCase							:     Any	=		(dooms_day + day - day_anchor) % 7
       return WEEK_DAY_NAMES[week_day]


if __name__ == "__main__":
       import doctest

       doctest.testmod()

