




# Copyright 2023 The HuggingFace Inc. team. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import re

from ..models.auto import AutoProcessor
from ..models.vision_encoder_decoder import VisionEncoderDecoderModel
from ..utils import is_vision_available
from .base import PipelineTool


if is_vision_available():
  from PIL import Image


class 							UpperCamelCase_       (					UpperCAmelCase__	):

    '''simple docstring'''






    UpperCAmelCase__				    = '''naver-clova-ix/donut-base-finetuned-docvqa'''
    UpperCAmelCase__				    = (
        '''This is a tool that answers a question about an document (pdf). It takes an input named `document` which '''
        '''should be the document containing the information, as well as a `question` that is the question about the '''
        '''document. It returns a text that contains the answer to the question.'''
    )
    UpperCAmelCase__				    = '''document_qa'''
    UpperCAmelCase__				    = AutoProcessor
    UpperCAmelCase__				    = VisionEncoderDecoderModel

    UpperCAmelCase__				    = ['''image''', '''text''']
    UpperCAmelCase__				    = ['''text''']


    def __init__(     self :      int   ,					*UpperCAmelCase__ :      Dict   ,					**UpperCAmelCase__ :      Dict)		->List[str]:





           '''simple docstring'''

           if not is_vision_available():
                  raise ValueError('''Pillow must be installed to use the DocumentQuestionAnsweringTool.''')

           super().__init__(*UpperCAmelCase__   ,					**UpperCAmelCase__)


    def 			SCREAMING_SNAKE_CASE				(     self :      Union[str, Any]   ,					UpperCAmelCase__ :      "Image"   ,					UpperCAmelCase__ :      str)		->Optional[int]:





           '''simple docstring'''

           A__ 					=       '''<s_docvqa><s_question>{user_input}</s_question><s_answer>'''
           A__ 					=       task_prompt.replace('''{user_input}'''   ,					UpperCAmelCase__)
           A__ 					=       self.pre_processor.tokenizer(
               UpperCAmelCase__   ,					add_special_tokens=UpperCAmelCase__   ,					return_tensors='''pt''').input_ids
           A__ 					=       self.pre_processor(UpperCAmelCase__   ,					return_tensors='''pt''').pixel_values

           return {"decoder_input_ids": decoder_input_ids, "pixel_values": pixel_values}


    def 			SCREAMING_SNAKE_CASE				(     self :      int   ,					UpperCAmelCase__ :      List[str])		->Any:





           '''simple docstring'''

           return self.model.generate(
               inputs['''pixel_values'''].to(self.device)   ,					decoder_input_ids=inputs['''decoder_input_ids'''].to(self.device)   ,					max_length=self.model.decoder.config.max_position_embeddings   ,					early_stopping=UpperCAmelCase__   ,					pad_token_id=self.pre_processor.tokenizer.pad_token_id   ,					eos_token_id=self.pre_processor.tokenizer.eos_token_id   ,					use_cache=UpperCAmelCase__   ,					num_beams=1   ,					bad_words_ids=[[self.pre_processor.tokenizer.unk_token_id]]   ,					return_dict_in_generate=UpperCAmelCase__   ,					).sequences





    def 			SCREAMING_SNAKE_CASE				(     self :      Dict   ,					UpperCAmelCase__ :      Optional[int])		->Dict:





           '''simple docstring'''

           A__ 					=       self.pre_processor.batch_decode(UpperCAmelCase__)[0]
           A__ 					=       sequence.replace(self.pre_processor.tokenizer.eos_token   ,					'''''')
           A__ 					=       sequence.replace(self.pre_processor.tokenizer.pad_token   ,					'''''')
           A__ 					=       re.sub(R'''<.*?>'''   ,					''''''   ,					UpperCAmelCase__   ,					count=1).strip()  # remove first task start token
           A__ 					=       self.pre_processor.tokenajson(UpperCAmelCase__)

           return sequence["answer"]






"""simple docstring"""



from collections import OrderedDict
from typing import TYPE_CHECKING, Any, List, Mapping, Optional, Union

from ...configuration_utils import PretrainedConfig
from ...onnx import OnnxConfig
from ...utils import TensorType, logging


if TYPE_CHECKING:
  from ...onnx.config import PatchingSpec
  from ...tokenization_utils_base import PreTrainedTokenizerBase


__snake_case       =       logging.get_logger(__name__)

__snake_case       =       {
    """allenai/longformer-base-4096""": """https://huggingface.co/allenai/longformer-base-4096/resolve/main/config.json""",
    """allenai/longformer-large-4096""": """https://huggingface.co/allenai/longformer-large-4096/resolve/main/config.json""",
    """allenai/longformer-large-4096-finetuned-triviaqa""": (
        """https://huggingface.co/allenai/longformer-large-4096-finetuned-triviaqa/resolve/main/config.json"""
    ),
    """allenai/longformer-base-4096-extra.pos.embd.only""": (
        """https://huggingface.co/allenai/longformer-base-4096-extra.pos.embd.only/resolve/main/config.json"""
    ),
    """allenai/longformer-large-4096-extra.pos.embd.only""": (
        """https://huggingface.co/allenai/longformer-large-4096-extra.pos.embd.only/resolve/main/config.json"""
    ),
}







class _lowerCAmelCase							( snake_case_      ):
   __UpperCAmelCase					:			Tuple				    =    '''longformer'''







   def __init__(      self		,      UpperCamelCase__ = 512		,      UpperCamelCase__ = 2		,      UpperCamelCase__ = 1		,      UpperCamelCase__ = 0		,      UpperCamelCase__ = 2		,      UpperCamelCase__ = 3_0522		,      UpperCamelCase__ = 768		,      UpperCamelCase__ = 12		,      UpperCamelCase__ = 12		,      UpperCamelCase__ = 3072		,      UpperCamelCase__ = "gelu"		,      UpperCamelCase__ = 0.1		,      UpperCamelCase__ = 0.1		,      UpperCamelCase__ = 512		,      UpperCamelCase__ = 2		,      UpperCamelCase__ = 0.02		,      UpperCamelCase__ = 1e-12		,      UpperCamelCase__ = False		,      **UpperCamelCase__		,      )      ->						str:

       '''simple docstring'''




       super().__init__(pad_token_id=UpperCamelCase__		,      **UpperCamelCase__		)

       snake_case       : int    =       attention_window
       snake_case       : Any    =       sep_token_id
       snake_case       : Dict    =       bos_token_id
       snake_case       : int    =       eos_token_id
       snake_case       : List[str]    =       vocab_size
       snake_case       : Dict    =       hidden_size
       snake_case       : Optional[int]    =       num_hidden_layers
       snake_case       : List[str]    =       num_attention_heads
       snake_case       : Dict    =       hidden_act
       snake_case       : Union[str, Any]    =       intermediate_size
       snake_case       : Optional[int]    =       hidden_dropout_prob
       snake_case       : List[Any]    =       attention_probs_dropout_prob
       snake_case       : Any    =       max_position_embeddings
       snake_case       : Union[str, Any]    =       type_vocab_size
       snake_case       : Union[str, Any]    =       initializer_range
       snake_case       : int    =       layer_norm_eps
       snake_case       : str    =       onnx_export







class _lowerCAmelCase							( snake_case_      ):







   def __init__(      self		,      UpperCamelCase__		,      UpperCamelCase__ = "default"		,      UpperCamelCase__ = None		)      ->						List[str]:

       '''simple docstring'''




       super().__init__(UpperCamelCase__		,      UpperCamelCase__		,      UpperCamelCase__		)
       snake_case       : int    =       True







   @property
   def 					lowerCamelCase						(      self		)      ->						Mapping[str, Mapping[int, str]]:

       '''simple docstring'''




       if self.task == "multiple-choice":
           snake_case       : str    =       {0: "batch", 1: "choice", 2: "sequence"}
       else:
           snake_case       : List[str]    =       {0: "batch", 1: "sequence"}
       return OrderedDict(
           [
               ("input_ids", dynamic_axis),
               ("attention_mask", dynamic_axis),
               ("global_attention_mask", dynamic_axis),
           ]		)







   @property
   def 					lowerCamelCase						(      self		)      ->						Mapping[str, Mapping[int, str]]:

       '''simple docstring'''




       snake_case       : str    =       super().outputs
       if self.task == "default":
           snake_case       : str    =       {0: "batch"}
       return outputs







   @property
   def 					lowerCamelCase						(      self		)      ->						float:

       '''simple docstring'''




       return 1e-4







   @property
   def 					lowerCamelCase						(      self		)      ->						int:

       '''simple docstring'''




       return max(super().default_onnx_opset		,      14		)







   def 					lowerCamelCase						(      self		,      UpperCamelCase__		,      UpperCamelCase__ = -1		,      UpperCamelCase__ = -1		,      UpperCamelCase__ = False		,      UpperCamelCase__ = None		,      )      ->						Mapping[str, Any]:

       '''simple docstring'''




       snake_case       : Optional[int]    =       super().generate_dummy_inputs(
           preprocessor=UpperCamelCase__		,      batch_size=UpperCamelCase__		,      seq_length=UpperCamelCase__		,      is_pair=UpperCamelCase__		,      framework=UpperCamelCase__		)
       import torch

       # for some reason, replacing this code by inputs["global_attention_mask"] = torch.randint(2, inputs["input_ids"].shape, dtype=torch.int64)
       # makes the export fail randomly
       snake_case       : Any    =       torch.zeros_like(inputs["input_ids"]		)
       # make every second token global
       snake_case       : Any    =       1

       return inputs





