# المعالجات متعددة الوسائط

يجمع المُعالِج بين مُجزِّئ (tokenizer) ومعالِج واحد أو أكثر للأنماط (modality processors)، مثل مُعالِج الصور أو مُعالِج الفيديو أو مستخرج الميزات. يعرّض طريقة `__call__` واحدة تُوجّه كل مدخل إلى المكوّن المناسب وتدمج المخرجات في قاموس واحد.

تقوم بعض النماذج متعددة الوسائط بتبديل النص مع الصور أو مقاطع الفيديو أو الصوت. ولأغراض هذه النماذج، يمكن لـ [ProcessorMixin](/docs/transformers/main/ar/main_classes/processors#transformers.ProcessorMixin) استبدال الرموز الوهمية مثل `<image>` و`<video>` و`<audio>` بنمط الرموز الذي يتوقعه النموذج.

## إضافة معالج جديد

حدد فئة المعالج (processor) من خلال إنشاء `src/transformers/models/<model>/processing_<my_model_name>.py` وإرث فئة `ProcessorMixin`. تأكد من تعريف كائن `TypedDict` بقيم افتراضية وتعيينه كـ `cls.valid_processor_kwargs`

```python
from ...processing_utils import ProcessorMixin, ProcessingKwargs, Unpack

class MyModelProcessorKwargs(ProcessingKwargs, total=False):
    images_kwargs: MyModelImageProcessorKwargs
    _defaults = {
        "text_kwargs": {"padding": True},
        "images_kwargs": {"do_convert_rgb": True},
    }

class MyModelProcessor(ProcessorMixin):
    valid_processor_kwargs = MyModelProcessorKwargs

    def __init__(self, image_processor, tokenizer, chat_template=None, **kwargs):
        self.image_token = tokenizer.image_token
        self.image_token_id = tokenizer.image_token_id
        super().__init__(
            image_processor=image_processor,
            tokenizer=tokenizer,
            chat_template=chat_template,
            **kwargs,
        )
```

نفّذ `replace_<modality>_token` عند الحاجة. يستقبل هذا الدالة قاموس المخرجات الكامل من المعالج الفرعي (subprocessor) وفهرس الإدخال الحالي، ويعيد سلسلة الاستبدال الموسّعة لذلك الإدخال. وتكون سلسلة الاستبدال هي ما يتوقعه النموذج في تسلسل الإدخال.

إذا لم يستخدم النموذج تكرار الرموز الوهمية على الإطلاق (لم يُعرَّف `image_token`)، فلا حاجة إلى تجاوز هذه الطريقة. اترك `self.image_token` غير مضبوط، وستتخطى الفئة الأساسية عملية الاستبدال بالكامل.

```python
def replace_image_token(self, image_inputs: dict, image_idx: int) -> str:
    num_crops = image_inputs["num_crops"][image_idx]
    return f"{self.boi_token}{self.image_token * self.num_image_tokens * num_crops}{self.eoi_token}"
```

يمكنك اختيارياً تجاوز طريقتي `prepare_inputs_layout` و`validate_inputs`. إذا كان النموذج يتطلب بنية إدخال محددة قبل بدء المعالجة، مثل إعادة ترتيب الصور كقائمة متداخلة، أو التحقق من صحة خاص بالنموذج فوق الفحوصات الشائعة.

```python
def prepare_inputs_layout(self, images=None, text=None, videos=None, audio=None, **kwargs):
    # Call `super()` to apply common preparation steps first 
    images, text, videos, audio = super().prepare_inputs_layout(images, text, videos, audio)
    if images is not None:
        images = make_nested_list_of_images(images)
    return images, text, videos, audio

def validate_inputs(self, images=None, text=None, videos=None, audio=None, **kwargs):
    super().validate_inputs(images=images, text=text, **kwargs)
    if text is not None and images is not None:
        n_tokens = [s.count(self.image_token) for s in text]
        n_images = [len(img_list) for img_list in images]
        if n_tokens != n_images:
            raise ValueError(
                f"Number of {self.image_token} tokens in text {n_tokens} does not match "
                f"number of images {n_images}."
            )
```

> [!TIP]
> راجع [Gemma4Processor](/docs/transformers/main/ar/model_doc/gemma4#transformers.Gemma4Processor) و [Qwen2VLProcessor](/docs/transformers/main/ar/model_doc/qwen2_vl#transformers.Qwen2VLProcessor) للاطلاع على التفاصيل.

## الاختبار

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

```python
# tests/models/my_model_name/test_processor_<my_model_name>.py

from transformers.testing_utils import require_vision
from transformers.utils import is_vision_available
from ...test_processing_common import ProcessorTesterMixin

if is_vision_available():
    from transformers import MyModelProcessor

@require_vision
class MyModelProcessorTest(ProcessorTesterMixin, unittest.TestCase):
    processor_class = MyModelProcessor

    def get_processor(self):
        return MyModelProcessor.from_pretrained("hf-internal-testing/my-model-test")
```

