# واجهات الخلفية للانتباه

تنفّذ جميع تطبيقات الانتباه (Attention) نفس العملية الحسابية. يُقارن كل رمز (Token) بكل رمز آخر. الفارق يكمن في *كيف* تُنفَّذ هذه العملية الحسابية. يعاني تطبيق الانتباه الأساسي من ضعف التوسع لأنه يُنشئ مصفوفة الانتباه الكاملة في الذاكرة، مما يُسبب اختناقات تُبطئ الاستدلال (Inference). تُعيد التطبيقات المُحسَّنة ترتيب العمليات الرياضية لتقليل حركة البيانات في الذاكرة، مما يؤدي إلى استدلال أسرع وأكثر ملاءمة من حيث التكلفة.

توفر [AttentionInterface](/docs/transformers/main/ar/internal/modeling_utils#transformers.AttentionInterface) تطبيقات مُحسّنة للانتباه. إنها تفصل تطبيق الانتباه عن تطبيق النموذج لتبسيط التجارب مع دوال مختلفة. أضف واجهات خلفية جديدة بسهولة باستخدام هذه الواجهة المتسقة.

واجهة الانتباه الوصفية "flash_attention_3" تحسّن FlashAttention-2 من خلال تداخل العمليات أيضًا، ودمج مساري الأمامي والخلفي بشكل أكثر إحكامًا "flash_attention_2" يقسّم الحسابات إلى كتل أصغر ويستخدم ذاكرة سريعة على الشريحة "flex_attention" إطار عمل لتحديد أنماط انتباه مخصصة (متناثرة، محلية للكتل، نافذة منزلقة) دون كتابة نوى منخفضة المستوى يدويًا "sdpa" تنفيذ PyTorch المدمج للانتباه بنقطة الضرب المُقَيَّسة "paged&#124;flash_attention_3" نسخة Paged من FlashAttention-3 "paged&#124;flash_attention_2" نسخة Paged من FlashAttention-2 "paged&#124;sdpa" نسخة Paged من SDPA "paged&#124;eager" نسخة Paged من eager

## تعيين واجهة خلفية للانتباه

استخدم الحجة `attn_implementation` في [from_pretrained()](/docs/transformers/main/ar/main_classes/model#transformers.PreTrainedModel.from_pretrained) لإنشاء نموذج مع دالة انتباه محددة.

```py
import torch
from transformers import AutoModelForCausalLM

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

يمكنك التبديل بين محركات الانتباه في وقت التشغيل دون إعادة تحميل النموذج باستخدام [set_attn_implementation()](/docs/transformers/main/ar/main_classes/model#transformers.PreTrainedModel.set_attn_implementation).

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

### النوى

قم بتنزيل نوى الحساب المُجمّعة وتحميلها مباشرةً من [Hub](https://huggingface.co/models?other=kernels) وقت التشغيل باستخدام مكتبة [Kernels](https://huggingface.co/docs/kernels/index). وهذا يتجنّب مشاكل التغليف الناتجة عن عدم تطابق إصدارات PyTorch أو CUDA.

تُسجَّل النوى تلقائيًا في [AttentionInterface](/docs/transformers/main/ar/internal/modeling_utils#transformers.AttentionInterface) عند اكتشافها. لا حاجة إلى تثبيت حزمة FlashAttention صراحةً. كما أن طلب FlashAttention بالاسم يؤدي إلى الرجوع إلى نواة Hub، راجع [الرجوع إلى FlashAttention](./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"
)
```

### مدير سياق SDPA

يختار منتج PyTorch الخاص بالانتباه بنقطة الضرب المُقيّمة (SDPA) تلقائيًا أسرع دالة انتباه لخوادم CUDA. أما للخوادم الأخرى، فيعتمد افتراضيًا على التنفيذ بلغة C++ في PyTorch.

فرض استخدام SDPA لتنفيذ محدد من خلال مدير السياق [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)
```

## انتباه محدد لكل هيكل

تستخدم النماذج متعددة الوسائط هياكل أساسية مختلفة لكل نمط. لتحسين الأداء، قم بتخصيص دوال انتباه محددة لكل هيكل أساسي. فبعض الهياكل الأساسية للرؤية تعمل بشكل أفضل في fp32، على سبيل المثال، وهو ما لا تدعمه FlashAttention.

يمكنك تعيين هياكل الرؤية الأساسية إلى دوال انتباه مختلفة باستخدام قاموس، بينما يستمر هيكل النص الأساسي في استخدام FlashAttention. يجب أن تتطابق المفاتيح في تطبيق الانتباه مع أسماء التكوينات الفرعية.

```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
)
```

احذف بعض الهياكل الأساسية من القاموس لاستخدام دالة الانتباه الافتراضية (SDPA).

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

اضبط دالة الانتباه نفسها لجميع الهياكل الأساسية باستخدام سلسلة واحدة.

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

اضبط دالة الانتباه على مستوى النظام باستخدام مفتاح فارغ.

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

## إنشاء دالة انتباه جديدة

يمكنك تخصيص دوال الانتباه أو إنشاء دوال جديدة عن طريق إضافتها إلى سجل الانتباه باستخدام [AttentionInterface.register()](/docs/transformers/main/ar/internal/modeling_utils#transformers.AttentionInterface.register). تستخدم النماذج هذه الدوال عبر الحجة `attn_implementation`.

> [!WARNING]  
> سجّل دالة قناع انتباه مطابقة عند تسجيل دالة انتباه مخصصة. إذا لم يكن اسم `attn_implementation` المخصص مسجلاً في [AttentionMaskInterface](/docs/transformers/main/ar/internal/modeling_utils#transformers.AttentionMaskInterface)، يتخطى Transformers إنشاء القناع ويمرر `attention_mask=None` إلى طبقات الانتباه. يجب أن تتعامل دالة الانتباه الخاصة بك بنفسها مع قيود السببية، أو الحشو، أو التعبئة، أو النافذة المنزلقة، وإلا فقد تُهمل تلك القيود بصمت.

يخصص هذا المثال دالة الانتباه لطباعة عبارة لكل طبقة. كما يحافظ على القناع في التنفيذ الأصلي عن طريق تسجيل `masking_utils.sdpa_mask` كدالة قناع الانتباه.

```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))
```

يمكنك أيضاً إضافة حُجج جديدة إلى دالة الانتباه. النماذج التي تدعم [AttentionInterface](/docs/transformers/main/ar/internal/modeling_utils#transformers.AttentionInterface) تنقل الحُجج الإضافية (kwargs) إلى طبقات الانتباه ودالة الانتباه. مرّر الحُجج كحُجج إضافية (kwargs) في دالة الأمامية (forward) للنموذج. يجب أن تتبع دوال الانتباه المخصصة هذا التوقيع (signature) وصيغة الإرجاع.

```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=...)
```

تحقّق من [كود النمذجة](https://github.com/huggingface/transformers/tree/main/src/transformers/models) للنموذج للتأكد من الحجج وkwargs التي يرسلها إلى دالة الانتباه.

## AttentionMaskInterface

[AttentionMaskInterface](/docs/transformers/main/ar/internal/modeling_utils#transformers.AttentionMaskInterface) هو السجل الذي تستشير منه دوال [`create_*_mask`](#build-an-attention-mask) لتحويل القناع إلى الصيغة التي يتوقعها مُنفّذ الانتباه النشط. يحتاج FlexAttention إلى [BlockMask](https://docs.pytorch.org/docs/stable/nn.attention.flex_attention.html#torch.nn.attention.flex_attention.BlockMask)، ويحتاج SDPA إلى متجه رباعي الأبعاد، ويحتاج FlashAttention إلى قناع الحشو الأساسي ثنائي الأبعاد. سجّل مُنفّذًا مخصصًا، أو تجاوز مُنسّق مُنفّذ قائم، باستخدام [AttentionMaskInterface.register()](/docs/transformers/main/ar/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)
```

في حال عدم وجود مُنسّق مسجّل لـ`attn_implementation` النشط، يتم تجاوز إنشاء القناع، ويمرّ `attention_mask=None` إلى طبقات الانتباه.

يجب أن تتطابق الدوال المسجّلة مع هذا التوقيع.

```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]:
```

الحجة `mask_function` هي `Callable` تحاكي دوال [mask_mod](https://pytorch.org/blog/flexattention/) في PyTorch. تستقبل 4 فهارس `(batch_idx, head_idx, q_idx, kv_idx)` وتعيد قيمة منطقية تشير إلى ما إذا كانت تلك الموضع تساهم في حساب الانتباه. هذا هو الشكل الأساسي نفسه المستخدم في `or_mask_function` و`and_mask_function` في [بناء قناع الانتباه](#build-an-attention-mask).

> [!TIP]
> استخدم هذا [الحل البديل](https://github.com/huggingface/transformers/blob/main/src/transformers/integrations/executorch.py) لـ torch.export إذا فشل `mask_function` في إنشاء قناع.

## إنشاء قناع الانتباه

أنشئ أقنعة الانتباه باستخدام دوال `create_*_mask` في [transformers.masking_utils](https://github.com/huggingface/transformers/blob/main/src/transformers/masking_utils.py#L894). تقرأ كل دالة واجهة الانتباه النشطة من إعدادات النموذج، وتبحث عن مُنسّق القناع الخاص بالواجهة في [AttentionMaskInterface](/docs/transformers/main/ar/internal/modeling_utils#transformers.AttentionMaskInterface)، ثم تُرجع التنسيق الذي تتوقعه تلك الواجهة. لا حاجة منك إلى قلب القناع أو توسيعه أو تحويل نوعه بنفسك.

اختر الدالة التي تتطابق مع نمط الانتباه.

| function | حالة الاستخدام |
|---|---|
| `create_causal_mask` | نماذج فك الترميز فقط حيث يهتم كل رمز بنفسه وبالرموز السابقة |
| `create_bidirectional_mask` | نماذج المُشفِّرات، أو الانتباه المتقاطع من المُفكِّك إلى حالات المُشفِّر |
| `create_sliding_window_causal_mask` | نماذج فك الترميز التي تستخدم نمط انتباه بنافذة منزلقة |
| `create_chunked_causal_mask` | نماذج فك الترميز التي تقسم التسلسل إلى كتل ذات حجم ثابت |
| `create_bidirectional_sliding_window_mask` | نماذج المُشفِّر التي تستخدم نمط انتباه بنافذة منزلقة |

> [!WARNING]
> تُصدر دوال الأقنعة القابلة للاستدعاء القديمة - `get_extended_attention_mask`، `create_extended_attention_mask_for_decoder`، `invert_attention_mask` - تحذيرًا بالإيقاف، وسيتم إزالتها في إصدار مستقبلي. استخدم دوال `create_*_mask` بدلاً من ذلك.

استدعِ `create_causal_mask` داخل مسار الترميز الأمامي (forward pass) في المُفكِّك (decoder). مرِّر الإعدادات (config)، وتضمينات الإدخال (input embeddings)، وقناع الانتباه ثنائي الأبعاد `attention_mask` الذي يوفّره المستخدم، والكاش (cache). تستخدم الدالة التضمينات لقراءة حجم الدفعة (batch size)، وطول الاستعلام (query length)، ونوع البيانات (dtype)، والجهاز (device)، وتستخدم الكاش لحساب طول المفتاح (key length).

```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,
)
```

استدعِ `create_bidirectional_mask` لانتباه المُشفِّر الذاتي. احذفي `past_key_values` لأن المُشفِّرات لا تُخزّن.

```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,
)
```

بالنسبة لانتباه التقاطع، مرّر حالات المُشفِّر كـ `encoder_hidden_states` حتى يستخدم القناع طول المفتاح والقيمة الخاصين بالمُشفِّر بدلاً من طول الاستعلام الخاص بالمُفكِّك.

```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,
)
```

أضِف قيودًا إضافية فوق القناع الأساسي باستخدام الحُجج `or_mask_function` و`and_mask_function`. استخدم `or_mask_function` للسماح لمواقع إضافية بالمشاركة، و`and_mask_function` لتقييد النمط الأساسي بشكل أكبر. يتبع كلاهما توقيع `mask_function` ذي الفهارس الأربعة الموصوف في [AttentionMaskInterface](#attentionmaskinterface). تستقبل `(batch_idx, head_idx, q_idx, kv_idx)` وتعيد قيمة منطقية.

> [!WARNING]
> يمكن للدالتين `or_mask_function` و`and_mask_function` التعبير عن أي نمط انتباه، لكنهما أبطأ من الأنماط المدمجة وغير متوافقتين مع ExecuTorch. يكون هذا العبء ملحوظاً بشكل أكبر في النماذج الأصغر (~200 مليون معامل)، حيث يستهلك إنشاء القناع حصة أكبر من زمن المرور الأمامي. لا تلجأ إليهما إلا عندما لا تستطيع دوال `create_*_mask` القياسية التعبير عما تحتاجه.

على سبيل المثال، يمكن تراكب دالة تُرجع `True` في كل مكان على قناع سببي لتحويله إلى قناع ثنائي الاتجاه بالكامل. يسمح الاتحاد مع النمط السببي لكل رمز بالانتباه إلى كل رمز آخر.

```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)
```

أثناء التوليد، يبني [generate()](/docs/transformers/main/ar/main_classes/text_generation#transformers.GenerationMixin.generate) الأقنعة عبر `create_masks_for_generate`، والذي يوجّه الطلب إلى `create_*_mask` المناسب بناءً على إعدادات النموذج. قم بتجاوز هذه الدالة في فئة النموذج لتضمين استراتيجية قناع مخصصة للتوليد.

## مرر قناع انتباه مخصص بأربعة أبعاد

مرّر قناعًا رباعي الأبعاد (4D) خاصًا بك عندما تحتاج إلى نمط انتباه لا تستطيع دوال `create_*_mask` التعبير عنه. يكون شكل القناع الرباعي الأبعاد `(batch_size, 1, query_length, kv_length)`، حيث يُبثّ `1` نفس القناع عبر جميع رؤوس الانتباه. يكتشف Transformers القناع ويستخدمه كما هو، متجاوزًا `create_*_mask`.

تستخدم قناع رباعي الأبعاد (4D) أحد نظامَي قيمتين.

| dtype | حضور | إخفاء |
|---|---|---|
| boolean | `True` | `False` |
| float | `0.0` | `-inf` |

تضيف اتفاقية float القناع إلى درجات الانتباه قبل softmax. تبقى الدرجة المضافة إليها `0.0` دون تغيير، وبالتالي يساهم الموقع. أما الدرجة المضافة إليها `-inf` فتصبح صفرًا بعد softmax، وبالتالي يُستبعد الموقع.

> [!IMPORTANT]
> تعتمد الاتفاقية المقبولة على واجهة معالجة الانتباه. يقبل `sdpa` قناعاً من نوع boolean أو float. يضيف `eager` القناع إلى الدرجات، لذا يقبل قناعاً من نوع float فقط. تستهلك `flash_attention_2` و`flex_attention` صيغها الخاصة (قناع padding ثنائي الأبعاد و[BlockMask](https://docs.pytorch.org/docs/stable/nn.attention.flex_attention.html#torch.nn.attention.flex_attention.BlockMask)) ولا تقبل قناعاً خاماً رباعي الأبعاد.

خطأ شائع هو إعادة استخدام اتفاقية `1`/`0` الخاصة بقناع الحشو ثنائي الأبعاد في قناع عائم رباعي الأبعاد. وبما أن القناع يُضاف إلى الدرجات، فإن `0.0` يحافظ على الموضع، بينما `1.0` يضيف انحيازًا صغيرًا فقط.

يُبيّن المثال أدناه تباينًا بين قناع خاطئ وقناع صحيح. كلاهما يبدأ من نفس النمط السببي `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]
```

يُبقي القناع الخاطئ على كل المواضع لأن `0.0` هو القيمة التي تُستخدم للإخفاء، لذا لا يستثني شيئًا أبدًا.

```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
```

## انتباه ثنائي الاتجاه

تستخدم نماذج المُفكِّك فقط (Decoder-only) الانتباه السببي (أحادي الاتجاه) افتراضيًا، حيث ينتبه كل رمز إلى نفسه وإلى الرموز السابقة فقط. اضبط `is_causal=False` للتبديل إلى الانتباه ثنائي الاتجاه، حيث ينتبه كل رمز إلى كل رمز آخر. يتيح لك ذلك استخدام نماذج المُفكِّك فقط كمُشفِّرات للنص، على سبيل المثال، لتوليد التضمينات (embeddings).

> [!NOTE]
> يعمل هذا فقط مع النماذج السببية (فكّ الترميز). إنه لا يحوّل نماذج الترميز إلى نماذج فكّ ترميز.

اضبط `is_causal=False` في إعدادات النموذج لجعل الانتباه ثنائي الاتجاه هو الافتراضي لكل تمريرة أمامية.

```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)
```

مرّر `is_causal` في استدعاء forward بدلاً من إعدادات النموذج للتبديل بين الانتباه السببي والانتباه ثنائي الاتجاه دون الحاجة إلى تحميل النموذج مرتين. يتجاوز هذا المعامل مؤقتًا الإعدادات ثم يُعاد ضبطها بعد انتهاء الاستدعاء.

```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)
```

