
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 ( *A_				,      **A_       )  ->					Dict:
									"""simple docstring"""
									pass






					def       A       (					lowercase )   ->  Optional[int]:
							'''simple docstring'''

							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					: List[str]      =       (
    "https://huggingface.co/spaces/impira/docquery/resolve/2f6c96314dc84dfda62d40de9da55f2f5165d403/invoice.png"
)


@is_pipeline_test
@require_torch
@require_vision
class 				lowercase					(		unittest.TestCase   ):
		__lowercase       :       Optional[int]	     =				MODEL_FOR_DOCUMENT_QUESTION_ANSWERING_MAPPING



		@require_pytesseract
		@require_vision
		def __UpperCamelCase ( self				,      A_				,      A_				,      A_       )  ->					int:
				"""simple docstring"""
				UpperCamelCase		=     pipeline(
				    'document-question-answering'				,      model=A_				,      tokenizer=A_				,      image_processor=A_       )

				UpperCamelCase		=     INVOICE_URL
				UpperCamelCase		=     list(zip(*apply_tesseract(load_image(A_       )				,      A_				,      ''       )       )       )
				UpperCamelCase		=     'What is the placebo?'
				UpperCamelCase		=     [
				    {
				        'image': load_image(A_       ),
				        'question': question,
				    },
				    {
				        'image': image,
				        'question': question,
				    },
				    {
				        'image': image,
				        'question': question,
				        'word_boxes': word_boxes,
				    },
				]
				return dqa_pipeline, examples



		def __UpperCamelCase ( self				,      A_				,      A_       )  ->					List[str]:
				"""simple docstring"""
				UpperCamelCase		=     dqa_pipeline(A_				,      top_k=2       )
				self.assertEqual(
				    A_				,      [
				        [
				            {'score': ANY(A_       ), 'answer': ANY(A_       ), 'start': ANY(A_       ), 'end': ANY(A_       )},
				            {'score': ANY(A_       ), 'answer': ANY(A_       ), 'start': ANY(A_       ), 'end': ANY(A_       )},
				        ]
				    ]
				    * 3				,      )



		@require_torch
		@require_detectrona
		@require_pytesseract
		def __UpperCamelCase ( self       )  ->					Optional[Any]:
				"""simple docstring"""
				UpperCamelCase		=     pipeline('document-question-answering'				,      model='hf-internal-testing/tiny-random-layoutlmv2'       )
				UpperCamelCase		=     INVOICE_URL
				UpperCamelCase		=     'How many cats are there?'

				UpperCamelCase		=     [
				    {'score': 0.0001, 'answer': 'oy 2312/2019', 'start': 38, 'end': 39},
				    {'score': 0.0001, 'answer': 'oy 2312/2019 DUE', 'start': 38, 'end': 40},
				]
				UpperCamelCase		=     dqa_pipeline(image=A_				,      question=A_				,      top_k=2       )
				self.assertEqual(nested_simplify(A_				,      decimals=4       )				,      A_       )

				UpperCamelCase		=     dqa_pipeline({'image': image, 'question': question}				,      top_k=2       )
				self.assertEqual(nested_simplify(A_				,      decimals=4       )				,      A_       )

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

				# We can optionnally pass directly the words and bounding boxes
				UpperCamelCase		=     './tests/fixtures/tests_samples/COCO/000000039769.png'
				UpperCamelCase		=     []
				UpperCamelCase		=     []
				UpperCamelCase		=     dqa_pipeline(image=A_				,      question=A_				,      words=A_				,      boxes=A_				,      top_k=2       )
				self.assertEqual(A_				,      []       )



		@slow
		@require_torch
		@require_detectrona
		@require_pytesseract
		def __UpperCamelCase ( self       )  ->					List[Any]:
				"""simple docstring"""
				UpperCamelCase		=     pipeline(
				    'document-question-answering'				,      model='tiennvcs/layoutlmv2-base-uncased-finetuned-docvqa'				,      revision='9977165'				,      )
				UpperCamelCase		=     INVOICE_URL
				UpperCamelCase		=     'What is the invoice number?'

				UpperCamelCase		=     dqa_pipeline(image=A_				,      question=A_				,      top_k=2       )
				self.assertEqual(
				    nested_simplify(A_				,      decimals=4       )				,      [
				        {'score': 0.9944, 'answer': 'us-001', 'start': 16, 'end': 16},
				        {'score': 0.0009, 'answer': 'us-001', 'start': 16, 'end': 16},
				    ]				,      )

				UpperCamelCase		=     dqa_pipeline({'image': image, 'question': question}				,      top_k=2       )
				self.assertEqual(
				    nested_simplify(A_				,      decimals=4       )				,      [
				        {'score': 0.9944, 'answer': 'us-001', 'start': 16, 'end': 16},
				        {'score': 0.0009, 'answer': 'us-001', 'start': 16, 'end': 16},
				    ]				,      )

				UpperCamelCase		=     dqa_pipeline(
				    [{'image': image, 'question': question}, {'image': image, 'question': question}]				,      top_k=2       )
				self.assertEqual(
				    nested_simplify(A_				,      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       )  ->					Tuple:
				"""simple docstring"""
				UpperCamelCase		=     pipeline(
				    'document-question-answering'				,      model='tiennvcs/layoutlmv2-base-uncased-finetuned-docvqa'				,      revision='9977165'				,      max_seq_len=50				,      )
				UpperCamelCase		=     INVOICE_URL
				UpperCamelCase		=     'What is the invoice number?'

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

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

				UpperCamelCase		=     dqa_pipeline(
				    [{'image': image, 'question': question}, {'image': image, 'question': question}]				,      top_k=2       )
				self.assertEqual(
				    nested_simplify(A_				,      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       )  ->					Optional[Any]:
				"""simple docstring"""
				UpperCamelCase		=     AutoTokenizer.from_pretrained(
				    'impira/layoutlm-document-qa'				,      revision='3dc6de3'				,      add_prefix_space=A_       )
				UpperCamelCase		=     pipeline(
				    'document-question-answering'				,      model='impira/layoutlm-document-qa'				,      tokenizer=A_				,      revision='3dc6de3'				,      )
				UpperCamelCase		=     INVOICE_URL
				UpperCamelCase		=     'What is the invoice number?'

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

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

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

				UpperCamelCase		=     list(zip(*apply_tesseract(load_image(A_       )				,      A_				,      ''       )       )       )

				# This model should also work if `image` is set to None
				UpperCamelCase		=     dqa_pipeline({'image': None, 'word_boxes': word_boxes, 'question': question}				,      top_k=2       )
				self.assertEqual(
				    nested_simplify(A_				,      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       )  ->					str:
				"""simple docstring"""
				UpperCamelCase		=     AutoTokenizer.from_pretrained(
				    'impira/layoutlm-document-qa'				,      revision='3dc6de3'				,      add_prefix_space=A_       )
				UpperCamelCase		=     pipeline(
				    'document-question-answering'				,      model='impira/layoutlm-document-qa'				,      tokenizer=A_				,      revision='3dc6de3'				,      max_seq_len=50				,      )
				UpperCamelCase		=     INVOICE_URL
				UpperCamelCase		=     'What is the invoice number?'

				UpperCamelCase		=     dqa_pipeline(image=A_				,      question=A_				,      top_k=2       )
				self.assertEqual(
				    nested_simplify(A_				,      decimals=4       )				,      [
				        {'score': 0.9999, 'answer': 'us-001', 'start': 16, 'end': 16},
				        {'score': 0.9998, 'answer': 'us-001', 'start': 16, 'end': 16},
				    ]				,      )

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

				UpperCamelCase		=     list(zip(*apply_tesseract(load_image(A_       )				,      A_				,      ''       )       )       )

				# This model should also work if `image` is set to None
				UpperCamelCase		=     dqa_pipeline({'image': None, 'word_boxes': word_boxes, 'question': question}				,      top_k=2       )
				self.assertEqual(
				    nested_simplify(A_				,      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       )  ->					List[Any]:
				"""simple docstring"""
				UpperCamelCase		=     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'				,      )

				UpperCamelCase		=     INVOICE_URL
				UpperCamelCase		=     'What is the invoice number?'
				UpperCamelCase		=     dqa_pipeline(image=A_				,      question=A_				,      top_k=2       )
				self.assertEqual(nested_simplify(A_				,      decimals=4       )				,      [{'answer': 'us-001'}]       )



		@require_tf
		@unittest.skip('Document question answering not implemented in TF'       )
		def __UpperCamelCase ( self       )  ->					List[str]:
				"""simple docstring"""
				pass


import os
import re
from shutil import copyfile
from typing import Any, Dict, List, Optional, Tuple

import sentencepiece as spm

from ...tokenization_utils import AddedToken, PreTrainedTokenizer
from ...utils import logging


_UpperCAmelCase					: List[Any]      =       logging.get_logger(__name__)

_UpperCAmelCase					: Dict      =       {"vocab_file": "spiece.model"}

_UpperCAmelCase					: Dict      =       {
    "vocab_file": {
        "google/bigbird-roberta-base": "https://huggingface.co/google/bigbird-roberta-base/resolve/main/spiece.model",
        "google/bigbird-roberta-large": (
            "https://huggingface.co/google/bigbird-roberta-large/resolve/main/spiece.model"
        ),
        "google/bigbird-base-trivia-itc": (
            "https://huggingface.co/google/bigbird-base-trivia-itc/resolve/main/spiece.model"
        ),
    }
}

_UpperCAmelCase					: int      =       {
    "google/bigbird-roberta-base": 4_096,
    "google/bigbird-roberta-large": 4_096,
    "google/bigbird-base-trivia-itc": 4_096,
}


class 				lowercase					(		_SCREAMING_SNAKE_CASE   ):
		__lowercase       :       List[str]	     =				VOCAB_FILES_NAMES
		__lowercase       :       int	     =				PRETRAINED_VOCAB_FILES_MAP
		__lowercase       :       List[Any]	     =				PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES
		__lowercase       :       List[Any]	     =				["input_ids", "attention_mask"]
		__lowercase       :       List[int]	     =				[]



		def __init__( self				,      A_				,      A_="<unk>"				,      A_="<s>"				,      A_="</s>"				,      A_="<pad>"				,      A_="[SEP]"				,      A_="[MASK]"				,      A_="[CLS]"				,      A_ = None				,      **A_				,      )  ->					None:
				"""simple docstring"""
				UpperCamelCase		=     AddedToken(A_				,      lstrip=A_				,      rstrip=A_       ) if isinstance(A_				,      A_       ) else bos_token
				UpperCamelCase		=     AddedToken(A_				,      lstrip=A_				,      rstrip=A_       ) if isinstance(A_				,      A_       ) else eos_token
				UpperCamelCase		=     AddedToken(A_				,      lstrip=A_				,      rstrip=A_       ) if isinstance(A_				,      A_       ) else unk_token
				UpperCamelCase		=     AddedToken(A_				,      lstrip=A_				,      rstrip=A_       ) if isinstance(A_				,      A_       ) else pad_token
				UpperCamelCase		=     AddedToken(A_				,      lstrip=A_				,      rstrip=A_       ) if isinstance(A_				,      A_       ) else cls_token
				UpperCamelCase		=     AddedToken(A_				,      lstrip=A_				,      rstrip=A_       ) if isinstance(A_				,      A_       ) else sep_token

				# Mask token behave like a normal word, i.e. include the space before it
				UpperCamelCase		=     AddedToken(A_				,      lstrip=A_				,      rstrip=A_       ) if isinstance(A_				,      A_       ) else mask_token

				UpperCamelCase		=     {} if sp_model_kwargs is None else sp_model_kwargs

				super().__init__(
				    bos_token=A_				,      eos_token=A_				,      unk_token=A_				,      pad_token=A_				,      sep_token=A_				,      mask_token=A_				,      cls_token=A_				,      sp_model_kwargs=self.sp_model_kwargs				,      **A_				,      )

				UpperCamelCase		=     vocab_file

				UpperCamelCase		=     spm.SentencePieceProcessor(**self.sp_model_kwargs       )
				self.sp_model.Load(A_       )



		@property
		def __UpperCamelCase ( self       )  ->					Dict:
				"""simple docstring"""
				return self.sp_model.get_piece_size()



		def __UpperCamelCase ( self       )  ->					List[Any]:
				"""simple docstring"""
				UpperCamelCase		=     {self.convert_ids_to_tokens(A_       ): i for i in range(self.vocab_size       )}
				vocab.update(self.added_tokens_encoder       )
				return vocab



		def __getstate__( self       )  ->					Optional[int]:
				"""simple docstring"""
				UpperCamelCase		=     self.__dict__.copy()
				UpperCamelCase		=     None
				return state



		def __setstate__( self				,      A_       )  ->					Optional[int]:
				"""simple docstring"""
				UpperCamelCase		=     d

				# for backward compatibility
				if not hasattr(self				,      'sp_model_kwargs'       ):
						UpperCamelCase		=     {}

				UpperCamelCase		=     spm.SentencePieceProcessor(**self.sp_model_kwargs       )
				self.sp_model.Load(self.vocab_file       )



		def __UpperCamelCase ( self				,      A_       )  ->					List[str]:
				"""simple docstring"""
				return self.sp_model.encode(A_				,      out_type=A_       )



		def __UpperCamelCase ( self				,      A_       )  ->					Optional[Any]:
				"""simple docstring"""
				return self.sp_model.piece_to_id(A_       )



		def __UpperCamelCase ( self				,      A_       )  ->					Tuple:
				"""simple docstring"""
				UpperCamelCase		=     self.sp_model.IdToPiece(A_       )
				return token



		def __UpperCamelCase ( self				,      A_       )  ->					List[Any]:
				"""simple docstring"""
				UpperCamelCase		=     []
				UpperCamelCase		=     ''
				UpperCamelCase		=     False
				for token in tokens:
						# make sure that special tokens are not decoded using sentencepiece model
						if token in self.all_special_tokens:
								if not prev_is_special:
										out_string += " "
								out_string += self.sp_model.decode(A_       ) + token
								UpperCamelCase		=     True
								UpperCamelCase		=     []
						else:
								current_sub_tokens.append(A_       )
								UpperCamelCase		=     False
				out_string += self.sp_model.decode(A_       )
				return out_string.strip()



		def __UpperCamelCase ( self				,      A_				,      A_ = False				,      A_ = None				,      A_ = True				,      **A_				,      )  ->					str:
				"""simple docstring"""
				UpperCamelCase		=     kwargs.pop('use_source_tokenizer'				,      A_       )

				UpperCamelCase		=     self.convert_ids_to_tokens(A_				,      skip_special_tokens=A_       )

				# To avoid mixing byte-level and unicode for byte-level BPT
				# we need to build string separately for added tokens and byte-level tokens
				# cf. https://github.com/huggingface/transformers/issues/1133
				UpperCamelCase		=     []
				UpperCamelCase		=     []
				for token in filtered_tokens:
						if skip_special_tokens and token in self.all_special_ids:
								continue
						if token in self.added_tokens_encoder:
								if current_sub_text:
										sub_texts.append(self.convert_tokens_to_string(A_       )       )
										UpperCamelCase		=     []
								sub_texts.append(A_       )
						else:
								current_sub_text.append(A_       )
				if current_sub_text:
						sub_texts.append(self.convert_tokens_to_string(A_       )       )

				# Mimic the behavior of the Rust tokenizer:
				# No space before [MASK] and [SEP]
				if spaces_between_special_tokens:
						UpperCamelCase		=     re.sub(r' (\[(MASK|SEP)\])'				,      r'\1'				,      ' '.join(A_       )       )
				else:
						UpperCamelCase		=     ''.join(A_       )

				UpperCamelCase		=     (
				    clean_up_tokenization_spaces
				    if clean_up_tokenization_spaces is not None
				    else self.clean_up_tokenization_spaces
				)
				if clean_up_tokenization_spaces:
						UpperCamelCase		=     self.clean_up_tokenization(A_       )
						return clean_text
				else:
						return text



		def __UpperCamelCase ( self				,      A_				,      A_ = None       )  ->					Tuple[str]:
				"""simple docstring"""
				if not os.path.isdir(A_       ):
						logger.error(F'''Vocabulary path ({save_directory}) should be a directory'''       )
						return
				UpperCamelCase		=     os.path.join(
				    A_				,      (filename_prefix + '-' if filename_prefix else '') + VOCAB_FILES_NAMES['vocab_file']       )

				if os.path.abspath(self.vocab_file       ) != os.path.abspath(A_       ) and os.path.isfile(self.vocab_file       ):
						copyfile(self.vocab_file				,      A_       )
				elif not os.path.isfile(self.vocab_file       ):
						with open(A_				,      'wb'       ) as fi:
								UpperCamelCase		=     self.sp_model.serialized_model_proto()
								fi.write(A_       )

				return (out_vocab_file,)



		def __UpperCamelCase ( self				,      A_				,      A_ = None       )  ->					List[int]:
				"""simple docstring"""
				if token_ids_a is None:
						return [self.cls_token_id] + token_ids_a + [self.sep_token_id]
				UpperCamelCase		=     [self.cls_token_id]
				UpperCamelCase		=     [self.sep_token_id]
				return cls + token_ids_a + sep + token_ids_a + sep



		def __UpperCamelCase ( self				,      A_				,      A_ = None				,      A_ = False       )  ->					List[int]:
				"""simple docstring"""
				if already_has_special_tokens:
						return super().get_special_tokens_mask(
						    token_ids_a=A_				,      token_ids_a=A_				,      already_has_special_tokens=A_       )

				if token_ids_a is None:
						return [1] + ([0] * len(A_       )) + [1]
				return [1] + ([0] * len(A_       )) + [1] + ([0] * len(A_       )) + [1]



		def __UpperCamelCase ( self				,      A_				,      A_ = None       )  ->					List[int]:
				"""simple docstring"""
				UpperCamelCase		=     [self.sep_token_id]
				UpperCamelCase		=     [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]
