FillMaskPipeline assumes model return dict but return_dict is not set
Author: richardwth
Pull request: no

## Environment info
<!-- You can run the command `transformers-cli env` and copy-and-paste its output below.
     Don't forget to fill out the missing fields in that output! -->

- `transformers` version: 4.11.3
- Platform: Linux
- Python version: 3.6.13
- PyTorch version (GPU?): 1.9
- Tensorflow version (GPU?): N/A
- Using GPU in script?: Yes
- Using distributed or parallel set-up in script?: Yes

### Who can help 
@Narsil
<!-- Your issue will be replied to more quickly if you can figure out the right person to tag with @
 If you know how to use git blame, that is the easiest way, otherwise, here is a rough guide of **who to tag**.
 Please tag fewer than 3 people.

Models:

- ALBERT, BERT, XLM, DeBERTa, DeBERTa-v2, ELECTRA, MobileBert, SqueezeBert: @LysandreJik
- encoder-decoder models (For example, BlenderBot, BART, Marian, Pegasus, T5, ByT5): @patrickvonplaten, @patil-suraj
- Longformer, Reformer, TransfoXL, XLNet, FNet: @patrickvonplaten
- FSMT: @stas00
- Funnel: @sgugger
- GPT-2, GPT: @patrickvonplaten, @LysandreJik
- RAG, DPR: @patrickvonplaten, @lhoestq
- TensorFlow: @Rocketknight1
- JAX/Flax: @patil-suraj @patrickvonplaten 
- TAPAS, LayoutLM, LayoutLMv2, LUKE, ViT, BEiT, DEiT, DETR, CANINE: @NielsRogge
- GPT-Neo, GPT-J, CLIP: @patil-suraj
- Wav2Vec2, HuBERT, SpeechEncoderDecoder: @patrickvonplaten, @anton-l

If the model isn't in the list, ping @LysandreJik who will redirect you to the correct contributor.

Library:

- Benchmarks: @patrickvonplaten
- Deepspeed: @stas00
- Ray/raytune: @richardliaw, @amogkam
- Text generation: @patrickvonplaten
- Tokenizers: @LysandreJik
- Trainer: @sgugger
- Pipelines: @Narsil
- Speech: @patrickvonplaten, @anton-l
- Vision: @NielsRogge, @sgugger

Documentation: @sgugger

Model hub:

- for issues with a model, report at https://discuss.huggingface.co/ and tag the model's creator.

HF projects:

- datasets: [different repo](https://github.com/huggingface/datasets)
- rust tokenizers: [different repo](https://github.com/huggingface/tokenizers)

Examples:

- maintained examples (not research project or legacy): @sgugger, @patil-suraj

For research projetcs, please ping the contributor directly. For example, on the following projects:

- research_projects/bert-loses-patience: @JetRunner
- research_projects/distillation: @VictorSanh

 -->

## Information

Model I am using (Bert, XLNet ...): Bert, Roberta, Deberta

The problem arises when using:
* [ ] the official example scripts: (give details below)
* [x] my own modified scripts: (give details below)

The tasks I am working on is:
* [ ] an official GLUE/SQUaD task: (give the name)
* [x] my own task or dataset: (give details below)

## To reproduce

Steps to reproduce the behavior:

I came across this error 
`'tuple' object does not support item assignment` 
when using `nlpaug` package ([link](https://github.com/makcedward/nlpaug)) for data augmentation. The code snippet is
```Python
import nlpaug.augmenter.word as naw
text = 'The chef cook the meal.'
aug = naw.ContextualWordEmbsAug(
    model_path=model_path, 
    model_type='roberta',
    action="insert")
augmented_text = aug.augment(text)
```
It is easy to locate this bug by checking `transformers.pipelines.fill_mask.py` [line 90](https://github.com/huggingface/transformers/blob/956a483173e77ebf655ca9636a5f7b6ef010b307/src/transformers/pipelines/fill_mask.py#L90):
```Python
def _forward(self, model_inputs):
        model_outputs = self.model(**model_inputs)
        model_outputs["input_ids"] = model_inputs["input_ids"]
        return model_outputs
```
and [line 184](https://github.com/huggingface/transformers/blob/956a483173e77ebf655ca9636a5f7b6ef010b307/src/transformers/pipelines/fill_mask.py#L184):
```Python
def _sanitize_parameters(self, top_k=None, targets=None):
        postprocess_params = {}

        if targets is not None:
            target_ids = self.get_target_ids(targets, top_k)
            postprocess_params["target_ids"] = target_ids

        if top_k is not None:
            postprocess_params["top_k"] = top_k

        if self.tokenizer.mask_token_id is None:
            raise PipelineException(
                "fill-mask", self.model.base_model_prefix, "The tokenizer does not define a `mask_token`."
            )
        return {}, {}, postprocess_params
```
~~The `_forward` assumes `model_outputs` is a `dict` but models like Bert, Roberta assume `return_dict=None` by default; the `_sanitize_parameters` returns empty `forward_params` so `model_inputs` does not contain `{'return_dict': True}`, thus causing the error.~~
Later on I realized the issue was that my checkpoint from `model_path` had set `return_dict=False` , so I modified the description as follows:
The `_forward` assumes `model_outputs` is a `dict` but the loaded checkpoint from `model_path` may have set `return_dict=False` and output a tuple to cause the error.  The `_sanitize_parameters` returns empty `forward_params` so user cannot configure this in the code, but have to modify the `return_dict` property of the checkpoint. 

<!-- If you have code snippets, error messages, stack traces please provide them here as well.
     Important! Use code tags to correctly format your code. See https://help.github.com/en/github/writing-on-github/creating-and-highlighting-code-blocks#syntax-highlighting
     Do not use screenshots, as they are hard to read and (more importantly) don't allow others to copy-and-paste your code.-->

## Expected behavior

Please do either
- Explicitly set `self.model(**model_inputs, return_dict=True)` in `_forward` (as @Narsil suggests).
- Allow `_sanitize_parameters` to accept `**kwargs`, allow `_forward` to accept `**forward_params` and pass them to model, so that the user can modify the behavior of the loaded model. 
- Provide other suggestions. 

<!-- A clear and concise description of what you would expect to happen. -->


Comments:
Ok, `_forward` assumes that the model will returns a `BaseModelOutput` which are Transformers specific dicts which are necessary to support all backends (PT, TF, flax).

There won't be support for tuples since it's harder and less readable to use.
The pipelines do need to change what get passed on to `postprocess` since information from `preprocess` might still be important (here `input_ids` for instance).
In addition, the pipeline can handle batching and auto padding which is impossible to handle without knowing tensor names. (since the padding value depends on the type of tensor)

AFAIK there is not downside to using `BaseModelOutput`. In general, `return_dict` does not have to be set, since it's the default of the library.

I am not sure where this information is lost in your script since you share only a very small amount of code.
Could you share a reproducible example so I can probably provide a better workaround ?

> Ok, `_forward` assumes that the model will returns a `BaseModelOutput` which are Transformers specific dicts which are necessary to support all backends (PT, TF, flax).
> 
> There won't be support for tuples since it's harder and less readable to use. The pipelines do need to change what get passed on to `postprocess` since information from `preprocess` might still be important (here `input_ids` for instance). In addition, the pipeline can handle batching and auto padding which is impossible to handle without knowing tensor names. (since the padding value depends on the type of tensor)
> 
> AFAIK there is not downside to using `BaseModelOutput`. In general, `return_dict` does not have to be set, since it's the default of the library.
> 
> I am not sure where this information is lost in your script since you share only a very small amount of code. Could you share a reproducible example so I can probably provide a better workaround ?

Thanks for your reply and sorry for a waste of your time.

I realize the issue was on my side that `return_dict` was set to False in the provided checkpoint at `model_path`. The default of the library is indeed to return a dictionary. 

I have modified the issue description to include this.

I think forcing `return_dict` to be `True` has no downsides and would prevent issues where a model has `return_dict` set to `False` before being loaded in the pipeline. I believe we would be open for an explicit setting of `return_dict` to `True` in the pipelines.

@LysandreJik do all models in all frameworks support the kwarg ?

If it's not an overridable option, we could definitely change every call to force `return_dict=True`

```python
self.model(**model_inputs)
```

to 
```python
self.model(**model_inputs, return_dict=True)
```

Would that work ?