--- title: Chandra OCR 2 emoji: 📄 colorFrom: indigo colorTo: purple sdk: gradio app_file: app.py pinned: false license: apache-2.0 short_description: Layout-aware document OCR to markdown + extracted figures models: - datalab-to/chandra-ocr-2 tags: - ocr - document-ai - vision-language suggested_hardware: zero-a10g --- # Chandra OCR 2 — Space demo Gradio demo for [`datalab-to/chandra-ocr-2`](https://huggingface.co/datalab-to/chandra-ocr-2), Datalab's layout-aware document OCR model. Upload PDFs or images and get back markdown with tables, math, forms, and reading order preserved — **plus** a separate figure-extraction stage that crops charts, diagrams, photos and stamps at full resolution and reports the model's caption and any structured data it read from them. ## Hardware **This will not run on the free CPU tier.** The model is ~10B parameters, roughly 20 GB in bf16. | Hardware | Works? | |---|---| | CPU basic (free) | No — OOM at load | | ZeroGPU (H200 slice) | Yes — recommended | | RTX PRO 6000 (Blackwell, sm_120) | Yes | | L40S / A100 | Yes | | T4 (16 GB) | No, unless you add 4-bit quantisation | Set this under **Settings → Hardware** after creating the Space. `suggested_hardware` in the frontmatter is only a hint to visitors; it does not provision anything. ## How it works - PDFs are rasterised page by page with PyMuPDF (no poppler/apt needed). - Each page is capped on its long edge before inference — visual token count scales with area, so this is the main lever on latency and memory. - Pages are batched `PAGES_PER_GPU_CALL` at a time so each ZeroGPU allocation finishes inside its duration budget. - **Stage 1 (text):** raw layout output → markdown via `parse_markdown`. - **Stage 2 (figures):** `parse_chunks` locates figure-like blocks, which are cropped from the **full-resolution** source page (the bbox is per-axis normalised, so it maps cleanly onto any resolution with the same aspect ratio). Captions and structured data come from the model's layout output and are labelled **degraded** when the fallback path was used. Output is offered as rendered markdown, markdown source, the raw model string, a figure gallery + metadata table, a combined `.md`, and a `.zip` containing per-page markdown, per-page raw output, extracted figure images, and a `manifest.json`. The app prefers the official `chandra` package (`generate_hf` + `BatchInputItem` + `parse_markdown` + `parse_chunks`). If that import fails, it falls back to driving the chat template through plain `transformers` so the Space still boots — and reports the degradation in the status panel and diagnostics. ## Configuration Edit the constants at the top of `app.py`: | Constant | Default | Purpose | |---|---|---| | `PAGES_PER_GPU_CALL` | 3 | Pages per ZeroGPU allocation | | `GPU_DURATION` | 180 | Seconds requested per allocation | | `MAX_PAGES` | 20 | Per-run page cap | Prompt types are **enumerated from the package** (`PROMPT_MAPPING`), not hardcoded. Only `ocr_layout` and `ocr` are currently exposed; the dropdown is editable so you can try undocumented values. ## Troubleshooting | Symptom | Cause / fix | |---|---| | Space won't start, opaque "upload failed" | Model load failed at import — the diagnostics panel auto-opens with the exact error. | | `CUDA out of memory` per page | Lower **Max image side**; it's the biggest VRAM lever. | | No figures in the gallery | The model returned no figure bboxes for this prompt type, or the `chandra` package is unavailable (outputs marked degraded). | | `flash-attn` build error | Do **not** add flash-attn — Blackwell (sm_120) has no prebuilt wheels. SDPA is used. | | `torch` version mismatch | Do **not** pin torch — the Space image ships a build matched to the driver/CUDA. | ## Licence — read before making this public The Space **code** here is Apache-2.0. The **model weights** are not: > Code is Apache 2.0. Model weights are under a modified OpenRAIL-M license. > Free for research, personal use, and startups under $2M funding/revenue. > Cannot be used competitively with our API. A public, free, hosted OCR endpoint is plausibly "competitive with our API." If you are past the revenue threshold, or intend this as a product rather than a demo, check with Datalab first. Setting the Space to **private** avoids the question entirely.