# استراتيجيات التخزين المؤقت

تُستخدم متجهات المفتاح-القيمة (KV) لحساب درجات الانتباه. بالنسبة للنماذج التوليدية الذاتية، تُحسب درجات KV *في كل مرة* لأن النموذج يتنبأ برمز واحد في كل مرة. يعتمد كل تنبؤ على الرموز السابقة، مما يعني أن النموذج يؤدي نفس العمليات الحسابية في كل مرة.

تُخزّن ذاكرة *cache* هذه الحسابات حتى يمكن إعادة استخدامها دون الحاجة إلى إعادة حسابها. يُعدّ التخزين المؤقت الفعّال أمراً بالغ الأهمية لتحسين أداء النموذج، لأنه يقلّل من زمن الحساب ويزيد من معدلات الاستجابة. للاطلاع على شرح أكثر تفصيلاً حول آلية عمل ذاكرة التخزين المؤقت، راجع وثيقة [Caching](./cache_explanation).

توفر مكتبة Transformers عدة فئات [Cache](/docs/transformers/main/ar/internal/generation_utils#transformers.Cache) تنفّذ آليات تخزين مؤقت مختلفة. بعض فئات [Cache](/docs/transformers/main/ar/internal/generation_utils#transformers.Cache) هذه مُحسّنة لتوفير الذاكرة، بينما صُمّمت فئات أخرى لتعظيم سرعة التوليد. راجع الجدول أدناه لمقارنة أنواع التخزين المؤقت، واستخدمه للمساعدة في اختيار أفضل تخزين مؤقت يناسب حالتك الاستخدامية.

| نوع الكاش             | يدعم طبقات الانزلاق  | يدعم تفريغ الأحمال | يدعم torch.compile() | الاستهلاك المتوقع للذاكرة |
|------------------------|--------------------------|---------------------|--------------------------|-----------------------|
| ذاكرة التخزين المؤقت الديناميكية          |           نعم            |          نعم        |           لا             |         متوسط        |
| الذاكرة المؤقتة الثابتة           |           نعم            |          نعم        |           نعم            |         مرتفع          |
| الذاكرة المؤقتة المُكمّاة        |           لا             |          لا         |           لا             |         منخفض           |

يُعرّفك هذا الدليل على فئات [Cache](/docs/transformers/main/ar/internal/generation_utils#transformers.Cache) المختلفة ويوضح لك كيفية استخدامها للتوليد.

## الذاكرة المؤقتة الافتراضية

يُعدّ [DynamicCache](/docs/transformers/main/ar/internal/generation_utils#transformers.DynamicCache) فئة التخزين المؤقت الافتراضية لجميع النماذج. فهو يتيح للتخزين المؤقت أن ينمو ديناميكيًا من أجل تخزين عدد متزايد من المفاتيح والقيم مع تقدم عملية التوليد.

لاحظ أنه في النماذج التي تستخدم انتباه النافذة المنزلقة (Mistral, Gemma2,...) أو الانتباه المقطعي (Llama4)، سيتوقف نمو الكاش عندما تصل الطبقات التي تستخدم هذه الأنواع من الانتباه إلى حجمها الأقصى (حجم النافذة المنزلقة أو حجم المقطع).

عطّل ذاكرة التخزين المؤقت من خلال ضبط `use_cache=False` في [generate()](/docs/transformers/main/ar/main_classes/text_generation#transformers.GenerationMixin.generate).

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

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-chat-hf")
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-chat-hf", dtype=torch.float16, device_map="auto")
inputs = tokenizer("I like rock music because", return_tensors="pt").to(model.device)

model.generate(**inputs, do_sample=False, max_new_tokens=20, use_cache=False)
```

يمكن أيضًا تهيئة فئات الكاش (Cache) أولاً قبل استدعاء النموذج ومرورها إلى معامل [past_key_values](/docs/transformers/main/ar/internal/generation_utils#transformers.generation.GenerateDecoderOnlyOutput.past_key_values). وقد يكون ذلك مفيدًا للحصول على تحكم أدق، أو لاستخدامات متقدمة مثل كاش السياق.

في معظم الحالات، يكون من الأسهل تحديد استراتيجية التخزين المؤقت في معامل [cache_implementation](/docs/transformers/main/ar/main_classes/text_generation#transformers.GenerationConfig.cache_implementation).

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

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-chat-hf")
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-chat-hf", dtype=torch.float16, device_map="auto")
inputs = tokenizer("I like rock music because", return_tensors="pt").to(model.device)

past_key_values = DynamicCache(config=model.config)
out = model.generate(**inputs, do_sample=False, max_new_tokens=20, past_key_values=past_key_values)
```

## ذاكرة مؤقتة ذات حجم ثابت

يمنعك [DynamicCache](/docs/transformers/main/ar/internal/generation_utils#transformers.DynamicCache) الافتراضي من الاستفادة من معظم تحسينات الترجمة الفورية (JIT) لأن حجم ذاكرة التخزين المؤقت غير ثابت. تتيح لك تحسينات JIT تقليل زمن الاستجابة على حساب استهلاك الذاكرة. جميع أنواع ذاكرة التخزين المؤقت التالية متوافقة مع تحسينات JIT مثل [torch.compile](./perf_torch_compile) لتسريع عملية التوليد.

يخصص مخزن ذو حجم ثابت ([StaticCache](/docs/transformers/main/ar/internal/generation_utils#transformers.StaticCache)) حداً أقصى محدداً مسبقاً لحجم المخزن لزوجات kv. يمكنك توليد ما يصل إلى الحد الأقصى لحجم المخزن دون الحاجة إلى تعديله. ومع ذلك، فإن وجود حجم ثابت (عادةً كبير) لحالات المفتاح/القيمة يعني أنه أثناء التوليد، سيتم إخفاء عدد كبير من الرموز فعلياً لأنها لا ينبغي أن تشارك في الانتباه. لذا يسمح هذا الحيلة بسهولة `compile` مرحلة فك الترميز، لكنه يتسبب في هدر الرموز في حساب الانتباه. وككل الأمور، فإن الأمر يتعلق بمفاضلة، وهي ستكون جيدة جداً إذا كنت تولد باستخدام عدة تسلسلات بطول متساوٍ تقريباً، لكنها قد تكون غير مثالية إذا كان لديك على سبيل المثال تسلسل كبير جداً، ثم تسلسلات قصيرة فقط (لأن حجم المخزن الثابت سيكون كبيراً، فسيتم هدر الكثير للتسلسلات القصيرة). تأكد من فهم الأثر إذا كنت تستخدمه!

أما بالنسبة إلى [DynamicCache](/docs/transformers/main/ar/internal/generation_utils#transformers.DynamicCache)، فانتبه إلى أنه في النماذج التي تستخدم انتباه النافذة المنزلقة (Mistral، Gemma2، ...) أو انتباه المقاطع (Llama4)، لن يتجاوز حجم الكاش حجم النافذة المنزلقة/المقطع في الطبقات التي تستخدم هذه الأنواع من الانتباه، حتى لو كان الحد الأقصى للطول المحدد أكبر.

يمكنك تفعيل [StaticCache](/docs/transformers/main/ar/internal/generation_utils#transformers.StaticCache) من خلال ضبط `cache_implementation="static"` في [generate()](/docs/transformers/main/ar/main_classes/text_generation#transformers.GenerationMixin.generate). كما سيؤدي ذلك إلى تفعيل `compilation` التلقائي لمراحل فك الترميز لاستراتيجيات فك الترميز الجشعة والعشوائية.

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

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-chat-hf")
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-chat-hf", dtype=torch.float16, device_map="auto")
inputs = tokenizer("Hello, my name is", return_tensors="pt").to(model.device)

out = model.generate(**inputs, do_sample=False, max_new_tokens=20, cache_implementation="static")
tokenizer.batch_decode(out, skip_special_tokens=True)[0]
"Hello, my name is [Your Name], and I am a [Your Profession] with [Number of Years] of"
```

## إبقاء تينسورات التوليد على وحدة المعالجة المركزية

تتتبع وحدات المعالجة الخلفية للمترجمات مثل Neuron وTPU نموذجك لتحويله إلى رسم حسابي ثابت. يحافظ حلقة التوليد على متجهات (output sequence, `attention_mask`, `position_ids`) تنمو بمقدار رمز واحد في كل خطوة. يعيد المترجم تتبع الرسم كل مرة تتغير فيها أبعاد هذه المتجهات على المعالج التسارعي، مما يُبطئ عملية التوليد.

تنقل [generate()](/docs/transformers/main/ar/main_classes/text_generation#transformers.GenerationMixin.generate) فقط الموترات التي يستهلكها `forward` إلى جهاز النموذج، مباشرةً قبل كل استدعاء لـ`forward`. ثم يُعاد نقل المخرجات إلى جهاز المدخلات لمطابقته. مرّر مدخلاتك على وحدة المعالجة المركزية (CPU) للحفاظ على سجل الموترات المتنامي في الحلقة بعيدًا عن المعجّل. تبقى المخطط المُجمَّع مستقرًا، وبما أن المخرجات تتبع جهاز المدخلات، فإن المخرجات المولّدة تبقى على وحدة المعالجة المركزية (CPU).

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

tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen3-0.6B")
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3-0.6B", device_map="auto")

# leave the inputs on CPU instead of calling .to(model.device).
inputs = tokenizer("The French Bread Law states", return_tensors="pt")

# generate runs forward on the model device but returns the output on the input_ids device.
output = model.generate(**inputs, do_sample=False, max_new_tokens=20)
print(output.device)
cpu
```

## إخلاء ذاكرة التخزين المؤقت

يمكن أن يشغل ذاكرة KV حصةً كبيرة من الذاكرة، ويصبح [عنقاً زجاجة](https://hf.co/blog/llama31#inference-memory-requirements) في توليد السياقات الطويلة. تركز الذاكرات الفعّالة من حيث استهلاك الذاكرة على الموازنة بين السرعة وتقليل استهلاك الذاكرة. وهذا أمرٌ مهمّ بشكل خاص بالنسبة لنماذج اللغة الكبيرة (LLMs) وفي حال كانت موارد الذاكرة في جهازك محدودة.

يُوفّر تفريغ ذاكرة التخزين المؤقت (Offloading) من ذاكرة وحدة معالجة الرسوميات (GPU) عن طريق نقل ذاكرة KV التخزينية لطبقات النموذج، باستثناء طبقة واحدة، إلى وحدة المعالجة المركزية (CPU). أثناء تكرار `forward` للنموذج عبر الطبقات، تُحافظ على ذاكرة التخزين المؤقت للطبقة الحالية على وحدة معالجة الرسوميات (GPU) فقط. سيقوم النظام مسبقاً بجلب ذاكرة التخزين المؤقت للطبقة التالية بشكل غير متزامن، وإرجاع ذاكرة التخزين المؤقت للطبقة الحالية إلى وحدة المعالجة المركزية (CPU) بعد حساب الانتباه (attention).

قد ترغب في النظر في خيار النقل (Offloading) إذا كان لديك بطاقة GPU صغيرة وتواجه أخطاء نفاد الذاكرة (OOM).

> [!WARNING]
> قد تلاحظ انخفاضًا طفيفًا في معدل إنتاج النص مقارنةً بذاكرة التخزين المؤقت الكاملة على الجهاز، وذلك اعتمادًا على النموذج وخيارات التوليد (حجم السياق، عدد الرموز المولّدة، عدد الحزم، إلخ). والسبب في ذلك أن نقل حالات المفتاح/القيمة ذهابًا وإيابًا يتطلب بعض المعالجة.

يتوفر التفريغ (Offloading) لكلٍّ من [DynamicCache](/docs/transformers/main/ar/internal/generation_utils#transformers.DynamicCache) و[StaticCache](/docs/transformers/main/ar/internal/generation_utils#transformers.StaticCache). يمكنك تفعيله عن طريق ضبط `cache_implementation="offloaded"` للنسخة الديناميكية، أو `cache_implementation="offloaded_static"` للنسخة الثابتة، في [GenerationConfig](/docs/transformers/main/ar/main_classes/text_generation#transformers.GenerationConfig) أو [generate()](/docs/transformers/main/ar/main_classes/text_generation#transformers.GenerationMixin.generate). بالإضافة إلى ذلك، يمكنك أيضًا إنشاء نسخة خاصة بك من [DynamicCache](/docs/transformers/main/ar/internal/generation_utils#transformers.DynamicCache) أو [StaticCache](/docs/transformers/main/ar/internal/generation_utils#transformers.StaticCache) مع خيار `offloading=True`، ثم تمرير هذا الكاش في `generate` أو في `forward` الخاص بنموذجك (على سبيل المثال، `past_key_values=DynamicCache(config=model.config, offloading=True)` لكاش ديناميكي).

لاحظ أن صفحتي [Cache](/docs/transformers/main/ar/internal/generation_utils#transformers.Cache) المذكورتين أعلاه تتضمنان خيارًا إضافيًا عند إنشاء كائناتهما مباشرة، وهو `offload_only_non_sliding`. يحدد هذا الحجة الإضافية ما إذا كانت الطبقات التي تستخدم الانتباه النافذة المنزلقة/المجزأة (إن وُجدت) ستُحمَّل أيضًا. وبما أن هذه الطبقات قصيرة عادةً، فقد يكون من الأفضل تجنب تحميلها، إذ قد يؤدي التحميل إلى عقوبة في السرعة. افتراضيًا، يكون هذا الخيار `False` لـ [DynamicCache](/docs/transformers/main/ar/internal/generation_utils#transformers.DynamicCache)، و`True` لـ [StaticCache](/docs/transformers/main/ar/internal/generation_utils#transformers.StaticCache).

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

ckpt = "microsoft/Phi-3-mini-4k-instruct"
tokenizer = AutoTokenizer.from_pretrained(ckpt)
model = AutoModelForCausalLM.from_pretrained(ckpt, dtype=torch.float16, device_map="auto")
inputs = tokenizer("Fun fact: The shortest", return_tensors="pt").to(model.device)

out = model.generate(**inputs, do_sample=False, max_new_tokens=23, cache_implementation="offloaded")
print(tokenizer.batch_decode(out, skip_special_tokens=True)[0])
Fun fact: The shortest war in history was between Britain and Zanzibar on August 27, 1896.
```

يُظهر المثال أدناه كيفية الرجوع إلى ذاكرة تخزين مؤقت مُحمّلة خارجياً إذا نفدت الذاكرة:

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

def resilient_generate(model, *args, **kwargs):
    oom = False
    device = Accelerator().device
    torch_device_module = getattr(torch, device, torch.cuda)
    try:
        return model.generate(*args, **kwargs)
    except torch.OutOfMemoryError as e:
        print(e)
        print("retrying with cache_implementation='offloaded'")
        oom = True
    if oom:
        torch_device_module.empty_cache()
        kwargs["cache_implementation"] = "offloaded"
        return model.generate(*args, **kwargs)

ckpt = "microsoft/Phi-3-mini-4k-instruct"
tokenizer = AutoTokenizer.from_pretrained(ckpt)
model = AutoModelForCausalLM.from_pretrained(ckpt, dtype=torch.float16, device_map="auto")
prompt = ["okay "*1000 + "Fun fact: The most"]
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
beams = { "num_beams": 40, "num_return_sequences": 20, "max_new_tokens": 23, "early_stopping": True, }
out = resilient_generate(model, **inputs, **beams)
responses = tokenizer.batch_decode(out[:,-28:], skip_special_tokens=True)
```

## ذاكرة مؤقتة مُكمّاة

يقلل [QuantizedCache](/docs/transformers/main/ar/internal/generation_utils#transformers.QuantizedCache) من متطلبات الذاكرة من خلال تكميم قيم KV إلى دقة أدنى. يدعم [QuantizedCache](/docs/transformers/main/ar/internal/generation_utils#transformers.QuantizedCache) حاليًا ثلاثة محركات خلفية للتكميم:

- يدعم `hqq` أنواع البيانات int1 وint2 وint3 وint4 وint8.
- يدعم `quanto` أنواع البيانات int2 و int4. وهو واجهة التكميم الافتراضية.
- `fp8` يخزّن قيم KV بنقطة عائمة 8-بت (`float8_e4m3fn`). لا يتطلب أي اعتمادية إضافية، ويقوم بتكميم على مستوى المصفوفة (per-tensor) بدلاً من تكميم على مستوى المجموعة (per-group)، لذا يرفض `nbits` و`axis_key` و`axis_value` و`q_group_size` و`residual_length`.

> [!WARNING]
> قد يُسبّب تكميم ذاكرة التخزين المؤقت تدهور زمن الاستجابة إذا كانت طول السياق قصيرًا وكان هناك ذاكرة GPU كافية للتوليد دون تفعيل تكميم ذاكرة التخزين المؤقت. حاول إيجاد توازن بين كفاءة استخدام الذاكرة وزمن الاستجابة.

فعّل [QuantizedCache](/docs/transformers/main/ar/internal/generation_utils#transformers.QuantizedCache) عن طريق ضبط `cache_implementation="quantized"` في [GenerationConfig](/docs/transformers/main/ar/main_classes/text_generation#transformers.GenerationConfig). يتم تحديد خلفية التكميم، إلى جانب أي معلمات تكميم إضافية، في قاموس `cache_config` المُمرَّر إلى [generate()](/docs/transformers/main/ar/main_classes/text_generation#transformers.GenerationMixin.generate). يجب عليك استخدام القيم الافتراضية لهذه المعلمات الإضافية ما لم تكن تواجه مشكلة نفاد الذاكرة. في تلك الحالة، فكّر في تقليل طول الباقي.

لواجهة `hqq`، ننصح بإعداد المعاملين `axis_key` و`axis_value` على القيمة `1`.

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

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-chat-hf")
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-chat-hf", dtype=torch.float16, device_map="auto")
inputs = tokenizer("I like rock music because", return_tensors="pt").to(model.device)

out = model.generate(
    **inputs,
    do_sample=False,
    max_new_tokens=20,
    cache_implementation="quantized",
    cache_config={
        "nbits": 4,
        "backend": "hqq",
        "axis_key": 1,
        "axis_value": 1
    }
)
print(tokenizer.batch_decode(out, skip_special_tokens=True)[0])
I like rock music because it's loud and energetic. It's a great way to express myself and rel
```

نوصي، في حالة استخدام واجهة `quanto`، بإعداد المعاملين `axis_key` و`axis_value` على القيمة `0`.

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

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-chat-hf")
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-chat-hf", dtype=torch.float16, device_map="auto")
inputs = tokenizer("I like rock music because", return_tensors="pt").to(model.device)

out = model.generate(
    **inputs,
    do_sample=False,
    max_new_tokens=20,
    cache_implementation="quantized",
    cache_config={
        "nbits": 4,
        "backend": "quanto",
        "axis_key": 0,
        "axis_value": 0
    }
)
print(tokenizer.batch_decode(out, skip_special_tokens=True)[0])
I like rock music because it's loud and energetic. It's a great way to express myself and rel
```

لا يقبل الواجهة الخلفية `fp8` أي معامل إضافي، وتُطلق استثناءً إذا تم تمرير أحد المعاملات الخاصة بالمجموعات.

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

tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen3-4B-Instruct-2507")
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3-4B-Instruct-2507", dtype=torch.float16, device_map="auto")
inputs = tokenizer("I like rock music because", return_tensors="pt").to(model.device)

out = model.generate(**inputs, do_sample=False, max_new_tokens=20, cache_implementation="quantized", cache_config={"backend": "fp8"})
print(tokenizer.batch_decode(out, skip_special_tokens=True)[0])
I like rock music because it is powerful and emotional. I also like classical music because it is elegant and sophisticated. I enjoy
```

## ذاكرة مؤقت للمشفّر-المفكّك

صُمم [EncoderDecoderCache](/docs/transformers/main/ar/internal/generation_utils#transformers.EncoderDecoderCache) لنماذج المُشفِّر-المُفكِّك. وهو يدير كاشات الانتباه الذاتي والانتباه المتقاطع معًا لضمان تخزين أزواج kv السابقة واسترجاعها. ومن الممكن تعيين نوع كاش مختلف بشكل مستقل لكل من المُشفِّر والمُفكِّك.

لا يتطلب هذا النوع من الكاش أي إعداد. إنه غلاف بسيط حول كاشين [Cache](/docs/transformers/main/ar/internal/generation_utils#transformers.Cache) كما هو موضح أعلاه، وسيُستخدمان بشكل مستقل ومباشر من قبل النموذج.

## الذاكرة المؤقتة الخاصة بالنموذج

تتميز بعض النماذج بطريقة فريدة لتخزين أزواج kv السابقة أو الحالات، وهي طريقة غير متوافقة مع أي من فئات التخزين المؤقت الأخرى.

تتطلب نماذج Mamba، مثل [Mamba](./model_doc/mamba)، ذاكرة مؤقتة محددة لأن النموذج لا يحتوي على آلية انتباه أو حالات kv. وبالتالي، فهي غير متوافقة مع فئات [Cache](/docs/transformers/main/ar/internal/generation_utils#transformers.Cache) المذكورة أعلاه.

## التوليد التكراري

يمكن أن يعمل الكاش أيضًا في إعدادات التوليد التكراري التي تتضمن تفاعلًا متبادلًا مع النموذج (روبوتات المحادثة). وبالمثل للتوليد العادي، يتيح التوليد التكراري باستخدام الكاش للنموذج معالجة المحادثات المستمرة بكفاءة دون إعادة حساب السياق الكامل في كل خطوة.

للتوليد التكراري مع استخدام ذاكرة مؤقتة، ابدأ بتهيئة فئة ذاكرة مؤقتة فارغة، ثم يمكنك إدخال الموجهات الجديدة. حافظ على سجل المحادثة باستخدام [قالب المحادثة](./chat_templating).

يُظهر المثال التالي [Llama-2-7b-chat-hf](https://huggingface.co/meta-llama/Llama-2-7b-chat-hf). إذا كنت تستخدم نموذجاً آخر بأسلوب المحادثة، فقد يعالج [apply_chat_template()](/docs/transformers/main/ar/internal/tokenization_utils#transformers.PreTrainedTokenizerBase.apply_chat_template) الرسائل بشكل مختلف. وقد يحذف رموزاً مهمة اعتماداً على كيفية كتابة قالب Jinja. بالنسبة لنماذج المحادثة متعددة الوسائط، راجع دليل [iterative chatting with cache](./tasks/image_text_to_text#iterative-chatting-with-cache) لمعرفة كيفية معالجة الصور أو الصوت.

على سبيل المثال، تستخدم بعض النماذج رموزًا خاصة `<think> ... </think>` أثناء الاستدلال. وقد تُفقد هذه الرموز أثناء إعادة الترميز، مما يسبب مشكلات في الفهرسة. قد تحتاج إلى إزالة أو تعديل الرموز الإضافية من الإكمالات يدويًا للحفاظ على استقرار الأمور.

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

model_id = "meta-llama/Llama-2-7b-chat-hf"
model = AutoModelForCausalLM.from_pretrained(model_id, dtype=torch.bfloat16, device_map='auto')
tokenizer = AutoTokenizer.from_pretrained(model_id)

user_prompts = ["Hello, what's your name?", "Btw, yesterday I was on a rock concert."]

past_key_values = DynamicCache(config=model.config)

messages = []
for prompt in user_prompts:
    messages.append({"role": "user", "content": prompt})
    inputs = tokenizer.apply_chat_template(messages, add_generation_prompt=True, return_tensors="pt", return_dict=True).to(model.device)
    input_length = inputs["input_ids"].shape[1]
    outputs = model.generate(**inputs, do_sample=False, max_new_tokens=256, past_key_values=past_key_values)
    completion = tokenizer.decode(outputs[0, input_length: ], skip_special_tokens=True)
    messages.append({"role": "assistant", "content": completion})
```

## قصّ ذاكرة التخزين المؤقت

استخدم [crop()](/docs/transformers/main/ar/internal/generation_utils#transformers.Cache.crop) للتراجع عن الرموز من ذاكرة التخزين المؤقت، وذلك عند رفض استمرارية مرشحة أثناء التوليد التكراري. مرّر عدد الرموز المراد إزالتها كعدد صحيح سالب.

```py
# Remove the last three tokens from the cache.
past_key_values.crop(-3)
```

تتخلّى طبقات الانتباه الخطي وطبقات نافذة الانزلاق عن الحالات السابقة أثناء المعالجة، لذا لا يوجد ما يمكن التراجع إليه افتراضيًا. استدعِ `activate_past_recording()` قبل تمرير الأمام (forward pass) لجعلها تحتفظ بتلك الحالات. بدونه، يرمي `crop` استثناء `RuntimeError` بمجرد امتلاء نافذة طبقة نافذة الانزلاق، وبشكل فوري في حالة طبقات الانتباه الخطي.

```py
# Enable this before the forward pass if you need to roll back tokens.
past_key_values.activate_past_recording()
```

`crop(0)` لا يمسح ذاكرة التخزين المؤقت. فهو لا يزيل أي رموز من التسلسل المخزّن، وهو إجراء لا يؤثر على طبقات الانتباه الكامل. أما في طبقات النافذة المنزلقة والانتباه الخطي، فقد يتخلّى عن معلومات مخزّنة لن يستخدمها استدعاء النموذج التالي. وهذا يقلّل من استهلاك الذاكرة دون التراجع عن الرموز.

```
                    cached positions
                    ┌───┬───┬───┬───┬───┬───┐
before crop(-3)     │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │
                    └───┴───┴───┴───┴───┴───┘
                                ╰─────┬─────╯
                                 rolled back

after crop(-3)
                    ┌───┬───┬───┐
full attention      │ 0 │ 1 │ 2 │    keeps the whole prefix
                    └───┴───┴───┘
                            ┌───┐
sliding_window=2            │ 2 │    keeps sliding_window - 1
                            └───┘
```

تُبلّغ كلا الطبقتين الآن عن طول تسلسل يساوي 3، وتُستأنف عملية التوليد من الموضع 3.

إمرار `0` لا يُزيل أي رموز من التسلسل. إنه إجراء لا يُحدث تغييراً في طبقات الانتباه الكاملة، لكن في طبقات النافذة المنزلقة والانتباه الخطي، لا يزال يتخلص من الحالات المسجلة التي لن تقرأها عملية الأمامية التالية، مما يُحرر الذاكرة دون التراجع عن أي شيء.

## تعبئة ذاكرة مؤقتة مسبقاً (تخزين بادئات مؤقت)

في بعض الحالات، قد ترغب في ملء [Cache](/docs/transformers/main/ar/internal/generation_utils#transformers.Cache) بأزواج kv لبادئة معينة وإعادة استخدامه لتوليد تسلسلات مختلفة.

يُهيّئ المثال أدناه [StaticCache](/docs/transformers/main/ar/internal/generation_utils#transformers.StaticCache)، ثم يخزّن مبدئيًا موقفاً أولياً. والآن يمكنك توليد عدة تسلسلات من الموقف المُعبّأ مسبقًا.

```py
import copy
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, DynamicCache, StaticCache

model_id = "meta-llama/Llama-2-7b-chat-hf"
model = AutoModelForCausalLM.from_pretrained(model_id, dtype=torch.bfloat16, device_map={"": 0})
tokenizer = AutoTokenizer.from_pretrained(model_id)

# Init StaticCache with big enough max-length (1024 tokens for the below example)
# You can also init a DynamicCache, if that suits you better
prompt_cache = StaticCache(config=model.config, max_cache_len=1024)

INITIAL_PROMPT = "You are a helpful assistant. "
inputs_initial_prompt = tokenizer(INITIAL_PROMPT, return_tensors="pt").to(model.device.type)
# This is the common prompt cached, we need to run forward without grad to be able to copy
with torch.no_grad():
     prompt_cache = model(**inputs_initial_prompt, past_key_values = prompt_cache).past_key_values

prompts = ["Help me to write a blogpost about travelling.", "What is the capital of France?"]
responses = []
for prompt in prompts:
    new_inputs = tokenizer(INITIAL_PROMPT + prompt, return_tensors="pt").to(model.device.type)
    past_key_values = copy.deepcopy(prompt_cache)
    outputs = model.generate(**new_inputs, past_key_values=past_key_values,max_new_tokens=20)
    response = tokenizer.batch_decode(outputs)[0]
    responses.append(response)

print(responses)
```

