From b06aa774c03dbbb624e726664b714a57d1f49815 Mon Sep 17 00:00:00 2001 From: Saba Fallah Date: Wed, 5 Aug 2026 15:30:14 +0200 Subject: [PATCH] mtmd: Unlimited-OCR fix max_tiles, setting in converter (#25614) --- conversion/deepseek.py | 15 ++++++++++++++- tools/mtmd/clip.cpp | 7 +++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/conversion/deepseek.py b/conversion/deepseek.py index 0518fcecc1..3dca369cf9 100644 --- a/conversion/deepseek.py +++ b/conversion/deepseek.py @@ -17,8 +17,11 @@ from .base import LazyTorchTensor, MmprojModel, ModelBase, TextModel, gguf, logg from .qwen import QwenModel -@ModelBase.register("DeepseekOCRForCausalLM", "UnlimitedOCRForCausalLM") +@ModelBase.register("DeepseekOCRForCausalLM") class DeepseekOCRVisionModel(MmprojModel): + # HF dynamic_preprocess() max_num, which differs per model + preproc_max_tiles = 9 + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.clip_projector_type = gguf.VisionProjectorType.DEEPSEEKOCR @@ -43,6 +46,9 @@ class DeepseekOCRVisionModel(MmprojModel): # @bluebread: there's no window_size in config but just add it here anyway self.gguf_writer.add_vision_window_size(self.hparams.get("window_size", 14)) + self.gguf_writer.add_vision_preproc_min_tiles(2) + self.gguf_writer.add_vision_preproc_max_tiles(self.preproc_max_tiles) + # SAM configuration sam_hparams = hparams['sam'] self.gguf_writer.add_vision_sam_layers_count(sam_hparams['layers']) @@ -93,8 +99,15 @@ class DeepseekOCRVisionModel(MmprojModel): return super().filter_tensors((name, gen)) +@ModelBase.register("UnlimitedOCRForCausalLM") +class UnlimitedOCRVisionModel(DeepseekOCRVisionModel): + preproc_max_tiles = 32 + + @ModelBase.register("DeepseekOCR2ForCausalLM") class DeepseekOCR2VisionModel(DeepseekOCRVisionModel): + preproc_max_tiles = 6 + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.clip_projector_type = gguf.VisionProjectorType.DEEPSEEKOCR2 diff --git a/tools/mtmd/clip.cpp b/tools/mtmd/clip.cpp index d6670030ff..c77e7cc9d3 100644 --- a/tools/mtmd/clip.cpp +++ b/tools/mtmd/clip.cpp @@ -1761,6 +1761,10 @@ struct clip_model_loader { // qwen2 encoder is GQA, requires KEY_N_HEAD_KV get_u32(string_format(KEY_N_HEAD_KV, "vision"), hparams.n_head_kv); } + // unlimited-ocr shares the v1 projector but tiles up to 32 + get_u32(KEY_PREPROC_MIN_TILES, hparams.preproc_min_tiles, false); + get_u32(KEY_PREPROC_MAX_TILES, hparams.preproc_max_tiles, false); + GGML_ASSERT(hparams.preproc_min_tiles <= hparams.preproc_max_tiles); } break; case PROJECTOR_TYPE_HUNYUANVL: { @@ -1909,6 +1913,9 @@ struct clip_model_loader { if (hparams.image_max_pixels > 0) { LOG_INF("%s: image_max_pixels: %d%s\n", __func__, hparams.image_max_pixels, hparams.custom_image_max_tokens > 0 ? " (custom value)" : ""); } + if (hparams.preproc_max_tiles > 0) { + LOG_INF("%s: preproc_tiles: %d - %d\n", __func__, hparams.preproc_min_tiles, hparams.preproc_max_tiles); + } } else if (is_audio) { LOG_INF("\n--- audio hparams ---\n"); LOG_INF("%s: n_mel_bins: %d\n", __func__, hparams.n_mel_bins);