From e2c05f06ef58ea77103d2c64492dd8d9a0b21c3f Mon Sep 17 00:00:00 2001 From: LysandreJik Date: Fri, 27 Mar 2020 09:28:21 -0400 Subject: [PATCH 01/10] Correct indentation in docstring For some reason Sphinx extremely dislikes this and crashes. --- src/transformers/modeling_tf_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/transformers/modeling_tf_utils.py b/src/transformers/modeling_tf_utils.py index e4e5449b1abb..9e4a155e2d84 100644 --- a/src/transformers/modeling_tf_utils.py +++ b/src/transformers/modeling_tf_utils.py @@ -231,7 +231,7 @@ def prune_heads(self, heads_to_prune): def save_pretrained(self, save_directory): """ Save a model and its configuration file to a directory, so that it - can be re-loaded using the `:func:`~transformers.PreTrainedModel.from_pretrained`` class method. + can be re-loaded using the :func:`~transformers.PreTrainedModel.from_pretrained` class method. """ assert os.path.isdir( save_directory @@ -541,7 +541,7 @@ def generate( ``1`` for tokens that are NOT MASKED, ``0`` for MASKED tokens. Defaults to `None`. - `What are attention masks? <../glossary.html#attention-mask>`__ + `What are attention masks? <../glossary.html#attention-mask>`__ decoder_start_token_id=None: (`optional`) int If an encoder-decoder model starts decoding with a different token than BOS. From ff80b731573d07a6633af9dac1e51f684dd6bc07 Mon Sep 17 00:00:00 2001 From: Lysandre Debut Date: Fri, 27 Mar 2020 10:56:59 -0400 Subject: [PATCH 02/10] Add option to choose T5 model size. (#3480) T5-small in test isort --- examples/summarization/t5/evaluate_cnn.py | 14 ++++++++++---- examples/summarization/t5/test_t5_examples.py | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/examples/summarization/t5/evaluate_cnn.py b/examples/summarization/t5/evaluate_cnn.py index 18750183ac85..535c11093b68 100644 --- a/examples/summarization/t5/evaluate_cnn.py +++ b/examples/summarization/t5/evaluate_cnn.py @@ -14,13 +14,13 @@ def chunks(lst, n): yield lst[i : i + n] -def generate_summaries(lns, output_file_path, batch_size, device): +def generate_summaries(lns, output_file_path, model_size, batch_size, device): output_file = Path(output_file_path).open("w") - model = T5ForConditionalGeneration.from_pretrained("t5-large") + model = T5ForConditionalGeneration.from_pretrained(model_size) model.to(device) - tokenizer = T5Tokenizer.from_pretrained("t5-large") + tokenizer = T5Tokenizer.from_pretrained(model_size) # update config with summarization specific params task_specific_params = model.config.task_specific_params @@ -61,6 +61,12 @@ def calculate_rouge(output_lns, reference_lns, score_path): def run_generate(): parser = argparse.ArgumentParser() + parser.add_argument( + "model_size", + type=str, + help="T5 model size, either 't5-small', 't5-base' or 't5-large'. Defaults to base.", + default="t5-base", + ) parser.add_argument( "input_path", type=str, help="like cnn_dm/test_articles_input.txt", ) @@ -83,7 +89,7 @@ def run_generate(): source_lns = [x.rstrip() for x in open(args.input_path).readlines()] - generate_summaries(source_lns, args.output_path, args.batch_size, args.device) + generate_summaries(source_lns, args.output_path, args.model_size, args.batch_size, args.device) output_lns = [x.rstrip() for x in open(args.output_path).readlines()] reference_lns = [x.rstrip() for x in open(args.reference_path).readlines()] diff --git a/examples/summarization/t5/test_t5_examples.py b/examples/summarization/t5/test_t5_examples.py index eb24c31c89cb..58b5db681eb3 100644 --- a/examples/summarization/t5/test_t5_examples.py +++ b/examples/summarization/t5/test_t5_examples.py @@ -22,7 +22,7 @@ def test_t5_cli(self): tmp = Path(tempfile.gettempdir()) / "utest_generations.hypo" with tmp.open("w") as f: f.write("\n".join(articles)) - testargs = ["evaluate_cnn.py", str(tmp), "output.txt", str(tmp), "score.txt"] + testargs = ["evaluate_cnn.py", "t5-small", str(tmp), "output.txt", str(tmp), "score.txt"] with patch.object(sys, "argv", testargs): run_generate() self.assertTrue(Path("output.txt").exists()) From fa9af2468a2ee48290be78e528d42b47da76fb23 Mon Sep 17 00:00:00 2001 From: Patrick von Platen Date: Fri, 27 Mar 2020 15:57:16 +0100 Subject: [PATCH 03/10] Add T5 to docs (#3461) * add t5 docs basis * improve docs * add t5 docs * improve t5 docstring * add t5 tokenizer docstring * finish docstring * make style * add pretrained models * correct typo * make examples work * finalize docs --- docs/source/index.rst | 1 + docs/source/model_doc/t5.rst | 69 +++++++++++++ docs/source/pretrained_models.rst | 4 - src/transformers/modeling_bart.py | 6 +- src/transformers/modeling_t5.py | 148 ++++++++++++++++----------- src/transformers/modeling_tf_t5.py | 152 +++++++++++++++++----------- src/transformers/tokenization_t5.py | 34 +++++-- 7 files changed, 285 insertions(+), 129 deletions(-) create mode 100644 docs/source/model_doc/t5.rst diff --git a/docs/source/index.rst b/docs/source/index.rst index 5180ae9af908..5ce54d5d9727 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -103,3 +103,4 @@ The library currently contains PyTorch and Tensorflow implementations, pre-train model_doc/xlmroberta model_doc/flaubert model_doc/bart + model_doc/t5 diff --git a/docs/source/model_doc/t5.rst b/docs/source/model_doc/t5.rst new file mode 100644 index 000000000000..3e4c28cf31e1 --- /dev/null +++ b/docs/source/model_doc/t5.rst @@ -0,0 +1,69 @@ +T5 +---------------------------------------------------- +**DISCLAIMER:** This model is still a work in progress, if you see something strange, +file a `Github Issue `_ + +Overview +~~~~~ +The T5 model was presented in `Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer `_ by Colin Raffel, Noam Shazeer, Adam Roberts, Katherine Lee, Sharan Narang, Michael Matena, Yanqi Zhou, Wei Li, Peter J. Liu in +Here the abstract: + +*Transfer learning, where a model is first pre-trained on a data-rich task before being fine-tuned on a downstream task, has emerged as a powerful technique in natural language processing (NLP). The effectiveness of transfer learning has given rise to a diversity of approaches, methodology, and practice. +In this paper, we explore the landscape of transfer learning techniques for NLP by introducing a unified framework that converts every language problem into a text-to-text format. +Our systematic study compares pre-training objectives, architectures, unlabeled datasets, transfer approaches, and other factors on dozens of language understanding tasks. +By combining the insights from our exploration with scale and our new "Colossal Clean Crawled Corpus", we achieve state-of-the-art results on many benchmarks covering summarization, question answering, text classification, and more. +To facilitate future work on transfer learning for NLP, we release our dataset, pre-trained models, and code.* + +The Authors' code can be found `here `_ . + +Tips +~~~~~~~~~~~~~~~~~~~~ +- T5 is an encoder-decoder model pre-trained on a multi-task mixture of unsupervised + and supervised tasks and which each task is cast as a sequence to sequence task. + Therefore T5 works well on a variety of tasks out-of-the-box by prepending a different prefix to the input corresponding to each task, e.g.: for translation: *translate English to German: ..., summarize: ...*. + For more information about the which prefix to use, it is easiest to look into Appendix D of the `paper `_ . +- For sequence to sequence generation, it is recommended to use ``T5ForConditionalGeneration.generate()``. The method takes care of feeding the encoded input via cross-attention layers to the decoder and auto-regressively generating the decoder output. +- T5 uses relative scalar embeddings. Encoder input padding can be done on the left and on the right. + + +T5Config +~~~~~~~~~~~~~~~~~~~~~ + +.. autoclass:: transformers.T5Config + :members: + + +T5Tokenizer +~~~~~~~~~~~~~~~~~~~~~ + +.. autoclass:: transformers.T5Tokenizer + :members: build_inputs_with_special_tokens, get_special_tokens_mask, + create_token_type_ids_from_sequences, save_vocabulary + + +T5Model +~~~~~~~~~~~~~~~~~~~~ + +.. autoclass:: transformers.T5Model + :members: + + +T5ForConditionalGeneration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autoclass:: transformers.T5ForConditionalGeneration + :members: + + +TFT5Model +~~~~~~~~~~~~~~~~~~~~ + +.. autoclass:: transformers.TFT5Model + :members: + + +TFT5ForConditionalGeneration +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autoclass:: transformers.TFT5ForConditionalGeneration + :members: diff --git a/docs/source/pretrained_models.rst b/docs/source/pretrained_models.rst index 565c861ccd38..65f718c3db2e 100644 --- a/docs/source/pretrained_models.rst +++ b/docs/source/pretrained_models.rst @@ -275,7 +275,6 @@ For a list that includes community-uploaded models, refer to `https://huggingfac | | | | FlauBERT large architecture | | | | (see `details `__) | +-------------------+------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------+ -+-------------------+------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------+ | Bart | ``bart-large`` | | 12-layer, 1024-hidden, 16-heads, 406M parameters | | | | (see `details `_) | | +------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------+ @@ -285,6 +284,3 @@ For a list that includes community-uploaded models, refer to `https://huggingfac | | ``bart-large-cnn`` | | 12-layer, 1024-hidden, 16-heads, 406M parameters (same as base) | | | | | bart-large base architecture finetuned on cnn summarization task | +-------------------+------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------+ - - -.. `__ diff --git a/src/transformers/modeling_bart.py b/src/transformers/modeling_bart.py index fe374d79dadc..d2f92b00549a 100644 --- a/src/transformers/modeling_bart.py +++ b/src/transformers/modeling_bart.py @@ -72,6 +72,10 @@ Mask to avoid performing attention on padding token indices in input_ids. Mask values selected in ``[0, 1]``: ``1`` for tokens that are NOT MASKED, ``0`` for MASKED tokens. + encoder_outputs (tuple(:obj:`tuple(torch.FloatTensor)`, `optional`, defaults to :obj:`None`): + Tuple consists of (`last_hidden_state`, `optional`: `hidden_states`, `optional`: `attentions`) + `last_hidden_state` of shape :obj:`(batch_size, sequence_length, hidden_size)`, `optional`, defaults to :obj:`None`) is a sequence of hidden-states at the output of the last layer of the encoder. + Used in the cross-attention of the decoder. decoder_input_ids (:obj:`torch.LongTensor` of shape :obj:`(batch_size, target_sequence_length)`, `optional`, defaults to :obj:`None`): Provide for translation and summarization training. By default, the model will create this tensor by shifting the input_ids right, following the paper. decoder_attention_mask (:obj:`torch.BoolTensor` of shape :obj:`(batch_size, tgt_seq_len)`, `optional`, defaults to :obj:`None`): @@ -972,7 +976,7 @@ def forward( Returns: :obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~transformers.BartConfig`) and inputs: loss (:obj:`torch.FloatTensor` of shape :obj:`(1,)`, `optional`, returned when :obj:`label` is provided): - Classification loss (cross entropy) + Classification loss (cross entropy) logits (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, config.num_labels)`): Classification (or regression if config.num_labels==1) scores (before SoftMax). hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_hidden_states=True``): diff --git a/src/transformers/modeling_t5.py b/src/transformers/modeling_t5.py index d03c40f5a679..cdfa1ce91704 100644 --- a/src/transformers/modeling_t5.py +++ b/src/transformers/modeling_t5.py @@ -27,7 +27,7 @@ from torch.nn import CrossEntropyLoss from .configuration_t5 import T5Config -from .file_utils import DUMMY_INPUTS, DUMMY_MASK, add_start_docstrings +from .file_utils import DUMMY_INPUTS, DUMMY_MASK, add_start_docstrings, add_start_docstrings_to_callable from .modeling_utils import PreTrainedModel, prune_linear_layer @@ -696,8 +696,8 @@ def forward( """ T5_INPUTS_DOCSTRING = r""" - Inputs: - **input_ids**: ``torch.LongTensor`` of shape ``(batch_size, sequence_length)``: + Args: + input_ids (:obj:`torch.LongTensor` of shape :obj:`(batch_size, sequence_length)`): Indices of input sequence tokens in the vocabulary. To match pre-training, T5 input sequence should be formatted with [CLS] and [SEP] tokens as follows: @@ -715,11 +715,27 @@ def forward( Indices can be obtained using :class:`transformers.T5Tokenizer`. See :func:`transformers.PreTrainedTokenizer.encode` and :func:`transformers.PreTrainedTokenizer.convert_tokens_to_ids` for details. - **attention_mask**: (`optional`) ``torch.FloatTensor`` of shape ``(batch_size, sequence_length)``: + attention_mask (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length)`, `optional`, defaults to :obj:`None`): Mask to avoid performing attention on padding token indices. Mask values selected in ``[0, 1]``: ``1`` for tokens that are NOT MASKED, ``0`` for MASKED tokens. - **head_mask**: (`optional`) ``torch.FloatTensor`` of shape ``(num_heads,)`` or ``(num_layers, num_heads)``: + encoder_outputs (tuple(:obj:`tuple(torch.FloatTensor)`, `optional`, defaults to :obj:`None`): + Tuple consists of (`last_hidden_state`, `optional`: `hidden_states`, `optional`: `attentions`) + `last_hidden_state` of shape :obj:`(batch_size, sequence_length, hidden_size)`, `optional`, defaults to :obj:`None`) is a sequence of hidden-states at the output of the last layer of the encoder. + Used in the cross-attention of the decoder. + decoder_input_ids (:obj:`torch.LongTensor` of shape :obj:`(batch_size, target_sequence_length)`, `optional`, defaults to :obj:`None`): + Provide for sequence to sequence training. T5 uses the pad_token_id as the starting token for decoder_input_ids generation. + decoder_attention_mask (:obj:`torch.BoolTensor` of shape :obj:`(batch_size, tgt_seq_len)`, `optional`, defaults to :obj:`None`): + Default behavior: generate a tensor that ignores pad tokens in decoder_input_ids. Causal mask will also be used by default. + inputs_embeds (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length, hidden_size)`, `optional`, defaults to :obj:`None`): + Optionally, instead of passing :obj:`input_ids` you can choose to directly pass an embedded representation. + This is useful if you want more control over how to convert `input_ids` indices into associated vectors + than the model's internal embedding lookup matrix. + decoder_inputs_embeds (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, target_sequence_length, hidden_size)`, `optional`, defaults to :obj:`None`): + Optionally, instead of passing :obj:`decoder_input_ids` you can choose to directly pass an embedded representation. + This is useful if you want more control over how to convert `decoder_input_ids` indices into associated vectors + than the model's internal embedding lookup matrix. + head_mask: (:obj:`torch.FloatTensor` of shape :obj:`(num_heads,)` or :obj:`(num_layers, num_heads)`, `optional`, defaults to :obj:`None`): Mask to nullify selected heads of the self-attention modules. Mask values selected in ``[0, 1]``: ``1`` indicates the head is **not masked**, ``0`` indicates the head is **masked**. @@ -729,31 +745,8 @@ def forward( @add_start_docstrings( "The bare T5 Model transformer outputting raw hidden-states" "without any specific head on top.", T5_START_DOCSTRING, - T5_INPUTS_DOCSTRING, ) class T5Model(T5PreTrainedModel): - r""" - Outputs: `Tuple` comprising various elements depending on the configuration (config) and inputs: - **last_hidden_state**: ``torch.FloatTensor`` of shape ``(batch_size, sequence_length, hidden_size)`` - Sequence of hidden-states at the output of the last layer of the model. - **hidden_states**: (`optional`, returned when ``config.output_hidden_states=True``) - list of ``torch.FloatTensor`` (one for the output of each layer + the output of the embeddings) - of shape ``(batch_size, sequence_length, hidden_size)``: - Hidden-states of the model at the output of each layer plus the initial embedding outputs. - **attentions**: (`optional`, returned when ``config.output_attentions=True``) - list of ``torch.FloatTensor`` (one for each layer) of shape ``(batch_size, num_heads, sequence_length, sequence_length)``: - Attentions weights after the attention softmax, used to compute the weighted average in the self-attention heads. - - Examples:: - - tokenizer = T5Tokenizer.from_pretrained('t5-small') - model = T5Model.from_pretrained('t5-small') - input_ids = torch.tensor(tokenizer.encode("Hello, my dog is cute")).unsqueeze(0) # Batch size 1 - outputs = model(input_ids=input_ids) - last_hidden_states = outputs[0] # The last hidden-state is the first element of the output tuple - - """ - def __init__(self, config): super().__init__(config) self.shared = nn.Embedding(config.vocab_size, config.d_model) @@ -783,6 +776,7 @@ def _prune_heads(self, heads_to_prune): for layer, heads in heads_to_prune.items(): self.encoder.layer[layer].attention.prune_heads(heads) + @add_start_docstrings_to_callable(T5_INPUTS_DOCSTRING) def forward( self, input_ids=None, @@ -794,6 +788,34 @@ def forward( decoder_inputs_embeds=None, head_mask=None, ): + r""" + Return: + :obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~transformers.T5Config`) and inputs. + last_hidden_state (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length, hidden_size)`): + Sequence of hidden-states at the output of the last layer of the model. + hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_hidden_states=True``): + Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer) + of shape :obj:`(batch_size, sequence_length, hidden_size)`. + + Hidden-states of the model at the output of each layer plus the initial embedding outputs. + attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_attentions=True``): + Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape + :obj:`(batch_size, num_heads, sequence_length, sequence_length)`. + + Attentions weights after the attention softmax, used to compute the weighted average in the self-attention + heads. + + Examples:: + + from transformers import T5Tokenizer, T5Model + + tokenizer = T5Tokenizer.from_pretrained('t5-small') + model = T5Model.from_pretrained('t5-small') + input_ids = tokenizer.encode("Hello, my dog is cute", return_tensors="pt") # Batch size 1 + outputs = model(input_ids=input_ids, decoder_input_ids=input_ids) + last_hidden_states = outputs[0] # The last hidden-state is the first element of the output tuple + + """ # Encode if needed (training, first prediction pass) if encoder_outputs is None: @@ -816,38 +838,8 @@ def forward( return decoder_outputs + encoder_outputs -@add_start_docstrings("""T5 Model with a `language modeling` head on top. """, T5_START_DOCSTRING, T5_INPUTS_DOCSTRING) +@add_start_docstrings("""T5 Model with a `language modeling` head on top. """, T5_START_DOCSTRING) class T5ForConditionalGeneration(T5PreTrainedModel): - r""" - **lm_labels**: (`optional`) ``torch.LongTensor`` of shape ``(batch_size, sequence_length)``: - Labels for computing the masked language modeling loss. - Indices should either be in ``[0, ..., config.vocab_size]`` or -100 (see ``input_ids`` docstring). - Tokens with indices set to ``-100`` are ignored (masked), the loss is only computed for the tokens with labels - in ``[0, ..., config.vocab_size]``. - - Outputs: `Tuple` comprising various elements depending on the configuration (config) and inputs: - **loss**: (`optional`, returned when ``lm_labels`` is provided) ``torch.FloatTensor`` of shape ``(1,)``: - Masked language modeling loss. - **prediction_scores**: ``torch.FloatTensor`` of shape ``(batch_size, sequence_length, config.vocab_size)`` - Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax). - **hidden_states**: (`optional`, returned when ``config.output_hidden_states=True``) - list of ``torch.FloatTensor`` (one for the output of each layer + the output of the embeddings) - of shape ``(batch_size, sequence_length, hidden_size)``: - Hidden-states of the model at the output of each layer plus the initial embedding outputs. - **attentions**: (`optional`, returned when ``config.output_attentions=True``) - list of ``torch.FloatTensor`` (one for each layer) of shape ``(batch_size, num_heads, sequence_length, sequence_length)``: - Attentions weights after the attention softmax, used to compute the weighted average in the self-attention heads. - - Examples:: - - tokenizer = T5Tokenizer.from_pretrained('t5-small') - model = T5ForConditionalGeneration.from_pretrained('t5-small') - input_ids = torch.tensor(tokenizer.encode("Hello, my dog is cute")).unsqueeze(0) # Batch size 1 - outputs = model(input_ids=input_ids, lm_labels=input_ids) - loss, prediction_scores = outputs[:2] - - """ - def __init__(self, config): super().__init__(config) self.model_dim = config.d_model @@ -879,6 +871,7 @@ def get_output_embeddings(self): def get_encoder(self): return self.encoder + @add_start_docstrings_to_callable(T5_INPUTS_DOCSTRING) def forward( self, input_ids=None, @@ -891,6 +884,43 @@ def forward( decoder_inputs_embeds=None, head_mask=None, ): + r""" + lm_labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`, defaults to :obj:`None`): + Labels for computing the sequence classification/regression loss. + Indices should be in :obj:`[0, ..., config.vocab_size - 1]`. + If :obj:`config.num_labels > 1` a classification loss is computed (Cross-Entropy). + + Returns: + :obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~transformers.T5Config`) and inputs. + loss (:obj:`torch.FloatTensor` of shape :obj:`(1,)`, `optional`, returned when :obj:`lm_label` is provided): + Classification loss (cross entropy). + prediction_scores (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length, config.vocab_size)`) + Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax). + hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_hidden_states=True``): + Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer) + of shape :obj:`(batch_size, sequence_length, hidden_size)`. + + Hidden-states of the model at the output of each layer plus the initial embedding outputs. + attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_attentions=True``): + Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape + :obj:`(batch_size, num_heads, sequence_length, sequence_length)`. + Attentions weights after the attention softmax, used to compute the weighted average in the self-attention. + + Examples:: + + from transformers import T5Tokenizer, T5ForConditionalGeneration + + tokenizer = T5Tokenizer.from_pretrained('t5-small') + model = T5ForConditionalGeneration.from_pretrained('t5-small') + input_ids = tokenizer.encode("Hello, my dog is cute", return_tensors="pt") # Batch size 1 + outputs = model(input_ids=input_ids, decoder_input_ids=input_ids, lm_labels=input_ids) + loss, prediction_scores = outputs[:2] + + tokenizer = T5Tokenizer.from_pretrained('t5-small') + model = T5ForConditionalGeneration.from_pretrained('t5-small') + input_ids = tokenizer.encode("summarize: Hello, my dog is cute", return_tensors="pt") # Batch size 1 + outputs = model.generate(input_ids) + """ # Encode if needed (training, first prediction pass) if encoder_outputs is None: diff --git a/src/transformers/modeling_tf_t5.py b/src/transformers/modeling_tf_t5.py index c17b2b678c26..ddc6b7a801b0 100644 --- a/src/transformers/modeling_tf_t5.py +++ b/src/transformers/modeling_tf_t5.py @@ -24,7 +24,7 @@ import tensorflow as tf from .configuration_t5 import T5Config -from .file_utils import DUMMY_INPUTS, DUMMY_MASK, add_start_docstrings +from .file_utils import DUMMY_INPUTS, DUMMY_MASK, add_start_docstrings, add_start_docstrings_to_callable from .modeling_tf_utils import TFPreTrainedModel, TFSharedEmbeddings, shape_list @@ -630,8 +630,12 @@ def dummy_inputs(self): """ T5_INPUTS_DOCSTRING = r""" - Inputs: - **input_ids**: ``Numpy array`` or ``tf.Tensor`` of shape ``(batch_size, sequence_length)``: + Args: + decoder_input_ids are usually used as a `dict` (see T5 description above for more information) containing all the following. + decoder_input_ids (:obj:`tf.Tensor` of shape :obj:`(batch_size, target_sequence_length)`, `optional`, defaults to :obj:`None`): + Provide for sequence to sequence training. T5 uses the pad_token_id as the starting token for decoder_input_ids generation. + + input_ids (:obj:`tf.Tensor` of shape :obj:`(batch_size, sequence_length)`): Indices of input sequence tokens in the vocabulary. To match pre-training, T5 input sequence should be formatted with [CLS] and [SEP] tokens as follows: @@ -643,18 +647,31 @@ def dummy_inputs(self): ``tokens: [CLS] the dog is hairy . [SEP]`` - T5 is a model with relative position embeddings so you should be able to pad the inputs on the right or the left. Indices can be obtained using :class:`transformers.T5Tokenizer`. See :func:`transformers.PreTrainedTokenizer.encode` and :func:`transformers.PreTrainedTokenizer.convert_tokens_to_ids` for details. - **attention_mask**: (`optional`) ``Numpy array`` or ``tf.Tensor`` of shape ``(batch_size, sequence_length)``: + attention_mask (:obj:`tf.Tensor` of shape :obj:`(batch_size, sequence_length)`, `optional`, defaults to :obj:`None`): Mask to avoid performing attention on padding token indices. Mask values selected in ``[0, 1]``: ``1`` for tokens that are NOT MASKED, ``0`` for MASKED tokens. - **head_mask**: (`optional`) ``Numpy array`` or ``tf.Tensor`` of shape ``(num_heads,)`` or ``(num_layers, num_heads)``: + encoder_outputs (tuple(:obj:`tuple(tf.FloatTensor)`, `optional`, defaults to :obj:`None`): + Tuple consists of (`last_hidden_state`, `optional`: `hidden_states`, `optional`: `attentions`) + `last_hidden_state` of shape :obj:`(batch_size, sequence_length, hidden_size)`, `optional`, defaults to :obj:`None`) is a sequence of hidden-states at the output of the last layer of the encoder. + Used in the cross-attention of the decoder. + decoder_attention_mask (:obj:`tf.Tensor` of shape :obj:`(batch_size, tgt_seq_len)`, `optional`, defaults to :obj:`None`): + Default behavior: generate a tensor that ignores pad tokens in decoder_input_ids. Causal mask will also be used by default. + inputs_embeds (:obj:`tf.Tensor` of shape :obj:`(batch_size, sequence_length, hidden_size)`, `optional`, defaults to :obj:`None`): + Optionally, instead of passing :obj:`input_ids` you can choose to directly pass an embedded representation. + This is useful if you want more control over how to convert `input_ids` indices into associated vectors + than the model's internal embedding lookup matrix. + decoder_inputs_embeds (:obj:`tf.Tensor` of shape :obj:`(batch_size, target_sequence_length, hidden_size)`, `optional`, defaults to :obj:`None`): + Optionally, instead of passing :obj:`decoder_input_ids` you can choose to directly pass an embedded representation. + This is useful if you want more control over how to convert `decoder_input_ids` indices into associated vectors + than the model's internal embedding lookup matrix. + head_mask: (:obj:`tf.Tensor` of shape :obj:`(num_heads,)` or :obj:`(num_layers, num_heads)`, `optional`, defaults to :obj:`None`): Mask to nullify selected heads of the self-attention modules. Mask values selected in ``[0, 1]``: ``1`` indicates the head is **not masked**, ``0`` indicates the head is **masked**. @@ -664,34 +681,8 @@ def dummy_inputs(self): @add_start_docstrings( "The bare T5 Model transformer outputting raw hidden-states" "without any specific head on top.", T5_START_DOCSTRING, - T5_INPUTS_DOCSTRING, ) class TFT5Model(TFT5PreTrainedModel): - r""" - Outputs: `Tuple` comprising various elements depending on the configuration (config) and inputs: - **last_hidden_state**: ``tf.Tensor`` of shape ``(batch_size, sequence_length, hidden_size)`` - Sequence of hidden-states at the output of the last layer of the model. - **hidden_states**: (`optional`, returned when ``config.output_hidden_states=True``) - list of ``tf.Tensor`` (one for the output of each layer + the output of the embeddings) - of shape ``(batch_size, sequence_length, hidden_size)``: - Hidden-states of the model at the output of each layer plus the initial embedding outputs. - **attentions**: (`optional`, returned when ``config.output_attentions=True``) - list of ``tf.Tensor`` (one for each layer) of shape ``(batch_size, num_heads, sequence_length, sequence_length)``: - Attentions weights after the attention softmax, used to compute the weighted average in the self-attention heads. - - Examples:: - - import tensorflow as tf - from transformers import T5Tokenizer, TFT5Model - - tokenizer = T5Tokenizer.from_pretrained('t5-small') - model = TFT5Model.from_pretrained('t5-small') - input_ids = tf.constant(tokenizer.encode("Hello, my dog is cute"))[None, :] # Batch size 1 - outputs = model(input_ids=input_ids) - last_hidden_states = outputs[0] # The last hidden-state is the first element of the output tuple - - """ - def __init__(self, config, *inputs, **kwargs): super().__init__(config, *inputs, **kwargs) self.shared = TFSharedEmbeddings(config.vocab_size, config.d_model, name="shared") @@ -715,7 +706,36 @@ def get_input_embeddings(self): def get_output_embeddings(self): return self.shared + @add_start_docstrings_to_callable(T5_INPUTS_DOCSTRING) def call(self, decoder_input_ids, **kwargs): + r""" + Return: + :obj:`tuple(tf.Tensor)` comprising various elements depending on the configuration (:class:`~transformers.T5Config`) and inputs. + last_hidden_state (:obj:`tf.Tensor` of shape :obj:`(batch_size, sequence_length, hidden_size)`): + Sequence of hidden-states at the output of the last layer of the model. + hidden_states (:obj:`tuple(tf.Tensor)`, `optional`, returned when ``config.output_hidden_states=True``): + Tuple of :obj:`tf.Tensor` (one for the output of the embeddings + one for the output of each layer) + of shape :obj:`(batch_size, sequence_length, hidden_size)`. + + Hidden-states of the model at the output of each layer plus the initial embedding outputs. + attentions (:obj:`tuple(tf.Tensor)`, `optional`, returned when ``config.output_attentions=True``): + Tuple of :obj:`tf.Tensor` (one for each layer) of shape + :obj:`(batch_size, num_heads, sequence_length, sequence_length)`. + + Attentions weights after the attention softmax, used to compute the weighted average in the self-attention + heads. + + Examples:: + + from transformers import T5Tokenizer, TFT5Model + + tokenizer = T5Tokenizer.from_pretrained('t5-small') + model = TFT5Model.from_pretrained('t5-small') + input_ids = tokenizer.encode("Hello, my dog is cute", return_tensors="tf") # Batch size 1 + outputs = model(input_ids, input_ids=input_ids) + last_hidden_states = outputs[0] # The last hidden-state is the first element of the output tuple + + """ if isinstance(decoder_input_ids, dict): kwargs.update(decoder_input_ids) @@ -753,33 +773,8 @@ def call(self, decoder_input_ids, **kwargs): return decoder_outputs + encoder_outputs -@add_start_docstrings("""T5 Model with a `language modeling` head on top. """, T5_START_DOCSTRING, T5_INPUTS_DOCSTRING) +@add_start_docstrings("""T5 Model with a `language modeling` head on top. """, T5_START_DOCSTRING) class TFT5ForConditionalGeneration(TFT5PreTrainedModel): - r""" - Outputs: `Tuple` comprising various elements depending on the configuration (config) and inputs: - **prediction_scores**: ``Numpy array`` or ``tf.Tensor`` of shape ``(batch_size, sequence_length, config.vocab_size)`` - Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax). - **hidden_states**: (`optional`, returned when ``config.output_hidden_states=True``) - list of ``Numpy array`` or ``tf.Tensor`` (one for the output of each layer + the output of the embeddings) - of shape ``(batch_size, sequence_length, hidden_size)``: - Hidden-states of the model at the output of each layer plus the initial embedding outputs. - **attentions**: (`optional`, returned when ``config.output_attentions=True``) - list of ``Numpy array`` or ``tf.Tensor`` (one for each layer) of shape ``(batch_size, num_heads, sequence_length, sequence_length)``: - Attentions weights after the attention softmax, used to compute the weighted average in the self-attention heads. - - Examples:: - - import tensorflow as tf - from transformers import T5Tokenizer, TFT5ForConditionalGeneration - - tokenizer = T5Tokenizer.from_pretrained('t5-small') - model = TFT5ForConditionalGeneration.from_pretrained('t5-small') - input_ids = tf.constant(tokenizer.encode("Hello, my dog is cute"))[None, :] # Batch size 1 - outputs = model(input_ids=input_ids) - prediction_scores = outputs[0] - - """ - def __init__(self, config, *inputs, **kwargs): super().__init__(config, *inputs, **kwargs) self.model_dim = config.d_model @@ -808,7 +803,47 @@ def get_output_embeddings(self): def get_encoder(self): return self.encoder + @add_start_docstrings_to_callable(T5_INPUTS_DOCSTRING) def call(self, decoder_input_ids, **kwargs): + r""" + lm_labels (:obj:`tf.Tensor` of shape :obj:`(batch_size,)`, `optional`, defaults to :obj:`None`): + Labels for computing the sequence classification/regression loss. + Indices should be in :obj:`[0, ..., config.vocab_size - 1]`. + If :obj:`config.num_labels > 1` a classification loss is computed (Cross-Entropy). + + Return: + :obj:`tuple(tf.Tensor)` comprising various elements depending on the configuration (:class:`~transformers.T5Config`) and inputs. + loss (:obj:`tf.Tensor` of shape :obj:`(1,)`, `optional`, returned when :obj:`lm_label` is provided): + Classification loss (cross entropy). + prediction_scores (:obj:`tf.Tensor` of shape :obj:`(batch_size, sequence_length, config.vocab_size)`) + Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax). + hidden_states (:obj:`tuple(tf.Tensor)`, `optional`, returned when ``config.output_hidden_states=True``): + Tuple of :obj:`tf.Tensor` (one for the output of the embeddings + one for the output of each layer) + of shape :obj:`(batch_size, sequence_length, hidden_size)`. + + Hidden-states of the model at the output of each layer plus the initial embedding outputs. + attentions (:obj:`tuple(tf.Tensor)`, `optional`, returned when ``config.output_attentions=True``): + Tuple of :obj:`tf.Tensor` (one for each layer) of shape + :obj:`(batch_size, num_heads, sequence_length, sequence_length)`. + + Attentions weights after the attention softmax, used to compute the weighted average in the self-attention. + + Examples:: + + from transformers import T5Tokenizer, TFT5ForConditionalGeneration + + tokenizer = T5Tokenizer.from_pretrained('t5-small') + model = TFT5ForConditionalGeneration.from_pretrained('t5-small') + input_ids = tokenizer.encode("Hello, my dog is cute", return_tensors="tf") # Batch size 1 + outputs = model(input_ids, input_ids=input_ids, lm_labels=input_ids) + prediction_scores = outputs[:1] # TODO: TFT5 still needs to implement + + tokenizer = T5Tokenizer.from_pretrained('t5-small') + model = TFT5ForConditionalGeneration.from_pretrained('t5-small') + input_ids = tokenizer.encode("summarize: Hello, my dog is cute", return_tensors="tf") # Batch size 1 + model.generate(input_ids) + + """ if isinstance(decoder_input_ids, dict): kwargs.update(decoder_input_ids) @@ -844,6 +879,7 @@ def call(self, decoder_input_ids, **kwargs): head_mask=head_mask, ) + # TODO (thom / patrick): add lm_labels for loss function sequence_output = decoder_outputs[0] * (self.model_dim ** -0.5) embed_tokens = self.get_output_embeddings() lm_logits = embed_tokens(sequence_output, mode="linear") diff --git a/src/transformers/tokenization_t5.py b/src/transformers/tokenization_t5.py index 3d0d4e698c6c..bc1cf9fd038b 100644 --- a/src/transformers/tokenization_t5.py +++ b/src/transformers/tokenization_t5.py @@ -61,14 +61,34 @@ class T5Tokenizer(PreTrainedTokenizer): """ - SentencePiece based tokenizer. Peculiarities: - - - requires `SentencePiece `_ - - `extra_ids` add a number of extra ids added to the end of the vocabulary for use as sentinels. - These tokens are accessible as `` where `{%d}` is a number between 0 and extra_ids-1. - Extra tokens are indexed from the end of the vocabulary up to beginnning ( is the last token in the vocabulary) - (like in T5 preprocessing + Constructs an XLNet tokenizer. Based on `SentencePiece `__ . + + This tokenizer inherits from :class:`~transformers.PreTrainedTokenizer` which contains most of the methods. Users + should refer to the superclass for more information regarding methods. + + Args: + vocab_file (:obj:`string`): + `SentencePiece `__ file (generally has a `.spm` extension) that + contains the vocabulary necessary to instantiate a tokenizer. + eos_token (:obj:`string`, `optional`, defaults to ""): + The end of sequence token. + + .. note:: + + When building a sequence using special tokens, this is not the token that is used for the end + of sequence. The token used is the :obj:`sep_token`. + unk_token (:obj:`string`, `optional`, defaults to ""): + The unknown token. A token that is not in the vocabulary cannot be converted to an ID and is set to be this + token instead. + pad_token (:obj:`string`, `optional`, defaults to ""): + The token used for padding, for example when batching sequences of different lengths. + extra_ids (:obj:`List[str]`, `optional`, defaults to :obj:`100`): + Add a number of extra ids added to the end of the vocabulary for use as sentinels. + These tokens are accessible as "" where "{%d}" is a number between 0 and extra_ids-1. + Extra tokens are indexed from the end of the vocabulary up to beginnning ("" is the last token in the vocabulary like in T5 preprocessing see: https://github.com/google-research/text-to-text-transfer-transformer/blob/9fd7b14a769417be33bc6c850f9598764913c833/t5/data/preprocessors.py#L2117) + additional_special_tokens (:obj:`List[str]`, `optional`, defaults to :obj:`None`): + Additional special tokens used by the tokenizer. """ vocab_files_names = VOCAB_FILES_NAMES From f4f4946836dd029b2015ffc59db3edac0f6edd45 Mon Sep 17 00:00:00 2001 From: Patrick von Platen Date: Fri, 27 Mar 2020 15:57:58 +0100 Subject: [PATCH 04/10] Rename `t5-large` to `t5-base` in README.md --- examples/summarization/t5/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/summarization/t5/README.md b/examples/summarization/t5/README.md index 222e5ff17cf4..783d67a8af40 100644 --- a/examples/summarization/t5/README.md +++ b/examples/summarization/t5/README.md @@ -1,4 +1,4 @@ -***This script evaluates the the multitask pre-trained checkpoint for ``t5-large`` (see paper [here](https://arxiv.org/pdf/1910.10683.pdf)) on the CNN/Daily Mail test dataset. Please note that the results in the paper were attained using a model fine-tuned on summarization, so that results will be worse here by approx. 0.5 ROUGE points*** +***This script evaluates the the multitask pre-trained checkpoint for ``t5-base`` (see paper [here](https://arxiv.org/pdf/1910.10683.pdf)) on the CNN/Daily Mail test dataset. Please note that the results in the paper were attained using a model fine-tuned on summarization, so that results will be worse here by approx. 0.5 ROUGE points*** ### Get the CNN Data First, you need to download the CNN data. It's about ~400 MB and can be downloaded by From b08259a12086dbd3b572ea71a7f08ba21518f355 Mon Sep 17 00:00:00 2001 From: Funtowicz Morgan Date: Fri, 27 Mar 2020 14:59:55 +0000 Subject: [PATCH 05/10] run_ner.py / bert-base-multilingual-cased can output empty tokens (#2991) * Use tokenizer.num_added_tokens to count number of added special_tokens instead of hardcoded numbers. Signed-off-by: Morgan Funtowicz * run_ner.py - Do not add a label to the labels_ids if word_tokens is empty. This can happen when using bert-base-multilingual-cased with an input containing an unique space. In this case, the tokenizer will output just an empty word_tokens thus leading to an non-consistent behavior over the labels_ids tokens adding one more tokens than tokens vector. Signed-off-by: Morgan Funtowicz --- examples/ner/utils_ner.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/examples/ner/utils_ner.py b/examples/ner/utils_ner.py index 510749c2f59c..bda1b65a7c2e 100644 --- a/examples/ner/utils_ner.py +++ b/examples/ner/utils_ner.py @@ -112,12 +112,15 @@ def convert_examples_to_features( label_ids = [] for word, label in zip(example.words, example.labels): word_tokens = tokenizer.tokenize(word) - tokens.extend(word_tokens) - # Use the real label id for the first token of the word, and padding ids for the remaining tokens - label_ids.extend([label_map[label]] + [pad_token_label_id] * (len(word_tokens) - 1)) + + # bert-base-multilingual-cased sometimes output "nothing ([]) when calling tokenize with just a space. + if len(word_tokens) > 0: + tokens.extend(word_tokens) + # Use the real label id for the first token of the word, and padding ids for the remaining tokens + label_ids.extend([label_map[label]] + [pad_token_label_id] * (len(word_tokens) - 1)) # Account for [CLS] and [SEP] with "- 2" and with "- 3" for RoBERTa. - special_tokens_count = 3 if sep_token_extra else 2 + special_tokens_count = tokenizer.num_added_tokens() if len(tokens) > max_seq_length - special_tokens_count: tokens = tokens[: (max_seq_length - special_tokens_count)] label_ids = label_ids[: (max_seq_length - special_tokens_count)] From 00ea100e965a9df44b2934bc2c5a40cd1cd70d91 Mon Sep 17 00:00:00 2001 From: Patrick von Platen Date: Fri, 27 Mar 2020 16:05:37 +0100 Subject: [PATCH 06/10] add summarization and translation to notebook (#3478) --- notebooks/03-pipelines.ipynb | 3487 +++++++++++++++++++++++++++++----- 1 file changed, 3013 insertions(+), 474 deletions(-) diff --git a/notebooks/03-pipelines.ipynb b/notebooks/03-pipelines.ipynb index 908cb004a397..b346d77ea444 100644 --- a/notebooks/03-pipelines.ipynb +++ b/notebooks/03-pipelines.ipynb @@ -1,511 +1,3050 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "## How can I leverage State-of-the-Art Natural Language Models with only one line of code ?" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "Newly introduced in transformers v2.3.0, **pipelines** provides a high-level, easy to use,\n", - "API for doing inference over a variety of downstream-tasks, including: \n", - "\n", - "- Sentence Classification (Sentiment Analysis): Indicate if the overall sentence is either positive or negative. _(Binary Classification task or Logitic Regression task)_\n", - "- Token Classification (Named Entity Recognition, Part-of-Speech tagging): For each sub-entities _(**tokens**)_ in the input, assign them a label _(Classification task)_.\n", - "- Question-Answering: Provided a tuple (question, context) the model should find the span of text in **content** answering the **question**.\n", - "- Mask-Filling: Suggests possible word(s) to fill the masked input with respect to the provided **context**.\n", - "- Feature Extraction: Maps the input to a higher, multi-dimensional space learned from the data.\n", - "\n", - "Pipelines encapsulate the overall process of every NLP process:\n", - " \n", - " 1. Tokenization: Split the initial input into multiple sub-entities with ... properties (i.e. tokens).\n", - " 2. Inference: Maps every tokens into a more meaningful representation. \n", - " 3. Decoding: Use the above representation to generate and/or extract the final output for the underlying task.\n", - "\n", - "The overall API is exposed to the end-user through the `pipeline()` method with the following \n", - "structure:\n", - "\n", - "```python\n", - "from transformers import pipeline\n", - "\n", - "# Using default model and tokenizer for the task\n", - "pipeline(\"\")\n", - "\n", - "# Using a user-specified model\n", - "pipeline(\"\", model=\"\")\n", - "\n", - "# Using custom model/tokenizer as str\n", - "pipeline('', model='', tokenizer='')\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "outputs": [], - "source": [ - "!pip install transformers" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%% code\n" - } - } - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "pycharm": { - "is_executing": false, - "name": "#%% code \n" - } - }, - "outputs": [], - "source": [ - "from __future__ import print_function\n", - "import ipywidgets as widgets\n", - "from transformers import pipeline" - ] - }, - { - "cell_type": "markdown", - "metadata": { + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.6" + }, "pycharm": { - "name": "#%% md\n" + "stem_cell": { + "cell_type": "raw", + "source": [], + "metadata": { + "collapsed": false + } + } + }, + "colab": { + "name": "03-pipelines.ipynb", + "provenance": [] + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "4bab5df43b3c46caadf48e264344ab42": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HBoxModel", + "state": { + "_view_name": "HBoxView", + "_dom_classes": [], + "_model_name": "HBoxModel", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.5.0", + "box_style": "", + "layout": "IPY_MODEL_9b426c68631f4bb288e2ca79aad9f9d9", + "_model_module": "@jupyter-widgets/controls", + "children": [ + "IPY_MODEL_6902104f7ec143519fb1a6ab9363d4a0", + "IPY_MODEL_c133fb34fe2a4aba8a6b233671af8b04" + ] + } + }, + "9b426c68631f4bb288e2ca79aad9f9d9": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "6902104f7ec143519fb1a6ab9363d4a0": { + "model_module": "@jupyter-widgets/controls", + "model_name": "IntProgressModel", + "state": { + "_view_name": "ProgressView", + "style": "IPY_MODEL_e3f72d443a74414ca62c2b848d34b125", + "_dom_classes": [], + "description": "Downloading: 100%", + "_model_name": "IntProgressModel", + "bar_style": "success", + "max": 230, + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": 230, + "_view_count": null, + "_view_module_version": "1.5.0", + "orientation": "horizontal", + "min": 0, + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_5462b581976e47048642aa6bc12435bd" + } + }, + "c133fb34fe2a4aba8a6b233671af8b04": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HTMLModel", + "state": { + "_view_name": "HTMLView", + "style": "IPY_MODEL_ad84da685cf44abb90d17d9d2e023b48", + "_dom_classes": [], + "description": "", + "_model_name": "HTMLModel", + "placeholder": "​", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": " 230/230 [00:01<00:00, 194B/s]", + "_view_count": null, + "_view_module_version": "1.5.0", + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_a246f9eea2d7440cb979e728741d2e32" + } + }, + "e3f72d443a74414ca62c2b848d34b125": { + "model_module": "@jupyter-widgets/controls", + "model_name": "ProgressStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "ProgressStyleModel", + "description_width": "initial", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "bar_color": null, + "_model_module": "@jupyter-widgets/controls" + } + }, + "5462b581976e47048642aa6bc12435bd": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "ad84da685cf44abb90d17d9d2e023b48": { + "model_module": "@jupyter-widgets/controls", + "model_name": "DescriptionStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "DescriptionStyleModel", + "description_width": "", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "_model_module": "@jupyter-widgets/controls" + } + }, + "a246f9eea2d7440cb979e728741d2e32": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "451464c936444ba5a652b46c1b4f9931": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HBoxModel", + "state": { + "_view_name": "HBoxView", + "_dom_classes": [], + "_model_name": "HBoxModel", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.5.0", + "box_style": "", + "layout": "IPY_MODEL_279291efd2c14a9eb2c3b98efbf152ad", + "_model_module": "@jupyter-widgets/controls", + "children": [ + "IPY_MODEL_b6e1a2e57f4948a39283f1370352612c", + "IPY_MODEL_9d4941ebdfa64978b47232f6e5908d97" + ] + } + }, + "279291efd2c14a9eb2c3b98efbf152ad": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "b6e1a2e57f4948a39283f1370352612c": { + "model_module": "@jupyter-widgets/controls", + "model_name": "IntProgressModel", + "state": { + "_view_name": "ProgressView", + "style": "IPY_MODEL_1006cc0fab1e4139bb7b135486261c92", + "_dom_classes": [], + "description": "Downloading: 100%", + "_model_name": "IntProgressModel", + "bar_style": "success", + "max": 230, + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": 230, + "_view_count": null, + "_view_module_version": "1.5.0", + "orientation": "horizontal", + "min": 0, + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_691c0bae60364890ab74934261207d4d" + } + }, + "9d4941ebdfa64978b47232f6e5908d97": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HTMLModel", + "state": { + "_view_name": "HTMLView", + "style": "IPY_MODEL_405afa5bb8b840d8bc0850e02f593ce4", + "_dom_classes": [], + "description": "", + "_model_name": "HTMLModel", + "placeholder": "​", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": " 230/230 [00:01<00:00, 198B/s]", + "_view_count": null, + "_view_module_version": "1.5.0", + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_78c718e3d5fa4cb892217260bea6d540" + } + }, + "1006cc0fab1e4139bb7b135486261c92": { + "model_module": "@jupyter-widgets/controls", + "model_name": "ProgressStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "ProgressStyleModel", + "description_width": "initial", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "bar_color": null, + "_model_module": "@jupyter-widgets/controls" + } + }, + "691c0bae60364890ab74934261207d4d": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "405afa5bb8b840d8bc0850e02f593ce4": { + "model_module": "@jupyter-widgets/controls", + "model_name": "DescriptionStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "DescriptionStyleModel", + "description_width": "", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "_model_module": "@jupyter-widgets/controls" + } + }, + "78c718e3d5fa4cb892217260bea6d540": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "7d66a4534c164d2f9493fc0467abebbd": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HBoxModel", + "state": { + "_view_name": "HBoxView", + "_dom_classes": [], + "_model_name": "HBoxModel", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.5.0", + "box_style": "", + "layout": "IPY_MODEL_7a15588f85b14f2b93e32b4c0442fa1b", + "_model_module": "@jupyter-widgets/controls", + "children": [ + "IPY_MODEL_213567d815894ca08041f6d682ced3c9", + "IPY_MODEL_ee6c95e700e64d0a9ebec2c1545dd083" + ] + } + }, + "7a15588f85b14f2b93e32b4c0442fa1b": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "213567d815894ca08041f6d682ced3c9": { + "model_module": "@jupyter-widgets/controls", + "model_name": "IntProgressModel", + "state": { + "_view_name": "ProgressView", + "style": "IPY_MODEL_3e556abf5c4a4ee69d52366fd59471b2", + "_dom_classes": [], + "description": "Downloading: 100%", + "_model_name": "IntProgressModel", + "bar_style": "success", + "max": 230, + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": 230, + "_view_count": null, + "_view_module_version": "1.5.0", + "orientation": "horizontal", + "min": 0, + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_876b2eba73fa46a6a941d2e3a8a975ad" + } + }, + "ee6c95e700e64d0a9ebec2c1545dd083": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HTMLModel", + "state": { + "_view_name": "HTMLView", + "style": "IPY_MODEL_cd64e3f20b23483daa79712bde6622ea", + "_dom_classes": [], + "description": "", + "_model_name": "HTMLModel", + "placeholder": "​", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": " 230/230 [00:02<00:00, 85.4B/s]", + "_view_count": null, + "_view_module_version": "1.5.0", + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_67cbaa1f55d24e62ad6b022af36bca56" + } + }, + "3e556abf5c4a4ee69d52366fd59471b2": { + "model_module": "@jupyter-widgets/controls", + "model_name": "ProgressStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "ProgressStyleModel", + "description_width": "initial", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "bar_color": null, + "_model_module": "@jupyter-widgets/controls" + } + }, + "876b2eba73fa46a6a941d2e3a8a975ad": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "cd64e3f20b23483daa79712bde6622ea": { + "model_module": "@jupyter-widgets/controls", + "model_name": "DescriptionStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "DescriptionStyleModel", + "description_width": "", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "_model_module": "@jupyter-widgets/controls" + } + }, + "67cbaa1f55d24e62ad6b022af36bca56": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "58669943d3064f309436157270544c08": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HBoxModel", + "state": { + "_view_name": "HBoxView", + "_dom_classes": [], + "_model_name": "HBoxModel", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.5.0", + "box_style": "", + "layout": "IPY_MODEL_3eff293c2b554d85aefaea863e29b678", + "_model_module": "@jupyter-widgets/controls", + "children": [ + "IPY_MODEL_d0b9925f3dde46008bf186cf5ef7722d", + "IPY_MODEL_427e07ce24a442af84ddc71f9463fdff" + ] + } + }, + "3eff293c2b554d85aefaea863e29b678": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "d0b9925f3dde46008bf186cf5ef7722d": { + "model_module": "@jupyter-widgets/controls", + "model_name": "IntProgressModel", + "state": { + "_view_name": "ProgressView", + "style": "IPY_MODEL_1eb2fa080ec44f8c8d5f6f52900277ab", + "_dom_classes": [], + "description": "Downloading: 100%", + "_model_name": "IntProgressModel", + "bar_style": "success", + "max": 230, + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": 230, + "_view_count": null, + "_view_module_version": "1.5.0", + "orientation": "horizontal", + "min": 0, + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_23377596349e40a89ea57c8558660073" + } + }, + "427e07ce24a442af84ddc71f9463fdff": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HTMLModel", + "state": { + "_view_name": "HTMLView", + "style": "IPY_MODEL_a35703cc8ff44e93a8c0eb413caddc40", + "_dom_classes": [], + "description": "", + "_model_name": "HTMLModel", + "placeholder": "​", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": " 230/230 [00:01<00:00, 120B/s]", + "_view_count": null, + "_view_module_version": "1.5.0", + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_9df7014c99b343f3b178fa020ff56010" + } + }, + "1eb2fa080ec44f8c8d5f6f52900277ab": { + "model_module": "@jupyter-widgets/controls", + "model_name": "ProgressStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "ProgressStyleModel", + "description_width": "initial", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "bar_color": null, + "_model_module": "@jupyter-widgets/controls" + } + }, + "23377596349e40a89ea57c8558660073": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "a35703cc8ff44e93a8c0eb413caddc40": { + "model_module": "@jupyter-widgets/controls", + "model_name": "DescriptionStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "DescriptionStyleModel", + "description_width": "", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "_model_module": "@jupyter-widgets/controls" + } + }, + "9df7014c99b343f3b178fa020ff56010": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "57e8c36594d043c581c766b434037771": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HBoxModel", + "state": { + "_view_name": "HBoxView", + "_dom_classes": [], + "_model_name": "HBoxModel", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.5.0", + "box_style": "", + "layout": "IPY_MODEL_82760185d5c14a808cbf6639b589f249", + "_model_module": "@jupyter-widgets/controls", + "children": [ + "IPY_MODEL_f2a1b430594b4736879cdff4ec532098", + "IPY_MODEL_c81338551e60474fab9e9950fe5df294" + ] + } + }, + "82760185d5c14a808cbf6639b589f249": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "f2a1b430594b4736879cdff4ec532098": { + "model_module": "@jupyter-widgets/controls", + "model_name": "IntProgressModel", + "state": { + "_view_name": "ProgressView", + "style": "IPY_MODEL_98563b405bd043a9a301a43909e43157", + "_dom_classes": [], + "description": "Downloading: 100%", + "_model_name": "IntProgressModel", + "bar_style": "success", + "max": 230, + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": 230, + "_view_count": null, + "_view_module_version": "1.5.0", + "orientation": "horizontal", + "min": 0, + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_8c0e1b7fb6ac4ee7bbbaf6020b40cc77" + } + }, + "c81338551e60474fab9e9950fe5df294": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HTMLModel", + "state": { + "_view_name": "HTMLView", + "style": "IPY_MODEL_ad78042ee71a41fd989e4b4ce9d2e3c1", + "_dom_classes": [], + "description": "", + "_model_name": "HTMLModel", + "placeholder": "​", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": " 230/230 [00:01<00:00, 128B/s]", + "_view_count": null, + "_view_module_version": "1.5.0", + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_40c8d2617f3d4c84b923b140456fa5da" + } + }, + "98563b405bd043a9a301a43909e43157": { + "model_module": "@jupyter-widgets/controls", + "model_name": "ProgressStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "ProgressStyleModel", + "description_width": "initial", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "bar_color": null, + "_model_module": "@jupyter-widgets/controls" + } + }, + "8c0e1b7fb6ac4ee7bbbaf6020b40cc77": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "ad78042ee71a41fd989e4b4ce9d2e3c1": { + "model_module": "@jupyter-widgets/controls", + "model_name": "DescriptionStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "DescriptionStyleModel", + "description_width": "", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "_model_module": "@jupyter-widgets/controls" + } + }, + "40c8d2617f3d4c84b923b140456fa5da": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "311a65b811964ebfa2c064eb348b3ce9": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HBoxModel", + "state": { + "_view_name": "HBoxView", + "_dom_classes": [], + "_model_name": "HBoxModel", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.5.0", + "box_style": "", + "layout": "IPY_MODEL_5a2032c44d0e4f8cbaf512e6c29214cd", + "_model_module": "@jupyter-widgets/controls", + "children": [ + "IPY_MODEL_54d1ff55e0094a4fa2b62ecdfb428328", + "IPY_MODEL_2e45f2d7d65246ecb8d6e666d026ac13" + ] + } + }, + "5a2032c44d0e4f8cbaf512e6c29214cd": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "54d1ff55e0094a4fa2b62ecdfb428328": { + "model_module": "@jupyter-widgets/controls", + "model_name": "IntProgressModel", + "state": { + "_view_name": "ProgressView", + "style": "IPY_MODEL_e05c0ec3b49e4d4990a943d428532fb0", + "_dom_classes": [], + "description": "Downloading: 100%", + "_model_name": "IntProgressModel", + "bar_style": "success", + "max": 230, + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": 230, + "_view_count": null, + "_view_module_version": "1.5.0", + "orientation": "horizontal", + "min": 0, + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_39721262fc1e4456966d92fabe0f54ea" + } + }, + "2e45f2d7d65246ecb8d6e666d026ac13": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HTMLModel", + "state": { + "_view_name": "HTMLView", + "style": "IPY_MODEL_4486f8a2efc34b9aab3864eb5ad2ba48", + "_dom_classes": [], + "description": "", + "_model_name": "HTMLModel", + "placeholder": "​", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": " 230/230 [00:01<00:00, 126B/s]", + "_view_count": null, + "_view_module_version": "1.5.0", + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_d6228324f3444aa6bd1323d65ae4ff75" + } + }, + "e05c0ec3b49e4d4990a943d428532fb0": { + "model_module": "@jupyter-widgets/controls", + "model_name": "ProgressStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "ProgressStyleModel", + "description_width": "initial", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "bar_color": null, + "_model_module": "@jupyter-widgets/controls" + } + }, + "39721262fc1e4456966d92fabe0f54ea": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "4486f8a2efc34b9aab3864eb5ad2ba48": { + "model_module": "@jupyter-widgets/controls", + "model_name": "DescriptionStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "DescriptionStyleModel", + "description_width": "", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "_model_module": "@jupyter-widgets/controls" + } + }, + "d6228324f3444aa6bd1323d65ae4ff75": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "fd44cf6ab17e4b768b2e1d5cb8ce5af9": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HBoxModel", + "state": { + "_view_name": "HBoxView", + "_dom_classes": [], + "_model_name": "HBoxModel", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.5.0", + "box_style": "", + "layout": "IPY_MODEL_b8c0ea31578d4eaaa69251d0004fd8c6", + "_model_module": "@jupyter-widgets/controls", + "children": [ + "IPY_MODEL_2015cd9c1da9467290ecd9019af231eb", + "IPY_MODEL_17bacdaee55b43e8977c4dfe4f7245bb" + ] + } + }, + "b8c0ea31578d4eaaa69251d0004fd8c6": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "2015cd9c1da9467290ecd9019af231eb": { + "model_module": "@jupyter-widgets/controls", + "model_name": "IntProgressModel", + "state": { + "_view_name": "ProgressView", + "style": "IPY_MODEL_879ef9e1a0e94f3d96ed56fb4bae64b8", + "_dom_classes": [], + "description": "Downloading: 100%", + "_model_name": "IntProgressModel", + "bar_style": "success", + "max": 230, + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": 230, + "_view_count": null, + "_view_module_version": "1.5.0", + "orientation": "horizontal", + "min": 0, + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_7ab70324d42647acac5020b387955caf" + } + }, + "17bacdaee55b43e8977c4dfe4f7245bb": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HTMLModel", + "state": { + "_view_name": "HTMLView", + "style": "IPY_MODEL_31d97ecf78fa412c99e6659196d82828", + "_dom_classes": [], + "description": "", + "_model_name": "HTMLModel", + "placeholder": "​", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": " 230/230 [00:01<00:00, 129B/s]", + "_view_count": null, + "_view_module_version": "1.5.0", + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_c6be5d48ec3c4c799d1445607e5f1ac6" + } + }, + "879ef9e1a0e94f3d96ed56fb4bae64b8": { + "model_module": "@jupyter-widgets/controls", + "model_name": "ProgressStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "ProgressStyleModel", + "description_width": "initial", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "bar_color": null, + "_model_module": "@jupyter-widgets/controls" + } + }, + "7ab70324d42647acac5020b387955caf": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "31d97ecf78fa412c99e6659196d82828": { + "model_module": "@jupyter-widgets/controls", + "model_name": "DescriptionStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "DescriptionStyleModel", + "description_width": "", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "_model_module": "@jupyter-widgets/controls" + } + }, + "c6be5d48ec3c4c799d1445607e5f1ac6": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "0bd407b4975f49c3827aede14c59501c": { + "model_module": "@jupyter-widgets/controls", + "model_name": "DropdownModel", + "state": { + "_options_labels": [ + "sentiment-analysis", + "ner", + "fill_mask" + ], + "_view_name": "DropdownView", + "style": "IPY_MODEL_3f5406df699e44f5b60678c1c13500f5", + "_dom_classes": [], + "description": "Task:", + "_model_name": "DropdownModel", + "index": 1, + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_view_count": null, + "disabled": false, + "_view_module_version": "1.5.0", + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_17768469581445b68246ed308ce69326" + } + }, + "3f5406df699e44f5b60678c1c13500f5": { + "model_module": "@jupyter-widgets/controls", + "model_name": "DescriptionStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "DescriptionStyleModel", + "description_width": "", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "_model_module": "@jupyter-widgets/controls" + } + }, + "17768469581445b68246ed308ce69326": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "74cbcbae5cac4f12abf080a38390f05c": { + "model_module": "@jupyter-widgets/controls", + "model_name": "TextModel", + "state": { + "_view_name": "TextView", + "style": "IPY_MODEL_62b10ca525cc4ac68f3a006434eb7416", + "_dom_classes": [], + "description": "Your input:", + "_model_name": "TextModel", + "placeholder": "Enter something", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": "Peter Pan likes to go on holiday in Marseille, France.", + "_view_count": null, + "disabled": false, + "_view_module_version": "1.5.0", + "continuous_update": true, + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_211109537fbe4e60b89a238c89db1346" + } + }, + "62b10ca525cc4ac68f3a006434eb7416": { + "model_module": "@jupyter-widgets/controls", + "model_name": "DescriptionStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "DescriptionStyleModel", + "description_width": "", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "_model_module": "@jupyter-widgets/controls" + } + }, + "211109537fbe4e60b89a238c89db1346": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "d79946ac16ea4855a0bbe2ca2a4d4bf5": { + "model_module": "@jupyter-widgets/controls", + "model_name": "TextareaModel", + "state": { + "_view_name": "TextareaView", + "style": "IPY_MODEL_ab5774ac19f84ab18ddf09a63433df00", + "rows": null, + "_dom_classes": [], + "description": "Context:", + "_model_name": "TextareaModel", + "placeholder": "Enter something", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": "Einstein is famous for the general theory of relativity", + "_view_count": null, + "disabled": false, + "_view_module_version": "1.5.0", + "continuous_update": true, + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_a02164204f0f43668bc36a907e720af7" + } + }, + "ab5774ac19f84ab18ddf09a63433df00": { + "model_module": "@jupyter-widgets/controls", + "model_name": "DescriptionStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "DescriptionStyleModel", + "description_width": "", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "_model_module": "@jupyter-widgets/controls" + } + }, + "a02164204f0f43668bc36a907e720af7": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "3b12aec414b14221ad2a11dfd975faa0": { + "model_module": "@jupyter-widgets/controls", + "model_name": "TextModel", + "state": { + "_view_name": "TextView", + "style": "IPY_MODEL_d305ba1662e3466c93ab5cca7ebf8f33", + "_dom_classes": [], + "description": "Question:", + "_model_name": "TextModel", + "placeholder": "Enter something", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": "Why is Einstein famous for ?", + "_view_count": null, + "disabled": false, + "_view_module_version": "1.5.0", + "continuous_update": true, + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_879f7a3747ad455d810c7a29918648ee" + } + }, + "d305ba1662e3466c93ab5cca7ebf8f33": { + "model_module": "@jupyter-widgets/controls", + "model_name": "DescriptionStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "DescriptionStyleModel", + "description_width": "", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "_model_module": "@jupyter-widgets/controls" + } + }, + "879f7a3747ad455d810c7a29918648ee": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + } + } } - }, - "source": [ - "## 1. Sentence Classification - Sentiment Analysis" - ] }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "pycharm": { - "is_executing": false, - "name": "#%% code\n" - } - }, - "outputs": [ + "cells": [ { - "data": { - "text/plain": "HBox(children=(FloatProgress(value=0.0, description='Downloading', max=230.0, style=ProgressStyle(description_…", - "application/vnd.jupyter.widget-view+json": { - "version_major": 2, - "version_minor": 0, - "model_id": "c9db53f30b9446c0af03268633a966c0" - } - }, - "metadata": {}, - "output_type": "display_data" + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + }, + "id": "qUU7wy-brl_H", + "colab_type": "text" + }, + "source": [ + "## How can I leverage State-of-the-Art Natural Language Models with only one line of code ?" + ] }, { - "name": "stdout", - "text": [ - "\n" - ], - "output_type": "stream" + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + }, + "id": "-HLOHXuArl_L", + "colab_type": "text" + }, + "source": [ + "Newly introduced in transformers v2.3.0, **pipelines** provides a high-level, easy to use,\n", + "API for doing inference over a variety of downstream-tasks, including: \n", + "\n", + "- ***Sentence Classification _(Sentiment Analysis)_***: Indicate if the overall sentence is either positive or negative, i.e. *binary classification task* or *logitic regression task*.\n", + "- ***Token Classification (Named Entity Recognition, Part-of-Speech tagging)***: For each sub-entities _(*tokens*)_ in the input, assign them a label, i.e. classification task.\n", + "- ***Question-Answering***: Provided a tuple (`question`, `context`) the model should find the span of text in `content` answering the `question`.\n", + "- ***Mask-Filling***: Suggests possible word(s) to fill the masked input with respect to the provided `context`.\n", + "- ***Summarization***: Summarizes the ``input`` article to a shorter article.\n", + "- ***Translation***: Translates the input from a language to another language.\n", + "- ***Feature Extraction***: Maps the input to a higher, multi-dimensional space learned from the data.\n", + "\n", + "Pipelines encapsulate the overall process of every NLP process:\n", + " \n", + " 1. *Tokenization*: Split the initial input into multiple sub-entities with ... properties (i.e. tokens).\n", + " 2. *Inference*: Maps every tokens into a more meaningful representation. \n", + " 3. *Decoding*: Use the above representation to generate and/or extract the final output for the underlying task.\n", + "\n", + "The overall API is exposed to the end-user through the `pipeline()` method with the following \n", + "structure:\n", + "\n", + "```python\n", + "from transformers import pipeline\n", + "\n", + "# Using default model and tokenizer for the task\n", + "pipeline(\"\")\n", + "\n", + "# Using a user-specified model\n", + "pipeline(\"\", model=\"\")\n", + "\n", + "# Using custom model/tokenizer as str\n", + "pipeline('', model='', tokenizer='')\n", + "```" + ] }, { - "data": { - "text/plain": "[{'label': 'POSITIVE', 'score': 0.9997656}]" - }, - "metadata": {}, - "output_type": "execute_result", - "execution_count": 8 - } - ], - "source": [ - "nlp_sentence_classif = pipeline('sentiment-analysis')\n", - "nlp_sentence_classif('Such a nice weather outside !')" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "## 2. Token Classification - Named Entity Recognition" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "pycharm": { - "is_executing": false, - "name": "#%% code\n" - } - }, - "outputs": [ + "cell_type": "code", + "metadata": { + "pycharm": { + "name": "#%% code\n" + }, + "id": "4maAknWNrl_N", + "colab_type": "code", + "colab": {} + }, + "source": [ + "!pip install -q transformers" + ], + "execution_count": 0, + "outputs": [] + }, { - "data": { - "text/plain": "HBox(children=(FloatProgress(value=0.0, description='Downloading', max=230.0, style=ProgressStyle(description_…", - "application/vnd.jupyter.widget-view+json": { - "version_major": 2, - "version_minor": 0, - "model_id": "1e300789e22644f1aed66a5ed60e75c4" - } - }, - "metadata": {}, - "output_type": "display_data" + "cell_type": "code", + "metadata": { + "pycharm": { + "is_executing": false, + "name": "#%% code \n" + }, + "id": "uKaqzCh6rl_V", + "colab_type": "code", + "colab": {} + }, + "source": [ + "from __future__ import print_function\n", + "import ipywidgets as widgets\n", + "from transformers import pipeline" + ], + "execution_count": 0, + "outputs": [] }, { - "name": "stdout", - "text": [ - "\n" - ], - "output_type": "stream" + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + }, + "id": "uDPZ42Uerl_b", + "colab_type": "text" + }, + "source": [ + "## 1. Sentence Classification - Sentiment Analysis" + ] }, { - "data": { - "text/plain": "[{'word': 'Hu', 'score': 0.9970937967300415, 'entity': 'I-ORG'},\n {'word': '##gging', 'score': 0.9345750212669373, 'entity': 'I-ORG'},\n {'word': 'Face', 'score': 0.9787060022354126, 'entity': 'I-ORG'},\n {'word': 'French', 'score': 0.9981995820999146, 'entity': 'I-MISC'},\n {'word': 'New', 'score': 0.9983047246932983, 'entity': 'I-LOC'},\n {'word': '-', 'score': 0.8913455009460449, 'entity': 'I-LOC'},\n {'word': 'York', 'score': 0.9979523420333862, 'entity': 'I-LOC'}]" - }, - "metadata": {}, - "output_type": "execute_result", - "execution_count": 9 - } - ], - "source": [ - "nlp_token_class = pipeline('ner')\n", - "nlp_token_class('Hugging Face is a French company based in New-York.')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3. Question Answering" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "pycharm": { - "is_executing": false, - "name": "#%% code\n" - } - }, - "outputs": [ + "cell_type": "code", + "metadata": { + "pycharm": { + "is_executing": false, + "name": "#%% code\n" + }, + "id": "AMRXHQw9rl_d", + "colab_type": "code", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 83, + "referenced_widgets": [ + "4bab5df43b3c46caadf48e264344ab42", + "9b426c68631f4bb288e2ca79aad9f9d9", + "6902104f7ec143519fb1a6ab9363d4a0", + "c133fb34fe2a4aba8a6b233671af8b04", + "e3f72d443a74414ca62c2b848d34b125", + "5462b581976e47048642aa6bc12435bd", + "ad84da685cf44abb90d17d9d2e023b48", + "a246f9eea2d7440cb979e728741d2e32" + ] + }, + "outputId": "a7a10851-b71e-4553-9afc-04066120410d" + }, + "source": [ + "nlp_sentence_classif = pipeline('sentiment-analysis')\n", + "nlp_sentence_classif('Such a nice weather outside !')" + ], + "execution_count": 3, + "outputs": [ + { + "output_type": "display_data", + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4bab5df43b3c46caadf48e264344ab42", + "version_minor": 0, + "version_major": 2 + }, + "text/plain": [ + "HBox(children=(IntProgress(value=0, description='Downloading', max=230, style=ProgressStyle(description_width=…" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "stream", + "text": [ + "\n" + ], + "name": "stdout" + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "[{'label': 'POSITIVE', 'score': 0.9997656}]" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 3 + } + ] + }, { - "data": { - "text/plain": "HBox(children=(FloatProgress(value=0.0, description='Downloading', max=230.0, style=ProgressStyle(description_…", - "application/vnd.jupyter.widget-view+json": { - "version_major": 2, - "version_minor": 0, - "model_id": "82aca58f1ea24b4cb37f16402e8a5923" - } - }, - "metadata": {}, - "output_type": "display_data" + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + }, + "id": "RY8aUJTvrl_k", + "colab_type": "text" + }, + "source": [ + "## 2. Token Classification - Named Entity Recognition" + ] }, { - "name": "stdout", - "text": [ - "\n" - ], - "output_type": "stream" + "cell_type": "code", + "metadata": { + "pycharm": { + "is_executing": false, + "name": "#%% code\n" + }, + "id": "B3BDRX_Krl_n", + "colab_type": "code", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 185, + "referenced_widgets": [ + "451464c936444ba5a652b46c1b4f9931", + "279291efd2c14a9eb2c3b98efbf152ad", + "b6e1a2e57f4948a39283f1370352612c", + "9d4941ebdfa64978b47232f6e5908d97", + "1006cc0fab1e4139bb7b135486261c92", + "691c0bae60364890ab74934261207d4d", + "405afa5bb8b840d8bc0850e02f593ce4", + "78c718e3d5fa4cb892217260bea6d540" + ] + }, + "outputId": "a6b90b11-a272-4ecb-960d-4c682551b399" + }, + "source": [ + "nlp_token_class = pipeline('ner')\n", + "nlp_token_class('Hugging Face is a French company based in New-York.')" + ], + "execution_count": 4, + "outputs": [ + { + "output_type": "display_data", + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "451464c936444ba5a652b46c1b4f9931", + "version_minor": 0, + "version_major": 2 + }, + "text/plain": [ + "HBox(children=(IntProgress(value=0, description='Downloading', max=230, style=ProgressStyle(description_width=…" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "stream", + "text": [ + "\n" + ], + "name": "stdout" + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "[{'entity': 'I-ORG', 'score': 0.9970937967300415, 'word': 'Hu'},\n", + " {'entity': 'I-ORG', 'score': 0.9345749020576477, 'word': '##gging'},\n", + " {'entity': 'I-ORG', 'score': 0.9787060022354126, 'word': 'Face'},\n", + " {'entity': 'I-MISC', 'score': 0.9981995820999146, 'word': 'French'},\n", + " {'entity': 'I-LOC', 'score': 0.9983047246932983, 'word': 'New'},\n", + " {'entity': 'I-LOC', 'score': 0.8913459181785583, 'word': '-'},\n", + " {'entity': 'I-LOC', 'score': 0.9979523420333862, 'word': 'York'}]" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 4 + } + ] }, { - "name": "stderr", - "text": [ - "convert squad examples to features: 100%|██████████| 1/1 [00:00<00:00, 225.51it/s]\n", - "add example index and unique id: 100%|██████████| 1/1 [00:00<00:00, 2158.67it/s]\n" - ], - "output_type": "stream" + "cell_type": "markdown", + "metadata": { + "id": "qIvUFEVarl_s", + "colab_type": "text" + }, + "source": [ + "## 3. Question Answering" + ] }, { - "data": { - "text/plain": "{'score': 0.9632966867654424, 'start': 42, 'end': 50, 'answer': 'New-York.'}" - }, - "metadata": {}, - "output_type": "execute_result", - "execution_count": 10 - } - ], - "source": [ - "nlp_qa = pipeline('question-answering')\n", - "nlp_qa(context='Hugging Face is a French company based in New-York.', question='Where is based Hugging Face ?')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 4. Text Generation - Mask Filling" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "pycharm": { - "is_executing": false, - "name": "#%% code\n" - } - }, - "outputs": [ + "cell_type": "code", + "metadata": { + "pycharm": { + "is_executing": false, + "name": "#%% code\n" + }, + "id": "ND_8LzQKrl_u", + "colab_type": "code", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 117, + "referenced_widgets": [ + "7d66a4534c164d2f9493fc0467abebbd", + "7a15588f85b14f2b93e32b4c0442fa1b", + "213567d815894ca08041f6d682ced3c9", + "ee6c95e700e64d0a9ebec2c1545dd083", + "3e556abf5c4a4ee69d52366fd59471b2", + "876b2eba73fa46a6a941d2e3a8a975ad", + "cd64e3f20b23483daa79712bde6622ea", + "67cbaa1f55d24e62ad6b022af36bca56" + ] + }, + "outputId": "c59ae695-c465-4de6-fa6e-181d8f1a3992" + }, + "source": [ + "nlp_qa = pipeline('question-answering')\n", + "nlp_qa(context='Hugging Face is a French company based in New-York.', question='Where is based Hugging Face ?')" + ], + "execution_count": 5, + "outputs": [ + { + "output_type": "display_data", + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7d66a4534c164d2f9493fc0467abebbd", + "version_minor": 0, + "version_major": 2 + }, + "text/plain": [ + "HBox(children=(IntProgress(value=0, description='Downloading', max=230, style=ProgressStyle(description_width=…" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "stream", + "text": [ + "\n" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "convert squad examples to features: 100%|██████████| 1/1 [00:00<00:00, 142.60it/s]\n", + "add example index and unique id: 100%|██████████| 1/1 [00:00<00:00, 4341.93it/s]\n" + ], + "name": "stderr" + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "{'answer': 'New-York.', 'end': 50, 'score': 0.9632969241603995, 'start': 42}" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 5 + } + ] + }, { - "data": { - "text/plain": "HBox(children=(FloatProgress(value=0.0, description='Downloading', max=230.0, style=ProgressStyle(description_…", - "application/vnd.jupyter.widget-view+json": { - "version_major": 2, - "version_minor": 0, - "model_id": "49df2227b4fa4eb28dcdcfc3d9261d0f" - } - }, - "metadata": {}, - "output_type": "display_data" + "cell_type": "markdown", + "metadata": { + "id": "9W_CnP5Zrl_2", + "colab_type": "text" + }, + "source": [ + "## 4. Text Generation - Mask Filling" + ] }, { - "name": "stdout", - "text": [ - "\n" - ], - "output_type": "stream" + "cell_type": "code", + "metadata": { + "pycharm": { + "is_executing": false, + "name": "#%% code\n" + }, + "id": "zpJQ2HXNrl_4", + "colab_type": "code", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 321, + "referenced_widgets": [ + "58669943d3064f309436157270544c08", + "3eff293c2b554d85aefaea863e29b678", + "d0b9925f3dde46008bf186cf5ef7722d", + "427e07ce24a442af84ddc71f9463fdff", + "1eb2fa080ec44f8c8d5f6f52900277ab", + "23377596349e40a89ea57c8558660073", + "a35703cc8ff44e93a8c0eb413caddc40", + "9df7014c99b343f3b178fa020ff56010" + ] + }, + "outputId": "3fb62e7a-25a6-4b06-ced8-51eb8aa6bf33" + }, + "source": [ + "nlp_fill = pipeline('fill-mask')\n", + "nlp_fill('Hugging Face is a French company based in ' + nlp_fill.tokenizer.mask_token)" + ], + "execution_count": 6, + "outputs": [ + { + "output_type": "display_data", + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "58669943d3064f309436157270544c08", + "version_minor": 0, + "version_major": 2 + }, + "text/plain": [ + "HBox(children=(IntProgress(value=0, description='Downloading', max=230, style=ProgressStyle(description_width=…" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "stream", + "text": [ + "\n" + ], + "name": "stdout" + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "[{'score': 0.23106741905212402,\n", + " 'sequence': ' Hugging Face is a French company based in Paris',\n", + " 'token': 2201},\n", + " {'score': 0.08198167383670807,\n", + " 'sequence': ' Hugging Face is a French company based in Lyon',\n", + " 'token': 12790},\n", + " {'score': 0.04769487306475639,\n", + " 'sequence': ' Hugging Face is a French company based in Geneva',\n", + " 'token': 11559},\n", + " {'score': 0.04762246832251549,\n", + " 'sequence': ' Hugging Face is a French company based in Brussels',\n", + " 'token': 6497},\n", + " {'score': 0.041305847465991974,\n", + " 'sequence': ' Hugging Face is a French company based in France',\n", + " 'token': 1470}]" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 6 + } + ] }, { - "data": { - "text/plain": "[{'sequence': ' Hugging Face is a French company based in Paris',\n 'score': 0.23106691241264343,\n 'token': 2201},\n {'sequence': ' Hugging Face is a French company based in Lyon',\n 'score': 0.0819825753569603,\n 'token': 12790},\n {'sequence': ' Hugging Face is a French company based in Geneva',\n 'score': 0.04769463092088699,\n 'token': 11559},\n {'sequence': ' Hugging Face is a French company based in Brussels',\n 'score': 0.047622501850128174,\n 'token': 6497},\n {'sequence': ' Hugging Face is a French company based in France',\n 'score': 0.04130595177412033,\n 'token': 1470}]" - }, - "metadata": {}, - "output_type": "execute_result", - "execution_count": 11 - } - ], - "source": [ - "nlp_fill = pipeline('fill-mask')\n", - "nlp_fill('Hugging Face is a French company based in ' + nlp_fill.tokenizer.mask_token)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 5. Projection - Features Extraction " - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "pycharm": { - "is_executing": false, - "name": "#%% code\n" - } - }, - "outputs": [ + "cell_type": "markdown", + "metadata": { + "id": "Fbs9t1KvrzDy", + "colab_type": "text" + }, + "source": [ + "## 5. Summarization\n", + "\n", + "Summarization is currently supported by `Bart` and `T5`." + ] + }, { - "data": { - "text/plain": "HBox(children=(FloatProgress(value=0.0, description='Downloading', max=230.0, style=ProgressStyle(description_…", - "application/vnd.jupyter.widget-view+json": { - "version_major": 2, - "version_minor": 0, - "model_id": "2af4cfb19e3243dda014d0f56b48f4b2" - } - }, - "metadata": {}, - "output_type": "display_data" + "cell_type": "code", + "metadata": { + "id": "8BaOgzi1u1Yc", + "colab_type": "code", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 88 + }, + "outputId": "2168e437-cfba-4247-a38c-07f02f555c6e" + }, + "source": [ + "TEXT_TO_SUMMARIZE = \"\"\" \n", + "New York (CNN)When Liana Barrientos was 23 years old, she got married in Westchester County, New York. \n", + "A year later, she got married again in Westchester County, but to a different man and without divorcing her first husband. \n", + "Only 18 days after that marriage, she got hitched yet again. Then, Barrientos declared \"I do\" five more times, sometimes only within two weeks of each other. \n", + "In 2010, she married once more, this time in the Bronx. In an application for a marriage license, she stated it was her \"first and only\" marriage. \n", + "Barrientos, now 39, is facing two criminal counts of \"offering a false instrument for filing in the first degree,\" referring to her false statements on the \n", + "2010 marriage license application, according to court documents. \n", + "Prosecutors said the marriages were part of an immigration scam. \n", + "On Friday, she pleaded not guilty at State Supreme Court in the Bronx, according to her attorney, Christopher Wright, who declined to comment further. \n", + "After leaving court, Barrientos was arrested and charged with theft of service and criminal trespass for allegedly sneaking into the New York subway through an emergency exit, said Detective \n", + "Annette Markowski, a police spokeswoman. In total, Barrientos has been married 10 times, with nine of her marriages occurring between 1999 and 2002. \n", + "All occurred either in Westchester County, Long Island, New Jersey or the Bronx. She is believed to still be married to four men, and at one time, she was married to eight men at once, prosecutors say. \n", + "Prosecutors said the immigration scam involved some of her husbands, who filed for permanent residence status shortly after the marriages. \n", + "Any divorces happened only after such filings were approved. It was unclear whether any of the men will be prosecuted. \n", + "The case was referred to the Bronx District Attorney\\'s Office by Immigration and Customs Enforcement and the Department of Homeland Security\\'s \n", + "Investigation Division. Seven of the men are from so-called \"red-flagged\" countries, including Egypt, Turkey, Georgia, Pakistan and Mali. \n", + "Her eighth husband, Rashid Rajput, was deported in 2006 to his native Pakistan after an investigation by the Joint Terrorism Task Force. \n", + "If convicted, Barrientos faces up to four years in prison. Her next court appearance is scheduled for May 18.\n", + "\"\"\"\n", + "\n", + "summarizer = pipeline('summarization')\n", + "summarizer(TEXT_TO_SUMMARIZE)" + ], + "execution_count": 7, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Couldn't reach server at 'https://s3.amazonaws.com/models.huggingface.co/bert/facebook/bart-large-cnn/modelcard.json' to download model card file.\n", + "Creating an empty model card.\n" + ], + "name": "stderr" + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "[{'summary_text': 'Liana Barrientos has been married 10 times, sometimes within two weeks of each other. Prosecutors say the marriages were part of an immigration scam. She is believed to still be married to four men, and at one time, she was married to eight men at once. Her eighth husband was deported in 2006 to his native Pakistan.'}]" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 7 + } + ] }, { - "name": "stdout", - "text": [ - "\n" - ], - "output_type": "stream" + "cell_type": "markdown", + "metadata": { + "id": "u5JA6IJsr-G0", + "colab_type": "text" + }, + "source": [ + "## 6. Translation\n", + "\n", + "Translation is currently supported by `T5` for the language mappings English-to-French (`translation_en_to_fr`), English-to-German (`translation_en_to_de`) and English-to-Romanian (`translation_en_to_ro`)." + ] }, { - "data": { - "text/plain": "(1, 12, 768)" - }, - "metadata": {}, - "output_type": "execute_result", - "execution_count": 12 - } - ], - "source": [ - "import numpy as np\n", - "nlp_features = pipeline('feature-extraction')\n", - "output = nlp_features('Hugging Face is a French company based in Paris')\n", - "np.array(output).shape # (Samples, Tokens, Vector Size)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "Alright ! Now you have a nice picture of what is possible through transformers' pipelines, and there is more\n", - "to come in future releases. \n", - "\n", - "In the meantime, you can try the different pipelines with your own inputs" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "pycharm": { - "is_executing": false, - "name": "#%% code\n" - } - }, - "outputs": [ + "cell_type": "code", + "metadata": { + "id": "8FwayP4nwV3Z", + "colab_type": "code", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 83, + "referenced_widgets": [ + "57e8c36594d043c581c766b434037771", + "82760185d5c14a808cbf6639b589f249", + "f2a1b430594b4736879cdff4ec532098", + "c81338551e60474fab9e9950fe5df294", + "98563b405bd043a9a301a43909e43157", + "8c0e1b7fb6ac4ee7bbbaf6020b40cc77", + "ad78042ee71a41fd989e4b4ce9d2e3c1", + "40c8d2617f3d4c84b923b140456fa5da" + ] + }, + "outputId": "66956816-c924-4718-fe58-cabef7d51974" + }, + "source": [ + "# English to French\n", + "translator = pipeline('translation_en_to_fr')\n", + "translator(\"HuggingFace is a French company that is based in New York City. HuggingFace's mission is to solve NLP one commit at a time\")" + ], + "execution_count": 8, + "outputs": [ + { + "output_type": "display_data", + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "57e8c36594d043c581c766b434037771", + "version_minor": 0, + "version_major": 2 + }, + "text/plain": [ + "HBox(children=(IntProgress(value=0, description='Downloading', max=230, style=ProgressStyle(description_width=…" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "stream", + "text": [ + "\n" + ], + "name": "stdout" + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "[{'translation_text': 'HuggingFace est une entreprise française basée à New York et dont la mission est de résoudre les problèmes de NLP, un engagement à la fois.'}]" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 8 + } + ] + }, { - "data": { - "text/plain": "Dropdown(description='Task:', index=1, options=('sentiment-analysis', 'ner', 'fill_mask'), value='ner')", - "application/vnd.jupyter.widget-view+json": { - "version_major": 2, - "version_minor": 0, - "model_id": "10bac065d46f4e4d9a8498dcc8104ecd" - } - }, - "metadata": {}, - "output_type": "display_data" + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "ra0-WfznwoIW", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 83, + "referenced_widgets": [ + "311a65b811964ebfa2c064eb348b3ce9", + "5a2032c44d0e4f8cbaf512e6c29214cd", + "54d1ff55e0094a4fa2b62ecdfb428328", + "2e45f2d7d65246ecb8d6e666d026ac13", + "e05c0ec3b49e4d4990a943d428532fb0", + "39721262fc1e4456966d92fabe0f54ea", + "4486f8a2efc34b9aab3864eb5ad2ba48", + "d6228324f3444aa6bd1323d65ae4ff75" + ] + }, + "outputId": "278a3d5f-cc42-40bc-a9db-c92ec5a3a2f0" + }, + "source": [ + "# English to German\n", + "translator = pipeline('translation_en_to_de')\n", + "translator(\"The history of natural language processing (NLP) generally started in the 1950s, although work can be found from earlier periods.\")" + ], + "execution_count": 9, + "outputs": [ + { + "output_type": "display_data", + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "311a65b811964ebfa2c064eb348b3ce9", + "version_minor": 0, + "version_major": 2 + }, + "text/plain": [ + "HBox(children=(IntProgress(value=0, description='Downloading', max=230, style=ProgressStyle(description_width=…" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "stream", + "text": [ + "\n" + ], + "name": "stdout" + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "[{'translation_text': 'Die Geschichte der natürlichen Sprachenverarbeitung (NLP) begann im Allgemeinen in den 1950er Jahren, obwohl die Arbeit aus früheren Zeiten zu finden ist.'}]" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 9 + } + ] }, { - "data": { - "text/plain": "Text(value='', description='Your input:', placeholder='Enter something')", - "application/vnd.jupyter.widget-view+json": { - "version_major": 2, - "version_minor": 0, - "model_id": "2c5f1411f7a94714bc00f01b0e3b27b2" - } - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "task = widgets.Dropdown(\n", - " options=['sentiment-analysis', 'ner', 'fill_mask'],\n", - " value='ner',\n", - " description='Task:',\n", - " disabled=False\n", - ")\n", - "\n", - "input = widgets.Text(\n", - " value='',\n", - " placeholder='Enter something',\n", - " description='Your input:',\n", - " disabled=False\n", - ")\n", - "\n", - "def forward(_):\n", - " if len(input.value) > 0: \n", - " if task.value == 'ner':\n", - " output = nlp_token_class(input.value)\n", - " elif task.value == 'sentiment-analysis':\n", - " output = nlp_sentence_classif(input.value)\n", - " else:\n", - " if input.value.find('') == -1:\n", - " output = nlp_fill(input.value + ' ')\n", - " else:\n", - " output = nlp_fill(input.value) \n", - " print(output)\n", - "\n", - "input.on_submit(forward)\n", - "display(task, input)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": { - "pycharm": { - "is_executing": false, - "name": "#%% Question Answering\n" - } - }, - "outputs": [ + "cell_type": "markdown", + "metadata": { + "id": "Utmldmetrl_9", + "colab_type": "text" + }, + "source": [ + "## 7. Projection - Features Extraction " + ] + }, { - "data": { - "text/plain": "Textarea(value='Einstein is famous for the general theory of relativity', description='Context:', placeholder=…", - "application/vnd.jupyter.widget-view+json": { - "version_major": 2, - "version_minor": 0, - "model_id": "019fde2343634e94b6f32d04f6350ec1" - } - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "context = widgets.Textarea(\n", - " value='Einstein is famous for the general theory of relativity',\n", - " placeholder='Enter something',\n", - " description='Context:',\n", - " disabled=False\n", - ")\n", - "\n", - "query = widgets.Text(\n", - " value='Why is Einstein famous for ?',\n", - " placeholder='Enter something',\n", - " description='Question:',\n", - " disabled=False\n", - ")\n", - "\n", - "def forward(_):\n", - " if len(context.value) > 0 and len(query.value) > 0: \n", - " output = nlp_qa(question=query.value, context=context.value) \n", - " print(output)\n", - "\n", - "query.on_submit(forward)\n", - "display(context, query)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.6" - }, - "pycharm": { - "stem_cell": { - "cell_type": "raw", - "source": [], - "metadata": { - "collapsed": false + "cell_type": "code", + "metadata": { + "pycharm": { + "is_executing": false, + "name": "#%% code\n" + }, + "id": "O4SjR1QQrl__", + "colab_type": "code", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 83, + "referenced_widgets": [ + "fd44cf6ab17e4b768b2e1d5cb8ce5af9", + "b8c0ea31578d4eaaa69251d0004fd8c6", + "2015cd9c1da9467290ecd9019af231eb", + "17bacdaee55b43e8977c4dfe4f7245bb", + "879ef9e1a0e94f3d96ed56fb4bae64b8", + "7ab70324d42647acac5020b387955caf", + "31d97ecf78fa412c99e6659196d82828", + "c6be5d48ec3c4c799d1445607e5f1ac6" + ] + }, + "outputId": "2ce966d5-7a89-4488-d48f-626d1c2a8222" + }, + "source": [ + "import numpy as np\n", + "nlp_features = pipeline('feature-extraction')\n", + "output = nlp_features('Hugging Face is a French company based in Paris')\n", + "np.array(output).shape # (Samples, Tokens, Vector Size)\n" + ], + "execution_count": 10, + "outputs": [ + { + "output_type": "display_data", + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "fd44cf6ab17e4b768b2e1d5cb8ce5af9", + "version_minor": 0, + "version_major": 2 + }, + "text/plain": [ + "HBox(children=(IntProgress(value=0, description='Downloading', max=230, style=ProgressStyle(description_width=…" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "stream", + "text": [ + "\n" + ], + "name": "stdout" + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "(1, 12, 768)" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 10 + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + }, + "id": "02j8km8YrmAE", + "colab_type": "text" + }, + "source": [ + "Alright ! Now you have a nice picture of what is possible through transformers' pipelines, and there is more\n", + "to come in future releases. \n", + "\n", + "In the meantime, you can try the different pipelines with your own inputs" + ] + }, + { + "cell_type": "code", + "metadata": { + "pycharm": { + "is_executing": false, + "name": "#%% code\n" + }, + "id": "yFlBPQHtrmAH", + "colab_type": "code", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 116, + "referenced_widgets": [ + "0bd407b4975f49c3827aede14c59501c", + "3f5406df699e44f5b60678c1c13500f5", + "17768469581445b68246ed308ce69326", + "74cbcbae5cac4f12abf080a38390f05c", + "62b10ca525cc4ac68f3a006434eb7416", + "211109537fbe4e60b89a238c89db1346" + ] + }, + "outputId": "03cc3207-a7e8-49fd-904a-63a7a1d0eb7a" + }, + "source": [ + "task = widgets.Dropdown(\n", + " options=['sentiment-analysis', 'ner', 'fill_mask'],\n", + " value='ner',\n", + " description='Task:',\n", + " disabled=False\n", + ")\n", + "\n", + "input = widgets.Text(\n", + " value='',\n", + " placeholder='Enter something',\n", + " description='Your input:',\n", + " disabled=False\n", + ")\n", + "\n", + "def forward(_):\n", + " if len(input.value) > 0: \n", + " if task.value == 'ner':\n", + " output = nlp_token_class(input.value)\n", + " elif task.value == 'sentiment-analysis':\n", + " output = nlp_sentence_classif(input.value)\n", + " else:\n", + " if input.value.find('') == -1:\n", + " output = nlp_fill(input.value + ' ')\n", + " else:\n", + " output = nlp_fill(input.value) \n", + " print(output)\n", + "\n", + "input.on_submit(forward)\n", + "display(task, input)" + ], + "execution_count": 11, + "outputs": [ + { + "output_type": "display_data", + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "0bd407b4975f49c3827aede14c59501c", + "version_minor": 0, + "version_major": 2 + }, + "text/plain": [ + "Dropdown(description='Task:', index=1, options=('sentiment-analysis', 'ner', 'fill_mask'), value='ner')" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "display_data", + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "74cbcbae5cac4f12abf080a38390f05c", + "version_minor": 0, + "version_major": 2 + }, + "text/plain": [ + "Text(value='', description='Your input:', placeholder='Enter something')" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "stream", + "text": [ + "[{'word': 'Peter', 'score': 0.9935821294784546, 'entity': 'I-PER'}, {'word': 'Pan', 'score': 0.9901397228240967, 'entity': 'I-PER'}, {'word': 'Marseille', 'score': 0.9984904527664185, 'entity': 'I-LOC'}, {'word': 'France', 'score': 0.9998687505722046, 'entity': 'I-LOC'}]\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "pycharm": { + "is_executing": false, + "name": "#%% Question Answering\n" + }, + "id": "GCoKbBTYrmAN", + "colab_type": "code", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 143, + "referenced_widgets": [ + "d79946ac16ea4855a0bbe2ca2a4d4bf5", + "ab5774ac19f84ab18ddf09a63433df00", + "a02164204f0f43668bc36a907e720af7", + "3b12aec414b14221ad2a11dfd975faa0", + "d305ba1662e3466c93ab5cca7ebf8f33", + "879f7a3747ad455d810c7a29918648ee" + ] + }, + "outputId": "57c3a647-160a-4b3a-e852-e7a1daf1294a" + }, + "source": [ + "context = widgets.Textarea(\n", + " value='Einstein is famous for the general theory of relativity',\n", + " placeholder='Enter something',\n", + " description='Context:',\n", + " disabled=False\n", + ")\n", + "\n", + "query = widgets.Text(\n", + " value='Why is Einstein famous for ?',\n", + " placeholder='Enter something',\n", + " description='Question:',\n", + " disabled=False\n", + ")\n", + "\n", + "def forward(_):\n", + " if len(context.value) > 0 and len(query.value) > 0: \n", + " output = nlp_qa(question=query.value, context=context.value) \n", + " print(output)\n", + "\n", + "query.on_submit(forward)\n", + "display(context, query)" + ], + "execution_count": 12, + "outputs": [ + { + "output_type": "display_data", + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d79946ac16ea4855a0bbe2ca2a4d4bf5", + "version_minor": 0, + "version_major": 2 + }, + "text/plain": [ + "Textarea(value='Einstein is famous for the general theory of relativity', description='Context:', placeholder=…" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "display_data", + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "3b12aec414b14221ad2a11dfd975faa0", + "version_minor": 0, + "version_major": 2 + }, + "text/plain": [ + "Text(value='Why is Einstein famous for ?', description='Question:', placeholder='Enter something')" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "stream", + "text": [ + "convert squad examples to features: 100%|██████████| 1/1 [00:00<00:00, 363.99it/s]\n", + "add example index and unique id: 100%|██████████| 1/1 [00:00<00:00, 5178.15it/s]\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "{'score': 0.40340594113729367, 'start': 27, 'end': 54, 'answer': 'general theory of relativity'}\n" + ], + "name": "stdout" + } + ] } - } - } - }, - "nbformat": 4, - "nbformat_minor": 1 + ] } \ No newline at end of file From 17dceae7a1de5577cd0c07a97dcd5821a08af07c Mon Sep 17 00:00:00 2001 From: Patrick von Platen Date: Fri, 27 Mar 2020 18:01:28 +0100 Subject: [PATCH 07/10] Fix circle ci flaky fail of wmt example (#3485) * force bleu * fix wrong file name * rename file * different filenames for each example test * test files should clean up after themselves * test files should clean up after themselves * do not force bleu * correct typo * fix isort --- .../summarization/bart/test_bart_examples.py | 10 +++++--- examples/summarization/t5/test_t5_examples.py | 14 ++++++++--- examples/translation/t5/test_t5_examples.py | 25 +++++++++++++++---- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/examples/summarization/bart/test_bart_examples.py b/examples/summarization/bart/test_bart_examples.py index faa0725b55cc..18064cc5d23c 100644 --- a/examples/summarization/bart/test_bart_examples.py +++ b/examples/summarization/bart/test_bart_examples.py @@ -1,4 +1,5 @@ import logging +import os import sys import tempfile import unittest @@ -8,6 +9,8 @@ from .evaluate_cnn import _run_generate +output_file_name = "output_bart_sum.txt" + articles = [" New York (CNN)When Liana Barrientos was 23 years old, she got married in Westchester County."] logging.basicConfig(level=logging.DEBUG) @@ -19,10 +22,11 @@ class TestBartExamples(unittest.TestCase): def test_bart_cnn_cli(self): stream_handler = logging.StreamHandler(sys.stdout) logger.addHandler(stream_handler) - tmp = Path(tempfile.gettempdir()) / "utest_generations.hypo" + tmp = Path(tempfile.gettempdir()) / "utest_generations_bart_sum.hypo" with tmp.open("w") as f: f.write("\n".join(articles)) - testargs = ["evaluate_cnn.py", str(tmp), "output.txt"] + testargs = ["evaluate_cnn.py", str(tmp), output_file_name] with patch.object(sys, "argv", testargs): _run_generate() - self.assertTrue(Path("output.txt").exists()) + self.assertTrue(Path(output_file_name).exists()) + os.remove(Path(output_file_name)) diff --git a/examples/summarization/t5/test_t5_examples.py b/examples/summarization/t5/test_t5_examples.py index 58b5db681eb3..57f3e342d77b 100644 --- a/examples/summarization/t5/test_t5_examples.py +++ b/examples/summarization/t5/test_t5_examples.py @@ -1,4 +1,5 @@ import logging +import os import sys import tempfile import unittest @@ -8,6 +9,9 @@ from .evaluate_cnn import run_generate +output_file_name = "output_t5_sum.txt" +score_file_name = "score_t5_sum.txt" + articles = ["New York (CNN)When Liana Barrientos was 23 years old, she got married in Westchester County."] logging.basicConfig(level=logging.DEBUG) @@ -19,11 +23,13 @@ class TestT5Examples(unittest.TestCase): def test_t5_cli(self): stream_handler = logging.StreamHandler(sys.stdout) logger.addHandler(stream_handler) - tmp = Path(tempfile.gettempdir()) / "utest_generations.hypo" + tmp = Path(tempfile.gettempdir()) / "utest_generations_t5_sum.hypo" with tmp.open("w") as f: f.write("\n".join(articles)) - testargs = ["evaluate_cnn.py", "t5-small", str(tmp), "output.txt", str(tmp), "score.txt"] + testargs = ["evaluate_cnn.py", "t5-small", str(tmp), output_file_name, str(tmp), score_file_name] with patch.object(sys, "argv", testargs): run_generate() - self.assertTrue(Path("output.txt").exists()) - self.assertTrue(Path("score.txt").exists()) + self.assertTrue(Path(output_file_name).exists()) + self.assertTrue(Path(score_file_name).exists()) + os.remove(Path(output_file_name)) + os.remove(Path(score_file_name)) diff --git a/examples/translation/t5/test_t5_examples.py b/examples/translation/t5/test_t5_examples.py index c7d1fe68828e..eea17c227a14 100644 --- a/examples/translation/t5/test_t5_examples.py +++ b/examples/translation/t5/test_t5_examples.py @@ -1,4 +1,5 @@ import logging +import os import sys import tempfile import unittest @@ -8,7 +9,11 @@ from .evaluate_wmt import run_generate -text = [" New York (CNN)When Liana Barrientos was 23 years old, she got married in Westchester County."] +text = ["When Liana Barrientos was 23 years old, she got married in Westchester County."] +translation = ["Als Liana Barrientos 23 Jahre alt war, heiratete sie in Westchester County."] + +output_file_name = "output_t5_trans.txt" +score_file_name = "score_t5_trans.txt" logging.basicConfig(level=logging.DEBUG) @@ -19,10 +24,20 @@ class TestT5Examples(unittest.TestCase): def test_t5_cli(self): stream_handler = logging.StreamHandler(sys.stdout) logger.addHandler(stream_handler) - tmp = Path(tempfile.gettempdir()) / "utest_generations.hypo" - with tmp.open("w") as f: + + tmp_source = Path(tempfile.gettempdir()) / "utest_generations_t5_trans.hypo" + with tmp_source.open("w") as f: f.write("\n".join(text)) - testargs = ["evaluate_cnn.py", str(tmp), "output.txt", str(tmp), "score.txt"] + + tmp_target = Path(tempfile.gettempdir()) / "utest_generations_t5_trans.target" + with tmp_target.open("w") as f: + f.write("\n".join(translation)) + + testargs = ["evaluate_wmt.py", str(tmp_source), output_file_name, str(tmp_target), score_file_name] + with patch.object(sys, "argv", testargs): run_generate() - self.assertTrue(Path("output.txt").exists()) + self.assertTrue(Path(output_file_name).exists()) + self.assertTrue(Path(score_file_name).exists()) + os.remove(Path(output_file_name)) + os.remove(Path(score_file_name)) From 601ac5b1dc1438f00d09696588f2deb0f045ae3b Mon Sep 17 00:00:00 2001 From: Stefan Schweter Date: Fri, 27 Mar 2020 22:00:03 +0100 Subject: [PATCH 08/10] [model_cards]: use MIT license for all dbmdz models --- model_cards/dbmdz/bert-base-german-cased/README.md | 1 + model_cards/dbmdz/bert-base-german-europeana-cased/README.md | 1 + model_cards/dbmdz/bert-base-german-europeana-uncased/README.md | 1 + model_cards/dbmdz/bert-base-german-uncased/README.md | 1 + model_cards/dbmdz/bert-base-italian-cased/README.md | 1 + model_cards/dbmdz/bert-base-italian-uncased/README.md | 1 + model_cards/dbmdz/bert-base-italian-xxl-cased/README.md | 1 + model_cards/dbmdz/bert-base-italian-xxl-uncased/README.md | 1 + model_cards/dbmdz/bert-base-turkish-128k-cased/README.md | 1 + model_cards/dbmdz/bert-base-turkish-128k-uncased/README.md | 1 + model_cards/dbmdz/bert-base-turkish-cased/README.md | 1 + model_cards/dbmdz/bert-base-turkish-uncased/README.md | 1 + model_cards/dbmdz/distilbert-base-turkish-cased/README.md | 1 + 13 files changed, 13 insertions(+) diff --git a/model_cards/dbmdz/bert-base-german-cased/README.md b/model_cards/dbmdz/bert-base-german-cased/README.md index 6249f1749686..08b52feca01a 100644 --- a/model_cards/dbmdz/bert-base-german-cased/README.md +++ b/model_cards/dbmdz/bert-base-german-cased/README.md @@ -1,5 +1,6 @@ --- language: german +license: mit --- # 🤗 + 📚 dbmdz German BERT models diff --git a/model_cards/dbmdz/bert-base-german-europeana-cased/README.md b/model_cards/dbmdz/bert-base-german-europeana-cased/README.md index c90f62a2b91b..4cc7e9c5f480 100644 --- a/model_cards/dbmdz/bert-base-german-europeana-cased/README.md +++ b/model_cards/dbmdz/bert-base-german-europeana-cased/README.md @@ -1,5 +1,6 @@ --- language: german +license: mit tags: - "historic german" --- diff --git a/model_cards/dbmdz/bert-base-german-europeana-uncased/README.md b/model_cards/dbmdz/bert-base-german-europeana-uncased/README.md index e1aafc72e074..37b587c7bd8e 100644 --- a/model_cards/dbmdz/bert-base-german-europeana-uncased/README.md +++ b/model_cards/dbmdz/bert-base-german-europeana-uncased/README.md @@ -1,5 +1,6 @@ --- language: german +license: mit tags: - "historic german" --- diff --git a/model_cards/dbmdz/bert-base-german-uncased/README.md b/model_cards/dbmdz/bert-base-german-uncased/README.md index 6249f1749686..08b52feca01a 100644 --- a/model_cards/dbmdz/bert-base-german-uncased/README.md +++ b/model_cards/dbmdz/bert-base-german-uncased/README.md @@ -1,5 +1,6 @@ --- language: german +license: mit --- # 🤗 + 📚 dbmdz German BERT models diff --git a/model_cards/dbmdz/bert-base-italian-cased/README.md b/model_cards/dbmdz/bert-base-italian-cased/README.md index 6031c6c782d6..08792150bd38 100644 --- a/model_cards/dbmdz/bert-base-italian-cased/README.md +++ b/model_cards/dbmdz/bert-base-italian-cased/README.md @@ -1,5 +1,6 @@ --- language: italian +license: mit --- # 🤗 + 📚 dbmdz BERT models diff --git a/model_cards/dbmdz/bert-base-italian-uncased/README.md b/model_cards/dbmdz/bert-base-italian-uncased/README.md index 6031c6c782d6..08792150bd38 100644 --- a/model_cards/dbmdz/bert-base-italian-uncased/README.md +++ b/model_cards/dbmdz/bert-base-italian-uncased/README.md @@ -1,5 +1,6 @@ --- language: italian +license: mit --- # 🤗 + 📚 dbmdz BERT models diff --git a/model_cards/dbmdz/bert-base-italian-xxl-cased/README.md b/model_cards/dbmdz/bert-base-italian-xxl-cased/README.md index 6031c6c782d6..08792150bd38 100644 --- a/model_cards/dbmdz/bert-base-italian-xxl-cased/README.md +++ b/model_cards/dbmdz/bert-base-italian-xxl-cased/README.md @@ -1,5 +1,6 @@ --- language: italian +license: mit --- # 🤗 + 📚 dbmdz BERT models diff --git a/model_cards/dbmdz/bert-base-italian-xxl-uncased/README.md b/model_cards/dbmdz/bert-base-italian-xxl-uncased/README.md index 6031c6c782d6..08792150bd38 100644 --- a/model_cards/dbmdz/bert-base-italian-xxl-uncased/README.md +++ b/model_cards/dbmdz/bert-base-italian-xxl-uncased/README.md @@ -1,5 +1,6 @@ --- language: italian +license: mit --- # 🤗 + 📚 dbmdz BERT models diff --git a/model_cards/dbmdz/bert-base-turkish-128k-cased/README.md b/model_cards/dbmdz/bert-base-turkish-128k-cased/README.md index 37dbe758fb24..7cbb189dce58 100644 --- a/model_cards/dbmdz/bert-base-turkish-128k-cased/README.md +++ b/model_cards/dbmdz/bert-base-turkish-128k-cased/README.md @@ -1,5 +1,6 @@ --- language: turkish +license: mit --- # 🤗 + 📚 dbmdz Turkish BERT model diff --git a/model_cards/dbmdz/bert-base-turkish-128k-uncased/README.md b/model_cards/dbmdz/bert-base-turkish-128k-uncased/README.md index 445779441a33..82bb5168269b 100644 --- a/model_cards/dbmdz/bert-base-turkish-128k-uncased/README.md +++ b/model_cards/dbmdz/bert-base-turkish-128k-uncased/README.md @@ -1,5 +1,6 @@ --- language: turkish +license: mit --- # 🤗 + 📚 dbmdz Turkish BERT model diff --git a/model_cards/dbmdz/bert-base-turkish-cased/README.md b/model_cards/dbmdz/bert-base-turkish-cased/README.md index 6bee01682740..166994daee68 100644 --- a/model_cards/dbmdz/bert-base-turkish-cased/README.md +++ b/model_cards/dbmdz/bert-base-turkish-cased/README.md @@ -1,5 +1,6 @@ --- language: turkish +license: mit --- # 🤗 + 📚 dbmdz Turkish BERT model diff --git a/model_cards/dbmdz/bert-base-turkish-uncased/README.md b/model_cards/dbmdz/bert-base-turkish-uncased/README.md index 58484a4334c6..8e2ab53cb12a 100644 --- a/model_cards/dbmdz/bert-base-turkish-uncased/README.md +++ b/model_cards/dbmdz/bert-base-turkish-uncased/README.md @@ -1,5 +1,6 @@ --- language: turkish +license: mit --- # 🤗 + 📚 dbmdz Turkish BERT model diff --git a/model_cards/dbmdz/distilbert-base-turkish-cased/README.md b/model_cards/dbmdz/distilbert-base-turkish-cased/README.md index 04a040a23761..30a03f983565 100644 --- a/model_cards/dbmdz/distilbert-base-turkish-cased/README.md +++ b/model_cards/dbmdz/distilbert-base-turkish-cased/README.md @@ -1,5 +1,6 @@ --- language: turkish +license: mit --- # 🤗 + 📚 dbmdz Distilled Turkish BERT model From f6a23d19116a62bd3c662d0aa381130b49abcff7 Mon Sep 17 00:00:00 2001 From: Sam Shleifer Date: Sun, 29 Mar 2020 10:51:13 -0400 Subject: [PATCH 09/10] [BART] add bart-large-xsum weights (#3422) --- src/transformers/configuration_bart.py | 1 + ..._original_pytorch_checkpoint_to_pytorch.py | 97 +++++++++++-------- src/transformers/modeling_bart.py | 1 + src/transformers/tokenization_bart.py | 2 +- tests/test_modeling_bart.py | 32 ++++++ 5 files changed, 93 insertions(+), 40 deletions(-) diff --git a/src/transformers/configuration_bart.py b/src/transformers/configuration_bart.py index 077e257a58cf..3e019b24767c 100644 --- a/src/transformers/configuration_bart.py +++ b/src/transformers/configuration_bart.py @@ -26,6 +26,7 @@ "bart-large": "https://s3.amazonaws.com/models.huggingface.co/bert/facebook/bart-large/config.json", "bart-large-mnli": "https://s3.amazonaws.com/models.huggingface.co/bert/facebook/bart-large-mnli/config.json", "bart-large-cnn": "https://s3.amazonaws.com/models.huggingface.co/bert/facebook/bart-large-cnn/config.json", + "bart-large-xsum": "https://s3.amazonaws.com/models.huggingface.co/bert/facebook/bart-large-xsum/config.json", } diff --git a/src/transformers/convert_bart_original_pytorch_checkpoint_to_pytorch.py b/src/transformers/convert_bart_original_pytorch_checkpoint_to_pytorch.py index e93a5b35c368..22fb047db7f6 100644 --- a/src/transformers/convert_bart_original_pytorch_checkpoint_to_pytorch.py +++ b/src/transformers/convert_bart_original_pytorch_checkpoint_to_pytorch.py @@ -17,6 +17,7 @@ import argparse import logging +import os from pathlib import Path import fairseq @@ -30,10 +31,11 @@ BartModel, BartTokenizer, ) +from transformers.modeling_bart import _make_linear_from_emb -FAIRSEQ_MODELS = ["bart.large", "bart.large.mnli", "bart.large.cnn"] - +FAIRSEQ_MODELS = ["bart.large", "bart.large.mnli", "bart.large.cnn", "bart_xsum/model.pt"] +extra_arch = {"bart.large": BartModel, "bart.large.mnli": BartForSequenceClassification} if version.parse(fairseq.__version__) < version.parse("0.9.0"): raise Exception("requires fairseq >= 0.9.0") @@ -57,62 +59,79 @@ def rename_key(dct, old, new): dct[new] = val -def convert_bart_checkpoint(checkpoint_path, pytorch_dump_folder_path): +def load_xsum_checkpoint(checkpoint_path): + """Checkpoint path should end in model.pt""" + sd = torch.load(checkpoint_path, map_location="cpu") + hub_interface = torch.hub.load("pytorch/fairseq", "bart.large.cnn").eval() + hub_interface.model.load_state_dict(sd["model"]) + return hub_interface + + +@torch.no_grad() +def convert_bart_checkpoint(checkpoint_path, pytorch_dump_folder_path, hf_checkpoint_name=None): """ Copy/paste/tweak model's weights to our BERT structure. """ - bart = torch.hub.load("pytorch/fairseq", checkpoint_path) - bart.eval() # disable dropout + if not os.path.exists(checkpoint_path): + bart = torch.hub.load("pytorch/fairseq", checkpoint_path).eval() + else: + bart = load_xsum_checkpoint(checkpoint_path) + bart.model.upgrade_state_dict(bart.model.state_dict()) - hf_model_name = checkpoint_path.replace(".", "-") - config = BartConfig.from_pretrained(hf_model_name) + if hf_checkpoint_name is None: + hf_checkpoint_name = checkpoint_path.replace(".", "-") + config = BartConfig.from_pretrained(hf_checkpoint_name) tokens = bart.encode(SAMPLE_TEXT).unsqueeze(0) - tokens2 = BartTokenizer.from_pretrained(hf_model_name).encode(SAMPLE_TEXT, return_tensors="pt").unsqueeze(0) + tokens2 = BartTokenizer.from_pretrained(hf_checkpoint_name).encode(SAMPLE_TEXT, return_tensors="pt").unsqueeze(0) assert torch.eq(tokens, tokens2).all() - if checkpoint_path in ["bart.large", "bart.large.cnn"]: - state_dict = bart.model.state_dict() - for k in IGNORE_KEYS: - state_dict.pop(k, None) - state_dict["shared.weight"] = state_dict["decoder.embed_tokens.weight"] - model = BartModel(config) - their_output = bart.extract_features(tokens) - else: # MNLI Case + if checkpoint_path == "bart.large.mnli": state_dict = bart.state_dict() - for k in IGNORE_KEYS: - state_dict.pop(k, None) + remove_ignore_keys_(state_dict) state_dict["model.shared.weight"] = state_dict["model.decoder.embed_tokens.weight"] for src, dest in rename_keys: rename_key(state_dict, src, dest) - model = BartForSequenceClassification(config) - their_output = bart.predict("mnli", tokens, return_logits=True) + model = BartForSequenceClassification(config).eval() + model.load_state_dict(state_dict) + fairseq_output = bart.predict("mnli", tokens, return_logits=True) + new_model_outputs = model(tokens)[0] # logits + else: # no classification heads to worry about + state_dict = bart.model.state_dict() + remove_ignore_keys_(state_dict) + state_dict["shared.weight"] = state_dict["decoder.embed_tokens.weight"] + fairseq_output = bart.extract_features(tokens) + if hf_checkpoint_name == "bart-large": + model = BartModel(config).eval() + model.load_state_dict(state_dict) + new_model_outputs = model(tokens).model[0] + else: + model = BartForConditionalGeneration(config).eval() # an existing summarization ckpt + model.model.load_state_dict(state_dict) + if hasattr(model, "lm_head"): + model.lm_head = _make_linear_from_emb(model.model.shared) + new_model_outputs = model.model(tokens)[0] - # Load state dict - model.load_state_dict(state_dict) - model.eval() # Check results - - if checkpoint_path == "bart.large.cnn": - model = BartForConditionalGeneration(config, base_model=model) - assert "lm_head.weight" in model.state_dict() - assert model.lm_head.out_features == config.max_position_embeddings - model.eval() - our_outputs = model.model(tokens)[0] - else: - our_outputs = model(tokens)[0] - assert their_output.shape == our_outputs.shape - assert (their_output == our_outputs).all().item() + assert fairseq_output.shape == new_model_outputs.shape + assert (fairseq_output == new_model_outputs).all().item() Path(pytorch_dump_folder_path).mkdir(exist_ok=True) model.save_pretrained(pytorch_dump_folder_path) +def remove_ignore_keys_(state_dict): + for k in IGNORE_KEYS: + state_dict.pop(k, None) + + if __name__ == "__main__": parser = argparse.ArgumentParser() # Required parameters - parser.add_argument("fairseq_path", choices=FAIRSEQ_MODELS, type=str, help="") - + parser.add_argument( + "fairseq_path", type=str, help="bart.large, bart.large.cnn or a path to a model.pt on local filesystem." + ) parser.add_argument("pytorch_dump_folder_path", default=None, type=str, help="Path to the output PyTorch model.") - args = parser.parse_args() - convert_bart_checkpoint( - args.fairseq_path, args.pytorch_dump_folder_path, + parser.add_argument( + "--hf_config", default=None, type=str, help="Which huggingface architecture to use: bart-large-xsum" ) + args = parser.parse_args() + convert_bart_checkpoint(args.fairseq_path, args.pytorch_dump_folder_path, hf_checkpoint_name=args.hf_config) diff --git a/src/transformers/modeling_bart.py b/src/transformers/modeling_bart.py index d2f92b00549a..cf88f9d5942e 100644 --- a/src/transformers/modeling_bart.py +++ b/src/transformers/modeling_bart.py @@ -34,6 +34,7 @@ "bart-large": "https://s3.amazonaws.com/models.huggingface.co/bert/facebook/bart-large/pytorch_model.bin", "bart-large-mnli": "https://s3.amazonaws.com/models.huggingface.co/bert/facebook/bart-large-mnli/pytorch_model.bin", "bart-large-cnn": "https://s3.amazonaws.com/models.huggingface.co/bert/facebook/bart-large-cnn/pytorch_model.bin", + "bart-large-xsum": "https://s3.amazonaws.com/models.huggingface.co/bert/facebook/bart-large-xsum/pytorch_model.bin", } BART_START_DOCSTRING = r""" diff --git a/src/transformers/tokenization_bart.py b/src/transformers/tokenization_bart.py index f5c0d8f1dd0e..76f184f50d96 100644 --- a/src/transformers/tokenization_bart.py +++ b/src/transformers/tokenization_bart.py @@ -19,7 +19,7 @@ # vocab and merges same as roberta vocab_url = "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-large-vocab.json" merges_url = "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-large-merges.txt" -_all_bart_models = ["bart-large", "bart-large-mnli", "bart-large-cnn"] +_all_bart_models = ["bart-large", "bart-large-mnli", "bart-large-cnn", "bart-large-xsum"] class BartTokenizer(RobertaTokenizer): diff --git a/tests/test_modeling_bart.py b/tests/test_modeling_bart.py index c463e4df3b8f..db7ce6331701 100644 --- a/tests/test_modeling_bart.py +++ b/tests/test_modeling_bart.py @@ -450,6 +450,38 @@ def test_model_from_pretrained(self): model = BartModel.from_pretrained(model_name, cache_dir=CACHE_DIR) self.assertIsNotNone(model) + @slow + def test_xsum_summarization_same_as_fairseq(self): + model = BartForConditionalGeneration.from_pretrained("bart-large-xsum").to(torch_device) + tok = BartTokenizer.from_pretrained("bart-large") + + PGE_ARTICLE = """ PG&E stated it scheduled the blackouts in response to forecasts for high winds amid dry conditions. The aim is to reduce the risk of wildfires. Nearly 800 thousand customers were scheduled to be affected by the shutoffs which were expected to last through at least midday tomorrow.""" + EXPECTED_SUMMARY = "California's largest power company has begun shutting off power to tens of thousands of homes and businesses in the state." + dct = tok.batch_encode_plus([PGE_ARTICLE], max_length=1024, pad_to_max_length=True, return_tensors="pt",) + + hypotheses_batch = model.generate( + input_ids=dct["input_ids"].to(torch_device), + attention_mask=dct["attention_mask"].to(torch_device), + num_beams=2, + max_length=62, + min_length=11, + length_penalty=1.0, + no_repeat_ngram_size=3, + early_stopping=True, + decoder_start_token_id=model.config.eos_token_ids[0], + ) + + decoded = [ + tok.decode(g, skip_special_tokens=True, clean_up_tokenization_spaces=False) for g in hypotheses_batch + ] + self.assertEqual(EXPECTED_SUMMARY, decoded[0]) + + def test_xsum_config_generation_params(self): + config = BartConfig.from_pretrained("bart-large-xsum") + expected_params = dict(num_beams=6, do_sample=False, early_stopping=True, length_penalty=1.0) + config_params = {k: getattr(config, k, "MISSING") for k, v in expected_params.items()} + self.assertDictEqual(expected_params, config_params) + @slow def test_cnn_summarization_same_as_fairseq(self): hf = BartForConditionalGeneration.from_pretrained("bart-large-cnn", output_past=True,).to(torch_device) From 33ef7002e17fe42b276dc6d36c07a3c39b1f09ed Mon Sep 17 00:00:00 2001 From: Sam Shleifer Date: Sun, 29 Mar 2020 13:25:42 -0400 Subject: [PATCH 10/10] =?UTF-8?q?[Docs]=20examples/summarization/bart:=20S?= =?UTF-8?q?implify=20CNN/DM=20preprocessi=E2=80=A6=20(#3516)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/summarization/bart/README.md | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/examples/summarization/bart/README.md b/examples/summarization/bart/README.md index ca30e8308b4d..97f60df79743 100644 --- a/examples/summarization/bart/README.md +++ b/examples/summarization/bart/README.md @@ -1,13 +1,15 @@ -### Get the CNN Data +### Get Preprocessed CNN Data To be able to reproduce the authors' results on the CNN/Daily Mail dataset you first need to download both CNN and Daily Mail datasets [from Kyunghyun Cho's website](https://cs.nyu.edu/~kcho/DMQA/) (the links next to "Stories") in the same folder. Then uncompress the archives by running: ```bash -tar -xvf cnn_stories.tgz && tar -xvf dailymail_stories.tgz +wget https://s3.amazonaws.com/datasets.huggingface.co/summarization/cnn_dm.tgz +tar -xzvf cnn_dm.tgz ``` + this should make a directory called cnn_dm/ with files like `test.source`. To use your own data, copy that files format. Each article to be summarized is on its own line. -### Usage +### Evaluation To create summaries for each article in dataset, run: ```bash python evaluate_cnn.py cnn_test_summaries.txt @@ -16,21 +18,12 @@ the default batch size, 8, fits in 16GB GPU memory, but may need to be adjusted ### Training - - - -After downloading the CNN and Daily Mail datasets, preprocess the dataset: -```commandline -git clone https://github.com/artmatsak/cnn-dailymail -cd cnn-dailymail && python make_datafiles.py ../cnn/stories/ ../dailymail/stories/ -``` - -Run the training script: `run_train.sh` - +Run/modify `run_train.sh` + ### Where is the code? The core model is in `src/transformers/modeling_bart.py`. This directory only contains examples. -### (WIP) Rouge Scores +## (WIP) Rouge Scores ### Stanford CoreNLP Setup ```