[ASR Pipeline] Fix init with timestamps
Author: sanchit-gandhi
Pull request: yes

# What does this PR do?

The PR #25344 added checks for the setting of `return_timestamps` in the method `sanitize_paramters` - this works when the argument `return_timestamps` is passed in the forward pass:
```python
from transformers import pipeline
import numpy as np

pipe = pipeline("automatic-speech-recognition", model="openai/whisper-tiny")

dummy_speech = np.ones(100)
pipe(dummy_speech, return_timestamps=True)
```

But fails when the argument is passed in the init (thanks to @ydshieh for flagging):
```python
from transformers import pipeline
import numpy as np

pipe = pipeline("automatic-speech-recognition", model="openai/whisper-tiny", return_timestamps=True)
```

<details> 

<summary> Traceback: </summary>

```
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ <ipython-input-2-d59778d5549a>:1 in <module>                                                     │
│                                                                                                  │
│ /Users/sanchitgandhi/transformers/src/transformers/pipelines/__init__.py:993 in pipeline         │
│                                                                                                  │
│   990 │   if device is not None:                                                                 │
│   991 │   │   kwargs["device"] = device                                                          │
│   992 │                                                                                          │
│ ❱ 993 │   return pipeline_class(model=model, framework=framework, task=task, **kwargs)           │
│   994                                                                                            │
│                                                                                                  │
│ /Users/sanchitgandhi/transformers/src/transformers/pipelines/automatic_speech_recognition.py:202 │
│ in __init__                                                                                      │
│                                                                                                  │
│   199 │   │   decoder: Optional[Union["BeamSearchDecoderCTC", str]] = None,                      │
│   200 │   │   **kwargs,                                                                          │
│   201 │   ):                                                                                     │
│ ❱ 202 │   │   super().__init__(**kwargs)                                                         │
│   203 │   │   self.feature_extractor = feature_extractor                                         │
│   204 │   │                                                                                      │
│   205 │   │   if self.model.config.model_type == "whisper":                                      │
│                                                                                                  │
│ /Users/sanchitgandhi/transformers/src/transformers/pipelines/base.py:822 in __init__             │
│                                                                                                  │
│    819 │   │   self.call_count = 0                                                               │
│    820 │   │   self._batch_size = kwargs.pop("batch_size", None)                                 │
│    821 │   │   self._num_workers = kwargs.pop("num_workers", None)                               │
│ ❱  822 │   │   self._preprocess_params, self._forward_params, self._postprocess_params = self._  │
│    823 │   │                                                                                     │
│    824 │   │   if self.image_processor is None and self.feature_extractor is not None:           │
│    825 │   │   │   if isinstance(self.feature_extractor, BaseImageProcessor):                    │
│                                                                                                  │
│ /Users/sanchitgandhi/transformers/src/transformers/pipelines/automatic_speech_recognition.py:326 │
│ in _sanitize_parameters                                                                          │
│                                                                                                  │
│   323 │   │   │   postprocess_params["decoder_kwargs"] = decoder_kwargs                          │
│   324 │   │   if return_timestamps is not None:                                                  │
│   325 │   │   │   # Check whether we have a valid setting for return_timestamps and throw an e   │
│ ❱ 326 │   │   │   if self.type == "seq2seq" and return_timestamps:                               │
│   327 │   │   │   │   raise ValueError("We cannot return_timestamps yet on non-CTC models apar   │
│   328 │   │   │   if self.type == "ctc_with_lm" and return_timestamps != "word":                 │
│   329 │   │   │   │   raise ValueError("CTC with LM can only predict word level timestamps, se   │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
AttributeError: 'AutomaticSpeechRecognitionPipeline' object has no attribute 'type'
```

</details>

=> this is because we call `sanitise_parameters` in the `__init__`, but **before** the attribute `self.type` is set, so these checks fail

This PR moves these `return_timestamps` checks to the `_forward` method. They are safe to perform here (we have set `self.type`), and are still performed **before** we perform any forward pass, so the error is thrown earlier rather than later.

Comments:
_The documentation is not available anymore as the PR was closed or merged._

Actually instead of moving parameter checking into logic of the pipeline, can we keep things inside `_sanitize_parameters` which is the proper location.

Maybe there are better way to make `self.type` available before hitting `_sanitizer_parameters` no ? 

The goal of those checks is to raise errors early rather than later. and also splitting checking from actual inference logic.

> Maybe there are better way to make self.type available before hitting _sanitizer_parameters no ?

Yes - to achieve this we have to override the `__init__` method of the pipeline. See the latest commit for how this design would look. If you're happy with this, I can tidy it up and complete the PR this way. Otherwise, we can keep the checks in the `_forward` method, since they'll still be done before any model computations.

IMO the key for me is that these checks are performed **before** the forward pass, rather than after the forward pass. Before https://github.com/huggingface/transformers/pull/25344, they were done **after** the forward pass in the `postprocess` method, which is wasteful if the settings are incorrect but we still run the model computations:
https://github.com/huggingface/transformers/blob/5b7ffd5492e13b10fcfe282b1ab99097a6e0230a/src/transformers/pipelines/automatic_speech_recognition.py#L500
So this design of moving them to the `_forward` is still an improvement over the old one.

> also splitting checking from actual inference logic.

Currently, there are numerous additional checks that are performed either in the forward pass or in the post-processing. See example above, and check in the forward pass below:
https://github.com/huggingface/transformers/blob/5b7ffd5492e13b10fcfe282b1ab99097a6e0230a/src/transformers/pipelines/automatic_speech_recognition.py#L447-L448

Happy to do a big refactor and move all of these to `_sanitize_paramters`, which we can do **if** the attribute `self.type` is set (as per the latest commit).

Thanks for fixing it !