# ColQwen2

[ColQwen2](https://huggingface.co/papers/2407.01449) es una variante del modelo [ColPali](./colpali) diseñada para recuperar documentos analizando sus características visuales. A diferencia de los sistemas tradicionales que dependen en gran medida de la extracción de texto y del OCR, ColQwen2 trata cada página como una imagen. Utiliza el backbone [Qwen2-VL](./qwen2_vl) para capturar no solo el texto, sino también el diseño, las tablas, los gráficos y otros elementos visuales, con el fin de crear embeddings multivectoriales detallados que pueden usarse para la recuperación mediante el cálculo de puntuaciones de similitud de interacción tardía por pares. Esto ofrece una comprensión más completa de los documentos y permite una recuperación más eficiente y precisa.

Este modelo fue aportado por [@tonywu71](https://huggingface.co/tonywu71) (ILLUIN Technology) y [@yonigozlan](https://huggingface.co/yonigozlan) (HuggingFace).

Puedes encontrar todos los puntos de control originales de ColPali en la colección [Hf-native ColVision Models](https://huggingface.co/collections/vidore/hf-native-colvision-models-6755d68fc60a8553acaa96f7) de Vidore.

> [!TIP]
> Haz clic en los modelos ColQwen2 en la barra lateral derecha para ver más ejemplos de cómo usar ColQwen2 para la recuperación de imágenes.

```python
import requests
import torch
from PIL import Image

from transformers import ColQwen2ForRetrieval, ColQwen2Processor
from transformers.utils.import_utils import is_flash_attn_2_available

# Load the model and the processor
model_name = "vidore/colqwen2-v1.0-hf"

model = ColQwen2ForRetrieval.from_pretrained(
    model_name,
    device_map="auto",  # "cpu", "cuda", "xpu" or "mps" for Apple Silicon
    attn_implementation="flash_attention_2" if is_flash_attn_2_available() else "sdpa",
)
processor = ColQwen2Processor.from_pretrained(model_name)

# The document page screenshots from your corpus
url1 = "https://upload.wikimedia.org/wikipedia/commons/8/89/US-original-Declaration-1776.jpg"
url2 = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4c/Romeoandjuliet1597.jpg/500px-Romeoandjuliet1597.jpg"

images = [
    Image.open(requests.get(url1, stream=True).raw),
    Image.open(requests.get(url2, stream=True).raw),
]

# The queries you want to retrieve documents for
queries = [
    "When was the United States Declaration of Independence proclaimed?",
    "Who printed the edition of Romeo and Juliet?",
]

# Process the inputs
inputs_images = processor(images=images).to(model.device)
inputs_text = processor(text=queries).to(model.device)

# Forward pass
with torch.no_grad():
    image_embeddings = model(**inputs_images).embeddings
    query_embeddings = model(**inputs_text).embeddings

# Score the queries against the images
scores = processor.score_retrieval(query_embeddings, image_embeddings)

print("Retrieval scores (query x image):")
print(scores)
```

Si tienes problemas para cargar las imágenes con PIL, puedes usar el siguiente código para crear imágenes de prueba:

```python
images = [
    Image.new("RGB", (128, 128), color="white"),
    Image.new("RGB", (64, 32), color="black"),
]
```

La cuantización reduce la carga de memoria de los modelos grandes al representar los pesos con una precisión inferior. Consulte el resumen de [Cuantización](../quantization/overview) para conocer más backends de cuantización disponibles.

El ejemplo siguiente utiliza [bitsandbytes](../quantization/bitsandbytes) para cuantizar los pesos a int4.

```python
import requests
import torch
from PIL import Image

from transformers import BitsAndBytesConfig, ColQwen2ForRetrieval, ColQwen2Processor

model_name = "vidore/colqwen2-v1.0-hf"

# 4-bit quantization configuration
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.float16,
)

model = ColQwen2ForRetrieval.from_pretrained(
    model_name,
    quantization_config=bnb_config,
    device_map="auto",
).eval()

processor = ColQwen2Processor.from_pretrained(model_name)

url1 = "https://upload.wikimedia.org/wikipedia/commons/8/89/US-original-Declaration-1776.jpg"
url2 = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4c/Romeoandjuliet1597.jpg/500px-Romeoandjuliet1597.jpg"

images = [
    Image.open(requests.get(url1, stream=True).raw),
    Image.open(requests.get(url2, stream=True).raw),
]

queries = [
    "When was the United States Declaration of Independence proclaimed?",
    "Who printed the edition of Romeo and Juliet?",
]

# Process the inputs
inputs_images = processor(images=images, return_tensors="pt").to(model.device)
inputs_text = processor(text=queries, return_tensors="pt").to(model.device)

# Forward pass
with torch.no_grad():
    image_embeddings = model(**inputs_images).embeddings
    query_embeddings = model(**inputs_text).embeddings

# Score the queries against the images
scores = processor.score_retrieval(query_embeddings, image_embeddings)

print("Retrieval scores (query x image):")
print(scores)
```

También puedes usar puntos de control para `ColQwen2.5` que sean **compatibles con la arquitectura ColQwen2**. Esta versión del modelo utiliza [Qwen2_5_VL](./qwen2_5_vl) como columna vertebral.

```python
from transformers import ColQwen2ForRetrieval, ColQwen2Processor
from transformers.utils.import_utils import is_flash_attn_2_available

model_name = "Sahil-Kabir/colqwen2.5-v0.2-hf" # An existing compatible checkpoint

model = ColQwen2ForRetrieval.from_pretrained(
    model_name,
    device_map="auto",
    attn_implementation="flash_attention_2" if is_flash_attn_2_available() else "sdpa"
)
processor = ColQwen2Processor.from_pretrained(model_name)
```

## Notas

- `score_retrieval()` devuelve un tensor 2D donde la primera dimensión es el número de consultas y la segunda dimensión es el número de imágenes. Una puntuación más alta indica mayor similitud entre la consulta y la imagen.
- A diferencia de ColPali, ColQwen2 admite resoluciones y relaciones de aspecto arbitrarias de las imágenes, lo que significa que las imágenes no se redimensionan en cuadrados de tamaño fijo. Esto preserva más de la señal de entrada original.
- Las imágenes de entrada más grandes generan incrustaciones multivector más largas, lo que permite a los usuarios ajustar la resolución de la imagen para equilibrar el rendimiento y el uso de memoria.

## ColQwen2Config[[transformers.ColQwen2Config]]

#### transformers.ColQwen2Config[[transformers.ColQwen2Config]]

```python
transformers.ColQwen2Config(transformers_version: str | None = None, architectures: list[str] | None = None, output_hidden_states: bool | None = False, return_dict: bool | None = True, dtype: str | torch.dtype | None = None, chunk_size_feed_forward: int = 0, is_encoder_decoder: bool = False, id2label: dict[int, str] | dict[str, str] | None = None, label2id: dict[str, int] | dict[str, str] | None = None, problem_type: Literal['regression', 'single_label_classification', 'multi_label_classification'] | None = None, vlm_config: dict | transformers.configuration_utils.PreTrainedConfig | None = None, embedding_dim: int = 128, initializer_range: float = 0.02)
```

[Fuente](https://github.com/huggingface/transformers/blob/main/src/transformers/models/colqwen2/configuration_colqwen2.py#L28)

**Parámetros:**

vlm_config (`Union[dict, ~configuration_utils.PreTrainedConfig]`, *opcional*) : El objeto de configuración o el diccionario del backbone de visión-lenguaje.

embedding_dim (`int`, *opcional*, valor predeterminado `128`) : Dimensionalidad de los embeddings y los estados ocultos.

initializer_range (`float`, *opcional*, valor predeterminado `0.02`) : La desviación estándar de truncated_normal_initializer para inicializar todas las matrices de pesos.

Esta es la clase de configuración para almacenar la configuración de un Colqwen2Model. Se utiliza para instanciar un modelo Colqwen2 según los argumentos especificados, definiendo la arquitectura del modelo. Instanciar una configuración con los valores predeterminados producirá una configuración similar a la de [vidore/colqwen2-v1.0-hf](https://huggingface.co/vidore/colqwen2-v1.0-hf)

Los objetos de configuración heredan de [PreTrainedConfig](/docs/transformers/main/es/main_classes/configuration#transformers.PreTrainedConfig) y se pueden utilizar para controlar las salidas del modelo. Consulte la documentación de [PreTrainedConfig](/docs/transformers/main/es/main_classes/configuration#transformers.PreTrainedConfig) para obtener más información.

Ejemplo:

```python
from transformers.models.colqwen2 import ColQwen2Config, ColQwen2ForRetrieval

config = ColQwen2Config()
model = ColQwen2ForRetrieval(config)
```

## ColQwen2Processor[[transformers.ColQwen2Processor]]

#### transformers.ColQwen2Processor[[transformers.ColQwen2Processor]]

```python
transformers.ColQwen2Processor(image_processor = None, tokenizer = None, chat_template = None, visual_prompt_prefix: str | None = None, query_prefix: str | None = None, **kwargs)
```

[Fuente](https://github.com/huggingface/transformers/blob/main/src/transformers/models/colqwen2/processing_colqwen2.py#L51)

**Parámetros:**

image_processor (`Qwen2VLImageProcessor`) : El procesador de imágenes es una entrada obligatoria.

tokenizer (`Qwen2Tokenizer`) : El tokenizador es una entrada obligatoria.

chat_template (`str`) : Una plantilla de Jinja para convertir listas de mensajes de un chat en una cadena tokenizable.

visual_prompt_prefix (`str`, *opcional*, valor predeterminado `"<|im_start|>user\n<|vision_start|><|image_pad|><|vision_end|>Describe the image.<|im_end|><|endoftext|>"`) : Una cadena que se tokeniza y se antepone a los tokens de la imagen.

query_prefix (`str`, *opcional*, valor predeterminado `"Query : "`): Un prefijo que se usará para la consulta.

Construye un ColQwen2Processor que envuelve un procesador de imágenes y un tokenizador en un único procesador.

[ColQwen2Processor](/docs/transformers/main/es/model_doc/colqwen2#transformers.ColQwen2Processor) ofrece todas las funcionalidades de [Qwen2VLImageProcessor](/docs/transformers/main/es/model_doc/qwen2_vl#transformers.Qwen2VLImageProcessor) y [Qwen2Tokenizer](/docs/transformers/main/es/model_doc/qwen2#transformers.Qwen2Tokenizer). Consulte [~Qwen2VLImageProcessor](/docs/transformers/main/es/model_doc/qwen2_vl#transformers.Qwen2VLImageProcessor) y [~Qwen2Tokenizer](/docs/transformers/main/es/model_doc/qwen2#transformers.Qwen2Tokenizer) para obtener más información.

#### __llamada__[[transformers.ColQwen2Processor.__call__]]

```python
__call__(images: typing.Union[ForwardRef('PIL.Image.Image'), numpy.ndarray, ForwardRef('torch.Tensor'), list['PIL.Image.Image'], list[numpy.ndarray], list['torch.Tensor'], NoneType] = None, text: str | list[str] | list[list[str]] = None, **kwargs: *<class 'transformers.models.colqwen2.processing_colqwen2.ColQwen2ProcessorKwargs'>)
```

[Fuente](https://github.com/huggingface/transformers/blob/main/src/transformers/models/colqwen2/processing_colqwen2.py#L77)

**Parámetros:**

images (`Union[PIL.Image.Image, numpy.ndarray, torch.Tensor, list[PIL.Image.Image], list[numpy.ndarray], list[torch.Tensor]]`, *opcional*) : Imagen para preprocesar. Espera una imagen única o un lote de imágenes con valores de píxeles que van de 0 a 255. Si se pasan imágenes con valores de píxeles entre 0 y 1, establezca `do_rescale=False`.

text (`Union[str, list[str], list[list[str]]]`, *opcional*) : La secuencia o el lote de secuencias que se van a codificar. Cada secuencia puede ser una cadena de caracteres o una lista de cadenas (cadena pretokenizada). Si se pasa una entrada pretokenizada, establezca `is_split_into_words=True` para evitar ambigüedad con las entradas en lote.

return_tensors (`str` o [TensorType](/docs/transformers/main/es/internal/file_utils#transformers.TensorType), *opcional*) : Si se establece, devolverá tensores de un marco de trabajo específico. Los valores aceptables son:  - `'pt'`: Devuelve objetos `torch.Tensor` de PyTorch. - `'np'`: Devuelve objetos `np.ndarray` de NumPy.

- ****kwargs** ([ProcessingKwargs](/docs/transformers/main/es/main_classes/processors#transformers.ProcessingKwargs), *opcional*) : Opciones de procesamiento adicionales para cada modalidad (texto, imágenes, vídeos, audio). Los parámetros específicos del modelo se enumeran arriba; consulte la clase TypedDict para obtener la lista completa de argumentos admitidos.

**Devuelve:** [BatchFeature](/docs/transformers/main/es/main_classes/feature_extractor#transformers.BatchFeature)

Un [BatchFeature](/docs/transformers/main/es/main_classes/feature_extractor#transformers.BatchFeature) con los siguientes campos:

- **input_ids** -- Lista de ids de tokens que se enviarán a un modelo. Se devuelve cuando `text` no es `None`. Si se proporciona `suffix`, `input_ids` también contendrá los ids de entrada del sufijo.
- **attention_mask** -- Lista de índices que especifica qué tokens deben ser atendidos por el modelo (cuando `return_attention_mask=True` o si *"attention_mask"* está en `self.model_input_names` y si `text` no es `None`).
- **pixel_values** -- Valores de píxeles que se enviarán a un modelo. Se devuelve cuando `images` no es `None`.
- **labels** -- Etiquetas compatibles con el entrenamiento si `suffix` no es None

## ColQwen2ForRetrieval[[transformers.ColQwen2ForRetrieval]]

#### transformers.ColQwen2ForRetrieval[[transformers.ColQwen2ForRetrieval]]

```python
transformers.ColQwen2ForRetrieval(config: ColQwen2Config)
```

[Fuente](https://github.com/huggingface/transformers/blob/main/src/transformers/models/colqwen2/modeling_colqwen2.py#L92)

**Parámetros:**

config ([ColQwen2Config](/docs/transformers/main/es/model_doc/colqwen2#transformers.ColQwen2Config)) : Clase de configuración del modelo con todos los parámetros del modelo. Inicializar con un archivo de configuración no carga los pesos asociados con el modelo, solo la configuración. Consulte el método [from_pretrained()](/docs/transformers/main/es/main_classes/model#transformers.PreTrainedModel.from_pretrained) para cargar los pesos del modelo.

Siguiendo el enfoque de ColPali, ColQwen2 aprovecha los VLM para construir embeddings multivectoriales eficientes directamente a partir de imágenes de documentos («capturas de pantalla») para la recuperación de documentos. El modelo se entrena para maximizar la similitud entre estos embeddings de documentos y los embeddings de consulta correspondientes, utilizando el método de interacción tardía introducido en ColBERT.

El uso de ColQwen2 elimina la necesidad de pipelines de reconocimiento de diseño y OCR que pueden ser complejos y frágiles, mediante un único modelo que puede tener en cuenta tanto el contenido textual como el visual (diseño, gráficos, ...) de un documento.

ColQwen2 forma parte de la familia de modelos ColVision, que se presentó con ColPali en el siguiente artículo: [*ColPali: Efficient Document Retrieval with Vision Language Models*](https://huggingface.co/papers/2407.01449).

Este modelo hereda de [PreTrainedModel](/docs/transformers/main/es/main_classes/model#transformers.PreTrainedModel). Consulte la documentación de la clase superior para los métodos genéricos que la biblioteca implementa para todos sus modelos (como la descarga o el guardado, el redimensionamiento de las incrustaciones de entrada, la poda de cabezas, etc.).

Este modelo también es una subclase de [torch.nn.Module](https://pytorch.org/docs/stable/nn.html#torch.nn.Module) de PyTorch. Úsalo como un módulo de PyTorch regular y consulta la documentación de PyTorch para todo lo relacionado con el uso y el comportamiento generales.

#### forward[[transformers.ColQwen2ForRetrieval.forward]]

```python
forward(input_ids: typing.Optional[torch.LongTensor] = None, attention_mask: typing.Optional[torch.Tensor] = None, position_ids: typing.Optional[torch.LongTensor] = None, past_key_values: transformers.cache_utils.Cache | None = None, labels: typing.Optional[torch.LongTensor] = None, inputs_embeds: typing.Optional[torch.Tensor] = None, use_cache: bool | None = None, output_attentions: bool | None = None, output_hidden_states: bool | None = None, return_dict: bool | None = None, pixel_values: typing.Optional[torch.Tensor] = None, image_grid_thw: typing.Optional[torch.LongTensor] = None, **kwargs)
```

[Fuente](https://github.com/huggingface/transformers/blob/main/src/transformers/models/colqwen2/modeling_colqwen2.py#L106)

**Parámetros:**

input_ids (`torch.LongTensor` de forma `(batch_size, sequence_length)`, *opcional*) : Índices de los tokens de la secuencia de entrada en el vocabulario. El relleno se ignorará de forma predeterminada. Los índices se pueden obtener mediante [AutoTokenizer](/docs/transformers/main/es/model_doc/auto#transformers.AutoTokenizer). Consulte [PreTrainedTokenizer.encode()](/docs/transformers/main/es/internal/tokenization_utils#transformers.PreTrainedTokenizerBase.encode) y [PreTrainedTokenizer.__call__()](/docs/transformers/main/es/internal/tokenization_utils#transformers.PreTrainedTokenizerBase.__call__) para obtener más detalles. [¿Qué son los IDs de entrada?](../glossary#input-ids)

attention_mask (`torch.Tensor` de forma `(batch_size, sequence_length)`, *opcional*) : Máscara para evitar realizar atención en los índices de tokens de relleno. Valores de la máscara seleccionados en `[0, 1]`:  - 1 para tokens que **no están enmascarados**, - 0 para tokens que **están enmascarados**.  [¿Qué son las máscaras de atención?](../glossary#attention-mask)

position_ids (`torch.LongTensor` de forma `(batch_size, sequence_length)`, *opcional*) : Índices de las posiciones de los tokens de cada secuencia de entrada en las incrustaciones de posición. Seleccionados en el rango `[0, config.n_positions - 1]`.  [¿Qué son los IDs de posición?](../glossary#position-ids)

past_key_values (`~cache_utils.Cache`, *opcional*) : Estados ocultos precalculados (claves y valores en los bloques de autoatención y en los bloques de atención cruzada) que se pueden utilizar para acelerar la decodificación secuencial. Esto suele consistir en los `past_key_values` devueltos por el modelo en una etapa anterior de la decodificación, cuando `use_cache=True` o `config.use_cache=True`.  Solo se permite una instancia de [Cache](/docs/transformers/main/es/internal/generation_utils#transformers.Cache) como entrada, consulte nuestra [guía de caché kv](https://huggingface.co/docs/transformers/en/kv_cache). Si no se pasan `past_key_values`, se inicializará [DynamicCache](/docs/transformers/main/es/internal/generation_utils#transformers.DynamicCache) de forma predeterminada.  El modelo devolverá el mismo formato de caché que se haya proporcionado como entrada.  Si se utilizan `past_key_values`, se espera que el usuario introduzca solo los `input_ids` no procesados (aquellos que no tienen sus estados de clave y valor previos dados a este modelo) con forma `(batch_size, unprocessed_length)` en lugar de todos los `input_ids` con forma `(batch_size, sequence_length)`.

labels (`torch.LongTensor` de forma `(batch_size, sequence_length)`, *opcional*) : Etiquetas para calcular la pérdida de modelado de lenguaje enmascarado. Los índices deben estar en `[0, ..., config.vocab_size]` o ser -100 (consulte la docstring de `input_ids`). Los tokens con índices fijados en `-100` se ignoran (se enmascaran); la pérdida solo se calcula para los tokens con etiquetas en `[0, ..., config.vocab_size]`.

inputs_embeds (`torch.Tensor` de forma `(batch_size, sequence_length, hidden_size)`, *opcional*) : Opcionalmente, en lugar de pasar `input_ids`, puedes elegir pasar directamente una representación incrustada. Esto es útil si deseas tener más control sobre cómo convertir los índices de `input_ids` en los vectores asociados que en la matriz de búsqueda de incrustaciones interna del modelo.

use_cache (`bool`, *opcional*) : Si se establece en `True`, se devuelven los estados de valores clave `past_key_values` y pueden usarse para acelerar la decodificación (ver `past_key_values`).

output_attentions (`bool`, *opcional*) : Indica si se deben devolver los tensores de atención de todas las capas de atención. Consulte `attentions` en los tensores devueltos para obtener más detalles.

output_hidden_states (`bool`, *opcional*) : Indica si se deben devolver los estados ocultos de todas las capas. Consulte `hidden_states` en los tensores devueltos para obtener más detalles.

return_dict (`bool`, *opcional*) : Indica si se debe devolver un [ModelOutput](/docs/transformers/main/es/main_classes/output#transformers.utils.ModelOutput) en lugar de una tupla simple.

pixel_values (`torch.Tensor` de forma `(batch_size, num_channels, image_size, image_size)`, *opcional*) : Los tensores correspondientes a las imágenes de entrada. Los valores de píxeles se pueden obtener usando [Qwen2VLImageProcessor](/docs/transformers/main/es/model_doc/qwen2_vl#transformers.Qwen2VLImageProcessor). Consulte [Qwen2VLImageProcessor.__call__()](/docs/transformers/main/es/model_doc/molmo2#transformers.Molmo2ImageProcessor.__call__) para obtener más detalles ([ColQwen2Processor](/docs/transformers/main/es/model_doc/colqwen2#transformers.ColQwen2Processor) utiliza [Qwen2VLImageProcessor](/docs/transformers/main/es/model_doc/qwen2_vl#transformers.Qwen2VLImageProcessor) para procesar las imágenes).

image_grid_thw (`torch.LongTensor` de forma `(num_images, 3)`, *opcional*) : La dimensión temporal, la altura y el ancho de la forma de las características de cada imagen en el LLM.

**Devuelve:** `ColQwen2ForRetrievalOutput` o `tuple(torch.Tensor)`

Un `ColQwen2ForRetrievalOutput` o una tupla de `torch.Tensor` (si se pasa `return_dict=False` o cuando `config.return_dict=False`) que comprende varios elementos según la configuración ([ColQwen2Config](/docs/transformers/main/es/model_doc/colqwen2#transformers.ColQwen2Config)) y las entradas.

El método forward de [ColQwen2ForRetrieval](/docs/transformers/main/es/model_doc/colqwen2#transformers.ColQwen2ForRetrieval) sobrescribe el método especial `__call__`.

Aunque la receta para la pasada hacia adelante debe definirse dentro de esta función, se debe llamar a la instancia de `Module` después, en lugar de a esta, ya que la primera se encarga de ejecutar los pasos de preprocesamiento y posprocesamiento, mientras que la segunda los ignora silenciosamente.

- **loss** (`torch.Tensor` de forma `(1,)`, *opcional*, se devuelve cuando se proporciona `labels`) -- Pérdida de modelado de lenguaje (para la predicción del siguiente token).
- **embeddings** (`torch.Tensor` de forma `(batch_size, sequence_length, hidden_size)`) -- Las embeddings del modelo.
- **past_key_values** (`Cache`, *opcional*, se devuelve cuando se pasa `use_cache=True` o cuando `config.use_cache=True`) -- Es una instancia de [Cache](/docs/transformers/main/es/internal/generation_utils#transformers.Cache). Para más detalles, consulte nuestra [guía de caché kv](https://huggingface.co/docs/transformers/en/kv_cache).

  Contiene estados ocultos precalculados (claves y valores en los bloques de autoatención) que pueden utilizarse (véase la entrada `past_key_values`) para acelerar la decodificación secuencial.
- **hidden_states** (`tuple[torch.Tensor]`, *opcional*, se devuelve cuando se pasa `output_hidden_states=True` o cuando `config.output_hidden_states=True`) -- Tupla de `torch.Tensor` (una para la salida de las incrustaciones, si el modelo tiene una capa de incrustaciones, + una para la salida de cada capa) de forma `(batch_size, sequence_length, hidden_size)`.

  Estados ocultos del modelo en la salida de cada capa más las salidas opcionales de la incrustación inicial.
- **attentions** (`tuple[torch.Tensor]`, *opcional*, se devuelve cuando se pasa `output_attentions=True` o cuando `config.output_attentions=True`) -- Tupla de `torch.Tensor` (una por cada capa) de forma `(batch_size, num_heads, sequence_length, sequence_length)`.

  Pesos de atención tras el softmax de atención, utilizados para calcular la media ponderada en las cabezas de autoatención.

Ejemplo:

```python
```

