Open-source project
datalab-to/lift avatar
datalab-to/lift

lift: schema-constrained JSON extraction from PDFs with a 9B vision model

Extract structured data from documents quickly and accurately.

908 stars84 forksPythonApache-2.0

At a glance

What is it?
lift passes a JSON Schema to a 9B vision model and returns schema-aligned JSON from PDFs and images. It ships as lift-pdf with a vLLM backend, a HuggingFace backend, and a Streamlit schema builder.
Who is it for?
Adopt lift if you have a fixed JSON Schema, a GPU budget, and tolerance for a 20.9% full-document accuracy ceiling on the project's own adversarial benchmark; skip it if you need per-field verification or citations, which the README reserves for the hosted Datalab API. Before committing, run lift_extract over ten of your own multi-page documents with your real schema and count how many come back fully correct, then check the MODEL_LICENSE file for your commercial case.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 93 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 19, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem lift targets: fixed schemas over messy documents

Most document extraction pipelines start with a schema. An invoice has an identifier, a total, line items. A contract has parties and dates. The hard part is not defining the schema, it is getting a model to honor it on every page of every document without post-processing that silently drops fields.

lift takes that schema as input. The README describes it as "a 9B vision model that returns a JSON object matching your schema, with schema-constrained decoding guaranteeing valid output." The intended user is a Python developer who already knows what fields they want and would rather write a JSON Schema than prompt a general model and parse whatever comes back.

The scope is deliberately narrow. lift is not a document chat tool and not a general OCR engine. It reads rendered page images, applies the schema, and returns JSON. If your extraction target changes per document, or you cannot express it as JSON Schema, the project's core mechanism does not help you.

How schema-constrained decoding keeps the output valid

The pipeline has three visible stages. First, pages are rendered to images: pypdfium2 is a base dependency, and the README states all models in the benchmark "receive the same rendered page images." Second, those images go to the 9B vision model. Third, the schema is compiled into a decoding constraint so the model can only emit tokens that keep the output valid against that schema. The README calls this "schema-constrained decoding guaranteeing valid output."

That guarantee has an escape hatch, and it is worth reading carefully. The README warns: "Avoid enum, anyOf/oneOf, $ref, and additionalProperties; the schema-constrained decoder skips schemas it can't compile, which weakens the output guarantee." So the constraint is real only for schemas the decoder can compile. A schema full of $ref and oneOf may run without error and still lose the guarantee you adopted the tool for.

Multi-page handling is a single pass per document, and the README claims it handles "values that span pages." Two inference modes exist: local via HuggingFace, and remote via a vLLM server. The base install depends on openai, which is how the CLI talks to that vLLM server. The optional hf extra pulls in torch, torchvision, transformers, and accelerate.

Installing lift-pdf and running a first extraction

The package name on PyPI is lift-pdf, not lift. The README's quickstart installs the base package, which is the vLLM backend, then launches a server and runs the CLI against a schema file.

bash
pip install lift-pdf

# With vLLM (recommended, lightweight install)
lift_vllm
lift_extract input.pdf ./output --schema schema.json

lift_vllm starts the local server; the README notes the CLI expects that server to be running. lift_extract then writes results into the output directory. The HuggingFace path is a separate extra and a separate flag.

bash
pip install lift-pdf[hf]
lift_extract input.pdf ./output --schema schema.json --method hf

A schema is standard JSON Schema, kept simple. The README's example uses string, number, and an array of objects, with descriptions on fields whose names are not self-explanatory.

json
{
  "type": "object",
  "properties": {
    "invoice_number": {"type": "string", "description": "Invoice identifier"},
    "total": {"type": "number", "description": "Total amount due"},
    "line_items": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "description": {"type": "string"},
          "amount": {"type": "number"}
        }
      }
    }
  },
  "required": ["invoice_number", "total"]
}

The CLI also accepts an inline schema string and whole directories, and the README shows a schema saved by name in a schemas/ directory with a page limit. Fields that are genuinely absent from a document come back null, so mark a field required only when it must appear. For interactive schema work there is a third entry point, lift_app, installed with the app extra, which launches Schema Studio, a Streamlit app for building and testing schemas against your documents.

What the benchmark table actually says about accuracy

The README reports a 225-document extraction benchmark with 6 to 64 pages per document and roughly 11,000 scored fields, scored by deterministic exact match against ground truth. lift scores 90.2% field accuracy and 20.9% full-document accuracy, with a median latency of 9.5 seconds per document at 8 concurrent requests on a single GPU.

The gap between those two numbers is the story. Field accuracy counts individual fields extracted correctly. Full-document accuracy counts documents where every field is correct. At 20.9%, roughly one document in five comes back complete. On a 40-field invoice, a 90.2% per-field rate implies several wrong fields per document even before you consider that errors cluster.

For context, the hosted Datalab API scores 95.9% field accuracy and 44.4% full-document accuracy, and Gemini Flash 3.5 scores 91.3% and 40.0%. lift beats NuExtract3 (81.5% field, 8.4% full-document) and Qwen3.5-9B (76.32% field, 24.0% full-document), though Qwen3.5-9B edges it on full-document accuracy. The README states the hosted platform runs "improved extraction with higher accuracy than the open weights, plus per-field verification, citations, and confidence scores." Those three features are not in the open weights. The latency figures are the project's own, measured on its own hardware, and the README itself says to treat them as relative rather than absolute.

One caveat on the table: it mixes local models served with vLLM against hosted APIs, and the README notes all models were served with default or recommended settings. It is a comparison of configurations, not an isolated measurement of model quality.

Where lift is the wrong tool

The first limitation is schema expressiveness. Because the decoder skips schemas it cannot compile, the features that make JSON Schema useful in production, such as enums for constrained values and oneOf for polymorphic fields, are exactly the ones the README tells you to avoid. If your extraction target needs a field restricted to a known set of values, you either drop the enum and validate afterward, or you accept a weaker output guarantee.

The second is the accuracy ceiling on multi-field documents. A pipeline that must be correct end to end cannot accept 20.9% full-document accuracy without a verification layer. The README points that layer at the hosted API, which is a commercial service, not part of the open weights.

The third is that lift is not an OCR engine in the traditional sense. It does not expose a plain text extraction mode, and there is no documented path for layout analysis, table structure export, or reading order. If you need the document as structured text rather than as a fixed set of fields, the schema-driven design works against you.

The fourth is hardware. The HuggingFace path requires torch and a GPU, and the README recommends flash attention for better performance. The base install avoids torch but still depends on a vLLM server running locally. There is no documented CPU-only path and no documented quantized variant. The README also does not document rollback or version pinning guidance for the model weights, so an upgrade that changes extraction behavior has no stated recovery procedure.

lift compared with Marker, and with prompting a general model

Datalab also publishes Marker, and the search terms around this project suggest people arrive looking for it. The two solve different problems. Marker converts documents into markdown and structured text, preserving layout, tables, and reading order, and leaves interpretation to you. lift takes the opposite position: you declare the fields up front and get JSON back. If your downstream step is a human reading the document, Marker is the better fit. If your downstream step is a database row, lift is.

The other alternative is prompting a general vision model with your schema and parsing the response. That approach has no compile step, so enums and oneOf work as written, and you can switch models without reinstalling anything. What you give up is the decoding constraint. A general model can return malformed JSON, omit required fields, or invent values, and you handle that with retries and validation. lift trades schema flexibility for a stronger structural guarantee on the schemas it supports. Whether that trade is worth it depends on how much of your schema survives the decoder.

Licences, versioning and the maintenance picture

The split licence is the part to read before anything else. The repository's code is Apache-2.0, per the LICENSE file and the pyproject metadata. The model weights are not: the README's badge points to OpenRAIL-M, and the repository carries a separate MODEL_LICENSE file. The README states plainly that "Commercial self-hosting requires a license" and links to a contact page for on-prem licensing. Apache-2.0 on the Python package does not settle the weights.

Versioning is young. The project reached v0.1.0 on 2026-06-18 and v0.1.1 on 2026-06-19, a naming cleanup, and the pyproject classifier still reads "Development Status :: 4 - Beta." The last push to the repository was on 2026-06-19. That is roughly three months before today, so the project is not stale, but there is no release cadence to extrapolate from: two releases, one day apart, both at 0.1.x.

Upgrade cost is dominated by the model weights rather than the Python API. The package pins requires-python to >=3.12, and the hf extra pulls torch, transformers, and accelerate, so a transformers major version bump can move the install footprint. The README does not document a weights versioning scheme or a way to pin a specific model revision, which means extraction output can shift under you on an upgrade with no documented rollback. If you deploy this, pin the package version and treat a weights change as a change to test against your own documents, not as a routine dependency bump.

Editorial conclusion

Adopt lift if you have a fixed JSON Schema, a GPU budget, and tolerance for a 20.9% full-document accuracy ceiling on the project's own adversarial benchmark; skip it if you need per-field verification or citations, which the README reserves for the hosted Datalab API. Before committing, run lift_extract over ten of your own multi-page documents with your real schema and count how many come back fully correct, then check the MODEL_LICENSE file for your commercial case.

Frequently asked questions

What is DataLab?

In this repository, Datalab is the organisation behind lift and the hosted platform at datalab.to. The README describes the managed platform as running improved extraction with higher accuracy than the open weights, plus per-field verification, citations, and confidence scores.

What is Chandra OCR?

The repository does not mention Chandra OCR. It documents lift, a 9B vision model that extracts JSON matching a supplied JSON Schema from PDFs and images, and references the hosted Datalab API.

How do I install lift-pdf and run a first extraction?

Install the base package with pip install lift-pdf, start the local server with lift_vllm, then run lift_extract input.pdf ./output --schema schema.json. The HuggingFace backend is a separate extra, pip install lift-pdf[hf], and adds the --method hf flag.

Which JSON Schema features does lift support?

The README supports string, number, integer, boolean, arrays of those, arrays of objects, and nested objects. It advises avoiding enum, anyOf/oneOf, $ref, and additionalProperties, because the schema-constrained decoder skips schemas it cannot compile, which weakens the output guarantee.

Can I self-host lift commercially?

The code is Apache-2.0 but the model weights use OpenRAIL-M, and the README states that commercial self-hosting requires a license, with a contact link for on-prem licensing. The repository keeps the two licences in separate files, LICENSE and MODEL_LICENSE.

How accurate is lift compared with the Datalab API?

On the README's 225-document benchmark, lift scores 90.2% field accuracy and 20.9% full-document accuracy, while the Datalab API scores 95.9% and 44.4%. The README attributes the API's advantage to per-field verification, citations, and confidence scores that the open weights do not include.

Official sources

  1. datalab-to/lift on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Community notes

Community notes