




import argparse
import logging
import os

import datasets
import tensorflow as tf

from transformers import AutoTokenizer


lowerCamelCase	:	Union[str, Any]				=   logging.getLogger(__name__)




def 						SCREAMING_SNAKE_CASE__ (   )  ->       str:
   snake_case				:    Optional[Any]           =	argparse.ArgumentParser(
       description="""Prepare TFRecord shards from pre-tokenized samples of the wikitext dataset."""					)
   parser.add_argument(
       """--dataset_name"""						,type=lowercase						,default="""wikitext"""						,help="""Name of the training. Explore datasets at: hf.co/datasets."""						,)
   parser.add_argument(
       """--dataset_config"""						,type=lowercase						,default="""wikitext-103-raw-v1"""						,help="""Configuration name of the dataset."""					)
   parser.add_argument(
       """--tokenizer_name_or_path"""						,type=lowercase						,default="""sayakpaul/unigram-tokenizer-wikitext"""						,help="""Tokenizer identifier. Can be a local filepath or a Hub identifier."""						,)
   parser.add_argument(
       """--shard_size"""						,type=lowercase						,default=1000						,help="""Number of entries to go in a single shard."""						,)
   parser.add_argument("""--split"""						,type=lowercase						,default="""train"""						,choices=["""train""", """test""", """validation"""]					)
   parser.add_argument(
       """--limit"""						,default=lowercase						,type=lowercase						,help="""Limit the number of shards (used for debugging)."""						,)
   parser.add_argument(
       """--max_length"""						,type=lowercase						,default=512						,help="""Maximum sequence length. For training on TPUs, it helps to have a maximum"""
       """ sequence length that is a multiple of 8."""						,)
   parser.add_argument(
       """--output_dir"""						,default="""tf-tpu"""						,type=lowercase						,help="""Output directory where the TFRecord shards will be saved. If the"""
       """ path is appended with `gs://` ('gs://tf-tpu', for example) then the TFRecord"""
       """ shards will be directly saved to a Google Cloud Storage bucket."""						,)

   snake_case				:    Union[str, Any]           =	parser.parse_args()
   return args




def 						SCREAMING_SNAKE_CASE__ (   lowercase					)  ->       List[str]:
   def fn(lowercase					):
      return tokenizer(examples["""text"""]					)

   return fn




def 						SCREAMING_SNAKE_CASE__ (   lowercase					)  ->       str:
   snake_case				:    Dict           =	[]
   for i in range(len(tokenized_data["""input_ids"""]					)					):
      snake_case				:    Union[str, Any]           =	{
          """input_ids""": tf.train.Feature(intaa_list=tf.train.IntaaList(value=tokenized_data["""input_ids"""][i]					)					),
          """attention_mask""": tf.train.Feature(
              intaa_list=tf.train.IntaaList(value=tokenized_data["""attention_mask"""][i]					)					),
      }
      snake_case				:    List[Any]           =	tf.train.Features(feature=lowercase					)
      snake_case				:    str           =	tf.train.Example(features=lowercase					)
      snake_case				:    Optional[int]           =	example.SerializeToString()
      records.append(lowercase					)
   return records




def 						SCREAMING_SNAKE_CASE__ (   lowercase					)  ->       Dict:
   snake_case				:    Tuple           =	datasets.load_dataset(args.dataset_name						,args.dataset_config						,split=args.split					)

   if args.limit is not None:
      snake_case				:    Tuple           =	min(len(lowercase					)						,args.limit					)
      snake_case				:    Union[str, Any]           =	dataset.select(range(lowercase					)					)
      print(f"""Limiting the dataset to {args.limit} entries."""					)

   snake_case				:    Dict           =	AutoTokenizer.from_pretrained(args.tokenizer_name_or_path					)

   # Handle output directory creation.
   # For serializing into a Google Cloud Storage Bucket, one needs to first
   # create a bucket.
   if "gs" not in args.output_dir:
      if not os.path.exists(args.output_dir					):
         os.makedirs(args.output_dir					)
      snake_case				:    List[Any]           =	os.path.join(args.output_dir						,args.split					)
      if not os.path.exists(lowercase					):
         os.makedirs(lowercase					)
   else:
      snake_case				:    List[str]           =	os.path.join(args.output_dir						,args.split					)

   # Tokenize the whole dataset at once.
   snake_case				:    str           =	tokenize_function(lowercase					)
   snake_case				:    Union[str, Any]           =	dataset.map(lowercase						,batched=lowercase						,num_proc=4						,remove_columns=["""text"""]					)

   # We need to concatenate all our texts together, and then split the result
   # into chunks of a fixed size, which we will call block_size. To do this, we
   # will use the map method again, with the option batched=True. When we use batched=True,
   # the function we pass to map() will be passed multiple inputs at once, allowing us
   # to group them into more or fewer examples than we had in the input.
   # This allows us to create our new fixed-length samples. The advantage of this
   # method is that we don't lose a whole lot of content from the dataset compared to the
   # case where we simply tokenize with a pre-defined max_length.

   def group_texts(lowercase					):
      # Concatenate all texts.
      snake_case				:    Dict           =	{k: sum(examples[k]						,[]					) for k in examples.keys()}
      snake_case				:    Dict           =	len(concatenated_examples[list(examples.keys()					)[0]]					)
      # We drop the small remainder, though you could add padding instead if the model supports it
      # In this, as in all things, we advise you to follow your heart 🫀
      snake_case				:    Dict           =	(total_length // args.max_length) * args.max_length
      # Split by chunks of max_len.
      snake_case				:    Dict           =	{
          k: [t[i : i + args.max_length] for i in range(0						,lowercase						,args.max_length					)]
          for k, t in concatenated_examples.items()
      }
      return result

   snake_case				:    List[Any]           =	dataset_tokenized.map(lowercase						,batched=lowercase						,batch_size=1000						,num_proc=4					)

   snake_case				:    Optional[int]           =	0
   snake_case				:    int           =	0
   for shard in range(0						,len(lowercase					)						,args.shard_size					):
      snake_case				:    str           =	grouped_dataset[shard : shard + args.shard_size]
      snake_case				:    Union[str, Any]           =	len(dataset_snapshot["""input_ids"""]					)
      snake_case				:    Optional[int]           =	os.path.join(lowercase						,f"""dataset-{shard_count}-{records_containing}.tfrecord"""					)
      snake_case				:    List[str]           =	get_serialized_examples(lowercase					)

      with tf.io.TFRecordWriter(lowercase					) as out_file:
         for i in range(len(lowercase					)					):
            snake_case				:    str           =	serialized_examples[i]
            out_file.write(lowercase					)
         print("""Wrote file {} containing {} records""".format(lowercase						,lowercase					)					)

      shard_count += 1
      total_records += records_containing

   with open(f"""split-{args.split}-records-count.txt"""						,"""w"""					) as f:
      print(f"""Total {args.split} records: {total_records}"""						,file=lowercase					)


if __name__ == "__main__":
       lowerCamelCase	:	Optional[int]				=   parse_args()
       main(args)











import warnings
from functools import wraps
from typing import Callable




def 						SCREAMING_SNAKE_CASE__ (   lowercase					)  ->       Callable:

   @wraps(lowercase					)
   def _inner_fn(*lowercase						,**lowercase					):
      warnings.warn(
          (f"""'{fn.__name__}' is experimental and might be subject to breaking changes in the future.""")						,lowercase						,)
      return fn(*lowercase						,**lowercase					)

   return _inner_fn





