[`FSMT`] Make it compatible with `xxxForConditionalGeneration` models
Author: younesbelkada
Pull request: yes

# What does this PR do?

Fixes https://github.com/huggingface/transformers/issues/20824

`FSMT` model is an encoder-decoder model. Most of `xxxForConditionalGeneration` models can use `decoder_inputs_embeds` and `inputs_embeds` in replacement respectively of `input_ids` and `decoder_input_ids`. 

`FSMT` does not implement this functionality which breaks some assumptions made by external libraries / APIs, an issue has been flagged and reported in https://github.com/inseq-team/inseq/issues/153 

This PR fixes this behavior, by adding `inputs_embeds` and `decoder_inputs_embed` support for `FSMT` to make it consistent with other `xxxForConditionalGeneration` models. The PR also adds `get_encoder` and `get_decoder` class functions for `FSMT`, following the implementation of `T5`

`self.embed_positions(input_ids)` and `self.embed_positions(inputs_embeds[:, :, 0])` are equivalent as the positional embedding is computed with respect to the hidden states shape. But I added an extra check by assuming that 0 hidden states correspond to padding tokens, as this information is needed later by the position embedding layer. 

All FSMT slow tests pass


Comments:
I think that `inputs_embed` cannot be added as T5, since [positional embeddings needs to be computed too](https://github.com/huggingface/transformers/blob/ecd7de3dff7ea5713004b2f05e3869c24b8eb6e2/src/transformers/models/fsmt/modeling_fsmt.py#L721), and this requires having `input_ids`, except if the user can pass `inputs_position_embeds`  too 

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

Hi @gsarti 
Here is an attempt to fix #20824 , could you double check if this fixes your root issue
I ran: 
```
import inseq

model = inseq.load_model("facebook/wmt19-en-de", "integrated_gradients")
out = model.attribute(
  "The developer argued with the designer because her idea cannot be implemented.",
  n_steps=100
)
out.show()
```
but getting an error which is different from the one described in https://github.com/inseq-team/inseq/issues/153
```
ValueError: Both `max_new_tokens` and `max_length` have been set but they serve the same purpose -- setting a limit to the generated output length. Remove one of those arguments. Please refer to the documentation for more information. 
(https://huggingface.co/docs/transformers/main/en/main_classes/text_generation)
```

The error you see is a problem of Inseq due to force-setting `max_new_tokens` for generation, you can bypass it by passing a custom `generated_text` argument to `model.attribute` so that no call to model.generate is performed, but only forwards for the attribution.

Trying this code now:

```python
import inseq

model = inseq.load_model("facebook/wmt19-en-de", "integrated_gradients")
out = model.attribute(
  "The developer argued with the designer because her idea cannot be implemented.",
  "Hallo Welt ich bin Gabriele",
  n_steps=100
)
out.show()
```

I still encounter an error:

```shell
/usr/local/lib/python3.8/dist-packages/transformers/models/fsmt/modeling_fsmt.py in forward(self, input_ids, attention_mask, decoder_input_ids, decoder_attention_mask, head_mask, decoder_head_mask, cross_attn_head_mask, encoder_outputs, past_key_values, use_cache, output_attentions, output_hidden_states, inputs_embeds, inputs_position_embeds, decoder_inputs_embeds, decoder_inputs_position_embeds, return_dict)
   1090             decoder_padding_mask, causal_mask = None, None
   1091 
-> 1092         assert decoder_input_ids is not None
   1093 
   1094         if encoder_outputs is None:

AssertionError:
```

@younesbelkada  Is this check needed now? I presume extra tests for the forward call using embeddings as inputs would fail, too, if they were present!

Thank you very much @gsarti for double checking, I adapted the assert condition based on your suggestion, getting now an error since `inputs_position_embeds` needs to be passed too. I think the next fix should go on `inseq` side to support sending `inputs_position_embeds` too

Is it standard to have `inputs_position_embeds` as forward inputs? Don't recall seeing them in other models. In principle if the positions are just created from sinusoidals they could be omitted and added in the forward itself, right?

Thanks for the heads up @gsarti , you are correct, I overlooked at the code and thought the positional embedding was using nn.Embedding, I can confirm the script you sent me above runs now!

You can refer to other models for the usual docstring that we write for `input_ids` etc. Let's keep consistency wherever we can

I will try to find time to review tomorrow, but I also wanted to point out @patil-suraj's sync https://github.com/huggingface/transformers/pull/11218 which never got merged, but might be a useful reference as I think the same work was done there.