





import argparse
import logging
import os

import datasets
import tensorflow as tf

from transformers import AutoTokenizer


UpperCAmelCase_					:   Optional[Any] 							=						logging.getLogger(__name__)






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

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






def 							_lowerCAmelCase (  _a   :					Tuple			)	->			Union[str, Any]:



     def fn(_a   :					int			):
          return tokenizer(examples["""text"""]			)

     return fn






def 							_lowerCAmelCase (  _a   :					Any			)	->			Union[str, Any]:
     lowerCAmelCase_					:       Optional[Any]    =		[]
     for i in range(len(tokenized_data["""input_ids"""]			)			):
          lowerCAmelCase_					:       Tuple    =		{
              '''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]			)			),
          }
          lowerCAmelCase_					:       List[Any]    =		tf.train.Features(feature=lowerCAmelCase_			)
          lowerCAmelCase_					:       str    =		tf.train.Example(features=lowerCAmelCase_			)
          lowerCAmelCase_					:       List[str]    =		example.SerializeToString()
          records.append(lowerCAmelCase_			)
     return records






def 							_lowerCAmelCase (  _a   :					List[Any]			)	->			Optional[Any]:
     lowerCAmelCase_					:       List[Any]    =		datasets.load_dataset(args.dataset_name					,   args.dataset_config					,   split=args.split			)

     if args.limit is not None:
          lowerCAmelCase_					:       str    =		min(len(lowerCAmelCase_			)					,   args.limit			)
          lowerCAmelCase_					:       Optional[Any]    =		dataset.select(range(lowerCAmelCase_			)			)
          print(F'Limiting the dataset to {args.limit} entries.'			)

     lowerCAmelCase_					:       int    =		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			)
          lowerCAmelCase_					:       Dict    =		os.path.join(args.output_dir					,   args.split			)
          if not os.path.exists(lowerCAmelCase_			):
               os.makedirs(lowerCAmelCase_			)
     else:
          lowerCAmelCase_					:       Optional[int]    =		os.path.join(args.output_dir					,   args.split			)

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

     lowerCAmelCase_					:       Tuple    =		dataset_tokenized.map(lowerCAmelCase_					,   batched=lowerCAmelCase_					,   batch_size=10_00					,   num_proc=4			)

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

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

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


if __name__ == "__main__":
      UpperCAmelCase_					:   int 							=						parse_args()
      main(args)












import unittest

from transformers import MODEL_FOR_DOCUMENT_QUESTION_ANSWERING_MAPPING, AutoTokenizer, is_vision_available
from transformers.pipelines import pipeline
from transformers.pipelines.document_question_answering import apply_tesseract
from transformers.testing_utils import (
    is_pipeline_test,
    nested_simplify,
    require_detectrona,
    require_pytesseract,
    require_tf,
    require_torch,
    require_vision,
    slow,
)

from .test_pipelines_common import ANY


if is_vision_available():
      from PIL import Image

      from transformers.image_utils import load_image
else:





      class      lowercase__    :







        @staticmethod
        def 	UpperCAmelCase__		(	*_lowercase    ,						**_lowercase						):
             pass






      def 							_lowerCAmelCase (  _a   :					List[str]			)	->			Any:
           return None


# This is a pinned image from a specific revision of a document question answering space, hosted by HuggingFace,
# so we can expect it to be available.
UpperCAmelCase_					:   Optional[Any] 							=						(
    """https://huggingface.co/spaces/impira/docquery/resolve/2f6c96314dc84dfda62d40de9da55f2f5165d403/invoice.png"""
)





@is_pipeline_test
@require_torch
@require_vision
class      lowercase__    (							unittest.TestCase  ):
  __UpperCamelCase	     =  MODEL_FOR_DOCUMENT_QUESTION_ANSWERING_MAPPING







  @require_pytesseract
  @require_vision
  def 	UpperCAmelCase__		(	self    ,						_lowercase    ,						_lowercase    ,						_lowercase						):
       lowerCAmelCase_					:       Optional[int]    =		pipeline(
           """document-question-answering"""    ,						model=_lowercase    ,						tokenizer=_lowercase    ,						image_processor=_lowercase						)

       lowerCAmelCase_					:       List[str]    =		INVOICE_URL
       lowerCAmelCase_					:       str    =		list(zip(*apply_tesseract(load_image(_lowercase						)    ,						_lowercase    ,						""""""						)						)						)
       lowerCAmelCase_					:       int    =		"""What is the placebo?"""
       lowerCAmelCase_					:       str    =		[
           {
               """image""": load_image(_lowercase						),
               """question""": question,
           },
           {
               """image""": image,
               """question""": question,
           },
           {
               """image""": image,
               """question""": question,
               """word_boxes""": word_boxes,
           },
       ]
       return dqa_pipeline, examples







  def 	UpperCAmelCase__		(	self    ,						_lowercase    ,						_lowercase						):
       lowerCAmelCase_					:       List[str]    =		dqa_pipeline(_lowercase    ,						top_k=2						)
       self.assertEqual(
           _lowercase    ,						[
               [
                   {"""score""": ANY(_lowercase						), """answer""": ANY(_lowercase						), """start""": ANY(_lowercase						), """end""": ANY(_lowercase						)},
                   {"""score""": ANY(_lowercase						), """answer""": ANY(_lowercase						), """start""": ANY(_lowercase						), """end""": ANY(_lowercase						)},
               ]
           ]
           * 3    ,						)







  @require_torch
  @require_detectrona
  @require_pytesseract
  def 	UpperCAmelCase__		(	self						):
       lowerCAmelCase_					:       Tuple    =		pipeline("""document-question-answering"""    ,						model="""hf-internal-testing/tiny-random-layoutlmv2"""						)
       lowerCAmelCase_					:       str    =		INVOICE_URL
       lowerCAmelCase_					:       int    =		"""How many cats are there?"""

       lowerCAmelCase_					:       List[Any]    =		[
           {"""score""": 0.0001, """answer""": """oy 2312/2019""", """start""": 38, """end""": 39},
           {"""score""": 0.0001, """answer""": """oy 2312/2019 DUE""", """start""": 38, """end""": 40},
       ]
       lowerCAmelCase_					:       Optional[Any]    =		dqa_pipeline(image=_lowercase    ,						question=_lowercase    ,						top_k=2						)
       self.assertEqual(nested_simplify(_lowercase    ,						decimals=4						)    ,						_lowercase						)

       lowerCAmelCase_					:       Any    =		dqa_pipeline({"""image""": image, """question""": question}    ,						top_k=2						)
       self.assertEqual(nested_simplify(_lowercase    ,						decimals=4						)    ,						_lowercase						)

       # This image does not detect ANY text in it, meaning layoutlmv2 should fail.
       # Empty answer probably
       lowerCAmelCase_					:       List[Any]    =		"""./tests/fixtures/tests_samples/COCO/000000039769.png"""
       lowerCAmelCase_					:       Any    =		dqa_pipeline(image=_lowercase    ,						question=_lowercase    ,						top_k=2						)
       self.assertEqual(_lowercase    ,						[]						)

       # We can optionnally pass directly the words and bounding boxes
       lowerCAmelCase_					:       int    =		"""./tests/fixtures/tests_samples/COCO/000000039769.png"""
       lowerCAmelCase_					:       int    =		[]
       lowerCAmelCase_					:       List[Any]    =		[]
       lowerCAmelCase_					:       List[Any]    =		dqa_pipeline(image=_lowercase    ,						question=_lowercase    ,						words=_lowercase    ,						boxes=_lowercase    ,						top_k=2						)
       self.assertEqual(_lowercase    ,						[]						)







  @slow
  @require_torch
  @require_detectrona
  @require_pytesseract
  def 	UpperCAmelCase__		(	self						):
       lowerCAmelCase_					:       Optional[Any]    =		pipeline(
           """document-question-answering"""    ,						model="""tiennvcs/layoutlmv2-base-uncased-finetuned-docvqa"""    ,						revision="""9977165"""    ,						)
       lowerCAmelCase_					:       Dict    =		INVOICE_URL
       lowerCAmelCase_					:       int    =		"""What is the invoice number?"""

       lowerCAmelCase_					:       Union[str, Any]    =		dqa_pipeline(image=_lowercase    ,						question=_lowercase    ,						top_k=2						)
       self.assertEqual(
           nested_simplify(_lowercase    ,						decimals=4						)    ,						[
               {"""score""": 0.9944, """answer""": """us-001""", """start""": 16, """end""": 16},
               {"""score""": 0.0009, """answer""": """us-001""", """start""": 16, """end""": 16},
           ]    ,						)

       lowerCAmelCase_					:       List[Any]    =		dqa_pipeline({"""image""": image, """question""": question}    ,						top_k=2						)
       self.assertEqual(
           nested_simplify(_lowercase    ,						decimals=4						)    ,						[
               {"""score""": 0.9944, """answer""": """us-001""", """start""": 16, """end""": 16},
               {"""score""": 0.0009, """answer""": """us-001""", """start""": 16, """end""": 16},
           ]    ,						)

       lowerCAmelCase_					:       List[str]    =		dqa_pipeline(
           [{"""image""": image, """question""": question}, {"""image""": image, """question""": question}]    ,						top_k=2						)
       self.assertEqual(
           nested_simplify(_lowercase    ,						decimals=4						)    ,						[
               [
                   {"""score""": 0.9944, """answer""": """us-001""", """start""": 16, """end""": 16},
                   {"""score""": 0.0009, """answer""": """us-001""", """start""": 16, """end""": 16},
               ],
           ]
           * 2    ,						)







  @slow
  @require_torch
  @require_detectrona
  @require_pytesseract
  def 	UpperCAmelCase__		(	self						):
       lowerCAmelCase_					:       Optional[int]    =		pipeline(
           """document-question-answering"""    ,						model="""tiennvcs/layoutlmv2-base-uncased-finetuned-docvqa"""    ,						revision="""9977165"""    ,						max_seq_len=50    ,						)
       lowerCAmelCase_					:       List[str]    =		INVOICE_URL
       lowerCAmelCase_					:       Optional[int]    =		"""What is the invoice number?"""

       lowerCAmelCase_					:       List[Any]    =		dqa_pipeline(image=_lowercase    ,						question=_lowercase    ,						top_k=2						)
       self.assertEqual(
           nested_simplify(_lowercase    ,						decimals=4						)    ,						[
               {"""score""": 0.9974, """answer""": """1110212019""", """start""": 23, """end""": 23},
               {"""score""": 0.9948, """answer""": """us-001""", """start""": 16, """end""": 16},
           ]    ,						)

       lowerCAmelCase_					:       Optional[Any]    =		dqa_pipeline({"""image""": image, """question""": question}    ,						top_k=2						)
       self.assertEqual(
           nested_simplify(_lowercase    ,						decimals=4						)    ,						[
               {"""score""": 0.9974, """answer""": """1110212019""", """start""": 23, """end""": 23},
               {"""score""": 0.9948, """answer""": """us-001""", """start""": 16, """end""": 16},
           ]    ,						)

       lowerCAmelCase_					:       List[Any]    =		dqa_pipeline(
           [{"""image""": image, """question""": question}, {"""image""": image, """question""": question}]    ,						top_k=2						)
       self.assertEqual(
           nested_simplify(_lowercase    ,						decimals=4						)    ,						[
               [
                   {"""score""": 0.9974, """answer""": """1110212019""", """start""": 23, """end""": 23},
                   {"""score""": 0.9948, """answer""": """us-001""", """start""": 16, """end""": 16},
               ]
           ]
           * 2    ,						)







  @slow
  @require_torch
  @require_pytesseract
  @require_vision
  def 	UpperCAmelCase__		(	self						):
       lowerCAmelCase_					:       int    =		AutoTokenizer.from_pretrained(
           """impira/layoutlm-document-qa"""    ,						revision="""3dc6de3"""    ,						add_prefix_space=_lowercase						)
       lowerCAmelCase_					:       Any    =		pipeline(
           """document-question-answering"""    ,						model="""impira/layoutlm-document-qa"""    ,						tokenizer=_lowercase    ,						revision="""3dc6de3"""    ,						)
       lowerCAmelCase_					:       int    =		INVOICE_URL
       lowerCAmelCase_					:       Union[str, Any]    =		"""What is the invoice number?"""

       lowerCAmelCase_					:       Optional[Any]    =		dqa_pipeline(image=_lowercase    ,						question=_lowercase    ,						top_k=2						)
       self.assertEqual(
           nested_simplify(_lowercase    ,						decimals=4						)    ,						[
               {"""score""": 0.4251, """answer""": """us-001""", """start""": 16, """end""": 16},
               {"""score""": 0.0819, """answer""": """1110212019""", """start""": 23, """end""": 23},
           ]    ,						)

       lowerCAmelCase_					:       int    =		dqa_pipeline({"""image""": image, """question""": question}    ,						top_k=2						)
       self.assertEqual(
           nested_simplify(_lowercase    ,						decimals=4						)    ,						[
               {"""score""": 0.4251, """answer""": """us-001""", """start""": 16, """end""": 16},
               {"""score""": 0.0819, """answer""": """1110212019""", """start""": 23, """end""": 23},
           ]    ,						)

       lowerCAmelCase_					:       Union[str, Any]    =		dqa_pipeline(
           [{"""image""": image, """question""": question}, {"""image""": image, """question""": question}]    ,						top_k=2						)
       self.assertEqual(
           nested_simplify(_lowercase    ,						decimals=4						)    ,						[
               [
                   {"""score""": 0.4251, """answer""": """us-001""", """start""": 16, """end""": 16},
                   {"""score""": 0.0819, """answer""": """1110212019""", """start""": 23, """end""": 23},
               ]
           ]
           * 2    ,						)

       lowerCAmelCase_					:       int    =		list(zip(*apply_tesseract(load_image(_lowercase						)    ,						_lowercase    ,						""""""						)						)						)

       # This model should also work if `image` is set to None
       lowerCAmelCase_					:       List[Any]    =		dqa_pipeline({"""image""": None, """word_boxes""": word_boxes, """question""": question}    ,						top_k=2						)
       self.assertEqual(
           nested_simplify(_lowercase    ,						decimals=4						)    ,						[
               {"""score""": 0.4251, """answer""": """us-001""", """start""": 16, """end""": 16},
               {"""score""": 0.0819, """answer""": """1110212019""", """start""": 23, """end""": 23},
           ]    ,						)







  @slow
  @require_torch
  @require_pytesseract
  @require_vision
  def 	UpperCAmelCase__		(	self						):
       lowerCAmelCase_					:       int    =		AutoTokenizer.from_pretrained(
           """impira/layoutlm-document-qa"""    ,						revision="""3dc6de3"""    ,						add_prefix_space=_lowercase						)
       lowerCAmelCase_					:       Optional[Any]    =		pipeline(
           """document-question-answering"""    ,						model="""impira/layoutlm-document-qa"""    ,						tokenizer=_lowercase    ,						revision="""3dc6de3"""    ,						max_seq_len=50    ,						)
       lowerCAmelCase_					:       Tuple    =		INVOICE_URL
       lowerCAmelCase_					:       Tuple    =		"""What is the invoice number?"""

       lowerCAmelCase_					:       Optional[int]    =		dqa_pipeline(image=_lowercase    ,						question=_lowercase    ,						top_k=2						)
       self.assertEqual(
           nested_simplify(_lowercase    ,						decimals=4						)    ,						[
               {"""score""": 0.9999, """answer""": """us-001""", """start""": 16, """end""": 16},
               {"""score""": 0.9998, """answer""": """us-001""", """start""": 16, """end""": 16},
           ]    ,						)

       lowerCAmelCase_					:       int    =		dqa_pipeline(
           [{"""image""": image, """question""": question}, {"""image""": image, """question""": question}]    ,						top_k=2						)
       self.assertEqual(
           nested_simplify(_lowercase    ,						decimals=4						)    ,						[
               [
                   {"""score""": 0.9999, """answer""": """us-001""", """start""": 16, """end""": 16},
                   {"""score""": 0.9998, """answer""": """us-001""", """start""": 16, """end""": 16},
               ]
           ]
           * 2    ,						)

       lowerCAmelCase_					:       Union[str, Any]    =		list(zip(*apply_tesseract(load_image(_lowercase						)    ,						_lowercase    ,						""""""						)						)						)

       # This model should also work if `image` is set to None
       lowerCAmelCase_					:       List[str]    =		dqa_pipeline({"""image""": None, """word_boxes""": word_boxes, """question""": question}    ,						top_k=2						)
       self.assertEqual(
           nested_simplify(_lowercase    ,						decimals=4						)    ,						[
               {"""score""": 0.9999, """answer""": """us-001""", """start""": 16, """end""": 16},
               {"""score""": 0.9998, """answer""": """us-001""", """start""": 16, """end""": 16},
           ]    ,						)







  @slow
  @require_torch
  def 	UpperCAmelCase__		(	self						):
       lowerCAmelCase_					:       int    =		pipeline(
           """document-question-answering"""    ,						model="""naver-clova-ix/donut-base-finetuned-docvqa"""    ,						tokenizer=AutoTokenizer.from_pretrained("""naver-clova-ix/donut-base-finetuned-docvqa"""						)    ,						feature_extractor="""naver-clova-ix/donut-base-finetuned-docvqa"""    ,						)

       lowerCAmelCase_					:       Union[str, Any]    =		INVOICE_URL
       lowerCAmelCase_					:       int    =		"""What is the invoice number?"""
       lowerCAmelCase_					:       str    =		dqa_pipeline(image=_lowercase    ,						question=_lowercase    ,						top_k=2						)
       self.assertEqual(nested_simplify(_lowercase    ,						decimals=4						)    ,						[{"""answer""": """us-001"""}]						)







  @require_tf
  @unittest.skip("""Document question answering not implemented in TF"""						)
  def 	UpperCAmelCase__		(	self						):
       pass
