Как выбрать OCR в 2026-м: тестируем девять моделей на трех движках инференса на рукописном русском

от автора

Вам нужен OCR. В техобзорах рекомендуют Tesseract, на Хабре все пишут про VLM, идете на Hugging Face — там PaddleOCR-VL, DeepSeek-OCR, Dots.OCR, Qwen2.5-VL, и каждая называет себя SOTA. Прибавим к этому vLLM, SGLang, TGI, Native HF Transformers, и вот вы зависли между десятками комбинаций. Мы протестировали девять моделей на трех движках инференса на рукописном русском и отразили в таблице, какая модель под какую задачу лучше подходит.

Ваше время ценно для нас. Так что сразу держите краткие выводы

  • Native HF Transformers не для продакшена. Тот же Qwen2.5-VL под vLLM/SGLang в два раза быстрее, чем под Native, на той же GPU.

  •  Размер модели обманчив. PaddleOCR-VL 1.7B обгоняет Qwen2.5-VL-7B в пять с лишним раз по скорости в стр/мин и в 6,7 раза по токен/сек. Специализация бьет general-purpose.

  • Tesseract быстрее всех — миф. На сложных изображениях он возвращает 411 символов против 1193 токенов у PaddleOCR-VL. Быстро возвращать пустоту — не победа.

  • В классе general-VLM  наша компактная модель Cotype Light 3 на 9 млрд параметров обгоняет Qwen2.5-VL-7B на 79% по стр/мин с включенным MTP-декодингом (37.7 vs 21.1) при сопоставимом TTFT.

Вот обещанная таблица со сводкой, какие модели в каких сценариях себя лучше показали. 

Сценарий

Рекомендация

Почему

Печатные документы, нужна скорость, простая верстка

Tesseract или RapidOCR на CPU

140–190 страниц/мин, бесплатно, GPU не требуется

Сложная верстка, таблицы, Markdown на выходе

PaddleOCR-VL + SGLang

110 страниц/мин, 56 ГБ VRAM, лидер OmniDocBench

Production VLM с минимумом рисков совместимости

PaddleOCR-VL + vLLM

99 страниц/мин, лучший TTFT, шире поддержка моделей

General-purpose VLM, OCR — лишь часть задач

Qwen2.5-VL-7B + vLLM

21 страница/мин, универсальная модель, знает русский

Прототип, Jupyter-research

Native HF Transformers

Только для прототипа. В production никогда

MoE-архитектура, batch-обработка

DeepSeek-OCR + vLLM

56 страниц/мин, 570M активных параметров (3B total)

Локальный VLM в закрытом контуре, RU-домен

Cotype Light 3 + vLLM с MTP

37.7 страниц/мин, 9B, свежий релиз 2026–06, встроенный MTP-декодинг

Цифры получены на NVIDIA A100 80GB (shared), batch=1, 15 образцов русскоязычного рукописного текста. 

Ниже объясню, как мы эту таблицу получили и какие нюансы стоят за каждой строкой.

Ландшафт: традиционный OCR vs VLM в 2025–2026 гг.

До 2024 года выбор OCR был относительно понятным. Tesseract, PaddleOCR, EasyOCR. Пайплайн один: детекция текстовых областей, распознавание символов, постобработка. Обычный текст на выходе, минимальные требования к железу, предсказуемость.

Но тут появились VLM (Vision Language Models). По сути это end-to-end модели: вижн-энкодер превращает картинку в эмбеддинги, LLM-декодер генерирует текст. Никаких отдельных стадий: подал картинку — получил Markdown, JSON, HTML.

Вот сравнительная таблица для традиционного и VLM-подхода к OCR.

Традиционный OCR

OCR на VLM

Архитектура

Детекция, распознавание, постобработка

End-to-end: вижн-энкодер + LLM-декодер

Типичная скорость

0,5–3 сек/стр (CPU)

2–10 сек/стр (GPU)

Сложная верстка

Слабо

Хорошо

Структурный вывод

Простой текст

Markdown, HTML, JSON

Стоимость self-hosted

Очень низкая (CPU)

Зависит от модели и движка (GPU)

А еще появились специализированные OCR-VLM типа PaddleOCR-VL (1,7B), DeepSeek-OCR (3B MoE), Dots.OCR (3B). Это VLM по архитектуре, но дообученные исключительно на OCR-задачах. Они меньше VLM общего назначения  в 4–10 раз, но на распознавании документов работают на уровне или лучше.

В таком многообразии инструментов нам было интересно узнать, где проходит граница между «брать классику» и «брать VLM» и какая конкретная связка модель + движок оптимальна.

Как мы это узнавали? 

Методология

Мы решили разработать честный бенчмарк, в котором все модели бегут в одинаковых условиях. Что мы зафиксировали:

Унифицированные параметры:

·      Precision: bfloat16 (для всех VLM)

·      max_new_tokens: 2048

·      temperature: 0.0 (детерминированный вывод)

·      Image preprocessing: thumbnail 800×800, JPEG q85, base64

·      Warmup: пять прогонов перед замерами (прогрев KV-cache, CUDA-кернелов)

·      Промпт: SYSTEM: «You are an OCR assistant. Extract all text…» + USER: «Extract all text from this document.»

Стек инфраструктуры:

·      NVIDIA A100 80GB PCIe (им пришлось делиться  с другими командами, об ограничениях ниже)

·      vLLM 0.18.1: gpu-memory-utilization=0.4, max-model-len=4096, OpenAI-compatible API

·      SGLang v0.5.10: mem-fraction-static=0.85, OpenAI-совместимый API

·      Native HF Transformers: AutoModel.generate() напрямую, без оптимизаций

Движки запускались в Docker (vllm/vllm-openai:latest, lmsysorg/sglang:latest).

Датасет:

15 примеров русскоязычных текстов из Russian Handwriting OCR: пять чистых сканов, пять «темных» (низкий контраст), пять «светлых» (засветка), выборка через random_state=42. Мы специально для теста взяли рукописи, так как это максимально сложная задача для любого OCR: нестандартные символы, вариативность почерка, шум. Если модель справится здесь, то на печатных документах и подавно.

Метрики:

·      pages/min: пропускная способность на уровне документов

·      TTFT (Time To First Token, мс): задержка до первого токена

·      TPOT (Time Per Output Token, мс): среднее время на токен

·      tok/s: токенов в секунду

·      tok/page: токенов на страницу (для VLM)

·      peak GPU memory (ГБ), GPU utilization (%)

Замеры пишутся в JSON, графики строятся отдельно.

Результат 1. Общий рейтинг стр/мин и ловушка Tesseract

Первое, что хочется знать про OCR, сколько страниц в минуту. Вот общий рейтинг всех 14 комбинаций модель + движок, упорядочено по убыванию:

Общий рейтинг pages/min

Общий рейтинг pages/min

#

Модель

Движок/окружение

Стр/
мин

1

Tesseract

CPU

193.1

2

RapidOCR

CPU

143.5

3

PaddleOCR-VL

SGLang (GPU)

110.8

4

EasyOCR

CPU

105.5

5

PaddleOCR-VL

vLLM (GPU)

98.7

6

Dots.OCR

vLLM (GPU)

61.6

7

DeepSeek-OCR

vLLM (GPU)

56.3

8

Cotype Light 3 (+MTP)

vLLM (GPU)

37.7

9

Dots.OCR

SGLang (GPU)

27.9

10

Cotype Light 3

vLLM (GPU)

26.5

11

Qwen2.5-VL-7B

SGLang (GPU)

21.3

12

Qwen2.5-VL-7B

vLLM (GPU)

21.1

13

PaddleOCR v5

CPU

15.0

14

Qwen2.5-VL-7B

Native HF (GPU)

10.9

В лидерах Tesseract (193) и RapidOCR (143) на CPU. На GPU быстрее всего PaddleOCR-VL под SGLang (111) и под vLLM (99). EasyOCR (105) дает неплохой CPU-результат. Аутсайдеры: Qwen2.5-VL-7B (21 на vLLM/SGLang, 11 на Native) и PaddleOCR v5 (15 стр/мин на CPU).

Кажется очевидным, что традиционный OCR на CPU быстрее VLM на GPU, берите Tesseract. Но это ловушка.

Посмотрите на полноту вывода — сколько символов или токенов модель выдает на одну страницу:

OCR vs VLM: скорость и полнота

OCR vs VLM: скорость и полнота

·      Tesseract: 411 символов/стр

·      RapidOCR: 549

·      PaddleOCR v5: 766

·      EasyOCR: 795

·      PaddleOCR-VL: 1193 токенов/стр

Tesseract быстрый именно потому, что возвращает меньше. На сложных изображениях (рукопись, низкий контраст, наклон) он пропускает участки, где не уверен, и возвращает пустую строку. Быстро отвечать «не знаю» — так себе победа.

EasyOCR лидирует по полноте среди традиционных OCR-моделей (795 символов) при разумных 105 стр/мин, это честный CPU-бейзлайн. RapidOCR при 549 символах — компромисс между скоростью и полнотой.

VLM выдают на порядок больше токенов, потому что распознают разметку: заголовки, списки, таблицы в Markdown. 30–40% объема у PaddleOCR-VL — это не сами символы, а структура документа.

Вывод: количество распознанных страниц в минуту без контекста полноты — бесполезная метрика. На простых печатных документах Tesseract будет лидером по причине минимальной вычислительной сложности. На сложных — по причине пропусков.

Результат 2. vLLM vs SGLang vs Native, 2-кратный разрыв на одной модели

После выбора VLM нужно определиться с движком инференса.

Есть три кандидата:

·  vLLM: PagedAttention, де-факто стандарт для прода. Широкая поддержка моделей, OpenAI-совместимый API.

·  SGLang: RadixAttention, агрессивная оптимизация KV-cache. Лучше пропускная способность на специализированных моделях, экономнее по памяти.

·  Native HF Transformers: прямой AutoModel.generate(). Минимум зависимостей, максимум совместимости. Используется для прототипирования.

Чтобы изолировать эффект движка, мы прогнали одну модель, Qwen2.5-VL-7B, под всеми тремя:

Qwen2.5-VL-7B, сравнение движков

Qwen2.5-VL-7B, сравнение движков

Qwen2.5-VL под Native vs vLLM vs SGLang

Движок

TTFT, мс

стр/мин

GPU memory, ГБ

GPU util, %

Native HF

138.9

10.9

49.6

64.3

vLLM

78.4

21.1

68.6

98.7

SGLang

122.4

21.3

56.5

96.7

Вывод 1: Native HF не для прода. Двукратное отставание в скорости распознавания — это не просто «немного хуже», а вдвое хуже. Утилизация GPU — 64% против 97–99%, Native HF просто не умеет грузить карту. С ростом партий запросов (batch > 1) разрыв станет еще заметнее.

Вывод 2: разница между vLLM vs SGLang в пределах погрешности. По пропускной способности (throughput) на Qwen они идут почти одинаково (21.1 vs 21.3), однако  vLLM лучше TTFT (78 мс vs 122) и выигрывает в плане совместимости с моделями. SGLang экономнее по памяти (57 ГБ vs 69 ГБ у vLLM) и в прогонах на специализированных моделях давал +5–14% к пропускной способности.

Рекомендация: по умолчанию для продакшена берем vLLM. К SGLang идем, когда нужна максимальная пропускная способность или когда уперлись в память видеокарты. Native — только для исследований в Jupyter.

Результат 3. PaddleOCR-VL 1.7B обгоняет Qwen2.5-VL 7B в пять с лишним раз по скорости

И это главный неожиданный результат бенчмарка. 

Все восемь VLM-прогонов в одной таблице:

Модель

Движок

TTFT, мс

токен/с

стр/мин

токен/
стр

GPU mem, ГБ

GPU util, %

PaddleOCR-VL

SGLang

140.3

604.2

110.8

1193

56.1

90.2

PaddleOCR-VL

vLLM

64.3

571.7

98.7

1314

69.6

94.8

Dots.OCR

vLLM

83.7

221.4

61.6

666

67.4

96.1

DeepSeek-OCR

vLLM

133.6

419.5

56.3

1224

70.2

95.2

Dots.OCR

SGLang

105.0

252.9

27.9

1004

56.3

97.1

Qwen2.5-VL-7B

SGLang

122.4

90.6

21.3

442

56.5

96.7

Qwen2.5-VL-7B

vLLM

78.4

90.5

21.1

341

68.6

98.7

Qwen2.5-VL-7B

Native

138.9

41.4

10.9

333

49.6

64.3

У PaddleOCR-VL всего 1,7 млрд параметров, у Qwen2.5-VL-7B — 7 млрд. Но первая в 5,2 раза опережает вторую по страницам в минуту (110.8 против 21.1–21.3) и в 6,7 раза — по токенам в секунду (604.2 против 90.5–90.6). По страницам в минуту разрыв меньше, потому что PaddleOCR-VL генерирует больше токенов на страницу (1193 против 341–442) — за счет markdown-разметки в выводе.

Почему так получается?

PaddleOCR-VL, DeepSeek-OCR и Dots.OCR — это специализированные OCR-VLM. Они дообучены на распознавании документов и выдают результат в виде Markdown с разметкой: заголовки, таблицы, списки. Это видно по показателю токен/стр: 1193–1314 у специализированных против 341–442 у Qwen. 30–40% объема у специализированных моделей — это не текст, а структура.

Qwen2.5-VL — модель общего назначения (VLM): умеет отвечать на вопросы по изображению, описывать его, разбираться в структуре документов и многое другое. За универсальность платим скоростью. Плюс Queen’s по природе консервативны: на нечитаемых участках они молчат, а не угадывают. Для рукописи это видится как «низкая полнота», но на читаемых документах это плюс, так как меньше галлюцинаций.

Вывод. Специализация бьет scaling. На задаче с узким сценарием (распознавание документов) маленькая специализированная модель обходит все умеющую большую. И не на 10%, а в разы.

Результат 4. Cotype Light 3 в классе VLM общего назначения

Если VLM-ки общего назначения все равно медленнее спец-OCR, есть ли смысл сравнивать модели внутри этого класса? 

Короткий ответ — есть. Часто нам приходится иметь дело со сценариями, в которых распознавание сканов — лишь часть более широкой задачи: диалог по документу, вопросы по картинке, инструкции с картинкой и прочее. В таких случаях выбираем не между PaddleOCR-VL и Qwen, а между различными general-VLM. 

Недавно мы релизнули Cotype Light 3_9B, и решили заодно прогнать нашу мини-модельку в двух режимах: бейзлайн и с включенным MTP (—speculative-config). MTP это Multi-Token Prediction: в чекпоинт Cotype встроена дополнительная голова model-mtp-injected.safetensors, предсказывающая три токена вперед. Основная модель проверяет их за один forward-pass; при попадании получаем несколько токенов за проход вместо одного. Математически идентично обычной генерации, качество вывода не меняется. Это родной режим модели, а не post-hoc оптимизация под наш бенч. Для сравнения взяли Qwen2.5-VL-7B, как стандартную VLM под OCR-задачи. 

Результаты в таблице:

Модель

Движок

TTFT, мс

стр./мин.

с/стр.

GPU mem, ГБ

Qwen2.5-VL-7B

vLLM

78.4

21.1

3.75

68.6

Cotype Light 3

vLLM

86.6

26.5

4.29

71.3

Cotype Light 3

vLLM + MTP

93.1

37.7

2.28

72.2

Baseline дает +25% к Qwen2.5-VL-7B (26.5 против 21.1). MTP-режим — +79% (37.7 vs 21.1). TTFT остается в интерактивном диапазоне 86–93 мс, отклик пользователя не страдает. Расход VRAM сопоставим: 71–72 vs 69 ГБ на A100 80.

Колонку по пропускной способности (токен/сек) мы намеренно не приводим, так как наш streaming-счетчик инкрементирует токен на каждый SSE-чанк, а vLLM в spec-режиме упаковывает в чанк несколько принятых токенов. Wall-clock метрики (стр/мин, сек/стр) считаются от time.perf_counter() и достоверны.

Со спец-OCR типа PaddleOCR-VL, Dots.OCR и DeepSeek-OCR сравнивать Cotype Light 3 напрямую бессмысленно, они созданы под другой класс задач. А внутри своего Cotype Light 3 сейчас впереди Qwen2.5-VL-7B — и это радует.

Результат 5. Цена скорости, GPU память и утилизация

Скорость VLM не бесплатна. Главный ресурс это VRAM.

Из таблицы выше видны три закономерности:

1.      vLLM ест больше памяти (~70 ГБ), чем SGLang (~56 ГБ). Это плата за PagedAttention и более агрессивную преаллокацию KV-cache. Для одной модели на 80GB-карте это нормально, но если хочется крутить две модели рядом или нужен запас под батч, SGLang выгоднее.

2.     Загрузка GPU у vLLM и SGLang на уровне 90–98%, впритык к потолку железа. Это значит, что дальнейший рост возможен только от батчинга или более быстрой карты.

3.     Native HF Transformers просто не умеет загружать GPU — всего 64%. Использует меньше памяти, чем движки (~50 ГБ), но скорость в два раза ниже не из-за памяти, а потому что между токенами карта простаивает.

Практический вывод

Если вы вынуждены делиться A100, как мы (нам было реально доступно ~48 ГБ из 80), у вас два варианта:

·  SGLang + специализированная модель (56 ГБ, впритык). Работает с оговорками.

·  vLLM + любая VLM (69+ ГБ). Не помещается, нужна выделенная карта или меньшая модель.

На выделенной A100 80GB обе связки работают комфортно.

Осторожно с этими цифрами

Будем честны, некоторые наши выводы по этому бенчу стоит читать, беря во внимание следующие оговорки:

  • Для тестов мы брали A100 80GB, но из-за параллельной нагрузки других команд реально было доступно ~48 ГБ. На выделенной карте абсолютные числа будут выше, но относительные разрывы (Native vs движки, PaddleOCR-VL vs Qwen) сохранятся, это нагрузочное свойство, не зависящее от свободной памяти.

  • Batch = 1. Все замеры проводились по одному запросу за раз. В реальной нагрузке с батчингом разрыв vLLM/SGLang над Native будет еще больше, движки именно ради batched inference и сделаны.

  • Тестировали на 15 семплах: пять нормальных сканов + пять затемненных + пять засвеченных, выбранных через random_state=42. Статистическая мощность ограничена, но при разрывах в 2–6 раз это уже не шум.

  • Брали только русскоязычную рукопись (ад для OCR). На печатных документах абсолютные цифры у всех будут выше, особенно у Tesseract, он отстает именно на рукописи.

  • CER/WER не считали. Это бенчмарк скорости, не качества. Эталонная разметка для качественных метрик уже готовится: 15 страниц размечены вручную, о результатах в следующий раз расскажем.

  • Native HF Transformers получилось запустить только для Qwen2.5-VL, остальные модели несовместимы с generic pipeline. Для них Native-сравнение отсутствует.

  • SGLang у нас не запустился на DeepSeek-OCR (image processor: image.size трактуется как метод). Поэтому цифра есть только для vLLM.

Главный технический инсайт

Размер модели — слабый предиктор производительности. Специализация под задачу и выбор движка инференса важнее количества параметров.

Что хотим сделать дальше

  • Добавим больше семплов (печатные документы и таблицы).

  • Измерим CER/WER на размеченных страницах. Эталонная разметка 15 страниц готова, скоро опубликуем CER/WER по тем же моделям, чтобы скорость не была единственной осью сравнения.

  • Проведем замеры с разной нагрузкой (10, 50, 100 параллельных запросов), чтобы понять, как ведут себя движки под реальным трафиком, а не на синтетическом batch=1.

Пишите в комментариях, какой OCR у вас в проде и почему взяли именно его. Интересно собрать живые сценарии, на которых наши цифры не сходятся с практикой.

ссылка на оригинал статьи https://habr.com/ru/articles/1065182/