# 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) - Русский текст: ⚠️ ~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 латинских языка, русского нет - **Вывод:** серверной русской модели в PaddleOCR не существует ### 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}$ — дисконтированная сумма возвратов, получаемых на t-ом периоде ``` - ~10s/блок, Anthropic API через `zen/go/v1/messages` - **Вывод:** лучшее качество, но требует API-доступа ### 7. Docling (IBM Research) **Результат:** ❌ не поддерживает PaddleOCR как OCR-backend. - Поддерживает: EasyOCR, Tesseract, RapidOCR, Nemotron - Генерирует HTML/Markdown из коробки - **Вывод:** несовместим с нашим пайплайном ### 8. PaddleOCR-VL (VLM-подход, ERNIE-4.5-0.3B) **Результат:** модель загружена (1.79 GB), но ~15 мин/стр на CPU. - Одна VLM вместо ансамбля: layout → распознавание единой моделью - Теоретически решает проблему русского (языковая модель понимает контекст) - **Вывод:** правильный подход при GPU, нереализуем на CPU ### 9. Surya 2 (Datalab, 650M VLM) **Результат:** ⭐ лучший русский OCR из коробки. - 95%+ точность русского текста без коррекции - Автоопределение inline-формул: `` - ~430s/стр на CPU (vs 140s у PaddleOCR, но качество несравнимо) - Вывод Markdown с `$$...$$` формулами - **Вывод:** лучший выбор при достаточных ресурсах --- ## Итоговая архитектура ``` Входное изображение (JPEG/PNG/TIFF) │ ┌─────────────┴─────────────┐ │ src/image_split.py │ │ --slice / --slice-auto │ │ --pre-rotate, --border │ │ --post-crop (default ON) │ └─────────────┬─────────────┘ │ JPEG страницы │ ┌─────────────┴─────────────┐ │ src/image_to_latex.py │ │ --ocr-engine paddle/surya │ │ --llm, --vlm (optional) │ └─────────────┬─────────────┘ │ ┌─────────────────────┼─────────────────────┐ ▼ ▼ ▼ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ src/ocr/ │ │ src/postprocess/ │ │ src/postprocess/ │ │ paddle_engine │ │ fixups.py │ │ llm_corrector │ │ surya_engine │ │ vlm_corrector │ │ corrector.py │ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │ │ │ └────────────────────┼─────────────────────┘ │ ParsedBlock[] │ ┌─────────────┴─────────────┐ │ src/markdown/ │ │ generator.py │ │ Валидация $, {}, \left │ └─────────────┬─────────────┘ │ ┌───────────────────┼───────────────────┐ ▼ ▼ ▼ .json (raw) .md .tex + .html (PP-StructureV3 (Markdown) (LaTeX + MathJax) полный дамп) ``` ### Модули ``` src/ cli_utils.py — run_main() общий для CLI image_split.py — CLI разрезания (Stage 1) image_to_latex.py — CLI OCR (Stage 2) split/ slicer.py — разрезание, поворот, рамка, post-crop ocr/ paddle_engine.py — PP-StructureV3 + кастом YAML (eslav) surya_engine.py — Surya 2 VLM + llama.cpp postprocess/ fixups.py — VaR, V^2 corrector.py — Corrector Protocol + apply_corrector() llm_corrector.py — Qwen2.5-7B локально (llama-cpp-python) vlm_corrector.py — Qwen3.8 Max через OpenCode API (Anthropic) markdown/ generator.py — Markdown + валидация LaTeX latex/ tex2html.py — .tex → .html + MathJax ``` ### Модели (локально, ~4 GB) ``` ~/.paddlex/official_models/ (PaddleOCR, ~2.5 GB) PP-DocLayout_plus-L layout detection PP-OCRv5_server_det text detection eslav_PP-OCRv5_mobile_rec RU/EN recognition PP-OCRv5_server_rec EN/CN recognition SLANeXt_wired table structure PP-FormulaNet_plus-L formula recognition (728 MB) ~/.cache/llama_models/ (LLM, ~4.4 GB) Qwen2.5-7B-Instruct-Q4_K_M.gguf локальный корректор HF Hub (Surya 2, ~1.5 GB) datalab-to/surya-ocr-2-gguf 650M VLM ``` --- ## Сравнение движков | Параметр | PaddleOCR (PP-StructV3) | Surya 2 | |----------|:---:|:---:| | Архитектура | Ансамбль 5 моделей | Один VLM (650M) | | Русский текст | ~85% | 95%+ | | Формулы | PP-FormulaNet (отлично) | VLM (отлично) | | Таблицы | PP-TableMagic + bbox | HTML `