# Bộ xử lý đa phương thức

Một processor kết hợp một tokenizer với một hoặc nhiều bộ xử lý modalities, chẳng hạn như image processor, video processor, hoặc feature extractor. Nó cung cấp một phương thức `__call__` duy nhất, có nhiệm vụ định tuyến mỗi đầu vào đến thành phần phù hợp và gộp các đầu ra thành một từ điển duy nhất.

Một số mô hình đa phương thức xen kẽ văn bản với hình ảnh, video hoặc âm thanh. Đối với các mô hình này, [ProcessorMixin](/docs/transformers/main/vi/main_classes/processors#transformers.ProcessorMixin) có thể thay thế các token chiếm chỗ như `<image>`, `<video>` và `<audio>` bằng mẫu token mà mô hình mong đợi.

## Thêm một bộ xử lý mới

Định nghĩa một lớp processor bằng cách tạo `src/transformers/models/<model>/processing_<my_model_name>.py` và kế thừa `ProcessorMixin`. Hãy đảm bảo định nghĩa một đối tượng `TypedDict` với các giá trị mặc định và gán nó cho `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,
        )
```

Thực hiện `replace_<modality>_token` nếu cần. Hàm này nhận dict đầu ra đầy đủ từ subprocessor và chỉ mục của đầu vào hiện tại, sau đó trả về chuỗi thay thế đã mở rộng cho đầu vào đó. Chuỗi thay thế chính là thứ mà model mong đợi trong chuỗi đầu vào.

Nếu mô hình không hề sử dụng lặp placeholder (không có `image_token` được định nghĩa), bạn không cần ghi đè phương thức này. Để `self.image_token` không được đặt và lớp cơ sở sẽ bỏ qua hoàn toàn việc thay thế.

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

Tùy chọn ghi đè các phương thức `prepare_inputs_layout` và `validate_inputs`. Nếu mô hình yêu cầu một cấu trúc đầu vào cụ thể trước khi bắt đầu xử lý, chẳng hạn như sắp xếp lại các hình ảnh thành một danh sách lồng nhau, hoặc một quy trình kiểm tra xác thực riêng của mô hình bên cạnh các kiểm tra chung.

```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]
> Xem [Gemma4Processor](/docs/transformers/main/vi/model_doc/gemma4#transformers.Gemma4Processor) và [Qwen2VLProcessor](/docs/transformers/main/vi/model_doc/qwen2_vl#transformers.Qwen2VLProcessor) để tham khảo.

## Kiểm thử

Tất cả bộ xử lý đa phương thức (multimodal processor) phải có một lớp kiểm thử kế thừa từ `ProcessorTesterMixin`. Mixin này cung cấp một bộ kiểm thử chuẩn bao gồm tokenization, xử lý ảnh, batching và mã hóa vòng lặp (round-trip encoding).

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

