



"""simple docstring"""





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    lowercase__     (					SCREAMING_SNAKE_CASE   ):







       '''simple docstring'''


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


             '''simple docstring'''




             UpperCAmelCase_    				=							tokenizer
             UpperCAmelCase_    				=							dataset
             UpperCAmelCase_    				=							len(_UpperCAmelCase					) if n_tasks is None else n_tasks
             UpperCAmelCase_    				=							n_copies







       def __iter__(							self    :						Tuple					)				->		List[Any]:


             '''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(_UpperCAmelCase	,       padding=_UpperCAmelCase	,       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    lowercase__     (					SCREAMING_SNAKE_CASE   ):







       '''simple docstring'''


       def __init__(							self    :						List[Any]	,       _UpperCAmelCase    :						Optional[Any]	,       _UpperCAmelCase    :						Tuple	,       _UpperCAmelCase    :						List[str]					)				->		Dict:


             '''simple docstring'''




             UpperCAmelCase_    				=							start_length
             UpperCAmelCase_    				=							eof_strings
             UpperCAmelCase_    				=							tokenizer







       def __call__(							self    :						str	,       _UpperCAmelCase    :						List[Any]	,       _UpperCAmelCase    :						List[Any]	,       **_UpperCAmelCase    :						Optional[Any]					)				->		Union[str, 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(_UpperCAmelCase					)



def      a__			(   lowerCAmelCase__   ):
      UpperCAmelCase_    				=							re.split("(%s)" % "|".join(lowerCAmelCase__   )			,    lowerCAmelCase__   )
      # last string should be ""
      return "".join(string_list[:-2]   )
def      a__			(   lowerCAmelCase__			,    lowerCAmelCase__			,    lowerCAmelCase__			,    lowerCAmelCase__			,    lowerCAmelCase__			,    lowerCAmelCase__=20			,    **lowerCAmelCase__   ):
      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__			(   ):
      # Setup configuration
      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()









"""simple docstring"""





def      a__			(   lowerCAmelCase__   ):
      if not head:
            return True
      # split the list to two parts
      UpperCAmelCase_				,					UpperCAmelCase_    				=							head.next, head
      while fast and fast.next:
            UpperCAmelCase_    				=							fast.next.next
            UpperCAmelCase_    				=							slow.next
      UpperCAmelCase_    				=							slow.next
      UpperCAmelCase_    				=							None  # Don't forget here! But forget still works!
      # reverse the second part
      UpperCAmelCase_    				=							None
      while second:
            UpperCAmelCase_    				=							second.next
            UpperCAmelCase_    				=							node
            UpperCAmelCase_    				=							second
            UpperCAmelCase_    				=							nxt
      # compare two parts
      # second part has the same or one less node
      while node:
            if node.val != head.val:
                  return False
            UpperCAmelCase_    				=							node.next
            UpperCAmelCase_    				=							head.next
      return True
def      a__			(   lowerCAmelCase__   ):
      if not head or not head.next:
            return True

      # 1. Get the midpoint (slow)
      UpperCAmelCase_    				=							UpperCAmelCase_    				=							UpperCAmelCase_    				=							head
      while fast and fast.next:
            UpperCAmelCase_				,					UpperCAmelCase_    				=							fast.next.next, slow.next

      # 2. Push the second half into the stack
      UpperCAmelCase_    				=							[slow.val]
      while slow.next:
            UpperCAmelCase_    				=							slow.next
            stack.append(slow.val   )

      # 3. Comparison
      while stack:
            if stack.pop() != cur.val:
                  return False
            UpperCAmelCase_    				=							cur.next

      return True


def      a__			(   lowerCAmelCase__   ):
      if not head or not head.next:
            return True
      UpperCAmelCase_    				=							{}
      UpperCAmelCase_    				=							0
      while head:
            if head.val in d:
                  d[head.val].append(lowerCAmelCase__   )
            else:
                  UpperCAmelCase_    				=							[pos]
            UpperCAmelCase_    				=							head.next
            pos += 1
      UpperCAmelCase_    				=							pos - 1
      UpperCAmelCase_    				=							0
      for v in d.values():
            if len(lowerCAmelCase__   ) % 2 != 0:
                  middle += 1
            else:
                  UpperCAmelCase_    				=							0
                  for i in range(0			,    len(lowerCAmelCase__   )   ):
                        if v[i] + v[len(lowerCAmelCase__   ) - 1 - step] != checksum:
                              return False
                        step += 1
            if middle > 1:
                  return False
      return True




