Repository: huggingface/transformers
Pull request: Fix ESM token_dropout crash when using inputs_embeds instead of input_ids

```markdown
# Fix ESM `token_dropout` crash when using `inputs_embeds` instead of `input_ids`

## Description
This PR fixes an issue in the ESM model where calling `forward` with `inputs_embeds` (and no `input_ids`) would trigger an `AttributeError` in the `token_dropout` logic:

```
AttributeError: 'bool' object has no attribute 'unsqueeze'
```

## Cause
The `token_dropout` block assumed `input_ids` was always provided.  
When only `inputs_embeds` were passed, `input_ids` was `None`, leading to a failure when attempting to run `.unsqueeze(-1)`.

## Fix
Updated the conditional to:

```python
if self.token_dropout and input_ids is not None:
```

This ensures the masking logic is only applied when `input_ids` are available.  
The behavior now mirrors other BERT-like models while retaining ESM's mask-dropout logic when possible.

## Impact
- `inputs_embeds`-only inference now works without disabling `token_dropout`.
- No change for the standard `input_ids` usage.
- Fully backward compatible.

## Reproduction

```python
from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch

esm_version = "facebook/esm2_t6_8M_UR50D"
tokenizer = AutoTokenizer.from_pretrained(esm_version)
model = AutoModelForSequenceClassification.from_pretrained(esm_version)

seq = ["HHASPRKQGKKENGPPHSHTLKGRRLVFDN"]
tok = tokenizer(seq, return_tensors="pt", truncation=True, max_length=1024)
embeds = model.esm.embeddings.word_embeddings(tok["input_ids"])
outputs = model(inputs_embeds=embeds)  # ✅ No error after fix
```

## Related Issue
Fixes #40166
```

Changed files:
filename: src/transformers/models/esm/modeling_esm.py
patch: @@ -216,7 +216,7 @@ def forward(
         # a factor of (fraction of unmasked tokens during training) / (fraction of unmasked tokens in sample).
         # This is analogous to the way that dropout layers scale down outputs during evaluation when not
         # actually dropping out values (or, equivalently, scale up their un-dropped outputs in training).
-        if self.token_dropout:
+        if self.token_dropout and input_ids is not None:
             embeddings = embeddings.masked_fill((input_ids == self.mask_token_id).unsqueeze(-1), 0.0)
             mask_ratio_train = 0.15 * 0.8  # Hardcoded as the ratio used in all ESM model training runs
             src_lengths = attention_mask.sum(-1)

filename: src/transformers/models/evolla/modeling_evolla.py
patch: @@ -138,7 +138,7 @@ def forward(
         # a factor of (fraction of unmasked tokens during training) / (fraction of unmasked tokens in sample).
         # This is analogous to the way that dropout layers scale down outputs during evaluation when not
         # actually dropping out values (or, equivalently, scale up their un-dropped outputs in training).
-        if self.token_dropout:
+        if self.token_dropout and input_ids is not None:
             embeddings = embeddings.masked_fill((input_ids == self.mask_token_id).unsqueeze(-1), 0.0)
             mask_ratio_train = 0.15 * 0.8  # Hardcoded as the ratio used in all EVOLLA_SA_PROT model training runs
             src_lengths = attention_mask.sum(-1)