Files

6.4 KiB
Raw Permalink Blame History

Локальный OCR-сервис Xiaomi-OCR-0

Контекст

На этой машине развёрнута и работает локальная OCR-модель Xiaomi-OCR-0 (SeerRay-Lab/Xiaomi-OCR-0). Это vision-language модель на 0.8B параметров (основа — Qwen3.5-0.8B, архитектура Qwen3_5ForConditionalGeneration). Она умеет:

  • Разбор документов → Markdown (таблицы в OTSL → HTML, формулы в LaTeX, порядок чтения).
  • KIE (извлечение ключевой информации) → JSON по заданной схеме полей.
  • VQA — короткие ответы на вопросы по изображению.
  • Разбор отдельных регионов: текст, таблица, формула.
  • Сканы, чеки, формулы (в т.ч. рукописные), рукописный текст, каллиграфию, PDF (через рендер страниц).
  • Всё работает только локально, без облачных API. Ключ API не нужен.

Окружение

Параметр Значение
ОС Ubuntu 26.04, Linux x86_64
GPU NVIDIA RTX 4060 Laptop, 8 ГБ VRAM (vLLM занимает ~75%)
Каталог проекта /home/alexives/OCR Xiaomi neuro (в пути есть пробел — всегда бери его в кавычки)
Python venv /home/alexives/OCR Xiaomi neuro/.venv → симлинк на /mnt/data/alexives_cache/xiaomi_ocr_venv (Python 3.12)
Кэш HF (веса модели) /mnt/data/alexives_cache/huggingface
Движок инференса vLLM 0.31.0, CUDA 13
Обязательная переменная окружения VLLM_USE_FLASHINFER_SAMPLER=0 (без неё vLLM падает: нет системного nvcc/CUDA toolkit для JIT FlashInfer)

На системном разделе / мало места (~3.7 ГБ). Любые тяжёлые кэши и зависимости клади в /mnt/data/alexives_cache/.

Запуск и остановка

"/home/alexives/OCR Xiaomi neuro/start.sh"   # запускает vLLM (:8000) и веб-демо (:8787), ждёт готовности
"/home/alexives/OCR Xiaomi neuro/stop.sh"    # останавливает оба процесса

Холодный старт vLLM занимает ~2 минуты (torch.compile + захват графов CUDA). Перед запросами опрашивай GET /v1/models, пока не придёт ответ. Логи: vllm.log и demo.log в каталоге проекта.

Сервисы

Сервис URL Назначение
vLLM (OpenAI-совместимый API) http://127.0.0.1:8000/v1 Прямой инференс. Основная точка интеграции.
Веб-демо + REST http://127.0.0.1:8787 UI в браузере и упрощённый REST с готовой пред- и постобработкой
  • Имя модели в запросах: SeerRay-Lab/Xiaomi-OCR-0 (именно так, с префиксом).
  • Проверка готовности: curl -s http://127.0.0.1:8000/v1/models и curl -s http://127.0.0.1:8787/api/health ("ready": true).
  • Сервисы слушают только loopback (127.0.0.1). Не открывай их наружу.

Вариант A: прямой вызов vLLM (рекомендуется)

Обязательные правила запроса

  1. Ровно одно изображение на запрос, сначала изображение, потом текст, в одном user-сообщении.
  2. Изображение передаётся как data-URL: data:image/png;base64,....
  3. Thinking-режим выключен: "chat_template_kwargs": {"enable_thinking": false}.
  4. Жадное декодирование (как в эталонном пайплайне): "temperature": 0, "top_p": 0.8, "presence_penalty": 0.0, "repetition_penalty": 1.0
  5. max_tokens: 4096 по умолчанию для целой страницы (максимум 16384, но картинка + промпт + вывод должны влезть в контекст 16384).
  6. Если finish_reason == "length" — вывод обрезан: увеличь max_tokens или уменьши картинку / раздели её на части.
  7. Без системного сообщения. Промпты — на английском, дословно.

Промпты (дословно)

  • Целая страница документа → Markdown: Extract all information from the main body of the document image and represent it in markdown format, ignoring headers and footers. Tables should be expressed in OTSL format, formulas in the document should be represented using LATEX format, and the parsing should be organized according to the reading order.
  • Регион с текстом / заголовком: Extract the text in the image.
  • Регион с таблицей: Parse the table in the image into OTSL.
  • Регион с формулой: Identify the formula in the image and represent it using LATEX format.
  • KIE с известными полями: Extract key information in the image Please output the key information in JSON format according to the following schema: {"company": "", "date": "", "total": ""}
  • KIE без заданных полей: Extract the key information from the document image as a JSON object. Use concise field names. Return JSON only; use an empty string for missing values.
  • VQA: <ВОПРОС> Answer the question using a single word or phrase.

Постобработка

Таблицы приходят в OTSL (токены <fcel>, <ecel>, <lcel>, <ucel>, <xcel>, <nl>). Конвертируй в HTML:

import sys; sys.path.insert(0, "/home/alexives/OCR Xiaomi neuro")
from postprocess.otsl import convert_otsl_to_html
from postprocess.document import finalize_document
md = finalize_document(raw_model_text)

Вариант B: REST веб-демо (:8787)

POST http://127.0.0.1:8787/api/ocr, Content-Type: application/json:

{
  "task": "document",
  "image_base64": "<base64 или data:image/...;base64,...>",
  "image_mime": "image/jpeg",
  "max_tokens": 4096,
  "temperature": 0
}