Set missing seq_length variable when using inputs_embeds with ALBERT & Remove code duplication
Author: olenmg
Pull request: yes

# What does this PR do?

<!--
Congratulations! You've made it this far! You're not quite done yet though.

Once merged, your PR is going to appear in the release notes with the title you set, so make sure it's a great title that fully reflects the extent of your awesome contribution.

Then, please replace this with a description of the change and which issue is fixed (if applicable). Please also include relevant motivation and context. List any dependencies (if any) that are required for this change.

Once you're done, someone will review your PR shortly (see the section "Who can review?" below to tag some potential reviewers). They may suggest changes to make the code even better. If no one reviewed your PR after a week has passed, don't hesitate to post a new comment @-mentioning the same persons---sometimes notifications get lost.
-->

<!-- Remove if not applicable -->

I think this bug is similar to #13128 , only difference is that this PR is for ALBERT. 
`AlbertModel` has the same issue that `seq_length` variable is not declared when using `inputs_embeds`

I checked that other models that were implemented in the same code format as ALBERT/ELECTRA don't have this issue anymore.

++Additional
Remove all of code duplications as @NielsRogge referred on the comments.
```Diff
        if input_ids is not None and inputs_embeds is not None:
            raise ValueError("You cannot specify both input_ids and inputs_embeds at the same time")
        elif input_ids is not None:
            input_shape = input_ids.size()
-           batch_size, seq_length = input_shape
        elif inputs_embeds is not None:
            input_shape = inputs_embeds.size()[:-1]
-           batch_size, seq_length = input_shape
        else:
            raise ValueError("You have to specify either input_ids or inputs_embeds")

+       batch_size, seq_length = input_shape        
        device = input_ids.device if input_ids is not None else inputs_embeds.device
```

I think it is trivial, so I don't make additional PR. (If this is the problem, please inform me.)

## Before submitting
- [ ] This PR fixes a typo or improves the docs (you can dismiss the other checks if that's the case).
- [x] Did you read the [contributor guideline](https://github.com/huggingface/transformers/blob/master/CONTRIBUTING.md#start-contributing-pull-requests),
      Pull Request section?
- [ ] Was this discussed/approved via a Github issue or the [forum](https://discuss.huggingface.co/)? Please add a link
      to it if that's the case.
- [ ] Did you make sure to update the documentation with your changes? Here are the
      [documentation guidelines](https://github.com/huggingface/transformers/tree/master/docs), and
      [here are tips on formatting docstrings](https://github.com/huggingface/transformers/tree/master/docs#writing-source-documentation).
- [ ] Did you write any new necessary tests?


## Who can review?

Anyone in the community is free to review the PR once the tests have passed. Feel free to tag
members/contributors who may be interested in your PR.
@LysandreJik

<!-- Your PR 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: @LysandreJik
- blenderbot, bart, marian, pegasus, encoderdecoder,  t5: @patrickvonplaten, @patil-suraj
- longformer, reformer, transfoxl, xlnet: @patrickvonplaten
- fsmt: @stas00
- funnel: @sgugger
- gpt2: @patrickvonplaten, @LysandreJik
- rag: @patrickvonplaten, @lhoestq
- tensorflow: @LysandreJik

Library:

- benchmarks: @patrickvonplaten
- deepspeed: @stas00
- ray/raytune: @richardliaw, @amogkam
- text generation: @patrickvonplaten
- tokenizers: @n1t0, @LysandreJik
- trainer: @sgugger
- pipelines: @LysandreJik

Documentation: @sgugger

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
- research_projects/bert-loses-patience: @JetRunner
- research_projects/distillation: @VictorSanh

 -->


Comments:
Not sure why I can't add the code suggestion, but it makes more sense to do this:

```diff
if input_ids is not None and inputs_embeds is not None:
            raise ValueError("You cannot specify both input_ids and inputs_embeds at the same time")
        elif input_ids is not None:
            input_shape = input_ids.size()
-            batch_size, seq_length = input_shape
        elif inputs_embeds is not None:
            input_shape = inputs_embeds.size()[:-1]
-           batch_size, seq_length = input_shape
        else:
            raise ValueError("You have to specify either input_ids or inputs_embeds")

+        batch_size, seq_length = input_shape        
         device = input_ids.device if input_ids is not None else inputs_embeds.device
```

> Not sure why I can't add the code suggestion, but it makes more sense to do this:
> 
> ```diff
> if input_ids is not None and inputs_embeds is not None:
>             raise ValueError("You cannot specify both input_ids and inputs_embeds at the same time")
>         elif input_ids is not None:
>             input_shape = input_ids.size()
> -            batch_size, seq_length = input_shape
>         elif inputs_embeds is not None:
>             input_shape = inputs_embeds.size()[:-1]
> -           batch_size, seq_length = input_shape
>         else:
>             raise ValueError("You have to specify either input_ids or inputs_embeds")
> 
> +        batch_size, seq_length = input_shape        
>          device = input_ids.device if input_ids is not None else inputs_embeds.device
> ```

@NielsRogge 
Yes, I fully agree with you. But most of the codes of other models are implemented as I wrote, and I just wanted to unify the format to prevent confusion.

For example, the code below is from src/transformers/models/bert/modeling_bert.py:
```python
if input_ids is not None and inputs_embeds is not None:
    raise ValueError("You cannot specify both input_ids and inputs_embeds at the same time")
elif input_ids is not None:
    input_shape = input_ids.size()
    batch_size, seq_length = input_shape
elif inputs_embeds is not None:
    input_shape = inputs_embeds.size()[:-1]
    batch_size, seq_length = input_shape
else:
    raise ValueError("You have to specify either input_ids or inputs_embeds")

device = input_ids.device if input_ids is not None else inputs_embeds.device
```

But if needed, I could change all of the code looks like above.

> But if needed, I could change all of the code looks like above.

Actually, I'm in favor of this, because it's duplicated code, and I think it's cleaner when just writing it once. 

In that case, you can also update the [CookieCutter template](https://github.com/huggingface/transformers/blob/master/templates/adding_a_new_model/cookiecutter-template-%7B%7Bcookiecutter.modelname%7D%7D/modeling_%7B%7Bcookiecutter.lowercase_modelname%7D%7D.py), which is used when adding a new model. 

@NielsRogge 
Okay, I reflected it! (for at least the files I've found)
Please check again.

LGTM! Thanks for making this cleaner.