





'''simple docstring'''







import argparse
import logging
import os

import datasets
import tensorflow as tf

from transformers import AutoTokenizer


_lowercase       						=			logging.getLogger(__name__)

def    __UpperCamelCase	(	) ->Dict:
 snake_case				=			argparse.ArgumentParser(
     description='''Prepare TFRecord shards from pre-tokenized samples of the wikitext dataset.'''     )
 parser.add_argument(
     '''--dataset_name'''					,   type=a					,   default='''wikitext'''					,   help='''Name of the training. Explore datasets at: hf.co/datasets.'''					,   )
 parser.add_argument(
     '''--dataset_config'''					,   type=a					,   default='''wikitext-103-raw-v1'''					,   help='''Configuration name of the dataset.'''     )
 parser.add_argument(
     '''--tokenizer_name_or_path'''					,   type=a					,   default='''sayakpaul/unigram-tokenizer-wikitext'''					,   help='''Tokenizer identifier. Can be a local filepath or a Hub identifier.'''					,   )
 parser.add_argument(
     '''--shard_size'''					,   type=a					,   default=1000					,   help='''Number of entries to go in a single shard.'''					,   )
 parser.add_argument('''--split'''					,   type=a					,   default='''train'''					,   choices=['''train''', '''test''', '''validation''']     )
 parser.add_argument(
     '''--limit'''					,   default=a					,   type=a					,   help='''Limit the number of shards (used for debugging).'''					,   )
 parser.add_argument(
     '''--max_length'''					,   type=a					,   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=a					,   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				=			parser.parse_args()
 return args

def    __UpperCamelCase	(	a    : List[Any]     ) ->Tuple:
 def fn(a    : Optional[int]     ):
  return tokenizer(examples['''text''']     )

 return fn

def    __UpperCamelCase	(	a    : Any     ) ->int:
 snake_case				=			[]
 for i in range(len(tokenized_data['''input_ids''']     )     ):
  snake_case				=			{
      '''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				=			tf.train.Features(feature=a     )
  snake_case				=			tf.train.Example(features=a     )
  snake_case				=			example.SerializeToString()
  records.append(a     )
 return records

def    __UpperCamelCase	(	a    : Tuple     ) ->List[str]:
 snake_case				=			datasets.load_dataset(args.dataset_name					,   args.dataset_config					,   split=args.split     )

 if args.limit is not None:
  snake_case				=			min(len(a     )					,   args.limit     )
  snake_case				=			dataset.select(range(a     )     )
  print(f"""Limiting the dataset to {args.limit} entries."""     )

 snake_case				=			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				=			os.path.join(args.output_dir					,   args.split     )
  if not os.path.exists(a     ):
   os.makedirs(a     )
 else:
  snake_case				=			os.path.join(args.output_dir					,   args.split     )

 # Tokenize the whole dataset at once.
 snake_case				=			tokenize_function(a     )
 snake_case				=			dataset.map(a					,   batched=a					,   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(a    : List[str]     ):
  # Concatenate all texts.
  snake_case				=			{k: sum(examples[k]					,   []     ) for k in examples.keys()}
  snake_case				=			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				=			(total_length // args.max_length) * args.max_length
  # Split by chunks of max_len.
  snake_case				=			{
      k: [t[i : i + args.max_length] for i in range(0					,   a					,   args.max_length     )]
      for k, t in concatenated_examples.items()
  }
  return result

 snake_case				=			dataset_tokenized.map(a					,   batched=a					,   batch_size=1000					,   num_proc=4     )

 snake_case				=			0
 snake_case				=			0
 for shard in range(0					,   len(a     )					,   args.shard_size     ):
  snake_case				=			grouped_dataset[shard : shard + args.shard_size]
  snake_case				=			len(dataset_snapshot['''input_ids''']     )
  snake_case				=			os.path.join(a					,   f"""dataset-{shard_count}-{records_containing}.tfrecord"""     )
  snake_case				=			get_serialized_examples(a     )

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

  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=a     )


if __name__ == "__main__":
 _lowercase       						=			parse_args()
 main(args)








'''simple docstring'''







import os
from dataclasses import dataclass, field
from io import BytesIO
from typing import TYPE_CHECKING, Any, ClassVar, Dict, Optional, Union

import numpy as np
import pyarrow as pa

from .. import config
from ..download.streaming_download_manager import xopen, xsplitext
from ..table import array_cast
from ..utils.py_utils import no_op_if_value_is_null, string_to_dict


if TYPE_CHECKING:
   from .features import FeatureType


_lowercase						,				_lowercase						,				_lowercase       						=			False, False, False
@dataclass
class 			_lowercase						:
     _UpperCAmelCase										=					None
     _UpperCAmelCase										=					True
     _UpperCAmelCase										=					True
     _UpperCAmelCase										=					None
     # Automatically constructed
     _UpperCAmelCase										=					"dict"
     _UpperCAmelCase										=					pa.struct({'''bytes''': pa.binary(), '''path''': pa.string()}					)
     _UpperCAmelCase										=					field(default='''Audio'''				,		init=__a				,		repr=__a					)







     def __call__( self    ) ->	Optional[Any]:
      return self.pa_type







     def     UpperCamelCase			( self    ,   A__    ) ->	dict:
      try:
       import soundfile as sf  # soundfile is a dependency of librosa, needed to decode audio files.
      except ImportError as err:
       raise ImportError('''To support encoding audio data, please install \'soundfile\'.'''    ) from err
      if isinstance(A__    ,   A__    ):
       return {"bytes": None, "path": value}
      elif isinstance(A__    ,   A__    ):
       return {"bytes": value, "path": None}
      elif "array" in value:
       # convert the audio array to wav bytes
       snake_case				=			BytesIO()
       sf.write(A__    ,   value['''array''']    ,   value['''sampling_rate''']    ,   format='''wav'''    )
       return {"bytes": buffer.getvalue(), "path": None}
      elif value.get('''path'''    ) is not None and os.path.isfile(value['''path''']    ):
       # we set "bytes": None to not duplicate the data if they're already available locally
       if value["path"].endswith('''pcm'''    ):
        # "PCM" only has raw audio bytes
        if value.get('''sampling_rate'''    ) is None:
         # At least, If you want to convert "PCM-byte" to "WAV-byte", you have to know sampling rate
         raise KeyError('''To use PCM files, please specify a \'sampling_rate\' in Audio object'''    )
        if value.get('''bytes'''    ):
         # If we already had PCM-byte, we don`t have to make "read file, make bytes" (just use it!)
         snake_case				=			np.frombuffer(value['''bytes''']    ,   dtype=np.intaa    ).astype(np.floataa    ) / 3_27_67
        else:
         snake_case				=			np.memmap(value['''path''']    ,   dtype='''h'''    ,   mode='''r'''    ).astype(np.floataa    ) / 3_27_67

        snake_case				=			BytesIO(bytes()    )
        sf.write(A__    ,   A__    ,   value['''sampling_rate''']    ,   format='''wav'''    )
        return {"bytes": buffer.getvalue(), "path": None}
       else:
        return {"bytes": None, "path": value.get('''path'''    )}
      elif value.get('''bytes'''    ) is not None or value.get('''path'''    ) is not None:
       # store the audio bytes, and path is used to infer the audio format using the file extension
       return {"bytes": value.get('''bytes'''    ), "path": value.get('''path'''    )}
      else:
       raise ValueError(
           F"""An audio sample should have one of 'path' or 'bytes' but they are missing or None in {value}."""    )







     def     UpperCamelCase			( self    ,   A__    ,   A__ = None    ) ->	dict:
      if not self.decode:
       raise RuntimeError('''Decoding is disabled for this feature. Please use Audio(decode=True) instead.'''    )

      snake_case				,		snake_case				=			(value['''path'''], BytesIO(value['''bytes''']    )) if value['''bytes'''] is not None else (value['''path'''], None)
      if path is None and file is None:
       raise ValueError(F"""An audio sample should have one of 'path' or 'bytes' but both are None in {value}."""    )

      try:
       import librosa
       import soundfile as sf
      except ImportError as err:
       raise ImportError('''To support decoding audio files, please install \'librosa\' and \'soundfile\'.'''    ) from err

      snake_case				=			xsplitext(A__    )[1][1:].lower() if path is not None else None
      if not config.IS_OPUS_SUPPORTED and audio_format == "opus":
       raise RuntimeError(
           '''Decoding \'opus\' files requires system library \'libsndfile\'>=1.0.31, '''
           '''You can try to update `soundfile` python library: `pip install "soundfile>=0.12.1"`. '''    )
      elif not config.IS_MP3_SUPPORTED and audio_format == "mp3":
       raise RuntimeError(
           '''Decoding \'mp3\' files requires system library \'libsndfile\'>=1.1.0, '''
           '''You can try to update `soundfile` python library: `pip install "soundfile>=0.12.1"`. '''    )

      if file is None:
       snake_case				=			token_per_repo_id or {}
       snake_case				=			path.split('''::'''    )[-1]
       try:
        snake_case				=			string_to_dict(A__    ,   config.HUB_DATASETS_URL    )['''repo_id''']
        snake_case				=			token_per_repo_id[repo_id]
       except (ValueError, KeyError):
        snake_case				=			None

       with xopen(A__    ,   '''rb'''    ,   use_auth_token=A__    ) as f:
        snake_case				,		snake_case				=			sf.read(A__    )

      else:
       snake_case				,		snake_case				=			sf.read(A__    )

      snake_case				=			array.T
      if self.mono:
       snake_case				=			librosa.to_mono(A__    )
      if self.sampling_rate and self.sampling_rate != sampling_rate:
       snake_case				=			librosa.resample(A__    ,   orig_sr=A__    ,   target_sr=self.sampling_rate    )
       snake_case				=			self.sampling_rate

      return {"path": path, "array": array, "sampling_rate": sampling_rate}







     def     UpperCamelCase			( self    ) ->	Union["FeatureType", Dict[str, "FeatureType"]]:
      from .features import Value

      if self.decode:
       raise ValueError('''Cannot flatten a decoded Audio feature.'''    )
      return {
          "bytes": Value('''binary'''    ),
          "path": Value('''string'''    ),
      }







     def     UpperCamelCase			( self    ,   A__    ) ->	pa.StructArray:
      if pa.types.is_string(storage.type    ):
       snake_case				=			pa.array([None] * len(A__    )    ,   type=pa.binary()    )
       snake_case				=			pa.StructArray.from_arrays([bytes_array, storage]    ,   ['''bytes''', '''path''']    ,   mask=storage.is_null()    )
      elif pa.types.is_binary(storage.type    ):
       snake_case				=			pa.array([None] * len(A__    )    ,   type=pa.string()    )
       snake_case				=			pa.StructArray.from_arrays([storage, path_array]    ,   ['''bytes''', '''path''']    ,   mask=storage.is_null()    )
      elif pa.types.is_struct(storage.type    ) and storage.type.get_all_field_indices('''array'''    ):
       snake_case				=			pa.array([Audio().encode_example(A__    ) if x is not None else None for x in storage.to_pylist()]    )
      elif pa.types.is_struct(storage.type    ):
       if storage.type.get_field_index('''bytes'''    ) >= 0:
        snake_case				=			storage.field('''bytes'''    )
       else:
        snake_case				=			pa.array([None] * len(A__    )    ,   type=pa.binary()    )
       if storage.type.get_field_index('''path'''    ) >= 0:
        snake_case				=			storage.field('''path'''    )
       else:
        snake_case				=			pa.array([None] * len(A__    )    ,   type=pa.string()    )
       snake_case				=			pa.StructArray.from_arrays([bytes_array, path_array]    ,   ['''bytes''', '''path''']    ,   mask=storage.is_null()    )
      return array_cast(A__    ,   self.pa_type    )







     def     UpperCamelCase			( self    ,   A__    ) ->	pa.StructArray:

      @no_op_if_value_is_null
      def path_to_bytes(A__    ):
       with xopen(A__    ,   '''rb'''    ) as f:
        snake_case				=			f.read()
       return bytes_

      snake_case				=			pa.array(
          [
              (path_to_bytes(x['''path''']    ) if x['''bytes'''] is None else x['''bytes''']) if x is not None else None
              for x in storage.to_pylist()
          ]    ,   type=pa.binary()    ,   )
      snake_case				=			pa.array(
          [os.path.basename(A__    ) if path is not None else None for path in storage.field('''path'''    ).to_pylist()]    ,   type=pa.string()    ,   )
      snake_case				=			pa.StructArray.from_arrays([bytes_array, path_array]    ,   ['''bytes''', '''path''']    ,   mask=bytes_array.is_null()    )
      return array_cast(A__    ,   self.pa_type    )

