





import argparse
import dataclasses
import json
import logging
import os
import shutil
from typing import List, Optional

import datasets
from accelerate import Accelerator
from datasets import load_dataset
from finetuning import finetune
from tqdm.auto import tqdm

import transformers
from transformers import AutoConfig, set_seed
from transformers.trainer_utils import IntervalStrategy


_lowerCAmelCase								=  logging.getLogger(__name__)

_lowerCAmelCase								=  """pytorch_model.bin"""

@dataclasses.dataclass
class  _UpperCAmelCase				:
      a    							=				dataclasses.field(
          metadata={'''help''': '''Path to pretrained model or model identifier from huggingface.co/models.'''}  )
      a    							=				dataclasses.field(
          default=a_      ,							metadata={'''help''': '''Where do you want to store the pretrained models downloaded from huggingface.co.'''}      ,							)






@dataclasses.dataclass
class  _UpperCAmelCase				:
      a    							=				dataclasses.field(metadata={'''help''': '''A csv or a json file containing the training data.'''}  )
      a    							=				dataclasses.field(metadata={'''help''': '''A csv or a json file containing the data to predict on.'''}  )
      a    							=				dataclasses.field(
          default=a_      ,							metadata={'''help''': '''A csv or a json file containing the validation data.'''}  )
      a    							=				dataclasses.field(
          default=a_      ,							metadata={'''help''': '''The name of the task to train on.'''}      ,							)
      a    							=				dataclasses.field(
          default=a_      ,							metadata={'''help''': '''The list of labels for the task.'''}  )






@dataclasses.dataclass
class  _UpperCAmelCase				:
      a    							=				dataclasses.field(
          metadata={'''help''': '''The output directory where the model predictions and checkpoints will be written.'''}  )
      a    							=				dataclasses.field(
          default='''accuracy'''      ,							metadata={'''help''': '''The evaluation metric used for the task.'''}  )
      a    							=				dataclasses.field(
          default='''no'''      ,							metadata={
              '''help''': '''The evaluation strategy to adopt during training. Possible values are: [\"no\", \"step\", \"epoch]'''
          }      ,							)
      a    							=				dataclasses.field(
          default=10      ,							metadata={'''help''': '''Number of evaluation calls with no improvement after which training will be stopped.'''}      ,							)
      a    							=				dataclasses.field(
          default=0.0      ,							metadata={
              '''help''': '''How much the specified evaluation metric must improve to satisfy early stopping conditions.'''
          }      ,							)
      a    							=				dataclasses.field(
          default=a_      ,							metadata={'''help''': '''Whether to filter the pseudo-labeled data based on the confidence score.'''}      ,							)
      a    							=				dataclasses.field(
          default=a_      ,							metadata={'''help''': '''Whether to filter the pseudo-labeled data based on the validation performance.'''}      ,							)
      a    							=				dataclasses.field(
          default=a_      ,							metadata={'''help''': '''Whether to fine-tune on labeled data after pseudo training.'''}      ,							)
      a    							=				dataclasses.field(
          default=0.0      ,							metadata={'''help''': '''Confidence threshold for pseudo-labeled data filtering.'''}      ,							)
      a    							=				dataclasses.field(
          default=100      ,							metadata={'''help''': '''Number of evaluation calls with no improvement after which training will be stopped.'''}      ,							)
      a    							=				dataclasses.field(
          default=a_      ,							metadata={'''help''': '''Random seed for initialization.'''}      ,							)






def      _lowerCAmelCase		(	_lowerCAmelCase	,_lowerCAmelCase	,_lowerCAmelCase	,_lowerCAmelCase	,_lowerCAmelCase	,_lowerCAmelCase  ):
   '''simple docstring'''


   A_  :					Optional[Any]         =						datasets.concatenate_datasets([infer_input, infer_output]	,axis=1  )

   if args.do_filter_by_confidence:
      A_  :					Optional[int]         =						dataset.filter(lambda _lowerCAmelCase  : example["probability"] > args.confidence_threshold  )

   if args.do_filter_by_val_performance:
      assert eval_result >= 0.0 and eval_result <= 1.0
      A_  :					Union[str, Any]         =						int(eval_result * len(__snake_case  )  )
      print(__snake_case  )
      A_  :					Dict         =						dataset.sort("""probability"""	,reverse=__snake_case  )
      A_  :					List[str]         =						dataset.select(range(__snake_case  )  )

   A_  :					Optional[Any]         =						dataset.remove_columns(["""label""", """probability"""]  )
   A_  :					Any         =						dataset.rename_column("""prediction"""	,"""label"""  )
   A_  :					Union[str, Any]         =						dataset.map(lambda _lowerCAmelCase  : {"label": idalabel[example["label"]]}  )
   A_  :					int         =						dataset.shuffle(seed=args.seed  )

   A_  :					Optional[int]         =						os.path.join(__snake_case	,f"""train_pseudo.{args.data_file_extension}"""  )
   if args.data_file_extension == "csv":
      dataset.to_csv(__snake_case	,index=__snake_case  )
   else:
      dataset.to_json(__snake_case  )







def      _lowerCAmelCase		(	_lowerCAmelCase	,_lowerCAmelCase	,_lowerCAmelCase	,_lowerCAmelCase	,**_lowerCAmelCase  ):
   '''simple docstring'''


   A_  :					Optional[int]         =						Accelerator()
   # Make one log on every process with the configuration for debugging.
   logging.basicConfig(
       format="""%(asctime)s - %(levelname)s - %(name)s - %(message)s"""	,datefmt="""%m/%d/%Y %H:%M:%S"""	,level=logging.INFO	,)
   logger.info(accelerator.state  )

   # Setup logging, we only want one process per machine to log things on the
   # screen. accelerator.is_local_main_process is only True for one process per
   # machine.
   logger.setLevel(logging.INFO if accelerator.is_local_main_process else logging.ERROR  )

   if accelerator.is_local_main_process:
      datasets.utils.logging.set_verbosity_warning()
      transformers.utils.logging.set_verbosity_info()
   else:
      datasets.utils.logging.set_verbosity_error()
      transformers.utils.logging.set_verbosity_error()

   A_  :					int         =						STModelArguments(model_name_or_path=__snake_case  )
   A_  :					Any         =						STDataArguments(train_file=__snake_case	,infer_file=__snake_case  )
   A_  :					Tuple         =						STTrainingArguments(output_dir=__snake_case  )
   A_  :					List[str]         =						argparse.Namespace()

   for arg_class in (model_args, data_args, training_args):
      for key, value in vars(__snake_case  ).items():
         setattr(__snake_case	,__snake_case	,__snake_case  )

   for key, value in kwargs.items():
      if hasattr(__snake_case	,__snake_case  ):
         setattr(__snake_case	,__snake_case	,__snake_case  )

    # Sanity checks
   A_  :					Optional[Any]         =						{}
   A_  :					Any         =						None

   # You need to provide the training data and the data to predict on
   assert args.train_file is not None
   assert args.infer_file is not None
   A_  :					List[Any]         =						args.train_file
   A_  :					Tuple         =						args.infer_file

   if args.evaluation_strategy != IntervalStrategy.NO.value:
      assert args.eval_file is not None
      A_  :					Any         =						args.eval_file

   for key in data_files:
      A_  :					List[str]         =						data_files[key].split("""."""  )[-1]
      assert extension in ["csv", "json"], f"""`{key}_file` should be a csv or a json file."""
      if args.data_file_extension is None:
         A_  :					Optional[Any]         =						extension
      else:
         assert extension == args.data_file_extension, f"""`{key}_file` should be a {args.data_file_extension} file`."""

   assert (
       args.eval_metric in datasets.list_metrics()
   ), f"""{args.eval_metric} not in the list of supported metrics {datasets.list_metrics()}."""

   # If passed along, set the training seed now.
   if args.seed is not None:
      set_seed(args.seed  )

   logger.info("""Creating the initial data directory for self-training..."""  )
   A_  :					Dict         =						f"""{args.output_dir}/self-train_iter-{{}}""".format
   A_  :					Tuple         =						data_dir_format(0  )

   if accelerator.is_main_process:
      if args.output_dir is not None:
         os.makedirs(args.output_dir	,exist_ok=__snake_case  )
         os.makedirs(__snake_case	,exist_ok=__snake_case  )
   accelerator.wait_for_everyone()

   A_  :					Union[str, Any]         =						None
   A_  :					Tuple         =						None
   A_  :					Any         =						0
   A_  :					Tuple         =						False
   # Show the progress bar
   A_  :					str         =						tqdm(range(args.max_selftrain_iterations  )	,disable=not accelerator.is_local_main_process  )

   # Self-train
   for iteration in range(0	,int(args.max_selftrain_iterations  )  ):
      A_  :					Optional[int]         =						data_dir_format(__snake_case  )
      assert os.path.exists(__snake_case  )

      # Stage 1: initial fine-tuning for iteration = 0 or pseudo-training for
      # iteration > 0
      A_  :					List[str]         =						os.path.join(__snake_case	,"""stage-1"""  )
      A_  :					str         =						{
          """accelerator""": accelerator,
          """model_name_or_path""": args.model_name_or_path,
          """cache_dir""": args.cache_dir,
          """do_train""": True,
          """train_file""": data_files["""train"""] if iteration == 0 else data_files["""train_pseudo"""],
          """do_eval""": True if args.eval_file is not None else False,
          """eval_file""": data_files["""eval"""],
          """do_predict""": True,
          """infer_file""": data_files["""infer"""],
          """task_name""": args.task_name,
          """label_list""": args.label_list,
          """output_dir""": current_output_dir,
          """eval_metric""": args.eval_metric,
          """evaluation_strategy""": args.evaluation_strategy,
          """early_stopping_patience""": args.early_stopping_patience,
          """early_stopping_threshold""": args.early_stopping_threshold,
          """seed""": args.seed,
      }
      # Add additional training arguments
      for key, value in kwargs.items():
         if key not in arguments_dict and not hasattr(__snake_case	,__snake_case  ):
            arguments_dict.update({key: value}  )

      A_  :					List[str]         =						os.path.join(__snake_case	,"""best-checkpoint"""	,__snake_case  )
      if os.path.exists(__snake_case  ):
         logger.info(
             """Found existing model checkpoint at %s. Skipping self-training: iteration: %d, stage: 1."""	,__snake_case	,__snake_case	,)
      else:
         logger.info("""***** Running self-training: iteration: %d, stage: 1 *****"""	,__snake_case  )
         finetune(**__snake_case  )
         accelerator.wait_for_everyone()
         assert os.path.exists(__snake_case  )
         logger.info("""Self-training job completed: iteration: %d, stage: 1."""	,__snake_case  )

      if iteration > 0 and args.finetune_on_labeled_data:
         # Stage 2 (optional): fine-tuning on the original labeled data
         A_  :					List[Any]         =						os.path.join(__snake_case	,"""best-checkpoint"""  )
         A_  :					str         =						os.path.join(__snake_case	,"""stage-2"""  )
         # Update arguments_dict
         A_  :					Union[str, Any]         =						model_path
         A_  :					Tuple         =						data_files["""train"""]
         A_  :					int         =						current_output_dir

         A_  :					Optional[Any]         =						os.path.join(__snake_case	,"""best-checkpoint"""	,__snake_case  )
         if os.path.exists(__snake_case  ):
            logger.info(
                """Found existing model checkpoint at %s. Skipping self-training: iteration: %d, stage: 2."""	,__snake_case	,__snake_case	,)
         else:
            logger.info("""***** Running self-training: iteration: %d, stage: 2 *****"""	,__snake_case  )
            finetune(**__snake_case  )
            accelerator.wait_for_everyone()
            assert os.path.exists(__snake_case  )
            logger.info("""Self-training job completed: iteration: %d, stage: 2."""	,__snake_case  )

      A_  :					Dict         =						iteration
      A_  :					int         =						data_dir_format(iteration + 1  )

      A_  :					Optional[int]         =						AutoConfig.from_pretrained(os.path.join(__snake_case	,"""best-checkpoint"""  )  )
      A_  :					Tuple         =						config.idalabel
      A_  :					int         =						os.path.join(__snake_case	,"""eval_results_best-checkpoint.json"""  )
      A_  :					List[str]         =						os.path.join(__snake_case	,"""test_results_best-checkpoint.json"""  )
      assert os.path.exists(__snake_case  )

      with open(__snake_case	,"""r"""  ) as f:
         A_  :					List[Any]         =						float(json.load(__snake_case  )[args.eval_metric]  )
      A_  :					List[str]         =						os.path.join(__snake_case	,"""infer_output_best-checkpoint.csv"""  )
      assert os.path.exists(__snake_case  )
      # Loading the dataset from local csv or json files.
      A_  :					List[Any]         =						load_dataset(args.data_file_extension	,data_files={"""data""": data_files["""infer"""]}  )["""data"""]
      A_  :					List[Any]         =						load_dataset("""csv"""	,data_files={"""data""": infer_output_file}  )["""data"""]

      if accelerator.is_main_process:
         os.makedirs(__snake_case	,exist_ok=__snake_case  )
         shutil.copy(__snake_case	,os.path.join(__snake_case	,f"""eval_results_iter-{iteration}.json"""  )  )
         if os.path.exists(__snake_case  ):
            shutil.copy(__snake_case	,os.path.join(__snake_case	,f"""test_results_iter-{iteration}.json"""  )  )
         create_pseudo_labeled_data(__snake_case	,__snake_case	,__snake_case	,__snake_case	,__snake_case	,__snake_case  )
      accelerator.wait_for_everyone()

      A_  :					Optional[int]         =						os.path.join(__snake_case	,f"""train_pseudo.{args.data_file_extension}"""  )

      if args.evaluation_strategy != IntervalStrategy.NO.value:
         A_  :					Any         =						eval_result

         if best_iteration is None:
            A_  :					int         =						new_iteration
            A_  :					List[str]         =						new_eval_result
         else:
            if new_eval_result - best_eval_result > args.early_stopping_threshold:
               A_  :					Dict         =						new_iteration
               A_  :					Optional[Any]         =						new_eval_result
               A_  :					Tuple         =						0
            else:
               if new_eval_result == best_eval_result:
                  A_  :					Dict         =						new_iteration
                  A_  :					Dict         =						new_eval_result
               early_stopping_patience_counter += 1

            if early_stopping_patience_counter >= args.early_stopping_patience:
               A_  :					Tuple         =						True

      progress_bar.update(1  )

      if should_training_stop:
         break

   if best_iteration is not None:
      # Save the best iteration
      logger.info("""Best iteration: %d"""	,__snake_case  )
      logger.info("""Best evaluation result: %s = %f"""	,args.eval_metric	,__snake_case  )
      accelerator.wait_for_everyone()
      if accelerator.is_main_process:
         shutil.copy(
             os.path.join(__snake_case	,f"""eval_results_iter-{iteration}.json"""  )	,os.path.join(__snake_case	,"""eval_results_best-iteration.json"""  )	,)
   else:
      # Assume that the last iteration is the best
      logger.info("""Best iteration: %d"""	,args.max_selftrain_iterations - 1  )
      logger.info("""Best evaluation result: %s = %f"""	,args.eval_metric	,__snake_case  )
      accelerator.wait_for_everyone()
      if accelerator.is_main_process:
         shutil.copy(
             os.path.join(__snake_case	,f"""eval_results_iter-{args.max_selftrain_iterations - 1}.json"""  )	,os.path.join(__snake_case	,"""eval_results_best-iteration.json"""  )	,)














"""simple docstring"""
import json
from typing import List, Optional, Tuple

from tokenizers import normalizers

from ...tokenization_utils_fast import PreTrainedTokenizerFast
from .tokenization_lxmert import LxmertTokenizer


snake_case : List[Any]     		=		{"""vocab_file""": """vocab.txt""", """tokenizer_file""": """tokenizer.json"""}

snake_case : List[Any]     		=		{
    """vocab_file""": {
        """unc-nlp/lxmert-base-uncased""": """https://huggingface.co/unc-nlp/lxmert-base-uncased/resolve/main/vocab.txt""",
    },
    """tokenizer_file""": {
        """unc-nlp/lxmert-base-uncased""": (
            """https://huggingface.co/unc-nlp/lxmert-base-uncased/resolve/main/tokenizer.json"""
        ),
    },
}

snake_case : Optional[int]     		=		{
    """unc-nlp/lxmert-base-uncased""": 5_1_2,
}

snake_case : List[Any]     		=		{
    """unc-nlp/lxmert-base-uncased""": {"""do_lower_case""": True},
}



class        UpperCamelCase__ (				a_):







    """simple docstring"""
    __UpperCAmelCase           = VOCAB_FILES_NAMES
    __UpperCAmelCase           = PRETRAINED_VOCAB_FILES_MAP
    __UpperCAmelCase           = PRETRAINED_INIT_CONFIGURATION
    __UpperCAmelCase           = PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES
    __UpperCAmelCase           = LxmertTokenizer







    def __init__(		self :	Union[str, Any]				,    UpperCamelCase_ :	List[str]=None				,    UpperCamelCase_ :	Dict=None				,    UpperCamelCase_ :	Optional[int]=True				,    UpperCamelCase_ :	Dict="[UNK]"				,    UpperCamelCase_ :	str="[SEP]"				,    UpperCamelCase_ :	Dict="[PAD]"				,    UpperCamelCase_ :	Optional[int]="[CLS]"				,    UpperCamelCase_ :	Any="[MASK]"				,    UpperCamelCase_ :	Any=True				,    UpperCamelCase_ :	List[Any]=None				,    **UpperCamelCase_ :	Dict				,    ):





           '''simple docstring'''

           super().__init__(
               UpperCamelCase_				,    tokenizer_file=UpperCamelCase_				,    do_lower_case=UpperCamelCase_				,    unk_token=UpperCamelCase_				,    sep_token=UpperCamelCase_				,    pad_token=UpperCamelCase_				,    cls_token=UpperCamelCase_				,    mask_token=UpperCamelCase_				,    tokenize_chinese_chars=UpperCamelCase_				,    strip_accents=UpperCamelCase_				,    **UpperCamelCase_				,    )

           __magic_name__      				=    json.loads(self.backend_tokenizer.normalizer.__getstate__() )
           if (
               normalizer_state.get('lowercase'				,    UpperCamelCase_ ) != do_lower_case
               or normalizer_state.get('strip_accents'				,    UpperCamelCase_ ) != strip_accents
               or normalizer_state.get('handle_chinese_chars'				,    UpperCamelCase_ ) != tokenize_chinese_chars
           ):
                  __magic_name__      				=    getattr(UpperCamelCase_				,    normalizer_state.pop('type' ) )
                  __magic_name__      				=    do_lower_case
                  __magic_name__      				=    strip_accents
                  __magic_name__      				=    tokenize_chinese_chars
                  __magic_name__      				=    normalizer_class(**UpperCamelCase_ )

           __magic_name__      				=    do_lower_case







    def 				a__			(		self :	Dict				,    UpperCamelCase_ :	Optional[Any]				,    UpperCamelCase_ :	Optional[int]=None ):





           '''simple docstring'''

           __magic_name__      				=    [self.cls_token_id] + token_ids_a + [self.sep_token_id]

           if token_ids_a:
                  output += token_ids_a + [self.sep_token_id]

           return output







    def 				a__			(		self :	int				,    UpperCamelCase_ :	List[int]				,    UpperCamelCase_ :	Optional[List[int]] = None ):





           '''simple docstring'''

           __magic_name__      				=    [self.sep_token_id]
           __magic_name__      				=    [self.cls_token_id]
           if token_ids_a is None:
                  return len(cls + token_ids_a + sep ) * [0]
           return len(cls + token_ids_a + sep ) * [0] + len(token_ids_a + sep ) * [1]







    def 				a__			(		self :	Dict				,    UpperCamelCase_ :	str				,    UpperCamelCase_ :	Optional[str] = None ):





           '''simple docstring'''

           __magic_name__      				=    self._tokenizer.model.save(UpperCamelCase_				,    name=UpperCamelCase_ )
           return tuple(UpperCamelCase_ )