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   :				Dict     			=						['''\nclass''', '''\ndef''', '''\n#''', '''\n@''', '''\nprint''', '''\nif''']


class   lowercase      (       a       ):




							def __init__(  self				:   int		,							_UpperCamelCase				:   Tuple		,							_UpperCamelCase				:   int		,							_UpperCamelCase				:   List[Any]=None		,							_UpperCamelCase				:   int=1 )   ->			List[Any]:



												'''simple docstring'''

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





							def __iter__(  self				:   Optional[int] )   ->			int:



												'''simple docstring'''

												SCREAMING_SNAKE_CASE           =    []
												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() )
												SCREAMING_SNAKE_CASE           =    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      (       a       ):




							def __init__(  self				:   Union[str, Any]		,							_UpperCamelCase				:   List[str]		,							_UpperCamelCase				:   Optional[int]		,							_UpperCamelCase				:   int )   ->			Optional[int]:



												'''simple docstring'''

												SCREAMING_SNAKE_CASE           =    start_length
												SCREAMING_SNAKE_CASE           =    eof_strings
												SCREAMING_SNAKE_CASE           =    tokenizer





							def __call__(  self				:   int		,							_UpperCamelCase				:   Optional[Any]		,							_UpperCamelCase				:   Dict		,							**_UpperCamelCase				:   List[str] )   ->			Optional[int]:



												'''simple docstring'''

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





def 		__lowerCamelCase							(UpperCAmelCase__       :							Optional[Any] ,	UpperCAmelCase__       :							Tuple ,	UpperCAmelCase__       :							Dict ,	UpperCAmelCase__       :							Any ,	UpperCAmelCase__       :							Union[str, Any] ,	UpperCAmelCase__       :							Dict=2_0 ,	**UpperCAmelCase__       :							Any					):
					SCREAMING_SNAKE_CASE           =    defaultdict(UpperCAmelCase__					)  # dict of list of generated tokens
					for step, batch in tqdm(enumerate(UpperCAmelCase__					)					):
										with torch.no_grad():
															SCREAMING_SNAKE_CASE           =    batch["ids"].shape[-1]
															SCREAMING_SNAKE_CASE           =    accelerator.unwrap_model(UpperCAmelCase__					).generate(
															    input_ids=batch["ids"][:, : batch["input_len"]] ,	num_return_sequences=UpperCAmelCase__ ,	**UpperCAmelCase__					)
															# each task is generated batch_size times
															SCREAMING_SNAKE_CASE           =    batch["task_id"].repeat(UpperCAmelCase__					)
															SCREAMING_SNAKE_CASE           =    accelerator.pad_across_processes(
															    UpperCAmelCase__ ,	dim=1 ,	pad_index=tokenizer.pad_token_id					)

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

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

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





def 		__lowerCamelCase							():
					# Setup configuration
					SCREAMING_SNAKE_CASE           =    HfArgumentParser(UpperCAmelCase__					)
					SCREAMING_SNAKE_CASE           =    parser.parse_args()

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

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

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

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

					# Generation settings
					SCREAMING_SNAKE_CASE           =    {
					    "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 ,	UpperCAmelCase__ ,	UpperCAmelCase__					)]					),
					}

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

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

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

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

					SCREAMING_SNAKE_CASE     ,				SCREAMING_SNAKE_CASE           =    accelerator.prepare(UpperCAmelCase__ ,	UpperCAmelCase__					)

					SCREAMING_SNAKE_CASE           =    complete_code(
					    UpperCAmelCase__ ,	UpperCAmelCase__ ,	UpperCAmelCase__ ,	UpperCAmelCase__ ,	n_tasks=UpperCAmelCase__ ,	batch_size=args.batch_size ,	**UpperCAmelCase__ ,	)

					if accelerator.is_main_process:
										SCREAMING_SNAKE_CASE           =    []

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

										# Evaluate completions with "code_eval" metric
										SCREAMING_SNAKE_CASE     ,				SCREAMING_SNAKE_CASE           =    code_eval_metric.compute(
										    references=UpperCAmelCase__ ,	predictions=UpperCAmelCase__ ,	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(UpperCAmelCase__ ,	UpperCAmelCase__					)


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





from dataclasses import dataclass
from typing import Tuple

import numpy as np
import torch


@dataclass
class   lowercase      :
							lowercase__  :    torch.Tensor  # [batch_size x 3]
							lowercase__  :    torch.Tensor  # [batch_size x 3]
							lowercase__  :    torch.Tensor  # [batch_size x 3]
							lowercase__  :    torch.Tensor  # [batch_size x 3]
							lowercase__  :    int
							lowercase__  :    int
							lowercase__  :    float
							lowercase__  :    float
							lowercase__  :    Tuple[int]




							def 		__snake_case(  self				:   str )   ->			Dict:



												'''simple docstring'''

												assert self.x.shape[0] == self.y.shape[0] == self.z.shape[0] == self.origin.shape[0]
												assert self.x.shape[1] == self.y.shape[1] == self.z.shape[1] == self.origin.shape[1] == 3
												assert len(self.x.shape ) == len(self.y.shape ) == len(self.z.shape ) == len(self.origin.shape ) == 2




							def 		__snake_case(  self				:   int )   ->			str:



												'''simple docstring'''

												return torch.from_numpy(np.array([self.width, self.height]		,							dtype=np.floataa ) )




							def 		__snake_case(  self				:   Tuple )   ->			List[str]:



												'''simple docstring'''

												return torch.from_numpy(np.array([self.x_fov, self.y_fov]		,							dtype=np.floataa ) )




							def 		__snake_case(  self				:   Any )   ->			torch.Tensor:



												'''simple docstring'''

												SCREAMING_SNAKE_CASE           =    torch.arange(self.height * self.width )
												SCREAMING_SNAKE_CASE           =    torch.stack(
												    [
												        pixel_indices % self.width,
												        torch.div(_UpperCamelCase		,							self.width		,							rounding_mode="trunc" ),
												    ]		,							axis=1		,							)
												return coords




							@property
							def 		__snake_case(  self				:   Any )   ->			Tuple:



												'''simple docstring'''

												SCREAMING_SNAKE_CASE     ,				*SCREAMING_SNAKE_CASE           =    self.shape
												SCREAMING_SNAKE_CASE           =    int(np.prod(_UpperCamelCase ) )

												SCREAMING_SNAKE_CASE           =    self.get_image_coords()
												SCREAMING_SNAKE_CASE           =    torch.broadcast_to(coords.unsqueeze(0 )		,							[batch_size * inner_batch_size, *coords.shape] )
												SCREAMING_SNAKE_CASE           =    self.get_camera_rays(_UpperCamelCase )

												SCREAMING_SNAKE_CASE           =    rays.view(_UpperCamelCase		,							inner_batch_size * self.height * self.width		,							2		,							3 )

												return rays




							def 		__snake_case(  self				:   Optional[int]		,							_UpperCamelCase				:   torch.Tensor )   ->			torch.Tensor:



												'''simple docstring'''

												SCREAMING_SNAKE_CASE     ,				*SCREAMING_SNAKE_CASE     ,				SCREAMING_SNAKE_CASE           =    coords.shape
												assert n_coords == 2
												assert batch_size == self.origin.shape[0]

												SCREAMING_SNAKE_CASE           =    coords.view(_UpperCamelCase		,							-1		,							2 )

												SCREAMING_SNAKE_CASE           =    self.resolution()
												SCREAMING_SNAKE_CASE           =    self.fov()

												SCREAMING_SNAKE_CASE           =    (flat.float() / (res - 1)) * 2 - 1
												SCREAMING_SNAKE_CASE           =    fracs * torch.tan(fov / 2 )

												SCREAMING_SNAKE_CASE           =    fracs.view(_UpperCamelCase		,							-1		,							2 )
												SCREAMING_SNAKE_CASE           =    (
												    self.z.view(_UpperCamelCase		,							1		,							3 )
												    + self.x.view(_UpperCamelCase		,							1		,							3 ) * fracs[:, :, :1]
												    + self.y.view(_UpperCamelCase		,							1		,							3 ) * fracs[:, :, 1:]
												)
												SCREAMING_SNAKE_CASE           =    directions / directions.norm(dim=-1		,							keepdim=_UpperCamelCase )
												SCREAMING_SNAKE_CASE           =    torch.stack(
												    [
												        torch.broadcast_to(self.origin.view(_UpperCamelCase		,							1		,							3 )		,							[batch_size, directions.shape[1], 3] ),
												        directions,
												    ]		,							dim=2		,							)
												return rays.view(_UpperCamelCase		,							*_UpperCamelCase		,							2		,							3 )





							def 		__snake_case(  self				:   List[Any]		,							_UpperCamelCase				:   int		,							_UpperCamelCase				:   int )   ->			"DifferentiableProjectiveCamera":



												'''simple docstring'''

												assert width * self.height == height * self.width, "The aspect ratio should not change."
												return DifferentiableProjectiveCamera(
												    origin=self.origin		,							x=self.x		,							y=self.y		,							z=self.z		,							width=_UpperCamelCase		,							height=_UpperCamelCase		,							x_fov=self.x_fov		,							y_fov=self.y_fov		,							)





def 		__lowerCamelCase							(UpperCAmelCase__       :							int					):
					SCREAMING_SNAKE_CASE           =    []
					SCREAMING_SNAKE_CASE           =    []
					SCREAMING_SNAKE_CASE           =    []
					SCREAMING_SNAKE_CASE           =    []
					for theta in np.linspace(0 ,	2 * np.pi ,	num=2_0					):
										SCREAMING_SNAKE_CASE           =    np.array([np.sin(UpperCAmelCase__					), np.cos(UpperCAmelCase__					), -0.5]					)
										z /= np.sqrt(np.sum(z**2					)					)
										SCREAMING_SNAKE_CASE           =    -z * 4
										SCREAMING_SNAKE_CASE           =    np.array([np.cos(UpperCAmelCase__					), -np.sin(UpperCAmelCase__					), 0.0]					)
										SCREAMING_SNAKE_CASE           =    np.cross(UpperCAmelCase__ ,	UpperCAmelCase__					)
										origins.append(UpperCAmelCase__					)
										xs.append(UpperCAmelCase__					)
										ys.append(UpperCAmelCase__					)
										zs.append(UpperCAmelCase__					)
					return DifferentiableProjectiveCamera(
					    origin=torch.from_numpy(np.stack(UpperCAmelCase__ ,	axis=0					)					).float() ,	x=torch.from_numpy(np.stack(UpperCAmelCase__ ,	axis=0					)					).float() ,	y=torch.from_numpy(np.stack(UpperCAmelCase__ ,	axis=0					)					).float() ,	z=torch.from_numpy(np.stack(UpperCAmelCase__ ,	axis=0					)					).float() ,	width=UpperCAmelCase__ ,	height=UpperCAmelCase__ ,	x_fov=0.7 ,	y_fov=0.7 ,	shape=(1, len(UpperCAmelCase__					)) ,	)




