# قوالب المحادثة متعددة الوسائط

تقبل نماذج الدردشة متعددة الوسائط مدخلات مثل الصور أو الصوت أو الفيديو، بالإضافة إلى النص. المفتاح `content` في سجل دردشة متعدد الوسائط هو قائمة تحتوي على عناصر متعددة من أنواع مختلفة. وهذا على عكس نماذج الدردشة النصية فقط، حيث يكون المفتاح `content` نصًا واحدًا.

على نحو مماثل لطريقة معالجة فئة [Tokenizer](./fast_tokenizers) للقوالب الدردشة والتجزئة (Tokenization) في النماذج النصية فقط، تتولى فئة [Processor](./processors) معالجة ما قبل المعالجة والتجزئة والقوالب الدردشة في النماذج متعددة الوسائط. وتكاد تكون دوال [apply_chat_template()](/docs/transformers/main/ar/main_classes/processors#transformers.ProcessorMixin.apply_chat_template) الخاصة بهما متطابقة.

ستُظهر لك هذه الدليل كيفية الدردشة مع النماذج متعددة الوسائط باستخدام [ImageTextToTextPipeline](/docs/transformers/main/ar/main_classes/pipelines#transformers.ImageTextToTextPipeline) على مستوى عالٍ، وعلى مستوى أدنى باستخدام طريقتي [apply_chat_template()](/docs/transformers/main/ar/main_classes/processors#transformers.ProcessorMixin.apply_chat_template) و[generate()](/docs/transformers/main/ar/main_classes/text_generation#transformers.GenerationMixin.generate).

## ImageTextToTextPipeline

[ImageTextToTextPipeline](/docs/transformers/main/ar/main_classes/pipelines#transformers.ImageTextToTextPipeline) هي فئة عالية المستوى لتوليد الصور والنصوص مع وضع “المحادثة”. يتم تفعيل وضع المحادثة عند اكتشاف نموذج محادثة وأن يكون موجه المحادثة [منسقًا بشكل صحيح](./llm_tutorial#prompt-format).

أضِف كتل الصور والنصوص إلى مفتاح `content` في سجل المحادثة.

```py
messages = [
    {
        "role": "system",
        "content": [{"type": "text", "text": "You are a friendly chatbot who always responds in the style of a pirate"}],
    },
    {
      "role": "user",
      "content": [
            {"type": "image", "url": "http://images.cocodataset.org/val2017/000000039769.jpg"},
            {"type": "text", "text": "What are these?"},
        ],
    },
]
```

أنشئ [ImageTextToTextPipeline](/docs/transformers/main/ar/main_classes/pipelines#transformers.ImageTextToTextPipeline) ومرّر المحادثة إليه. بالنسبة للنماذج الكبيرة، يساعد تعيين [device_map="auto"](./models#big-model-inference) في تحميل النموذج بشكل أسرع ووضعِه تلقائياً على أسرع جهاز متاح. كما يساعد تعيين نوع البيانات إلى [auto](./models#model-data-type) في توفير الذاكرة وتحسين السرعة.

```python
import torch
from transformers import pipeline

pipe = pipeline("image-text-to-text", model="Qwen/Qwen2.5-VL-3B-Instruct", device_map="auto", dtype="auto")
out = pipe(text=messages, max_new_tokens=128)
print(out[0]['generated_text'][-1]['content'])
```

```text
Ahoy, me hearty! These be two feline friends, likely some tabby cats, taking a siesta on a cozy pink blanket. They're resting near remote controls, perhaps after watching some TV or just enjoying some quiet time together. Cats sure know how to find comfort and relaxation, don't they?
```

بخلاف التدرج في الانتقال من لغة القراصنة إلى الإنجليزية الأمريكية الحديثة (فهو **في** النهاية نموذج بحجم 3B فقط)، فإن هذا صحيح!

## استخدام `apply_chat_template`

كما هو الحال مع [النماذج النصية فقط](./chat_templating)، استخدم طريقة [apply_chat_template()](/docs/transformers/main/ar/main_classes/processors#transformers.ProcessorMixin.apply_chat_template) لتحضير رسائل الدردشة للنماذج متعددة الوسائط. تتولى هذه طريقة معالجة الترميز والتنسيق لرسائل الدردشة، بما في ذلك الصور وأنواع الوسائط الأخرى. تُمرَّر المدخلات الناتجة إلى النموذج من أجل التوليد.

```python
from transformers import AutoProcessor, AutoModelForImageTextToText

model = AutoModelForImageTextToText.from_pretrained("Qwen/Qwen2.5-VL-3B-Instruct", device_map="auto", torch_dtype="auto")
processor = AutoProcessor.from_pretrained("Qwen/Qwen2.5-VL-3B-Instruct")

messages = [
    {
      "role": "system",
      "content": [{"type": "text", "text": "You are a friendly chatbot who always responds in the style of a pirate"}],
    },
    {
      "role": "user",
      "content": [
            {"type": "image", "url": "http://images.cocodataset.org/val2017/000000039769.jpg"},
            {"type": "text", "text": "What are these?"},
        ],
    },
]
```

مرّر `messages` إلى [apply_chat_template()](/docs/transformers/main/ar/main_classes/processors#transformers.ProcessorMixin.apply_chat_template) لتحويل المحتوى المدخل إلى رموز. على عكس نماذج النص، يحتوي ناتج `apply_chat_template` على مفتاح `pixel_values` يحتوي على بيانات الصورة المعالجة مسبقًا، بالإضافة إلى النص المحوّل إلى رموز.

```py
processed_chat = processor.apply_chat_template(messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt")
print(list(processed_chat.keys()))
```

```text
['input_ids', 'attention_mask', 'pixel_values', 'image_grid_thw']
```

مرر هذه المدخلات إلى [generate()](/docs/transformers/main/ar/main_classes/text_generation#transformers.GenerationMixin.generate).

```python
out = model.generate(**processed_chat.to(model.device), max_new_tokens=128)
print(processor.decode(out[0]))
```

يتضمن المخرج المُفكَّك المحادثة الكاملة حتى الآن، بما في ذلك رسالة المستخدم ورموز الوكيل التي تحتوي على معلومات الصورة. قد تحتاج إلى قصّ المحادثة السابقة من المخرج قبل عرضها للمستخدم.

## مدخلات الفيديو

تدعم بعض نماذج الرؤية أيضًا مدخلات الفيديو. يشبه تنسيق الرسائل إلى حد كبير تنسيق مدخلات الصور الموصوف في القسم السابق.

- يجب أن يكون المحتوى `"type"` هو `"video"` للإشارة إلى أن المحتوى عبارة عن فيديو.
- بالنسبة للفيديوهات، يمكن أن يكون رابطاً إلى الفيديو (`"url"`) أو مسار ملف (`"path"`). يتم فك ترميز الفيديوهات باستخدام [torchcodec](https://meta-pytorch.org/torchcodec/stable/index.html). إذا لم يكن torchcodec متاحاً وكنت تستخدم إصداراً أقدم من torchvision، فإن فك الترميز يعتمد على torchvision.
- بالإضافة إلى تحميل مقاطع الفيديو من عنوان URL أو مسار ملف، يمكنك أيضاً تمرير بيانات الفيديو المُفكّكة مباشرة. وهذا مفيد إذا كنت قد قمت مسبقاً بمعالجة إطارات الفيديو أو فكّ ترميزها في مكان آخر داخل الذاكرة. لا حاجة إلى حفظها في ملفات أو تخزينها في عنوان URL.

> [!TIP]
> يتوفر [PyAV](https://pyav.basswood-io.com/docs/stable/) و [Decord](https://github.com/dmlc/decord)، ولكن فقط إذا قمت بفك ترميز الفيديو بنفسك وطلبت الخلفية بشكل صريح باستخدام `load_video(backend=...)`.

```python
from transformers import AutoProcessor, LlavaOnevisionForConditionalGeneration

model_id = "llava-hf/llava-onevision-qwen2-0.5b-ov-hf"
model = LlavaOnevisionForConditionalGeneration.from_pretrained(model_id)
processor = AutoProcessor.from_pretrained(model_id)

messages = [
    {
      "role": "system",
      "content": [{"type": "text", "text": "You are a friendly chatbot who always responds in the style of a pirate"}],
    },
    {
      "role": "user",
      "content": [
            {"type": "video", "url": "https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/720/Big_Buck_Bunny_720_10s_10MB.mp4"},
            {"type": "text", "text": "What do you see in this video?"},
        ],
    },
]
```

### مثال: تمرير كائنات فيديو مفكوكة

```python
import numpy as np

video_object1 = np.random.randint(0, 255, size=(16, 224, 224, 3), dtype=np.uint8),

messages = [
    {
        "role": "system",
        "content": [{"type": "text", "text": "You are a friendly chatbot who always responds in the style of a pirate"}],
    },
    {
        "role": "user",
        "content": [
            {"type": "video", "video": video_object1},
            {"type": "text", "text": "What do you see in this video?"}
        ],
    },
]
```

يمكنك أيضًا استخدام الدالة الموجودة (`"load_video()"`) لتحميل فيديو، وتعديله في الذاكرة، ثم تمريره في الرسائل.

```python

# Make sure a video backend library (torchcodec, pyav, or decord) is available.
from transformers.video_utils import load_video

# load a video file in memory for testing
video_object2, _ = load_video(
    "https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/720/Big_Buck_Bunny_720_10s_10MB.mp4"
)

messages = [
    {
        "role": "system",
        "content": [{"type": "text", "text": "You are a friendly chatbot who always responds in the style of a pirate"}],
    },
    {
        "role": "user",
        "content": [
            {"type": "video", "video": video_object2},
            {"type": "text", "text": "What do you see in this video?"}
        ],
    },
]
```

مرّر `messages` إلى [apply_chat_template()](/docs/transformers/main/ar/main_classes/processors#transformers.ProcessorMixin.apply_chat_template) لتحويل المحتوى المدخل إلى رموز. هناك بعض المعلمات الإضافية التي يجب تضمينها في [apply_chat_template()](/docs/transformers/main/ar/main_classes/processors#transformers.ProcessorMixin.apply_chat_template) للتحكم في عملية العينة.

يتحكم معامل `num_frames` في عدد الإطارات التي يتم أخذ عينة منها بشكل منتظم من الفيديو. لكل نقطة تفتيش (checkpoint) حد أقصى لعدد الإطارات الذي تم تدريبه المسبق عليه، وقد يؤدي تجاوز هذا العدد إلى انخفاض كبير في جودة التوليد. من المهم اختيار عدد إطارات يناسب سعة النموذج وموارد العتاد لديك. إذا لم يتم تحديد `num_frames`، يتم تحميل الفيديو بالكامل دون أي أخذ عينات للإطارات.

```python
processed_chat = processor.apply_chat_template(
    messages,
    add_generation_prompt=True,
    tokenize=True,
    return_dict=True,
    return_tensors="pt",
    num_frames=32,
)
print(processed_chat.keys())
```

أصبحت هذه المدخلات الآن جاهزة للاستخدام في [generate()](/docs/transformers/main/ar/main_classes/text_generation#transformers.GenerationMixin.generate).

بالنسبة للفيديوهات الأطول، قد يكون من الأفضل أخذ عينات من عدد أكبر من الإطارات للحصول على تمثيل أدق باستخدام معامل `fps`. يحدد هذا المعامل عدد الإطارات التي يجب استخراجها في الثانية. كمثال، إذا كان الفيديو مدته 10 ثوانٍ و`fps=2`، فإن النموذج يأخذ عينات من 20 إطارًا. بمعنى آخر، يتم أخذ عينات بشكل متساوٍ من إطارين كل 10 ثوانٍ.

```py
processed_chat = processor.apply_chat_template(
    messages,
    add_generation_prompt=True,
    tokenize=True,
    return_dict=True,
    fps=16,
)
print(processed_chat.keys())
```

قد توجد مقاطع الفيديو أيضًا على شكل مجموعة من الإطارات المُستخرجة والمُخزّنة على هيئة صور، بدلاً من ملف الفيديو الكامل.

في هذه الحالة، مرّر قائمة مسارات ملفات الصور وسيعمل المعالج تلقائيًا على دمجها في فيديو. تأكد من أن جميع الصور بنفس الحجم نظرًا لكونها مفترضةً أنها من نفس الفيديو.

```py
frames_paths = ["/path/to/frame0.png", "/path/to/frame5.png", "/path/to/frame10.png"]
messages = [
    {
        "role": "system",
        "content": [{"type": "text", "text": "You are a friendly chatbot who always responds in the style of a pirate"}],
    },
    {
      "role": "user",
      "content": [
            {"type": "video", "path": frames_paths},
            {"type": "text", "text": "What do you see in this video?"},
        ],
    },
]

processed_chat = processor.apply_chat_template(
    messages,
    add_generation_prompt=True,
    tokenize=True,
    return_dict=True,
)
print(processed_chat.keys())
```

