Fix torch_float casting to int instead of float
Author: Osamaali313
Pull request: yes
Labels: name: Code agent slop

# What does this PR do?

`torch_float` (`src/transformers/utils/generic.py`) is documented to cast its input *"to a Python float"* (and, in a tracing context, to a `torch.float32` tensor). But both of its non-tracing return paths call `int(x)` instead of `float(x)`:

```python
def torch_float(x):
    """
    Casts an input to a torch float32 tensor if we are in a tracing context, otherwise to a Python float.
    """
    if not _is_torch_available:
        return int(x)                                                                              # truncates

    import torch

    return x.to(torch.float32) if torch.jit.is_tracing() and isinstance(x, torch.Tensor) else int(x)  # truncates
```

This is a copy-paste leftover from the sibling `torch_int` immediately above, which correctly uses `int(x)` in both branches. Because the value is truncated, the function named `torch_float` returns an **int** on the normal eager path, contradicting both its name and its docstring (and inconsistent with the `torch.float32` cast it does under tracing).

## Impact

The in-tree caller is ImageGPT attention scaling (`models/imagegpt/modeling_imagegpt.py:106`):

```python
attn_weights = attn_weights / torch_float(value.size(-1) ** 0.5)
```

`value.size(-1) ** 0.5` is the (float) square root of the attention head dimension. Truncating it corrupts the scaling denominator for any non-perfect-square head dim:

| checkpoint | head_dim | `sqrt(head_dim)` | current (int) | correct (float) |
|---|---|---|---|---|
| imagegpt-small | 64 | 8.0000 | 8 | 8.0 (unaffected) |
| imagegpt-medium | 128 | 11.3137 | **11** | 11.3137 |
| imagegpt-large | 96 | 9.7980 | **9** | 9.7980 |

The default small config has a perfect-square head dim, which is why this slipped through.

## Fix

Return a `float` from both branches, matching the docstring and the tracing-path `float32` cast:

```python
    if not _is_torch_available:
        return float(x)
    ...
    return x.to(torch.float32) if torch.jit.is_tracing() and isinstance(x, torch.Tensor) else float(x)
```

## Reproduction (no torch required)

The `not _is_torch_available` branch is identical to the non-tracing `else` branch (both `int(x)`), so the bug is observable with plain Python:

```
current torch_float(sqrt(128)) = 11                  -> attn 100.0 / 11        = 9.090909  (wrong)
fixed   torch_float(sqrt(128)) = 11.313708498984761  -> attn 100.0 / 11.3137   = 8.838835  (correct)
```

## Before submitting
- [x] This PR fixes a bug (behavior + docstring mismatch), minimal 2-line change.
- [x] Did you make sure to update the documentation? (no doc changes needed; the docstring already describes the correct behavior.)


Comments:
Thank you for your contribution 🤗!

## CI Security Gate — automatic approval blocked

This PR was **not** automatically approved for CI because the security gate failed.

**Possible reasons:**
- The PR touches 50 or more files — only PRs with fewer than 50 changed files are automatically approved
- A changed file is outside the allowed directories (`src/`, `tests/`, `docs/`, `utils/`), has a disallowed extension (only `.py`, `.txt`, `.md` permitted outside `tests/` and `docs/`), or is not `.md`/`.yml` inside `docs/`
- A new high-severity security issue was detected in the changed Python files (Bandit check)

See the [workflow run](https://github.com/huggingface/transformers/actions/runs/29535018239) for the exact violations.

A maintainer can review and manually approve CI if a finding is a false positive.

For triage: the `security-gate / bandit-check` failure here isn't a Bandit finding in the diff. The job aborts before Bandit runs, at the `actions/checkout` step:

> Refusing to check out fork pull request code from a 'pull_request_target' workflow ... set 'allow-unsafe-pr-checkout: true' on the actions/checkout step.

So the gate can't fetch the fork's code to scan it. The change itself is a 2-line `int(x)` → `float(x)` fix confined to `src/transformers/utils/generic.py` (1 file, within the allowed paths and well under the 50-file limit), so there should be nothing for Bandit to flag. Happy to adjust if a maintainer would prefer a different approach.