# Backends de atención

Todas las implementaciones de atención realizan el mismo cálculo. Cada token se compara con todos los demás. La diferencia es *cómo* se realiza el cálculo. La atención básica escala mal porque materializa la matriz de atención completa en memoria, creando cuellos de botella que ralentizan la inferencia. Las implementaciones optimizadas reorganizan la matemática para reducir el tráfico de memoria y lograr una inferencia más rápida y asequible.

La [AttentionInterface](/docs/transformers/main/es/internal/modeling_utils#transformers.AttentionInterface) proporciona implementaciones de atención optimizadas. Desacopla la implementación de la atención de la implementación del modelo para simplificar la experimentación con diferentes funciones. Añade nuevos backends fácilmente con esta interfaz coherente.

Backend de atenciónDescripción "flash_attention_3"mejora FlashAttention-2 al superponer también las operaciones y fusionar de manera más estrecha las pasadas hacia adelante y hacia atrás "flash_attention_2"divide los cálculos en bloques más pequeños y utiliza la memoria rápida en el chip "flex_attention"marco de trabajo para especificar patrones de atención personalizados (esparcidos, de bloque local, de ventana deslizante) sin escribir kernels de bajo nivel a mano "sdpa"implementación integrada de PyTorch de la atención de producto punto escalado "paged&#124;flash_attention_3"Versión paginada de FlashAttention-3 "paged&#124;flash_attention_2"Versión paginada de FlashAttention-2 "paged&#124;sdpa"Versión paginada de SDPA "paged&#124;eager"Versión paginada de eager

## Establecer un backend de atención

Use el argumento `attn_implementation` en [from_pretrained()](/docs/transformers/main/es/main_classes/model#transformers.PreTrainedModel.from_pretrained) para instanciar un modelo con una función de atención específica.

```py
import torch
from transformers import AutoModelForCausalLM

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-3.2-1B", attn_implementation="flash_attention_2"
)
```

Cambia entre backends de atención en tiempo de ejecución sin recargar el modelo usando [set_attn_implementation()](/docs/transformers/main/es/main_classes/model#transformers.PreTrainedModel.set_attn_implementation).

```py
model.set_attn_implementation("sdpa")
```

### Kernels

Descargue y cargue kernels de cálculo compilados directamente desde el [Hub](https://huggingface.co/models?other=kernels) en tiempo de ejecución con la biblioteca [Kernels](https://huggingface.co/docs/kernels/index). Esto evita problemas de empaquetado derivados de versiones incompatibles de PyTorch o CUDA.

Los kernels se registran automáticamente en [AttentionInterface](/docs/transformers/main/es/internal/modeling_utils#transformers.AttentionInterface) al detectarse. No es necesario instalar el paquete FlashAttention explícitamente. Solicitar FlashAttention por nombre también recurre al kernel del Hub, consulte [FlashAttention fallback](./kernel_doc/loading_kernels#flashattention-fallback).

```py
import torch
from transformers import AutoModelForCausalLM

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-3.2-1B", attn_implementation="kernels-community/flash-attn2"
)
```

### Gestor de contexto de SDPA

La atención de producto punto escalado (SDPA) de PyTorch selecciona automáticamente la función de atención más rápida para los backends de CUDA. Para otros backends, utiliza por defecto la implementación de C++ de PyTorch.

Fuerza a SDPA a usar una implementación específica con el gestor de contexto [torch.nn.attention.sdpa_kernel](https://pytorch.org/docs/stable/generated/torch.nn.attention.sdpa_kernel.html).

```py
import torch
from torch.nn.attention import SDPBackend, sdpa_kernel
from transformers import AutoModelForCausalLM

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-3.2-1B", attn_implementation="sdpa"
)

with sdpa_kernel(SDPBackend.FLASH_ATTENTION):
    outputs = model.generate(**inputs)
```

## Atención específica del backbone

Los modelos multimodales utilizan backbones diferentes para cada modalidad. Optimiza el rendimiento asignando funciones de atención específicas a cada backbone. Algunos backbones de visión funcionan mejor en fp32, por ejemplo, algo que FlashAttention no admite.

Mapee los backbones de visión a diferentes funciones de atención mediante un diccionario, mientras que el backbone de texto continúa utilizando FlashAttention. Las claves en la implementación de atención deben coincidir con los nombres de las subconfiguraciones.

```py
from transformers import AutoModelForImageTextToText

attention_implementation_per_backbone = {"vision_config": "sdpa", "text_config": "flash_attention_2"}

for key in attention_implementation_per_backbone:
    assert key in model.config.sub_configs, f"Invalid key in `attention_implementation`"

model = AutoModelForImageTextToText.from_pretrained(
    "facebook/chameleon-7b", attn_implementation=attention_implementation_per_backbone
)
```

Omita ciertos backbones del diccionario para usar la función de atención predeterminada (SDPA).

```py
model = AutoModelForImageTextToText.from_pretrained(
    "facebook/chameleon-7b", attn_implementation={"text_config": "flash_attention_2"}
)
```

Establezca la misma función de atención para todos los backbones con una sola cadena.

```py
model = AutoModelForImageTextToText.from_pretrained(
    "facebook/chameleon-7b", attn_implementation="eager"
)
```

Establezca la función de atención globalmente con una clave vacía.

```py
model = AutoModelForImageTextToText.from_pretrained(
    "facebook/chameleon-7b", attn_implementation={"": "eager"}
)
```

## Crear una nueva función de atención

Personalice o cree nuevas funciones de atención añadiéndolas al registro de atención con [AttentionInterface.register()](/docs/transformers/main/es/internal/modeling_utils#transformers.AttentionInterface.register). Los modelos utilizan estas funciones a través del argumento `attn_implementation`.

> [!WARNING]  
> Registre una función de máscara de atención correspondiente cuando registre una función de atención personalizada. Si el nombre de `attn_implementation` personalizado no está registrado en [AttentionMaskInterface](/docs/transformers/main/es/internal/modeling_utils#transformers.AttentionMaskInterface), Transformers omite la creación de la máscara y pasa `attention_mask=None` a las capas de atención. Su función de atención debe manejar por sí misma las restricciones causales, de relleno, de empaquetado o de ventana deslizante, o bien dichas restricciones pueden omitirse silenciosamente.

Este ejemplo personaliza la función de atención para imprimir un mensaje en cada capa. Mantiene la máscara de la implementación original registrando `masking_utils.sdpa_mask` como la función de máscara de atención.

```python
import torch
from transformers import AutoModelForCausalLM, AttentionInterface, AttentionMaskInterface
from transformers.integrations.sdpa_attention import sdpa_attention_forward
from transformers.masking_utils import sdpa_mask

def my_new_sdpa(*args, **kwargs):
    print("I just entered the attention computation")
    return sdpa_attention_forward(*args, **kwargs)

AttentionInterface.register("my_new_sdpa", my_new_sdpa)
AttentionMaskInterface.register("my_new_sdpa", sdpa_mask)  # must have the same name as the registered attention function

model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3.2-1B", attn_implementation="my_new_sdpa")
model(torch.ones(1, 5, dtype=int))
```

También puede agregar nuevos argumentos a la función de atención. Los modelos que admiten [AttentionInterface](/docs/transformers/main/es/internal/modeling_utils#transformers.AttentionInterface) propagan los kwargs a las capas de atención y a la función de atención. Pase los argumentos como kwargs en la función forward del modelo. Las funciones de atención personalizadas deben seguir esta firma y formato de retorno.

```python
import torch
from transformers import AutoModelForCausalLM, AttentionInterface, AttentionMaskInterface
from transformers.integrations.sdpa_attention import sdpa_attention_forward
from transformers.masking_utils import sdpa_mask

def custom_attention(
    module: torch.nn.Module,  # required arg
    query: torch.Tensor,  # required arg
    key: torch.Tensor,  # required arg
    value: torch.Tensor,  # required arg
    attention_mask: Optional[torch.Tensor],  # required arg
    a_new_kwargs = None,  # You can now add as many kwargs as you need
    another_new_kwargs = None,  # You can now add as many kwargs as you need
    **kwargs,  # You need to accept **kwargs as models will pass other args
) -> tuple[torch.Tensor, Optional[torch.Tensor]]
    ...  # do your magic!
    return attn_output, attn_weights  # attn_weights are optional here

AttentionInterface.register("custom", custom_attention)
AttentionMaskInterface.register("custom", sdpa_mask)  # to leave the existing mask untouched

model = AutoModelForCausalLM.from_pretrained(model_id, attn_implementation="custom")
model(torch.ones(1, 5, dtype=int), a_new_kwargs=..., another_new_kwargs=...)
```

Comprueba el [código de modelado](https://github.com/huggingface/transformers/tree/main/src/transformers/models) de un modelo para confirmar qué argumentos y kwargs envía a la función de atención.

## AttentionMaskInterface

[AttentionMaskInterface](/docs/transformers/main/es/internal/modeling_utils#transformers.AttentionMaskInterface) es el registro que consultan las funciones [`create_*_mask`](#build-an-attention-mask) para convertir una máscara al formato que espera el backend de atención activo. FlexAttention necesita una [BlockMask](https://docs.pytorch.org/docs/stable/nn.attention.flex_attention.html#torch.nn.attention.flex_attention.BlockMask), SDPA necesita un tensor 4D y FlashAttention necesita la máscara de relleno base 2D. Registra un backend personalizado o sobrescribe el formateador de uno existente con [AttentionMaskInterface.register()](/docs/transformers/main/es/internal/modeling_utils#transformers.AttentionInterface.register).

```python
import torch
from transformers import AttentionMaskInterface
from transformers.masking_utils import sdpa_mask

def my_new_sdpa_mask(*args, **kwargs):
    print("I just entered the attention mask computation")
    return sdpa_mask(*args, **kwargs)

AttentionMaskInterface.register("my_new_sdpa_mask", my_new_sdpa_mask)
```

Sin un formateador registrado para el `attn_implementation` activo, se omite la creación de la máscara y `attention_mask=None` se pasa a las capas de atención.

Las funciones registradas deben coincidir con esta firma.

```python
def custom_attention_mask(
    batch_size: int,  # required arg
    q_length: int,  # required arg
    kv_length: int,  # required arg
    q_offset: int = 0,  # required arg
    kv_offset: int = 0,  # required arg
    mask_function: Callable = causal_mask_function,  # required arg
    attention_mask: Optional[torch.Tensor] = None,  # required arg
    **kwargs,  # a few additional args may be passed as kwargs, especially the model's config is always passed
) -> Optional[torch.Tensor]:
```

El argumento `mask_function` es un `Callable` que imita a las funciones [mask_mod](https://pytorch.org/blog/flexattention/) de PyTorch. Recibe 4 índices `(batch_idx, head_idx, q_idx, kv_idx)` y devuelve un valor booleano que indica si esa posición contribuye al cálculo de la atención. Esta es la misma forma primitiva utilizada por `or_mask_function` y `and_mask_function` en [Construir una máscara de atención](#build-an-attention-mask).

> [!TIP]
> Usa este [solución temporal](https://github.com/huggingface/transformers/blob/main/src/transformers/integrations/executorch.py) para torch.export si `mask_function` no logra crear una máscara.

## Construir una máscara de atención

Construya máscaras de atención con las funciones `create_*_mask` en [transformers.masking_utils](https://github.com/huggingface/transformers/blob/main/src/transformers/masking_utils.py#L894). Cada función lee el backend de atención activo desde la configuración del modelo, busca el formateador de máscaras del backend en [AttentionMaskInterface](/docs/transformers/main/es/internal/modeling_utils#transformers.AttentionMaskInterface) y devuelve el formato que ese backend espera. No necesita invertir, expandir ni convertir la máscara usted mismo.

Elija la función que coincide con el patrón de atención.

| función | caso de uso |
|---|---|
| `create_causal_mask` | modelos solo decodificador en los que cada token atiende a sí mismo y a los tokens anteriores |
| `create_bidirectional_mask` | modelos codificadores, o atención cruzada desde un decodificador hacia los estados del codificador |
| `create_sliding_window_causal_mask` | modelos decodificadores con un patrón de atención de ventana deslizante |
| `create_chunked_causal_mask` | modelos decodificadores que dividen la secuencia en bloques de tamaño fijo |
| `create_bidirectional_sliding_window_mask` | modelos codificadores con un patrón de atención de ventana deslizante |

> [!WARNING]
> Los helpers de máscara legibles legados - `get_extended_attention_mask`, `create_extended_attention_mask_for_decoder`, `invert_attention_mask` - emiten una advertencia de obsolescencia y se eliminarán en una versión futura. Utilice en su lugar las funciones `create_*_mask`.

Llama a `create_causal_mask` dentro de una pasada de decodificación. Pasa la configuración, los embeddings de entrada, la `attention_mask` de 2D proporcionada por el usuario y la caché. La función utiliza los embeddings para leer el tamaño del lote, la longitud de la consulta, el dtype y el dispositivo, y utiliza la caché para calcular la longitud de la clave.

```py
from transformers.masking_utils import create_causal_mask

attention_mask = create_causal_mask(
    config=self.config,
    inputs_embeds=inputs_embeds,
    attention_mask=attention_mask,
    past_key_values=past_key_values,
)
```

Llama a `create_bidirectional_mask` para la autoatención del codificador. Descarta `past_key_values` porque los codificadores no almacenan en caché.

```py
from transformers.masking_utils import create_bidirectional_mask

attention_mask = create_bidirectional_mask(
    config=self.config,
    inputs_embeds=embedding_output,
    attention_mask=attention_mask,
)
```

Para la atención cruzada, pase los estados del codificador como `encoder_hidden_states` para que la máscara utilice la longitud de las claves y los valores del codificador en lugar de la longitud de las consultas del decodificador.

```py
encoder_attention_mask = create_bidirectional_mask(
    config=self.config,
    inputs_embeds=embedding_output,
    attention_mask=encoder_attention_mask,
    encoder_hidden_states=encoder_hidden_states,
)
```

Añada restricciones adicionales sobre la máscara base con los argumentos `or_mask_function` y `and_mask_function`. Use `or_mask_function` para permitir que posiciones adicionales atiendan, y `and_mask_function` para restringir aún más el patrón base. Ambos siguen la firma de `mask_function` de 4 índices descrita en [AttentionMaskInterface](#attentionmaskinterface). Reciben `(batch_idx, head_idx, q_idx, kv_idx)` y devuelven un booleano.

> [!WARNING]
> `or_mask_function` y `and_mask_function` pueden expresar cualquier patrón de atención, pero son más lentos que los patrones integrados y no son compatibles con ExecuTorch. El sobrecoste es más notable en modelos más pequeños (~200M de parámetros), donde la creación de la máscara ocupa una mayor proporción del tiempo de la pasada hacia adelante. Úsalos solo cuando las funciones estándar `create_*_mask` no puedan expresar lo que necesitas.

Por ejemplo, superponga una función que devuelve `True` en todas partes sobre una máscara causal para convertirla en una completamente bidireccional. La unión con el patrón causal permite que cada token atienda a cualquier otro token.

```py
mask_kwargs = {
    "config": self.config,
    "inputs_embeds": inputs_embeds,
    "attention_mask": attention_mask,
    "past_key_values": past_key_values,
    "position_ids": position_ids,
    "or_mask_function": lambda *args: torch.tensor(True, dtype=torch.bool),
}

attention_mask = create_causal_mask(**mask_kwargs)
```

Durante la generación, [generate()](/docs/transformers/main/es/main_classes/text_generation#transformers.GenerationMixin.generate) construye las máscaras a través de `create_masks_for_generate`, que deriva a la función `create_*_mask` adecuada según la configuración del modelo. Sobrescríbela en una clase de modelo para incorporar una estrategia de enmascarado personalizada para la generación.

## Pasar una máscara de atención 4D personalizada

Pasa tu propia máscara 4D cuando necesites un patrón de atención que las funciones `create_*_mask` no puedan expresar. Una máscara 4D tiene la forma `(batch_size, 1, query_length, kv_length)`, donde `1` difunde la misma máscara a través de todas las cabezas de atención. Transformers detecta y utiliza la máscara tal cual, omitiendo `create_*_mask`.

Una máscara 4D utiliza una de dos convenciones de valores.

| dtype | atender | enmascarar |
|---|---|---|
| boolean | `True` | `False` |
| float | `0.0` | `-inf` |

La convención float añade la máscara a las puntuaciones de atención antes del softmax. Una puntuación más `0.0` permanece sin cambios, por lo que la posición contribuye. Una puntuación más `-inf` cae a cero después del softmax, por lo que la posición se excluye.

> [!IMPORTANT]
> La convención aceptada depende del backend de atención. `sdpa` acepta una máscara booleana o de tipo float. `eager` suma la máscara a las puntuaciones, por lo que solo acepta una máscara de tipo float. `flash_attention_2` y `flex_attention` consumen sus propios formatos (una máscara de relleno 2D y un [BlockMask](https://docs.pytorch.org/docs/stable/nn.attention.flex_attention.html#torch.nn.attention.flex_attention.BlockMask)) y no aceptan una máscara 4D sin procesar.

Un error común es reutilizar la convención `1`/`0` de una máscara de relleno 2D en una máscara 4D de tipo float. Dado que la máscara se suma a las puntuaciones, `0.0` conserva una posición y `1.0` solo añade un pequeño sesgo.

El ejemplo siguiente contrasta una máscara incorrecta con una correcta. Ambas parten del mismo patrón causal `1`/`0`.

```py
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

model = AutoModelForCausalLM.from_pretrained("TinyLlama/TinyLlama-1.1B-Chat-v1.0", attn_implementation="sdpa")
tokenizer = AutoTokenizer.from_pretrained("TinyLlama/TinyLlama-1.1B-Chat-v1.0")

input_ids = tokenizer("my favorite condiment on a", return_tensors="pt").input_ids
seq_len = input_ids.shape[1]

# 1 attends, 0 masks
causal = torch.tril(torch.ones(seq_len, seq_len))

# wrong: 1.0/0.0 floats are added to the scores, so 0.0 keeps a token and 1.0 barely changes it
wrong_mask = causal[None, None]

# correct: 0.0 attends, -inf masks
correct_mask = torch.where(causal.bool(), 0.0, float("-inf"))[None, None]
```

La máscara incorrecta conserva todas las posiciones porque `0.0` es el valor que enmascara, por lo que nunca excluye nada.

```text
        wrong_mask                          correct_mask
   (1 attends, 0 masks)              (0 attends, -inf masks)

      k0 k1 k2 k3 k4                     k0   k1   k2   k3   k4
   q0  1  0  0  0  0                  q0  0  -inf -inf -inf -inf
   q1  1  1  0  0  0                  q1  0   0   -inf -inf -inf
   q2  1  1  1  0  0                  q2  0   0    0   -inf -inf
   q3  1  1  1  1  0                  q3  0   0    0    0   -inf
   q4  1  1  1  1  1                  q4  0   0    0    0    0
```

## Atención bidireccional

Los modelos solo decodificador utilizan atención causal (unidireccional) de forma predeterminada, donde cada token solo atiende a sí mismo y a los tokens anteriores. Establezca `is_causal=False` para cambiar a atención bidireccional, donde cada token atiende a todos los demás tokens. Esto le permite utilizar modelos solo decodificador como codificadores de texto, por ejemplo, para generar embeddings.

> [!NOTE]
> Esto solo funciona para modelos causales (decodificadores). No convierte los modelos codificadores en modelos decodificadores.

Establezca `is_causal=False` en la configuración del modelo para que la atención bidireccional sea el valor predeterminado en cada paso de propagación hacia adelante.

```py
from transformers import AutoModel, AutoConfig

config = AutoConfig.from_pretrained("meta-llama/Llama-3.2-1B")
config.is_causal = False

model = AutoModel.from_pretrained("meta-llama/Llama-3.2-1B", config=config)

# all forward passes now use bidirectional attention
outputs = model(**inputs)
```

Pase `is_causal` en la llamada forward en lugar de en la configuración del modelo para alternar entre atención causal y bidireccional sin cargar el modelo dos veces. Este parámetro de palabra clave sobrescribe temporalmente la configuración y se restaura después de la llamada.

```py
from transformers import AutoModel

model = AutoModel.from_pretrained("meta-llama/Llama-3.2-1B")

# run with bidirectional attention
outputs = model(**inputs, is_causal=False)

# run with default causal attention
outputs = model(**inputs)
```

