scan, split, OCR, prepare for LLM
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

stage2_results.md 9.6KB

Stage 2 Results — OCR Pipeline

Путь проекта

Исходная точка

Единый скрипт src/cli.py → разрезание изображений на страницы (Stage 1). Нужен Stage 2 — распознавание текста и структуры документа, генерация LaTeX/HTML/Markdown для последующего анализа LLM.


Опробованные варианты

1. PaddleOCR базовый (PP-OCRv5)

Результат: 66 текстовых блоков, русский текст — ~60% точности.

  • i-WHAeKC AOrOBOpa вместо і - индекс договора
  • t - номер месяцаB дефолте — латиница смешана с кириллицей
  • Нет структуры документа (заголовки, формулы, таблицы слиты в сплошной текст)
  • Вывод: только для английского, для русского требуется структура

2. PP-StructureV3 (ансамбль специализированных моделей)

Результат: 22 структурированных блока с layout-разметкой.

  • Layout detection: ✅ [number], [formula], [text], [paragraph_title]
  • Display-формулы: ✅ \mathrm{C Rec}_{\mathrm{it}}=\sum...
  • Таблицы: ✅ PP-TableMagic с bbox ячеек
  • Русский текст: ⚠️ ~85% (eslav_PP-OCRv5_mobile_rec)
  • Вывод: структура отлично, текст — терпимо

3. Замена на cyrillic_PP-OCRv5_mobile_rec

Результат: разница ~1-2%, несущественна.

  • eslav: LGD_ехtг; (кириллица г)
  • cyrillic: LGD_ехtr; (латиница r) — чуть лучше
  • Вывод: обе мобильные модели, серверной русской не существует

4. PP-OCRv5_server_rec / PP-OCRv6

Результат: ❌ не поддерживают русский.

  • Server model: только CN/JP/EN
  • PP-OCRv6: 52 латинских языка
  • Вывод: русский — только mobile-версии

5. Локальный LLM-корректор (Qwen2.5-7B GGUF)

Результат: +25% читаемости текста.

До:   t - номер месяцаB дефолте, на который прогнозируются возвраты
После: т — номер месяца в диапазоне между текущим сроком в дефолте и горизонтом взыскания
  • ~4 tok/sec на CPU, ~20s/блок
  • Вывод: эффективен для пост-обработки

6. VLM-корректор (Qwen3.8 Max через OpenCode API)

Результат: полное восстановление текста + авто inline-формулы.

До:   ΣДсе, - дисконтированная сумма возвратов
После: $\sum_t DCF_{i,t}$ — дисконтированная сумма возвратов
  • ~10s/блок, Anthropic API zen/go/v1/messages
  • Вывод: лучшее качество, требует API-доступа

7. Docling (IBM Research)

Результат: ❌ не поддерживает PaddleOCR как OCR-backend.

  • Поддерживает: EasyOCR, Tesseract, RapidOCR, Nemotron
  • Вывод: несовместим с нашим пайплайном

8. PaddleOCR-VL (ERNIE-4.5-0.3B)

Результат: модель загружена (1.79 GB), ~15 мин/стр на CPU.

  • Одна VLM вместо ансамбля
  • Теоретически решает проблему русского (LM понимает контекст)
  • Вывод: правильный подход при GPU, нереализуем на CPU

9. Surya 2 (Datalab, 650M VLM) ⭐

Результат: лучший русский OCR из коробки — но медленно на CPU.

  • 95%+ точность русского текста без коррекции
  • Авто inline-формулы: <math>MRec_{it}</math>$MRec_{it}$
  • ~300s/стр после CPU-оптимизаций (vs 140s PaddleOCR)
  • Слабость: таблицы требуют много токенов → таймауты на CPU
  • Вывод: лучший выбор по качеству, медленнее на CPU

10. VLM full-page (Qwen3.8 Max) для таблиц

Результат: 118s на страницу с таблицей, качество отличное.

  • Таблица → pipe-Markdown: | col1 | col2 |
  • Формулы → $...$
  • Структура заголовков сохранена
  • Вывод: для табличных страниц — лучший вариант

Итоговая архитектура

Входное изображение (JPEG/PNG/TIFF)
    │
    ▼
src/image_prepare.py          ← Stage 1: разрезание
    │ --slice / --slice-auto
    │ --border, --post-crop
    │
    ▼
src/image_ocr.py            ← Stage 2: OCR + Markdown
    │ --ocr-engine paddle|surya
    │ --llm, --vlm
    │ --force-ocr, --pause
    │ --result-one-document (ON по умолчанию)
    │
    ├─ PaddleEngine / SuryaEngine   (OCR)
    ├─ fix_ocr_errors               (VaR, V^2)
    ├─ LlmCorrector                 (Qwen2.5-7B, local)
    ├─ VlmCorrector                 (Qwen3.8 Max, API)
    │
    ▼
.md + .json (per page) + merged.md

По умолчанию включено

Функция Статус
--resume (пропуск JSON) ON
--result-one-document ON
--pause 5 ON
--post-crop (Stage 1) ON

Модули

src/
  image_prepare.py         — CLI Stage 1
  image_ocr.py           — CLI Stage 2
  cli_utils.py           — run_main()
  env.py                 — загрузка .env
  split/slicer.py        — разрезание, post-crop, border
  ocr/
    paddle_engine.py     — PP-StructureV3 + кастом YAML (eslav)
    surya_engine.py      — Surya 2 + CPU-оптимизации + health_check
  postprocess/
    fixups.py            — VaR, V^2
    corrector.py         — Corrector Protocol
    llm_corrector.py     — Qwen2.5-7B локально
    vlm_corrector.py     — Qwen3.8 Max API (Anthropic)
  markdown/generator.py  — Markdown + валидация LaTeX
  latex/
    json_to_latex.py     — Единый JSON→LaTeX (Paddle + Surya)
    json_to_latex.py     — Единый JSON→LaTeX+HTML (Paddle + Surya + Qwen)

Оптимизации Surya 2 для CPU

Параметр До После Эффект
KEEP_ALIVE off on -23s повторный старт
CTX per slot 12288 8192 -30% RAM
Parallel slots 8 1 -80% слотов
Pre-scale 2552px 1056px -60% пикселей
Threads default -t 8 стабильно
Итого 430s 300s -30%

Health-check + retry

llama-server не отвечает → logger.warning → перезапуск SuryaEngine
→ повторный health_check → OK / RuntimeError с инструкцией

Сравнение движков

Параметр PaddleOCR Surya 2 VLM Qwen3.8
Архитектура Ансамбль 5 моделей Один VLM (650M) Cloud VLM
Русский текст ~85% 95%+ 98%+
Формулы PP-FormulaNet VLM (отлично) VLM (отлично)
Таблицы PP-TableMagic + bbox ❌ CPU timeout ✅ Pipe-Markdown
Inline-формулы Нет <math> тэги $...$
Скорость CPU ~140s ~300s ~120s (API)
Офлайн
Размер моделей ~2.5 GB ~1.5 GB 0 (cloud)

Ключевые цифры (на CPU: 8 ядер, 32 GB RAM)

Этап PaddleOCR Surya 2 VLM
OCR (одна страница) 140s 300s 120s
LLM-корректор +5 min не нужен не нужен
VLM-корректор +10s/блок не нужен
JSON + MD сохранение <1s <1s <1s
Merge в один документ <1s <1s <1s
Итого на страницу ~5 min ~5 min ~2 min
12 страниц (batch) ~28 min* ~60 min ~24 min

* PaddleOCR с --pause 5


Неиспользованные подходы

  1. EasyOCR — WER 0.12 vs Paddle 0.056
  2. Tesseract — нет GPU, хуже на русском
  3. RapidOCR — легче, качество ниже
  4. Fine-tune eslav — требует GPU + датасет

Выводы

  1. PP-StructureV3 — надёжен для структуры и формул, русский текст требует LLM/VLM коррекции
  2. Surya 2 — лучший русский OCR из коробки, CPU-оптимизации дали -30% времени
  3. VLM Qwen3.8 Max — решает таблицы там, где Surya падает, при приемлемой скорости
  4. Гибридный подход: Surya для текста + VLM для таблиц = лучший баланс
  5. LLM/VLM коррекция эффективна для PaddleOCR, не нужна для Surya 2
  6. CPU-ограничения — основной фактор, GPU сделал бы Surya/PaddleOCR-VL идеальным выбором