--- title: OvisOCR2 emoji: 🔎 colorFrom: blue colorTo: gray sdk: gradio sdk_version: 6.20.0 python_version: "3.12.12" app_file: app.py pinned: false license: apache-2.0 hardware: zero-gpu startup_duration_timeout: 30m models: - ATH-MaaS/OvisOCR2 preload_from_hub: - ATH-MaaS/OvisOCR2 short_description: Stream structured Markdown from document images and PDFs. --- # OvisOCR2 — document OCR demo A focused image and PDF document parsing demo for [ATH-MaaS/OvisOCR2](https://huggingface.co/ATH-MaaS/OvisOCR2). It preserves reading order and emits Markdown with LaTeX formulas, HTML tables, and rendered visual-region crops. Model tokens stream into the interface as they are generated. PDFs are rasterized locally and processed one page at a time in Base mode. Up to four pages share one streamed GPU request by default, while each page is still inferred independently and sequentially. The browser merges the results, so long documents do not have to fit inside one ZeroGPU lease. GPU duration is estimated from the number of pages that actually remain in each group, so a short second group does not reserve the same ZeroGPU quota as a four-page group. If a Gradio stream closes without an explicit backend error, the browser reconnects from the first unfinished page while retaining every completed page. This demo intentionally does not expose a separate Long mode. The five packaged examples cover two financial tables, two Chinese handwriting pages, and one formula-rich OmniDocBench research-paper page. They are selectable directly in the interface and are also covered by the local smoke-test workflow. The workspace opens empty so examples remain an explicit user choice rather than an automatic input. ## Local run The verified local model directory is `/root/models/ATH-MaaS/OvisOCR2`. ```bash conda env create -f environment.yml conda activate ovisocr2-demo npm ci npm run build CUDA_VISIBLE_DEVICES=0 \ OVISOCR_MODEL_PATH=/root/models/ATH-MaaS/OvisOCR2 \ python app.py ``` Open `http://127.0.0.1:7860`. ### DSW proxy The server already listens on `0.0.0.0`. Set a DSW id and the public proxy URL is generated from the same `PORT` automatically: ```bash CUDA_VISIBLE_DEVICES=0 \ PORT=7869 \ OVISOCR_DSW_ID=1976932 \ OVISOCR_MODEL_PATH=/root/models/ATH-MaaS/OvisOCR2 \ python app.py ``` The corresponding URL is `https://1976932-proxy-7869.dsw-gateway-cn-hangzhou.data.aliyun.com/`. For a different gateway or an explicit public URL, set `OVISOCR_ROOT_PATH` instead; it takes precedence over `OVISOCR_DSW_ID`. DSW's per-port proxy uses its own hostname and serves at `/`, so the ASGI root path stays empty. If an explicit URL contains a real subpath, such as `https://example.test/ocr/`, the app passes only `/ocr` to Gradio's `root_path`; passing the whole URL into this custom FastAPI server would break static mounts. For a UI-only smoke that does not load the model: ```bash OVISOCR_TEST_MODE=1 python app.py ``` ## Hugging Face Space The checked-in `dist/` directory is the production frontend, so the folder can be uploaded directly to a Gradio Space without a Node build step. Select ZeroGPU hardware in the Space settings. The README metadata pins Python 3.12.12 and Gradio 6.20.0 and declares `hardware: zero-gpu`; `app.py` decorates only the inference endpoint with `@spaces.GPU` and loads the model on CUDA at module scope, following the ZeroGPU loading contract. On Hugging Face, the model source automatically falls back from the local path to `ATH-MaaS/OvisOCR2`. PDFs are limited to 50 pages by default. Groups of up to four pages share a ZeroGPU reservation while the frontend preserves already completed pages. ## Runtime knobs - `OVISOCR_MODEL_PATH`: local directory or Hub model id. - `OVISOCR_MAX_NEW_TOKENS`: defaults to `16384`, matching the model README inference configuration. - `OVISOCR_MAX_PDF_PAGES`: defaults to `50`. - `OVISOCR_PAGES_PER_GPU_REQUEST`: defaults to `4` and is capped at `5`. - `OVISOCR_PDF_RENDER_SCALE`: PDF rasterization scale, defaults to `2.0`. - `OVISOCR_STREAM_MIN_CHARS`: minimum new characters between stream updates, defaults to `64`. - `OVISOCR_STREAM_MAX_INTERVAL`: maximum seconds between available stream updates, defaults to `0.25`. - `OVISOCR_GPU_SECONDS_PER_PAGE`: duration-estimation budget, defaults to `30` seconds per page. - `OVISOCR_GPU_DURATION_FLOOR`: minimum per-group ZeroGPU reservation, defaults to `45` seconds. - `OVISOCR_GPU_DURATION_CEILING`: maximum estimated per-group reservation, defaults to `120` seconds. - `OVISOCR_GPU_DURATION`: optional fixed per-group override; unset by default so dynamic duration is used. - `OVISOCR_ATTN_IMPLEMENTATION`: defaults to `sdpa`. - `OVISOCR_DSW_ID`: generates the Hangzhou DSW proxy root using the active `PORT`. - `OVISOCR_ROOT_PATH`: explicit proxy URL or ASGI path prefix; overrides `OVISOCR_DSW_ID`. - `OVISOCR_TEST_MODE=1`: deterministic mock inference for UI/integration tests.