import argparse
import random

import joblib
import numpy as np
import torch
from igf.igf import (
    SecondaryLearner,
    collect_objective_set,
    compute_perplexity,
    generate_datasets,
    load_gpta,
    recopy_gpta,
    set_seed,
    train_secondary_learner,
)
from torch.utils.data import DataLoader, RandomSampler

from transformers import GPTaLMHeadModel


def 	lowerCamelCase					(	UpperCamelCase     :				List[Any]=32			,       UpperCamelCase     :				int=10			,       UpperCamelCase     :				Optional[Any]=1_00			,       UpperCamelCase     :				Optional[Any]=10_26			,       UpperCamelCase     :				List[str]=True			,       UpperCamelCase     :				Optional[Any]="data/tokenized_stories_train_wikitext103.jbl"			,       UpperCamelCase     :				int="igf_context_pairs.jbl"			,       )   ->    List[str]:
		set_seed(3							)
		# generate train_data and objective_set
		_lowerCamelCase   ,							_lowerCamelCase				   =  generate_datasets(
		    UpperCamelCase			,       UpperCamelCase			,       number=UpperCamelCase			,       min_len=10_26			,       trim=UpperCamelCase							)
		# keeps model same across runs
		set_seed(4							)
		# model, lm_optimizer, lm_scheduler = recopy_gpt2(model, device, max_steps) # store original model weights
		# can we train on GPU?
		_lowerCamelCase				   =  torch.device('cuda:0' if torch.cuda.is_available() else 'cpu'							)

		# load pretrained model
		_lowerCamelCase				   =  load_gpta('gpt2'							).to(UpperCamelCase							)
		print('computing perplexity on objective set'							)
		_lowerCamelCase				   =  compute_perplexity(UpperCamelCase			,       UpperCamelCase			,       UpperCamelCase							).item()
		print('perplexity on objective set:'			,       UpperCamelCase							)

		# collect igf pairs and save to file demo.jbl
		collect_objective_set(UpperCamelCase			,       UpperCamelCase			,       UpperCamelCase			,       UpperCamelCase			,       UpperCamelCase			,       UpperCamelCase			,       UpperCamelCase			,       UpperCamelCase							)

		# clean up, delete model and data we don't need anymore
		del model, train_data, objective_set
		torch.cuda.empty_cache()


def 	lowerCamelCase					(	UpperCamelCase     :				Union[str, Any]			,       UpperCamelCase     :				List[Any]=15			,       UpperCamelCase     :				Tuple=1_28			,       UpperCamelCase     :				int=1_00			,       UpperCamelCase     :				Tuple="igf_model.pt"			,       )   ->    List[Any]:
		set_seed(42							)

		# Load pre-trained model
		_lowerCamelCase				   =  GPTaLMHeadModel.from_pretrained('gpt2'							)

		# Initialize secondary learner to use embedding weights of model
		_lowerCamelCase				   =  SecondaryLearner(UpperCamelCase							)

		# Train secondary learner
		_lowerCamelCase				   =  train_secondary_learner(
		    UpperCamelCase			,       UpperCamelCase			,       max_epochs=UpperCamelCase			,       batch_size=UpperCamelCase			,       eval_freq=1_00			,       igf_model_path=UpperCamelCase			,       )

		del model, secondary_learner_train_data
		torch.cuda.empty_cache()

		return secondary_learner


def 	lowerCamelCase					(	UpperCamelCase     :				List[Any]			,       UpperCamelCase     :				Tuple			,       UpperCamelCase     :				Optional[int]			,       UpperCamelCase     :				Union[str, Any]=32			,       UpperCamelCase     :				int=10_00			,       UpperCamelCase     :				List[Any]=16			,       UpperCamelCase     :				Optional[Any]=1.0			,       UpperCamelCase     :				Optional[int]=recopy_gpta			,       UpperCamelCase     :				List[Any]=None			,       UpperCamelCase     :				Tuple=10			,       UpperCamelCase     :				Tuple="gpt2_finetuned.pt"			,       )   ->    str:
		_lowerCamelCase				   =  torch.device('cuda:0' if torch.cuda.is_available() else 'cpu'							)
		_lowerCamelCase				   =  RandomSampler(UpperCamelCase							)
		_lowerCamelCase				   =  DataLoader(UpperCamelCase			,       sampler=UpperCamelCase							)

		_lowerCamelCase				   =  max_steps // (len(UpperCamelCase							)) + 1
		_lowerCamelCase				   =  0
		_lowerCamelCase				   =  torch.zeros((1, context_len)			,       dtype=torch.long			,       device=UpperCamelCase							)
		_lowerCamelCase   ,							_lowerCamelCase   ,							_lowerCamelCase				   =  recopy_model(UpperCamelCase			,       UpperCamelCase			,       UpperCamelCase							)

		model.train()
		if secondary_learner is not None:
				secondary_learner.to(UpperCamelCase							)
				secondary_learner.eval()
		_lowerCamelCase				   =  []
		_lowerCamelCase				   =  0

		_lowerCamelCase				   =  []
		_lowerCamelCase				   =  []

		# Compute the performance of the transformer model at the beginning
		_lowerCamelCase				   =  compute_perplexity(UpperCamelCase			,       UpperCamelCase			,       UpperCamelCase							)
		test_perps.append(UpperCamelCase							)
		print('Test perplexity, step'			,       UpperCamelCase			,       ':'			,       UpperCamelCase							)
		for epoch in range(int(UpperCamelCase							)							):
				for step, example in enumerate(UpperCamelCase							):
						torch.cuda.empty_cache()
						_lowerCamelCase				   =  random.randint(0			,       example.size(2							) - context_len - 1							)
						_lowerCamelCase				   =  example[0, 0, start : start + context_len]
						lm_optimizer.zero_grad()
						_lowerCamelCase				   =  model(UpperCamelCase			,       labels=UpperCamelCase							)
						_lowerCamelCase				   =  True

						if secondary_learner is not None:
								_lowerCamelCase				   =  secondary_learner.forward(
								    torch.tensor(UpperCamelCase			,       dtype=torch.long			,       device=UpperCamelCase							).unsqueeze(0							)							)[0].item()
								observed_qs.append(float(UpperCamelCase							)							)

								# Here we implement the simple non-constant threshold for the predicted IG(X) value
								# We will decay the selectivity of our secondary learner filter from
								# 1 standard deviation above average to 1 below average after 10 batches.

								if global_step == 10:
										_lowerCamelCase				   =  -1
								if predicted_q < threshold:
										_lowerCamelCase				   =  False

            # If we passed the filter, add the context to the batch!
						if do_backprop:
								contexts.append(np.array(context.cpu()							)							)
								_lowerCamelCase				   =  outputs[0]
								lm_loss.backward()
								examples += 1

						del outputs

						# Once the batch is filled with enough contexts, backprop on the batch.
						if examples == batch_size:
								torch.cuda.empty_cache()
								_lowerCamelCase				   =  0
								# Do LM backprop
								torch.nn.utils.clip_grad_norm_(model.parameters()			,       3.0							)
								lm_optimizer.step()
								lm_scheduler.step()  # Update learning rate schedule
								global_step += 1
								# Compute the performance of the transformer model at this batch
								if global_step % eval_interval == 0:
										_lowerCamelCase				   =  compute_perplexity(UpperCamelCase			,       UpperCamelCase			,       UpperCamelCase							)
										test_perps.append(UpperCamelCase							)

										print('Test perplexity, step'			,       UpperCamelCase			,       ':'			,       UpperCamelCase							)
            # Break out of the loop after 60 batches
						if max_steps > 0 and global_step > 60:
								break
				if max_steps > 0 and global_step > 60:
						break

    # save finetuned transformer model
		torch.save(model.state_dict()			,       UpperCamelCase							)
		torch.cuda.empty_cache()
		# Do some cleaning up so we can reinitialize for the next run of this function
		del lm_optimizer
		del lm_scheduler
		return model


def 	lowerCamelCase					(	)   ->    Union[str, Any]:
		_lowerCamelCase				   =  argparse.ArgumentParser(description='Fine-tune a transformer model with IGF on a language modeling task'							)

		# Required parameters
		parser.add_argument(
		    '--data_dir'			,       default=UpperCamelCase			,       type=UpperCamelCase			,       required=UpperCamelCase			,       help='The input data dir. Should contain data files for WikiText.'			,       )
		parser.add_argument(
		    '--model_name_or_path'			,       default=UpperCamelCase			,       type=UpperCamelCase			,       required=UpperCamelCase			,       help='Path to pretrained model or model identifier from huggingface.co/models'			,       )
		parser.add_argument(
		    '--data_file'			,       type=UpperCamelCase			,       default=UpperCamelCase			,       help=(
		        'A jbl file containing tokenized data which can be split as objective dataset, '
		        'train_dataset and test_dataset.'
		    )			,       )

		parser.add_argument(
		    '--igf_data_file'			,       type=UpperCamelCase			,       default=UpperCamelCase			,       help='A jbl file containing the context and information gain pairs to train secondary learner.'			,       )

		parser.add_argument(
		    '--output_dir'			,       default=UpperCamelCase			,       type=UpperCamelCase			,       required=UpperCamelCase			,       help='The output directory where the final fine-tuned model is stored.'			,       )

		parser.add_argument(
		    '--tokenizer_name'			,       default=UpperCamelCase			,       type=UpperCamelCase			,       help='Pretrained tokenizer name or path if not the same as model_name'			,       )
		parser.add_argument('--seed'			,       type=UpperCamelCase			,       default=UpperCamelCase			,       help='A seed for reproducible training.'							)

		parser.add_argument(
		    '--context_len'			,       default=32			,       type=UpperCamelCase			,       help=(
		        'The maximum total input sequence length after tokenization. Sequences longer '
		        'than this will be truncated, sequences shorter will be padded.'
		    )			,       )

		parser.add_argument(
		    '--size_objective_set'			,       default=1_00			,       type=UpperCamelCase			,       help='number of articles that are long enough to be used as our objective set'			,       )
		parser.add_argument(
		    '--eval_freq'			,       default=1_00			,       type=UpperCamelCase			,       help='secondary model evaluation is triggered at eval_freq'							)

		parser.add_argument('--max_steps'			,       default=10_00			,       type=UpperCamelCase			,       help='To calculate training epochs'							)

		parser.add_argument(
		    '--secondary_learner_batch_size'			,       default=1_28			,       type=UpperCamelCase			,       help='batch size of training data for secondary learner'			,       )

		parser.add_argument(
		    '--batch_size'			,       default=16			,       type=UpperCamelCase			,       help='batch size of training data of language model(gpt2) '							)

		parser.add_argument(
		    '--eval_interval'			,       default=10			,       type=UpperCamelCase			,       help=(
		        'decay the selectivity of our secondary learner filter from'
		        '1 standard deviation above average to 1 below average after 10 batches'
		    )			,       )

		parser.add_argument(
		    '--number'			,       default=1_00			,       type=UpperCamelCase			,       help='The number of examples split to be used as objective_set/test_data'							)

		parser.add_argument(
		    '--min_len'			,       default=10_26			,       type=UpperCamelCase			,       help='The minimum length of the article to be used as objective set'							)

		parser.add_argument(
		    '--secondary_learner_max_epochs'			,       default=15			,       type=UpperCamelCase			,       help='number of epochs to train secondary learner'							)

		parser.add_argument('--trim'			,       default=UpperCamelCase			,       type=UpperCamelCase			,       help='truncate the example if it exceeds context length'							)

		parser.add_argument(
		    '--threshold'			,       default=1.0			,       type=UpperCamelCase			,       help=(
		        'The threshold value used by secondary learner to filter the train_data and allow only'
		        ' informative data as input to the model'
		    )			,       )

		parser.add_argument('--finetuned_model_name'			,       default='gpt2_finetuned.pt'			,       type=UpperCamelCase			,       help='finetuned_model_name'							)

		parser.add_argument(
		    '--recopy_model'			,       default=UpperCamelCase			,       type=UpperCamelCase			,       help='Reset the model to the original pretrained GPT-2 weights after each iteration'			,       )

		# function calls
		# Collecting *n* pairs of context and information gain(X, IG(X)) for training the secondary learner
		generate_n_pairs(
		    context_len=32			,       max_steps=10			,       size_objective_set=1_00			,       min_len=10_26			,       trim=UpperCamelCase			,       data_file='data/tokenized_stories_train_wikitext103.jbl'			,       igf_data_file='igf_context_pairs.jbl'			,       )

		# Load train data for secondary learner
		_lowerCamelCase				   =  joblib.load('data/IGF_values.jbl'							)

		# Train secondary learner
		_lowerCamelCase				   =  training_secondary_learner(
		    UpperCamelCase			,       secondary_learner_max_epochs=15			,       secondary_learner_batch_size=1_28			,       eval_freq=1_00			,       igf_model_path='igf_model.pt'			,       )

		# load pretrained gpt2 model
		_lowerCamelCase				   =  GPTaLMHeadModel.from_pretrained('gpt2'							)
		set_seed(42							)

		# Generate train and test data to train and evaluate gpt2 model
		_lowerCamelCase   ,							_lowerCamelCase				   =  generate_datasets(
		    context_len=32			,       file='data/tokenized_stories_train_wikitext103.jbl'			,       number=1_00			,       min_len=10_26			,       trim=UpperCamelCase							)

		# fine-tuning of the gpt2 model using igf (Information Gain Filtration)
		finetune(
		    UpperCamelCase			,       UpperCamelCase			,       UpperCamelCase			,       context_len=32			,       max_steps=10_00			,       batch_size=16			,       threshold=1.0			,       recopy_model=UpperCamelCase			,       secondary_learner=UpperCamelCase			,       eval_interval=10			,       finetuned_model_name='gpt2_finetuned.pt'			,       )


if __name__ == "__main__":
				main()
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     lowerCAmelCase__     :


						'''simple docstring'''






						@staticmethod
						def   _snake_case       (       *snake_case__     :     Optional[int]     ,  **snake_case__     :     Tuple		)      ->	Optional[Any]:
								pass



				def 	lowerCamelCase					(	UpperCamelCase     :				str							)   ->    Tuple:
						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.
A						=			(
    'https://huggingface.co/spaces/impira/docquery/resolve/2f6c96314dc84dfda62d40de9da55f2f5165d403/invoice.png'
)





@is_pipeline_test
@require_torch
@require_vision
class     lowerCAmelCase__     (				unittest.TestCase			):


		'''simple docstring'''






		lowerCAmelCase_     =   MODEL_FOR_DOCUMENT_QUESTION_ANSWERING_MAPPING
		@require_pytesseract
		@require_vision
		def   _snake_case       (       self     :     str     ,  snake_case__     :     Optional[Any]     ,  snake_case__     :     Any     ,  snake_case__     :     Union[str, Any]		)      ->	Dict:
				_lowerCamelCase				   =  pipeline(
				    'document-question-answering'     ,  model=snake_case__     ,  tokenizer=snake_case__     ,  image_processor=snake_case__		)

				_lowerCamelCase				   =  INVOICE_URL
				_lowerCamelCase				   =  list(zip(*apply_tesseract(load_image(snake_case__		)     ,  snake_case__     ,  ''		)		)		)
				_lowerCamelCase				   =  'What is the placebo?'
				_lowerCamelCase				   =  [
				    {
				        'image': load_image(snake_case__		),
				        'question': question,
				    },
				    {
				        'image': image,
				        'question': question,
				    },
				    {
				        'image': image,
				        'question': question,
				        'word_boxes': word_boxes,
				    },
				]
				return dqa_pipeline, examples
		def   _snake_case       (       self     :     Union[str, Any]     ,  snake_case__     :     Union[str, Any]     ,  snake_case__     :     List[Any]		)      ->	Tuple:
				_lowerCamelCase				   =  dqa_pipeline(snake_case__     ,  top_k=2		)
				self.assertEqual(
				    snake_case__     ,  [
				        [
				            {'score': ANY(snake_case__		), 'answer': ANY(snake_case__		), 'start': ANY(snake_case__		), 'end': ANY(snake_case__		)},
				            {'score': ANY(snake_case__		), 'answer': ANY(snake_case__		), 'start': ANY(snake_case__		), 'end': ANY(snake_case__		)},
				        ]
				    ]
				    * 3     ,  )
		@require_torch
		@require_detectrona
		@require_pytesseract
		def   _snake_case       (       self     :     Union[str, Any]		)      ->	Optional[int]:
				_lowerCamelCase				   =  pipeline('document-question-answering'     ,  model='hf-internal-testing/tiny-random-layoutlmv2'		)
				_lowerCamelCase				   =  INVOICE_URL
				_lowerCamelCase				   =  'How many cats are there?'

				_lowerCamelCase				   =  [
				    {'score': 0.0001, 'answer': 'oy 2312/2019', 'start': 3_8, 'end': 3_9},
				    {'score': 0.0001, 'answer': 'oy 2312/2019 DUE', 'start': 3_8, 'end': 4_0},
				]
				_lowerCamelCase				   =  dqa_pipeline(image=snake_case__     ,  question=snake_case__     ,  top_k=2		)
				self.assertEqual(nested_simplify(snake_case__     ,  decimals=4		)     ,  snake_case__		)

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

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

				# We can optionnally pass directly the words and bounding boxes
				_lowerCamelCase				   =  './tests/fixtures/tests_samples/COCO/000000039769.png'
				_lowerCamelCase				   =  []
				_lowerCamelCase				   =  []
				_lowerCamelCase				   =  dqa_pipeline(image=snake_case__     ,  question=snake_case__     ,  words=snake_case__     ,  boxes=snake_case__     ,  top_k=2		)
				self.assertEqual(snake_case__     ,  []		)
		@slow
		@require_torch
		@require_detectrona
		@require_pytesseract
		def   _snake_case       (       self     :     Optional[int]		)      ->	List[Any]:
				_lowerCamelCase				   =  pipeline(
				    'document-question-answering'     ,  model='tiennvcs/layoutlmv2-base-uncased-finetuned-docvqa'     ,  revision='9977165'     ,  )
				_lowerCamelCase				   =  INVOICE_URL
				_lowerCamelCase				   =  'What is the invoice number?'

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

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

				_lowerCamelCase				   =  dqa_pipeline(
				    [{'image': image, 'question': question}, {'image': image, 'question': question}]     ,  top_k=2		)
				self.assertEqual(
				    nested_simplify(snake_case__     ,  decimals=4		)     ,  [
				        [
				            {'score': 0.9944, 'answer': 'us-001', 'start': 1_6, 'end': 1_6},
				            {'score': 0.0009, 'answer': 'us-001', 'start': 1_6, 'end': 1_6},
				        ],
				    ]
				    * 2     ,  )
		@slow
		@require_torch
		@require_detectrona
		@require_pytesseract
		def   _snake_case       (       self     :     int		)      ->	Optional[Any]:
				_lowerCamelCase				   =  pipeline(
				    'document-question-answering'     ,  model='tiennvcs/layoutlmv2-base-uncased-finetuned-docvqa'     ,  revision='9977165'     ,  max_seq_len=5_0     ,  )
				_lowerCamelCase				   =  INVOICE_URL
				_lowerCamelCase				   =  'What is the invoice number?'

				_lowerCamelCase				   =  dqa_pipeline(image=snake_case__     ,  question=snake_case__     ,  top_k=2		)
				self.assertEqual(
				    nested_simplify(snake_case__     ,  decimals=4		)     ,  [
				        {'score': 0.9974, 'answer': '1110212019', 'start': 2_3, 'end': 2_3},
				        {'score': 0.9948, 'answer': 'us-001', 'start': 1_6, 'end': 1_6},
				    ]     ,  )

				_lowerCamelCase				   =  dqa_pipeline({'image': image, 'question': question}     ,  top_k=2		)
				self.assertEqual(
				    nested_simplify(snake_case__     ,  decimals=4		)     ,  [
				        {'score': 0.9974, 'answer': '1110212019', 'start': 2_3, 'end': 2_3},
				        {'score': 0.9948, 'answer': 'us-001', 'start': 1_6, 'end': 1_6},
				    ]     ,  )

				_lowerCamelCase				   =  dqa_pipeline(
				    [{'image': image, 'question': question}, {'image': image, 'question': question}]     ,  top_k=2		)
				self.assertEqual(
				    nested_simplify(snake_case__     ,  decimals=4		)     ,  [
				        [
				            {'score': 0.9974, 'answer': '1110212019', 'start': 2_3, 'end': 2_3},
				            {'score': 0.9948, 'answer': 'us-001', 'start': 1_6, 'end': 1_6},
				        ]
				    ]
				    * 2     ,  )
		@slow
		@require_torch
		@require_pytesseract
		@require_vision
		def   _snake_case       (       self     :     int		)      ->	List[Any]:
				_lowerCamelCase				   =  AutoTokenizer.from_pretrained(
				    'impira/layoutlm-document-qa'     ,  revision='3dc6de3'     ,  add_prefix_space=snake_case__		)
				_lowerCamelCase				   =  pipeline(
				    'document-question-answering'     ,  model='impira/layoutlm-document-qa'     ,  tokenizer=snake_case__     ,  revision='3dc6de3'     ,  )
				_lowerCamelCase				   =  INVOICE_URL
				_lowerCamelCase				   =  'What is the invoice number?'

				_lowerCamelCase				   =  dqa_pipeline(image=snake_case__     ,  question=snake_case__     ,  top_k=2		)
				self.assertEqual(
				    nested_simplify(snake_case__     ,  decimals=4		)     ,  [
				        {'score': 0.4251, 'answer': 'us-001', 'start': 1_6, 'end': 1_6},
				        {'score': 0.0819, 'answer': '1110212019', 'start': 2_3, 'end': 2_3},
				    ]     ,  )

				_lowerCamelCase				   =  dqa_pipeline({'image': image, 'question': question}     ,  top_k=2		)
				self.assertEqual(
				    nested_simplify(snake_case__     ,  decimals=4		)     ,  [
				        {'score': 0.4251, 'answer': 'us-001', 'start': 1_6, 'end': 1_6},
				        {'score': 0.0819, 'answer': '1110212019', 'start': 2_3, 'end': 2_3},
				    ]     ,  )

				_lowerCamelCase				   =  dqa_pipeline(
				    [{'image': image, 'question': question}, {'image': image, 'question': question}]     ,  top_k=2		)
				self.assertEqual(
				    nested_simplify(snake_case__     ,  decimals=4		)     ,  [
				        [
				            {'score': 0.4251, 'answer': 'us-001', 'start': 1_6, 'end': 1_6},
				            {'score': 0.0819, 'answer': '1110212019', 'start': 2_3, 'end': 2_3},
				        ]
				    ]
				    * 2     ,  )

				_lowerCamelCase				   =  list(zip(*apply_tesseract(load_image(snake_case__		)     ,  snake_case__     ,  ''		)		)		)

				# This model should also work if `image` is set to None
				_lowerCamelCase				   =  dqa_pipeline({'image': None, 'word_boxes': word_boxes, 'question': question}     ,  top_k=2		)
				self.assertEqual(
				    nested_simplify(snake_case__     ,  decimals=4		)     ,  [
				        {'score': 0.4251, 'answer': 'us-001', 'start': 1_6, 'end': 1_6},
				        {'score': 0.0819, 'answer': '1110212019', 'start': 2_3, 'end': 2_3},
				    ]     ,  )
		@slow
		@require_torch
		@require_pytesseract
		@require_vision
		def   _snake_case       (       self     :     Dict		)      ->	List[str]:
				_lowerCamelCase				   =  AutoTokenizer.from_pretrained(
				    'impira/layoutlm-document-qa'     ,  revision='3dc6de3'     ,  add_prefix_space=snake_case__		)
				_lowerCamelCase				   =  pipeline(
				    'document-question-answering'     ,  model='impira/layoutlm-document-qa'     ,  tokenizer=snake_case__     ,  revision='3dc6de3'     ,  max_seq_len=5_0     ,  )
				_lowerCamelCase				   =  INVOICE_URL
				_lowerCamelCase				   =  'What is the invoice number?'

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

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

				_lowerCamelCase				   =  list(zip(*apply_tesseract(load_image(snake_case__		)     ,  snake_case__     ,  ''		)		)		)

				# This model should also work if `image` is set to None
				_lowerCamelCase				   =  dqa_pipeline({'image': None, 'word_boxes': word_boxes, 'question': question}     ,  top_k=2		)
				self.assertEqual(
				    nested_simplify(snake_case__     ,  decimals=4		)     ,  [
				        {'score': 0.9999, 'answer': 'us-001', 'start': 1_6, 'end': 1_6},
				        {'score': 0.9998, 'answer': 'us-001', 'start': 1_6, 'end': 1_6},
				    ]     ,  )
		@slow
		@require_torch
		def   _snake_case       (       self     :     Dict		)      ->	int:
				_lowerCamelCase				   =  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				   =  INVOICE_URL
				_lowerCamelCase				   =  'What is the invoice number?'
				_lowerCamelCase				   =  dqa_pipeline(image=snake_case__     ,  question=snake_case__     ,  top_k=2		)
				self.assertEqual(nested_simplify(snake_case__     ,  decimals=4		)     ,  [{'answer': 'us-001'}]		)



		@require_tf
		@unittest.skip('Document question answering not implemented in TF'		)
		def   _snake_case       (       self     :     Optional[Any]		)      ->	Any:
				pass