Spaces:
Running on Zero
A newer version of the Gradio SDK is available: 6.26.0
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,
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_CALLat 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_chunkslocates 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 plaintransformersso 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.