test_pipeline_mixin.py 29 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# coding=utf-8
# 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 copy
import json
import os
import random
20
import unittest
21
22
23
from pathlib import Path

from transformers.testing_utils import (
24
    is_pipeline_test,
25
26
27
28
29
30
31
    require_decord,
    require_pytesseract,
    require_timm,
    require_torch,
    require_torch_or_tf,
    require_vision,
)
32
from transformers.utils import direct_transformers_import, logging
33
34
35
36
37
38
39
40

from .pipelines.test_pipelines_audio_classification import AudioClassificationPipelineTests
from .pipelines.test_pipelines_automatic_speech_recognition import AutomaticSpeechRecognitionPipelineTests
from .pipelines.test_pipelines_depth_estimation import DepthEstimationPipelineTests
from .pipelines.test_pipelines_document_question_answering import DocumentQuestionAnsweringPipelineTests
from .pipelines.test_pipelines_feature_extraction import FeatureExtractionPipelineTests
from .pipelines.test_pipelines_fill_mask import FillMaskPipelineTests
from .pipelines.test_pipelines_image_classification import ImageClassificationPipelineTests
41
from .pipelines.test_pipelines_image_feature_extraction import ImageFeatureExtractionPipelineTests
42
from .pipelines.test_pipelines_image_segmentation import ImageSegmentationPipelineTests
43
from .pipelines.test_pipelines_image_to_image import ImageToImagePipelineTests
44
from .pipelines.test_pipelines_image_to_text import ImageToTextPipelineTests
45
from .pipelines.test_pipelines_mask_generation import MaskGenerationPipelineTests
46
47
48
49
50
51
52
from .pipelines.test_pipelines_object_detection import ObjectDetectionPipelineTests
from .pipelines.test_pipelines_question_answering import QAPipelineTests
from .pipelines.test_pipelines_summarization import SummarizationPipelineTests
from .pipelines.test_pipelines_table_question_answering import TQAPipelineTests
from .pipelines.test_pipelines_text2text_generation import Text2TextGenerationPipelineTests
from .pipelines.test_pipelines_text_classification import TextClassificationPipelineTests
from .pipelines.test_pipelines_text_generation import TextGenerationPipelineTests
53
from .pipelines.test_pipelines_text_to_audio import TextToAudioPipelineTests
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
from .pipelines.test_pipelines_token_classification import TokenClassificationPipelineTests
from .pipelines.test_pipelines_translation import TranslationPipelineTests
from .pipelines.test_pipelines_video_classification import VideoClassificationPipelineTests
from .pipelines.test_pipelines_visual_question_answering import VisualQuestionAnsweringPipelineTests
from .pipelines.test_pipelines_zero_shot import ZeroShotClassificationPipelineTests
from .pipelines.test_pipelines_zero_shot_audio_classification import ZeroShotAudioClassificationPipelineTests
from .pipelines.test_pipelines_zero_shot_image_classification import ZeroShotImageClassificationPipelineTests
from .pipelines.test_pipelines_zero_shot_object_detection import ZeroShotObjectDetectionPipelineTests


pipeline_test_mapping = {
    "audio-classification": {"test": AudioClassificationPipelineTests},
    "automatic-speech-recognition": {"test": AutomaticSpeechRecognitionPipelineTests},
    "depth-estimation": {"test": DepthEstimationPipelineTests},
    "document-question-answering": {"test": DocumentQuestionAnsweringPipelineTests},
    "feature-extraction": {"test": FeatureExtractionPipelineTests},
    "fill-mask": {"test": FillMaskPipelineTests},
    "image-classification": {"test": ImageClassificationPipelineTests},
72
    "image-feature-extraction": {"test": ImageFeatureExtractionPipelineTests},
73
    "image-segmentation": {"test": ImageSegmentationPipelineTests},
74
    "image-to-image": {"test": ImageToImagePipelineTests},
75
    "image-to-text": {"test": ImageToTextPipelineTests},
76
    "mask-generation": {"test": MaskGenerationPipelineTests},
77
78
79
80
81
82
83
    "object-detection": {"test": ObjectDetectionPipelineTests},
    "question-answering": {"test": QAPipelineTests},
    "summarization": {"test": SummarizationPipelineTests},
    "table-question-answering": {"test": TQAPipelineTests},
    "text2text-generation": {"test": Text2TextGenerationPipelineTests},
    "text-classification": {"test": TextClassificationPipelineTests},
    "text-generation": {"test": TextGenerationPipelineTests},
84
    "text-to-audio": {"test": TextToAudioPipelineTests},
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
    "token-classification": {"test": TokenClassificationPipelineTests},
    "translation": {"test": TranslationPipelineTests},
    "video-classification": {"test": VideoClassificationPipelineTests},
    "visual-question-answering": {"test": VisualQuestionAnsweringPipelineTests},
    "zero-shot": {"test": ZeroShotClassificationPipelineTests},
    "zero-shot-audio-classification": {"test": ZeroShotAudioClassificationPipelineTests},
    "zero-shot-image-classification": {"test": ZeroShotImageClassificationPipelineTests},
    "zero-shot-object-detection": {"test": ZeroShotObjectDetectionPipelineTests},
}

for task, task_info in pipeline_test_mapping.items():
    test = task_info["test"]
    task_info["mapping"] = {
        "pt": getattr(test, "model_mapping", None),
        "tf": getattr(test, "tf_model_mapping", None),
    }


103
104
105
106
107
108
109
110
# The default value `hf-internal-testing` is for running the pipeline testing against the tiny models on the Hub.
# For debugging purpose, we can specify a local path which is the `output_path` argument of a previous run of
# `utils/create_dummy_models.py`.
TRANSFORMERS_TINY_MODEL_PATH = os.environ.get("TRANSFORMERS_TINY_MODEL_PATH", "hf-internal-testing")
if TRANSFORMERS_TINY_MODEL_PATH == "hf-internal-testing":
    TINY_MODEL_SUMMARY_FILE_PATH = os.path.join(Path(__file__).parent.parent, "tests/utils/tiny_model_summary.json")
else:
    TINY_MODEL_SUMMARY_FILE_PATH = os.path.join(TRANSFORMERS_TINY_MODEL_PATH, "reports", "tiny_model_summary.json")
111
112
113
114
115
116
117
118
119
120
with open(TINY_MODEL_SUMMARY_FILE_PATH) as fp:
    tiny_model_summary = json.load(fp)


PATH_TO_TRANSFORMERS = os.path.join(Path(__file__).parent.parent, "src/transformers")


# Dynamically import the Transformers module to grab the attribute classes of the processor form their names.
transformers_module = direct_transformers_import(PATH_TO_TRANSFORMERS)

121
122
logger = logging.get_logger(__name__)

123
124
125
126
127
128

class PipelineTesterMixin:
    model_tester = None
    pipeline_model_mapping = None
    supported_frameworks = ["pt", "tf"]

129
    def run_task_tests(self, task, torch_dtype="float32"):
130
131
132
133
134
        """Run pipeline tests for a specific `task`

        Args:
            task (`str`):
                A task name. This should be a key in the mapping `pipeline_test_mapping`.
135
136
            torch_dtype (`str`, `optional`, defaults to `'float32'`):
                The torch dtype to use for the model. Can be used for FP16/other precision inference.
137
138
139
        """
        if task not in self.pipeline_model_mapping:
            self.skipTest(
140
                f"{self.__class__.__name__}::test_pipeline_{task.replace('-', '_')}_{torch_dtype} is skipped: `{task}` is not in "
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
                f"`self.pipeline_model_mapping` for `{self.__class__.__name__}`."
            )

        model_architectures = self.pipeline_model_mapping[task]
        if not isinstance(model_architectures, tuple):
            model_architectures = (model_architectures,)
        if not isinstance(model_architectures, tuple):
            raise ValueError(f"`model_architectures` must be a tuple. Got {type(model_architectures)} instead.")

        for model_architecture in model_architectures:
            model_arch_name = model_architecture.__name__

            # Get the canonical name
            for _prefix in ["Flax", "TF"]:
                if model_arch_name.startswith(_prefix):
                    model_arch_name = model_arch_name[len(_prefix) :]
                    break

            tokenizer_names = []
            processor_names = []
161
            commit = None
162
163
164
            if model_arch_name in tiny_model_summary:
                tokenizer_names = tiny_model_summary[model_arch_name]["tokenizer_classes"]
                processor_names = tiny_model_summary[model_arch_name]["processor_classes"]
165
166
                if "sha" in tiny_model_summary[model_arch_name]:
                    commit = tiny_model_summary[model_arch_name]["sha"]
167
168
169
170
171
            # Adding `None` (if empty) so we can generate tests
            tokenizer_names = [None] if len(tokenizer_names) == 0 else tokenizer_names
            processor_names = [None] if len(processor_names) == 0 else processor_names

            repo_name = f"tiny-random-{model_arch_name}"
172
173
            if TRANSFORMERS_TINY_MODEL_PATH != "hf-internal-testing":
                repo_name = model_arch_name
174

175
            self.run_model_pipeline_tests(
176
                task, repo_name, model_architecture, tokenizer_names, processor_names, commit, torch_dtype
177
            )
178

179
180
181
    def run_model_pipeline_tests(
        self, task, repo_name, model_architecture, tokenizer_names, processor_names, commit, torch_dtype="float32"
    ):
182
183
184
185
186
187
188
189
190
191
192
193
194
        """Run pipeline tests for a specific `task` with the give model class and tokenizer/processor class names

        Args:
            task (`str`):
                A task name. This should be a key in the mapping `pipeline_test_mapping`.
            repo_name (`str`):
                A model repository id on the Hub.
            model_architecture (`type`):
                A subclass of `PretrainedModel` or `PretrainedModel`.
            tokenizer_names (`List[str]`):
                A list of names of a subclasses of `PreTrainedTokenizerFast` or `PreTrainedTokenizer`.
            processor_names (`List[str]`):
                A list of names of subclasses of `BaseImageProcessor` or `FeatureExtractionMixin`.
195
196
197
198
            commit (`str`):
                The commit hash of the model repository on the Hub.
            torch_dtype (`str`, `optional`, defaults to `'float32'`):
                The torch dtype to use for the model. Can be used for FP16/other precision inference.
199
200
201
202
203
204
205
        """
        # Get an instance of the corresponding class `XXXPipelineTests` in order to use `get_test_pipeline` and
        # `run_pipeline_test`.
        pipeline_test_class_name = pipeline_test_mapping[task]["test"].__name__

        for tokenizer_name in tokenizer_names:
            for processor_name in processor_names:
206
                if self.is_pipeline_test_to_skip(
207
208
209
210
211
212
                    pipeline_test_class_name,
                    model_architecture.config_class,
                    model_architecture,
                    tokenizer_name,
                    processor_name,
                ):
213
                    logger.warning(
214
                        f"{self.__class__.__name__}::test_pipeline_{task.replace('-', '_')}_{torch_dtype} is skipped: test is "
215
216
217
                        f"currently known to fail for: model `{model_architecture.__name__}` | tokenizer "
                        f"`{tokenizer_name}` | processor `{processor_name}`."
                    )
218
                    continue
219
220
221
                self.run_pipeline_test(
                    task, repo_name, model_architecture, tokenizer_name, processor_name, commit, torch_dtype
                )
222

223
224
225
    def run_pipeline_test(
        self, task, repo_name, model_architecture, tokenizer_name, processor_name, commit, torch_dtype="float32"
    ):
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
        """Run pipeline tests for a specific `task` with the give model class and tokenizer/processor class name

        The model will be loaded from a model repository on the Hub.

        Args:
            task (`str`):
                A task name. This should be a key in the mapping `pipeline_test_mapping`.
            repo_name (`str`):
                A model repository id on the Hub.
            model_architecture (`type`):
                A subclass of `PretrainedModel` or `PretrainedModel`.
            tokenizer_name (`str`):
                The name of a subclass of `PreTrainedTokenizerFast` or `PreTrainedTokenizer`.
            processor_name (`str`):
                The name of a subclass of `BaseImageProcessor` or `FeatureExtractionMixin`.
241
242
243
244
            commit (`str`):
                The commit hash of the model repository on the Hub.
            torch_dtype (`str`, `optional`, defaults to `'float32'`):
                The torch dtype to use for the model. Can be used for FP16/other precision inference.
245
        """
246
247
248
249
        repo_id = f"{TRANSFORMERS_TINY_MODEL_PATH}/{repo_name}"
        if TRANSFORMERS_TINY_MODEL_PATH != "hf-internal-testing":
            model_type = model_architecture.config_class.model_type
            repo_id = os.path.join(TRANSFORMERS_TINY_MODEL_PATH, model_type, repo_name)
250
251
252
253

        tokenizer = None
        if tokenizer_name is not None:
            tokenizer_class = getattr(transformers_module, tokenizer_name)
254
            tokenizer = tokenizer_class.from_pretrained(repo_id, revision=commit)
255
256
257
258
259
260

        processor = None
        if processor_name is not None:
            processor_class = getattr(transformers_module, processor_name)
            # If the required packages (like `Pillow` or `torchaudio`) are not installed, this will fail.
            try:
261
                processor = processor_class.from_pretrained(repo_id, revision=commit)
262
            except Exception:
263
                logger.warning(
264
                    f"{self.__class__.__name__}::test_pipeline_{task.replace('-', '_')}_{torch_dtype} is skipped: Could not load the "
265
266
                    f"processor from `{repo_id}` with `{processor_name}`."
                )
amyeroberts's avatar
amyeroberts committed
267
                self.skipTest(f"Could not load the processor from {repo_id} with {processor_name}.")
268
269
270

        # TODO: Maybe not upload such problematic tiny models to Hub.
        if tokenizer is None and processor is None:
271
            logger.warning(
272
                f"{self.__class__.__name__}::test_pipeline_{task.replace('-', '_')}_{torch_dtype} is skipped: Could not find or load "
273
274
                f"any tokenizer / processor from `{repo_id}`."
            )
amyeroberts's avatar
amyeroberts committed
275
            self.skipTest(f"Could not find or load any tokenizer / processor from {repo_id}.")
276
277
278

        # TODO: We should check if a model file is on the Hub repo. instead.
        try:
279
            model = model_architecture.from_pretrained(repo_id, revision=commit)
280
        except Exception:
281
            logger.warning(
282
                f"{self.__class__.__name__}::test_pipeline_{task.replace('-', '_')}_{torch_dtype} is skipped: Could not find or load "
283
284
                f"the model from `{repo_id}` with `{model_architecture}`."
            )
amyeroberts's avatar
amyeroberts committed
285
            self.skipTest(f"Could not find or load the model from {repo_id} with {model_architecture}.")
286

287
288
289
        pipeline_test_class_name = pipeline_test_mapping[task]["test"].__name__
        if self.is_pipeline_test_to_skip_more(pipeline_test_class_name, model.config, model, tokenizer, processor):
            logger.warning(
290
                f"{self.__class__.__name__}::test_pipeline_{task.replace('-', '_')}_{torch_dtype} is skipped: test is "
291
292
293
                f"currently known to fail for: model `{model_architecture.__name__}` | tokenizer "
                f"`{tokenizer_name}` | processor `{processor_name}`."
            )
amyeroberts's avatar
amyeroberts committed
294
295
296
            self.skipTest(
                f"Test is known to fail for: model `{model_architecture.__name__}` | tokenizer `{tokenizer_name}` | processor `{processor_name}`."
            )
297

298
299
300
301
302
303
304
305
306
307
        # validate
        validate_test_components(self, task, model, tokenizer, processor)

        if hasattr(model, "eval"):
            model = model.eval()

        # Get an instance of the corresponding class `XXXPipelineTests` in order to use `get_test_pipeline` and
        # `run_pipeline_test`.
        task_test = pipeline_test_mapping[task]["test"]()

308
        pipeline, examples = task_test.get_test_pipeline(model, tokenizer, processor, torch_dtype=torch_dtype)
309
310
311
        if pipeline is None:
            # The test can disable itself, but it should be very marginal
            # Concerns: Wav2Vec2ForCTC without tokenizer test (FastTokenizer don't exist)
312
            logger.warning(
313
                f"{self.__class__.__name__}::test_pipeline_{task.replace('-', '_')}_{torch_dtype} is skipped: Could not get the "
314
315
                "pipeline for testing."
            )
amyeroberts's avatar
amyeroberts committed
316
            self.skipTest(reason="Could not get the pipeline for testing.")
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332

        task_test.run_pipeline_test(pipeline, examples)

        def run_batch_test(pipeline, examples):
            # Need to copy because `Conversation` are stateful
            if pipeline.tokenizer is not None and pipeline.tokenizer.pad_token_id is None:
                return  # No batching for this and it's OK

            # 10 examples with batch size 4 means there needs to be a unfinished batch
            # which is important for the unbatcher
            def data(n):
                for _ in range(n):
                    # Need to copy because Conversation object is mutated
                    yield copy.deepcopy(random.choice(examples))

            out = []
333
334
            for item in pipeline(data(10), batch_size=4):
                out.append(item)
335
336
337
338
            self.assertEqual(len(out), 10)

        run_batch_test(pipeline, examples)

339
    @is_pipeline_test
340
341
342
    def test_pipeline_audio_classification(self):
        self.run_task_tests(task="audio-classification")

343
344
345
346
347
    @is_pipeline_test
    @require_torch
    def test_pipeline_audio_classification_fp16(self):
        self.run_task_tests(task="audio-classification", torch_dtype="float16")

348
    @is_pipeline_test
349
350
351
    def test_pipeline_automatic_speech_recognition(self):
        self.run_task_tests(task="automatic-speech-recognition")

352
353
354
355
356
    @is_pipeline_test
    @require_torch
    def test_pipeline_automatic_speech_recognition_fp16(self):
        self.run_task_tests(task="automatic-speech-recognition", torch_dtype="float16")

357
    @is_pipeline_test
358
359
360
361
362
363
    @require_vision
    @require_timm
    @require_torch
    def test_pipeline_depth_estimation(self):
        self.run_task_tests(task="depth-estimation")

364
365
366
367
368
369
370
    @is_pipeline_test
    @require_vision
    @require_timm
    @require_torch
    def test_pipeline_depth_estimation_fp16(self):
        self.run_task_tests(task="depth-estimation", torch_dtype="float16")

371
    @is_pipeline_test
372
373
374
375
376
377
    @require_pytesseract
    @require_torch
    @require_vision
    def test_pipeline_document_question_answering(self):
        self.run_task_tests(task="document-question-answering")

378
379
380
381
382
383
384
    @is_pipeline_test
    @require_pytesseract
    @require_torch
    @require_vision
    def test_pipeline_document_question_answering_fp16(self):
        self.run_task_tests(task="document-question-answering", torch_dtype="float16")

385
    @is_pipeline_test
386
387
388
    def test_pipeline_feature_extraction(self):
        self.run_task_tests(task="feature-extraction")

389
390
391
392
393
    @is_pipeline_test
    @require_torch
    def test_pipeline_feature_extraction_fp16(self):
        self.run_task_tests(task="feature-extraction", torch_dtype="float16")

394
    @is_pipeline_test
395
396
397
    def test_pipeline_fill_mask(self):
        self.run_task_tests(task="fill-mask")

398
399
400
401
402
    @is_pipeline_test
    @require_torch
    def test_pipeline_fill_mask_fp16(self):
        self.run_task_tests(task="fill-mask", torch_dtype="float16")

403
    @is_pipeline_test
404
405
406
407
408
    @require_torch_or_tf
    @require_vision
    def test_pipeline_image_classification(self):
        self.run_task_tests(task="image-classification")

409
410
411
412
413
414
    @is_pipeline_test
    @require_vision
    @require_torch
    def test_pipeline_image_classification_fp16(self):
        self.run_task_tests(task="image-classification", torch_dtype="float16")

415
    @is_pipeline_test
416
417
418
419
420
421
    @require_vision
    @require_timm
    @require_torch
    def test_pipeline_image_segmentation(self):
        self.run_task_tests(task="image-segmentation")

422
423
424
425
426
427
428
    @is_pipeline_test
    @require_vision
    @require_timm
    @require_torch
    def test_pipeline_image_segmentation_fp16(self):
        self.run_task_tests(task="image-segmentation", torch_dtype="float16")

429
    @is_pipeline_test
430
431
432
433
    @require_vision
    def test_pipeline_image_to_text(self):
        self.run_task_tests(task="image-to-text")

434
435
436
437
438
439
    @is_pipeline_test
    @require_vision
    @require_torch
    def test_pipeline_image_to_text_fp16(self):
        self.run_task_tests(task="image-to-text", torch_dtype="float16")

440
441
442
443
444
445
446
    @is_pipeline_test
    @require_timm
    @require_vision
    @require_torch
    def test_pipeline_image_feature_extraction(self):
        self.run_task_tests(task="image-feature-extraction")

447
448
449
450
451
452
453
    @is_pipeline_test
    @require_timm
    @require_vision
    @require_torch
    def test_pipeline_image_feature_extraction_fp16(self):
        self.run_task_tests(task="image-feature-extraction", torch_dtype="float16")

454
    @unittest.skip(reason="`run_pipeline_test` is currently not implemented.")
455
456
457
458
459
460
    @is_pipeline_test
    @require_vision
    @require_torch
    def test_pipeline_mask_generation(self):
        self.run_task_tests(task="mask-generation")

461
462
463
464
465
466
467
    @unittest.skip(reason="`run_pipeline_test` is currently not implemented.")
    @is_pipeline_test
    @require_vision
    @require_torch
    def test_pipeline_mask_generation_fp16(self):
        self.run_task_tests(task="mask-generation", torch_dtype="float16")

468
    @is_pipeline_test
469
470
471
472
473
474
    @require_vision
    @require_timm
    @require_torch
    def test_pipeline_object_detection(self):
        self.run_task_tests(task="object-detection")

475
476
477
478
479
480
481
    @is_pipeline_test
    @require_vision
    @require_timm
    @require_torch
    def test_pipeline_object_detection_fp16(self):
        self.run_task_tests(task="object-detection", torch_dtype="float16")

482
    @is_pipeline_test
483
484
485
    def test_pipeline_question_answering(self):
        self.run_task_tests(task="question-answering")

486
487
488
489
490
    @is_pipeline_test
    @require_torch
    def test_pipeline_question_answering_fp16(self):
        self.run_task_tests(task="question-answering", torch_dtype="float16")

491
    @is_pipeline_test
492
493
494
    def test_pipeline_summarization(self):
        self.run_task_tests(task="summarization")

495
496
497
498
499
    @is_pipeline_test
    @require_torch
    def test_pipeline_summarization_fp16(self):
        self.run_task_tests(task="summarization", torch_dtype="float16")

500
    @is_pipeline_test
501
502
503
    def test_pipeline_table_question_answering(self):
        self.run_task_tests(task="table-question-answering")

504
505
506
507
508
    @is_pipeline_test
    @require_torch
    def test_pipeline_table_question_answering_fp16(self):
        self.run_task_tests(task="table-question-answering", torch_dtype="float16")

509
    @is_pipeline_test
510
511
512
    def test_pipeline_text2text_generation(self):
        self.run_task_tests(task="text2text-generation")

513
514
515
516
517
    @is_pipeline_test
    @require_torch
    def test_pipeline_text2text_generation_fp16(self):
        self.run_task_tests(task="text2text-generation", torch_dtype="float16")

518
    @is_pipeline_test
519
520
521
    def test_pipeline_text_classification(self):
        self.run_task_tests(task="text-classification")

522
523
524
525
526
    @is_pipeline_test
    @require_torch
    def test_pipeline_text_classification_fp16(self):
        self.run_task_tests(task="text-classification", torch_dtype="float16")

527
    @is_pipeline_test
528
529
530
531
    @require_torch_or_tf
    def test_pipeline_text_generation(self):
        self.run_task_tests(task="text-generation")

532
533
534
535
536
    @is_pipeline_test
    @require_torch
    def test_pipeline_text_generation_fp16(self):
        self.run_task_tests(task="text-generation", torch_dtype="float16")

537
538
539
540
541
    @is_pipeline_test
    @require_torch
    def test_pipeline_text_to_audio(self):
        self.run_task_tests(task="text-to-audio")

542
543
544
545
546
    @is_pipeline_test
    @require_torch
    def test_pipeline_text_to_audio_fp16(self):
        self.run_task_tests(task="text-to-audio", torch_dtype="float16")

547
    @is_pipeline_test
548
549
550
    def test_pipeline_token_classification(self):
        self.run_task_tests(task="token-classification")

551
552
553
554
555
    @is_pipeline_test
    @require_torch
    def test_pipeline_token_classification_fp16(self):
        self.run_task_tests(task="token-classification", torch_dtype="float16")

556
    @is_pipeline_test
557
558
559
    def test_pipeline_translation(self):
        self.run_task_tests(task="translation")

560
561
562
563
564
    @is_pipeline_test
    @require_torch
    def test_pipeline_translation_fp16(self):
        self.run_task_tests(task="translation", torch_dtype="float16")

565
    @is_pipeline_test
566
567
568
569
570
571
    @require_torch_or_tf
    @require_vision
    @require_decord
    def test_pipeline_video_classification(self):
        self.run_task_tests(task="video-classification")

572
573
574
575
576
577
578
    @is_pipeline_test
    @require_vision
    @require_decord
    @require_torch
    def test_pipeline_video_classification_fp16(self):
        self.run_task_tests(task="video-classification", torch_dtype="float16")

579
    @is_pipeline_test
580
581
582
583
584
    @require_torch
    @require_vision
    def test_pipeline_visual_question_answering(self):
        self.run_task_tests(task="visual-question-answering")

585
586
587
588
589
590
    @is_pipeline_test
    @require_torch
    @require_vision
    def test_pipeline_visual_question_answering_fp16(self):
        self.run_task_tests(task="visual-question-answering", torch_dtype="float16")

591
    @is_pipeline_test
592
593
594
    def test_pipeline_zero_shot(self):
        self.run_task_tests(task="zero-shot")

595
596
597
598
599
    @is_pipeline_test
    @require_torch
    def test_pipeline_zero_shot_fp16(self):
        self.run_task_tests(task="zero-shot", torch_dtype="float16")

600
    @is_pipeline_test
601
602
603
604
    @require_torch
    def test_pipeline_zero_shot_audio_classification(self):
        self.run_task_tests(task="zero-shot-audio-classification")

605
606
607
608
609
    @is_pipeline_test
    @require_torch
    def test_pipeline_zero_shot_audio_classification_fp16(self):
        self.run_task_tests(task="zero-shot-audio-classification", torch_dtype="float16")

610
    @is_pipeline_test
611
612
613
614
    @require_vision
    def test_pipeline_zero_shot_image_classification(self):
        self.run_task_tests(task="zero-shot-image-classification")

615
616
617
618
619
620
    @is_pipeline_test
    @require_vision
    @require_torch
    def test_pipeline_zero_shot_image_classification_fp16(self):
        self.run_task_tests(task="zero-shot-image-classification", torch_dtype="float16")

621
    @is_pipeline_test
622
623
624
625
626
    @require_vision
    @require_torch
    def test_pipeline_zero_shot_object_detection(self):
        self.run_task_tests(task="zero-shot-object-detection")

627
628
629
630
631
632
    @is_pipeline_test
    @require_vision
    @require_torch
    def test_pipeline_zero_shot_object_detection_fp16(self):
        self.run_task_tests(task="zero-shot-object-detection", torch_dtype="float16")

633
    # This contains the test cases to be skipped without model architecture being involved.
634
635
636
    def is_pipeline_test_to_skip(
        self, pipeline_test_casse_name, config_class, model_architecture, tokenizer_name, processor_name
    ):
637
638
639
640
        """Skip some tests based on the classes or their names without the instantiated objects.

        This is to avoid calling `from_pretrained` (so reducing the runtime) if we already know the tests will fail.
        """
641
642
643
644
645
646
647
648
649
        # No fix is required for this case.
        if (
            pipeline_test_casse_name == "DocumentQuestionAnsweringPipelineTests"
            and tokenizer_name is not None
            and not tokenizer_name.endswith("Fast")
        ):
            # `DocumentQuestionAnsweringPipelineTests` requires a fast tokenizer.
            return True

650
651
        return False

652
653
654
655
656
657
658
659
660
661
662
663
664
665
    def is_pipeline_test_to_skip_more(self, pipeline_test_casse_name, config, model, tokenizer, processor):  # noqa
        """Skip some more tests based on the information from the instantiated objects."""
        # No fix is required for this case.
        if (
            pipeline_test_casse_name == "QAPipelineTests"
            and tokenizer is not None
            and getattr(tokenizer, "pad_token", None) is None
            and not tokenizer.__class__.__name__.endswith("Fast")
        ):
            # `QAPipelineTests` doesn't work with a slow tokenizer that has no pad token.
            return True

        return False

666
667
668
669
670
671
672
673
674
675
676
677
678
679

def validate_test_components(test_case, task, model, tokenizer, processor):
    # TODO: Move this to tiny model creation script
    # head-specific (within a model type) necessary changes to the config
    # 1. for `BlenderbotForCausalLM`
    if model.__class__.__name__ == "BlenderbotForCausalLM":
        model.config.encoder_no_repeat_ngram_size = 0

    # TODO: Change the tiny model creation script: don't create models with problematic tokenizers
    # Avoid `IndexError` in embedding layers
    CONFIG_WITHOUT_VOCAB_SIZE = ["CanineConfig"]
    if tokenizer is not None:
        config_vocab_size = getattr(model.config, "vocab_size", None)
        # For CLIP-like models
680
681
682
683
684
685
        if config_vocab_size is None:
            if hasattr(model.config, "text_config"):
                config_vocab_size = getattr(model.config.text_config, "vocab_size", None)
            elif hasattr(model.config, "text_encoder"):
                config_vocab_size = getattr(model.config.text_encoder, "vocab_size", None)

686
687
688
689
        if config_vocab_size is None and model.config.__class__.__name__ not in CONFIG_WITHOUT_VOCAB_SIZE:
            raise ValueError(
                "Could not determine `vocab_size` from model configuration while `tokenizer` is not `None`."
            )