
Вам нужен 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 комбинаций модель + движок, упорядочено по убыванию:
|
# |
Модель |
Движок/окружение |
Стр/ |
|
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. Но это ловушка.
Посмотрите на полноту вывода — сколько символов или токенов модель выдает на одну страницу:
· 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 под 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/