| 1 | # SPDX-License-Identifier: Apache-2.0 |
| 2 | # SPDX-FileCopyrightText: Copyright contributors to the vLLM project |
| 3 | """Image processor for Unlimited-OCR (baidu/Unlimited-OCR).""" |
| 4 | |
| 5 | from PIL import Image |
| 6 | |
| 7 | from vllm.logger import init_logger |
| 8 | from vllm.transformers_utils.processors.deepseek_ocr import DeepseekOCRProcessor |
| 9 | |
| 10 | logger = init_logger(__name__) |
| 11 | |
| 12 | |
| 13 | class UnlimitedOCRProcessor(DeepseekOCRProcessor): |
| 14 | """DeepseekOCRProcessor variant for Unlimited-OCR. |
| 15 | |
| 16 | The only behavioural difference from the base processor is a multi-image |
| 17 | safeguard: when more than one image is present, crop ("gundam") mode is |
| 18 | disabled. |
| 19 | |
| 20 | Because the effective crop flag then depends on *how many* images are in the |
| 21 | request, the per-item processing output is no longer invariant of sibling |
| 22 | images. ``UnlimitedOCRMultiModalProcessor`` accounts for this by bypassing |
| 23 | the multimodal processing cache for multi-image requests (see its |
| 24 | ``_cached_apply_hf_processor``), so the two paths stay consistent. |
| 25 | |
| 26 | DeepSeek-OCR does *not* have this restriction because its ``max_crops=6`` is |
| 27 | small enough to be safe for multi-image use. |
| 28 | """ |
| 29 | |
| 30 | def tokenize_with_images( |
| 31 | self, |
| 32 | conversation: str, |
| 33 | images: list[Image.Image], |
| 34 | bos: bool = True, |
| 35 | eos: bool = True, |
| 36 | cropping: bool = True, |
| 37 | ): |
| 38 | if len(images) > 1 and cropping: |
| 39 | logger.warning_once( |
| 40 | "Unlimited-OCR: crop mode is not supported for multi-image " |
| 41 | "input. Falling back to cropping=False." |
| 42 | ) |
| 43 | cropping = False |
| 44 | return super().tokenize_with_images( |
| 45 | conversation, images, bos=bos, eos=eos, cropping=cropping |
| 46 | ) |