"examples/movement-pruning/masked_run_squad.py" did not exist on "e4c07faf0ae125559c30998c3513dd85f012c88e"
test_pipelines.py 15.9 KB
Newer Older
1
import unittest
Julien Chaumond's avatar
Julien Chaumond committed
2
from typing import Iterable, List, Optional
Morgan Funtowicz's avatar
Morgan Funtowicz committed
3
4

from transformers import pipeline
Lysandre Debut's avatar
Lysandre Debut committed
5
6
7
8
9
10
11
12
from transformers.pipelines import (
    FeatureExtractionPipeline,
    FillMaskPipeline,
    NerPipeline,
    Pipeline,
    QuestionAnsweringPipeline,
    TextClassificationPipeline,
)
13

Lysandre Debut's avatar
Lysandre Debut committed
14
from .utils import require_tf, require_torch, slow
15

Aymeric Augustin's avatar
Aymeric Augustin committed
16

17
18
19
20
21
QA_FINETUNED_MODELS = [
    (("bert-base-uncased", {"use_fast": False}), "bert-large-uncased-whole-word-masking-finetuned-squad", None),
    (("bert-base-cased", {"use_fast": False}), "bert-large-cased-whole-word-masking-finetuned-squad", None),
    (("bert-base-cased", {"use_fast": False}), "distilbert-base-cased-distilled-squad", None),
]
Morgan Funtowicz's avatar
Morgan Funtowicz committed
22

23
24
25
26
27
TF_QA_FINETUNED_MODELS = [
    (("bert-base-uncased", {"use_fast": False}), "bert-large-uncased-whole-word-masking-finetuned-squad", None),
    (("bert-base-cased", {"use_fast": False}), "bert-large-cased-whole-word-masking-finetuned-squad", None),
    (("bert-base-cased", {"use_fast": False}), "distilbert-base-cased-distilled-squad", None),
]
28
29
30

TF_NER_FINETUNED_MODELS = {
    (
31
        "bert-base-cased",
Julien Chaumond's avatar
Julien Chaumond committed
32
33
        "dbmdz/bert-large-cased-finetuned-conll03-english",
        "dbmdz/bert-large-cased-finetuned-conll03-english",
34
35
36
    )
}

Morgan Funtowicz's avatar
Morgan Funtowicz committed
37
38
NER_FINETUNED_MODELS = {
    (
39
        "bert-base-cased",
Julien Chaumond's avatar
Julien Chaumond committed
40
41
        "dbmdz/bert-large-cased-finetuned-conll03-english",
        "dbmdz/bert-large-cased-finetuned-conll03-english",
Morgan Funtowicz's avatar
Morgan Funtowicz committed
42
43
44
45
    )
}

FEATURE_EXTRACT_FINETUNED_MODELS = {
46
47
    ("bert-base-cased", "bert-base-cased", None),
    # ('xlnet-base-cased', 'xlnet-base-cased', None), # Disabled for now as it crash for TF2
48
    ("distilbert-base-cased", "distilbert-base-cased", None),
Morgan Funtowicz's avatar
Morgan Funtowicz committed
49
}
50

51
TF_FEATURE_EXTRACT_FINETUNED_MODELS = {
52
53
    ("bert-base-cased", "bert-base-cased", None),
    # ('xlnet-base-cased', 'xlnet-base-cased', None), # Disabled for now as it crash for TF2
54
    ("distilbert-base-cased", "distilbert-base-cased", None),
55
56
57
58
}

TF_TEXT_CLASSIF_FINETUNED_MODELS = {
    (
59
        "bert-base-uncased",
60
61
        "distilbert-base-uncased-finetuned-sst-2-english",
        "distilbert-base-uncased-finetuned-sst-2-english",
62
63
64
    )
}

Morgan Funtowicz's avatar
Morgan Funtowicz committed
65
66
TEXT_CLASSIF_FINETUNED_MODELS = {
    (
67
        "bert-base-uncased",
68
69
        "distilbert-base-uncased-finetuned-sst-2-english",
        "distilbert-base-uncased-finetuned-sst-2-english",
Morgan Funtowicz's avatar
Morgan Funtowicz committed
70
    )
71
72
}

73
74
75
FILL_MASK_FINETUNED_MODELS = [
    (("distilroberta-base", {"use_fast": False}), "distilroberta-base", None),
]
Julien Chaumond's avatar
Julien Chaumond committed
76

77
78
79
TF_FILL_MASK_FINETUNED_MODELS = [
    (("distilroberta-base", {"use_fast": False}), "distilroberta-base", None),
]
Julien Chaumond's avatar
Julien Chaumond committed
80

81
82
83
SUMMARIZATION_FINETUNED_MODELS = {("bart-large-cnn", "bart-large-cnn"), ("t5-small", "t5-small")}
TF_SUMMARIZATION_FINETUNED_MODELS = {("t5-small", "t5-small")}

84
85
86
87
88
89
TRANSLATION_FINETUNED_MODELS = {
    ("t5-small", "t5-small", "translation_en_to_de"),
    ("t5-small", "t5-small", "translation_en_to_ro"),
}
TF_TRANSLATION_FINETUNED_MODELS = {("t5-small", "t5-small", "translation_en_to_fr")}

90

Morgan Funtowicz's avatar
Morgan Funtowicz committed
91
class MonoColumnInputTestCase(unittest.TestCase):
Julien Chaumond's avatar
Julien Chaumond committed
92
93
94
95
96
97
98
99
100
    def _test_mono_column_pipeline(
        self,
        nlp: Pipeline,
        valid_inputs: List,
        invalid_inputs: List,
        output_keys: Iterable[str],
        expected_multi_result: Optional[List] = None,
        expected_check_keys: Optional[List[str]] = None,
    ):
Morgan Funtowicz's avatar
Morgan Funtowicz committed
101
102
103
104
105
106
107
108
109
110
111
112
        self.assertIsNotNone(nlp)

        mono_result = nlp(valid_inputs[0])
        self.assertIsInstance(mono_result, list)
        self.assertIsInstance(mono_result[0], (dict, list))

        if isinstance(mono_result[0], list):
            mono_result = mono_result[0]

        for key in output_keys:
            self.assertIn(key, mono_result[0])

113
        multi_result = [nlp(input) for input in valid_inputs]
Morgan Funtowicz's avatar
Morgan Funtowicz committed
114
115
116
        self.assertIsInstance(multi_result, list)
        self.assertIsInstance(multi_result[0], (dict, list))

Julien Chaumond's avatar
Julien Chaumond committed
117
118
119
120
121
122
123
        if expected_multi_result is not None:
            for result, expect in zip(multi_result, expected_multi_result):
                for key in expected_check_keys or []:
                    self.assertEqual(
                        set([o[key] for o in result]), set([o[key] for o in expect]),
                    )

Morgan Funtowicz's avatar
Morgan Funtowicz committed
124
125
126
127
128
129
130
131
132
        if isinstance(multi_result[0], list):
            multi_result = multi_result[0]

        for result in multi_result:
            for key in output_keys:
                self.assertIn(key, result)

        self.assertRaises(Exception, nlp, invalid_inputs)

133
    @require_torch
Morgan Funtowicz's avatar
Morgan Funtowicz committed
134
    def test_ner(self):
135
136
        mandatory_keys = {"entity", "word", "score"}
        valid_inputs = ["HuggingFace is solving NLP one commit at a time.", "HuggingFace is based in New-York & Paris"]
Morgan Funtowicz's avatar
Morgan Funtowicz committed
137
138
        invalid_inputs = [None]
        for tokenizer, model, config in NER_FINETUNED_MODELS:
139
            nlp = pipeline(task="ner", model=model, config=config, tokenizer=tokenizer)
140
            self._test_mono_column_pipeline(nlp, valid_inputs, invalid_inputs, mandatory_keys)
Morgan Funtowicz's avatar
Morgan Funtowicz committed
141

142
143
    @require_tf
    def test_tf_ner(self):
144
145
        mandatory_keys = {"entity", "word", "score"}
        valid_inputs = ["HuggingFace is solving NLP one commit at a time.", "HuggingFace is based in New-York & Paris"]
146
        invalid_inputs = [None]
147
        for tokenizer, model, config in TF_NER_FINETUNED_MODELS:
148
            nlp = pipeline(task="ner", model=model, config=config, tokenizer=tokenizer, framework="tf")
149
            self._test_mono_column_pipeline(nlp, valid_inputs, invalid_inputs, mandatory_keys)
Morgan Funtowicz's avatar
Morgan Funtowicz committed
150

151
    @require_torch
Morgan Funtowicz's avatar
Morgan Funtowicz committed
152
    def test_sentiment_analysis(self):
Julien Chaumond's avatar
Julien Chaumond committed
153
        mandatory_keys = {"label", "score"}
154
        valid_inputs = ["HuggingFace is solving NLP one commit at a time.", "HuggingFace is based in New-York & Paris"]
Morgan Funtowicz's avatar
Morgan Funtowicz committed
155
156
        invalid_inputs = [None]
        for tokenizer, model, config in TEXT_CLASSIF_FINETUNED_MODELS:
157
            nlp = pipeline(task="sentiment-analysis", model=model, config=config, tokenizer=tokenizer)
158
            self._test_mono_column_pipeline(nlp, valid_inputs, invalid_inputs, mandatory_keys)
Morgan Funtowicz's avatar
Morgan Funtowicz committed
159

160
161
    @require_tf
    def test_tf_sentiment_analysis(self):
Julien Chaumond's avatar
Julien Chaumond committed
162
        mandatory_keys = {"label", "score"}
163
        valid_inputs = ["HuggingFace is solving NLP one commit at a time.", "HuggingFace is based in New-York & Paris"]
164
        invalid_inputs = [None]
165
        for tokenizer, model, config in TF_TEXT_CLASSIF_FINETUNED_MODELS:
166
            nlp = pipeline(task="sentiment-analysis", model=model, config=config, tokenizer=tokenizer, framework="tf")
167
            self._test_mono_column_pipeline(nlp, valid_inputs, invalid_inputs, mandatory_keys)
Morgan Funtowicz's avatar
Morgan Funtowicz committed
168

169
    @require_torch
Julien Chaumond's avatar
Julien Chaumond committed
170
    def test_feature_extraction(self):
171
        valid_inputs = ["HuggingFace is solving NLP one commit at a time.", "HuggingFace is based in New-York & Paris"]
Morgan Funtowicz's avatar
Morgan Funtowicz committed
172
173
        invalid_inputs = [None]
        for tokenizer, model, config in FEATURE_EXTRACT_FINETUNED_MODELS:
Julien Chaumond's avatar
Julien Chaumond committed
174
            nlp = pipeline(task="feature-extraction", model=model, config=config, tokenizer=tokenizer)
175
            self._test_mono_column_pipeline(nlp, valid_inputs, invalid_inputs, {})
Morgan Funtowicz's avatar
Morgan Funtowicz committed
176

177
    @require_tf
Julien Chaumond's avatar
Julien Chaumond committed
178
    def test_tf_feature_extraction(self):
179
        valid_inputs = ["HuggingFace is solving NLP one commit at a time.", "HuggingFace is based in New-York & Paris"]
180
        invalid_inputs = [None]
181
        for tokenizer, model, config in TF_FEATURE_EXTRACT_FINETUNED_MODELS:
182
            nlp = pipeline(task="feature-extraction", model=model, config=config, tokenizer=tokenizer, framework="tf")
183
            self._test_mono_column_pipeline(nlp, valid_inputs, invalid_inputs, {})
Morgan Funtowicz's avatar
Morgan Funtowicz committed
184

Julien Chaumond's avatar
Julien Chaumond committed
185
186
187
188
189
190
191
192
193
194
    @require_torch
    def test_fill_mask(self):
        mandatory_keys = {"sequence", "score", "token"}
        valid_inputs = [
            "My name is <mask>",
            "The largest city in France is <mask>",
        ]
        invalid_inputs = [None]
        expected_multi_result = [
            [
195
196
                {"sequence": "<s> My name is:</s>", "score": 0.009954338893294334, "token": 35},
                {"sequence": "<s> My name is John</s>", "score": 0.0080940006300807, "token": 610},
Julien Chaumond's avatar
Julien Chaumond committed
197
198
199
            ],
            [
                {
200
201
202
203
204
205
206
                    "sequence": "<s> The largest city in France is Paris</s>",
                    "score": 0.3185044229030609,
                    "token": 2201,
                },
                {
                    "sequence": "<s> The largest city in France is Lyon</s>",
                    "score": 0.21112334728240967,
Julien Chaumond's avatar
Julien Chaumond committed
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
                    "token": 12790,
                },
            ],
        ]
        for tokenizer, model, config in FILL_MASK_FINETUNED_MODELS:
            nlp = pipeline(task="fill-mask", model=model, config=config, tokenizer=tokenizer, topk=2)
            self._test_mono_column_pipeline(
                nlp,
                valid_inputs,
                invalid_inputs,
                mandatory_keys,
                expected_multi_result=expected_multi_result,
                expected_check_keys=["sequence"],
            )

    @require_tf
    def test_tf_fill_mask(self):
        mandatory_keys = {"sequence", "score", "token"}
        valid_inputs = [
            "My name is <mask>",
            "The largest city in France is <mask>",
        ]
        invalid_inputs = [None]
        expected_multi_result = [
            [
232
233
                {"sequence": "<s> My name is:</s>", "score": 0.009954338893294334, "token": 35},
                {"sequence": "<s> My name is John</s>", "score": 0.0080940006300807, "token": 610},
Julien Chaumond's avatar
Julien Chaumond committed
234
235
236
            ],
            [
                {
237
238
239
240
241
242
243
                    "sequence": "<s> The largest city in France is Paris</s>",
                    "score": 0.3185044229030609,
                    "token": 2201,
                },
                {
                    "sequence": "<s> The largest city in France is Lyon</s>",
                    "score": 0.21112334728240967,
Julien Chaumond's avatar
Julien Chaumond committed
244
245
246
247
248
                    "token": 12790,
                },
            ],
        ]
        for tokenizer, model, config in TF_FILL_MASK_FINETUNED_MODELS:
249
            nlp = pipeline(task="fill-mask", model=model, config=config, tokenizer=tokenizer, framework="tf", topk=2)
Julien Chaumond's avatar
Julien Chaumond committed
250
251
252
253
254
255
256
257
258
            self._test_mono_column_pipeline(
                nlp,
                valid_inputs,
                invalid_inputs,
                mandatory_keys,
                expected_multi_result=expected_multi_result,
                expected_check_keys=["sequence"],
            )

259
260
261
262
263
    @require_torch
    def test_summarization(self):
        valid_inputs = ["A string like this", ["list of strings entry 1", "list of strings v2"]]
        invalid_inputs = [4, "<mask>"]
        mandatory_keys = ["summary_text"]
264
265
266
267
268
269
270
271
272
273
274
275
276
277
        for model, tokenizer in SUMMARIZATION_FINETUNED_MODELS:
            nlp = pipeline(task="summarization", model=model, tokenizer=tokenizer)
            self._test_mono_column_pipeline(
                nlp, valid_inputs, invalid_inputs, mandatory_keys,
            )

    @require_tf
    def test_tf_summarization(self):
        valid_inputs = ["A string like this", ["list of strings entry 1", "list of strings v2"]]
        invalid_inputs = [4, "<mask>"]
        mandatory_keys = ["summary_text"]
        for model, tokenizer in TF_SUMMARIZATION_FINETUNED_MODELS:
            nlp = pipeline(task="summarization", model=model, tokenizer=tokenizer, framework="tf")
            self._test_mono_column_pipeline(
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
                nlp, valid_inputs, invalid_inputs, mandatory_keys,
            )

    @require_torch
    def test_translation(self):
        valid_inputs = ["A string like this", ["list of strings entry 1", "list of strings v2"]]
        invalid_inputs = [4, "<mask>"]
        mandatory_keys = ["translation_text"]
        for model, tokenizer, task in TRANSLATION_FINETUNED_MODELS:
            nlp = pipeline(task=task, model=model, tokenizer=tokenizer)
            self._test_mono_column_pipeline(
                nlp, valid_inputs, invalid_inputs, mandatory_keys,
            )

    @require_tf
    def test_tf_translation(self):
        valid_inputs = ["A string like this", ["list of strings entry 1", "list of strings v2"]]
        invalid_inputs = [4, "<mask>"]
        mandatory_keys = ["translation_text"]
        for model, tokenizer, task in TF_TRANSLATION_FINETUNED_MODELS:
            nlp = pipeline(task=task, model=model, tokenizer=tokenizer, framework="tf")
            self._test_mono_column_pipeline(
300
301
                nlp, valid_inputs, invalid_inputs, mandatory_keys,
            )
302

Morgan Funtowicz's avatar
Morgan Funtowicz committed
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324

class MultiColumnInputTestCase(unittest.TestCase):
    def _test_multicolumn_pipeline(self, nlp, valid_inputs: list, invalid_inputs: list, output_keys: Iterable[str]):
        self.assertIsNotNone(nlp)

        mono_result = nlp(valid_inputs[0])
        self.assertIsInstance(mono_result, dict)

        for key in output_keys:
            self.assertIn(key, mono_result)

        multi_result = nlp(valid_inputs)
        self.assertIsInstance(multi_result, list)
        self.assertIsInstance(multi_result[0], dict)

        for result in multi_result:
            for key in output_keys:
                self.assertIn(key, result)

        self.assertRaises(Exception, nlp, invalid_inputs[0])
        self.assertRaises(Exception, nlp, invalid_inputs)

325
    @require_torch
Morgan Funtowicz's avatar
Morgan Funtowicz committed
326
    def test_question_answering(self):
327
        mandatory_output_keys = {"score", "answer", "start", "end"}
Morgan Funtowicz's avatar
Morgan Funtowicz committed
328
        valid_samples = [
329
            {"question": "Where was HuggingFace founded ?", "context": "HuggingFace was founded in Paris."},
Morgan Funtowicz's avatar
Morgan Funtowicz committed
330
            {
331
332
333
                "question": "In what field is HuggingFace working ?",
                "context": "HuggingFace is a startup based in New-York founded in Paris which is trying to solve NLP.",
            },
Morgan Funtowicz's avatar
Morgan Funtowicz committed
334
335
        ]
        invalid_samples = [
336
337
338
339
            {"question": "", "context": "This is a test to try empty question edge case"},
            {"question": None, "context": "This is a test to try empty question edge case"},
            {"question": "What is does with empty context ?", "context": ""},
            {"question": "What is does with empty context ?", "context": None},
Morgan Funtowicz's avatar
Morgan Funtowicz committed
340
341
342
        ]

        for tokenizer, model, config in QA_FINETUNED_MODELS:
343
            nlp = pipeline(task="question-answering", model=model, config=config, tokenizer=tokenizer)
344
            self._test_multicolumn_pipeline(nlp, valid_samples, invalid_samples, mandatory_output_keys)
Morgan Funtowicz's avatar
Morgan Funtowicz committed
345

346
    @require_tf
Lysandre's avatar
Lysandre committed
347
    @slow
348
    def test_tf_question_answering(self):
349
        mandatory_output_keys = {"score", "answer", "start", "end"}
350
        valid_samples = [
351
            {"question": "Where was HuggingFace founded ?", "context": "HuggingFace was founded in Paris."},
352
            {
353
354
355
                "question": "In what field is HuggingFace working ?",
                "context": "HuggingFace is a startup based in New-York founded in Paris which is trying to solve NLP.",
            },
356
357
        ]
        invalid_samples = [
358
359
360
361
            {"question": "", "context": "This is a test to try empty question edge case"},
            {"question": None, "context": "This is a test to try empty question edge case"},
            {"question": "What is does with empty context ?", "context": ""},
            {"question": "What is does with empty context ?", "context": None},
362
        ]
Morgan Funtowicz's avatar
Morgan Funtowicz committed
363

364
        for tokenizer, model, config in TF_QA_FINETUNED_MODELS:
365
            nlp = pipeline(task="question-answering", model=model, config=config, tokenizer=tokenizer, framework="tf")
366
            self._test_multicolumn_pipeline(nlp, valid_samples, invalid_samples, mandatory_output_keys)
Lysandre Debut's avatar
Lysandre Debut committed
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393


class PipelineCommonTests(unittest.TestCase):

    pipelines = (
        NerPipeline,
        FeatureExtractionPipeline,
        QuestionAnsweringPipeline,
        FillMaskPipeline,
        TextClassificationPipeline,
    )

    @slow
    @require_tf
    def test_tf_defaults(self):
        # Test that pipelines can be correctly loaded without any argument
        for default_pipeline in self.pipelines:
            with self.subTest(msg="Testing Torch defaults with PyTorch and {}".format(default_pipeline.task)):
                default_pipeline(framework="tf")

    @slow
    @require_torch
    def test_pt_defaults(self):
        # Test that pipelines can be correctly loaded without any argument
        for default_pipeline in self.pipelines:
            with self.subTest(msg="Testing Torch defaults with PyTorch and {}".format(default_pipeline.task)):
                default_pipeline(framework="pt")