Model or dataset
enoch3712/ExtractThinker avatar
enoch3712/ExtractThinker

ExtractThinker: an ORM-style layer for LLM document extraction in Python

ExtractThinker is a Document Intelligence library for LLMs, offering ORM-style interaction for flexible and powerful document workflows.

1,599 stars153 forksPythonApache-2.0

At a glance

What is it?
ExtractThinker wraps Pydantic contracts, pluggable document loaders and LLM calls into one extractor object. It suits Python teams that already have a model budget and want typed output from PDFs and images, not a hosted document pipeline.
Who is it for?
Adopt ExtractThinker if your team writes Python, already pays for an LLM provider and wants Pydantic-typed output from PDFs, images and spreadsheets without building the loader, splitter and retry plumbing yourself. Skip it if you need a hosted service with a support contract, or if your documents are simple enough for a deterministic parser.
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 2 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 18, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The gap ExtractThinker fills between raw LLM calls and a document platform

Calling an LLM with a PDF is easy. Getting a typed object back, page after page, across invoices and driver licences in the same upload, is the part that turns into a small internal framework. ExtractThinker is that framework, packaged. The README describes it as functioning "like an ORM for document processing workflows", and the comparison holds in one useful sense: you declare what you want (a contract), you point at a source (a file path or an IO stream), and the library handles the loading, prompting and parsing in between.

The intended audience is a Python developer who already has an API key for a model provider and a folder of documents. Nothing in the repository suggests a hosted component. Loaders cover Tesseract OCR, Azure Form Recognizer, AWS Textract and Google Document AI, so the library sits on top of whatever OCR or parsing service you already trust rather than replacing it. If your documents arrive as scanned images, you bring the OCR; ExtractThinker brings the schema and the LLM call.

Contracts, loaders and splitters: how the pieces connect

Three objects do most of the work. A Contract is a Pydantic model with the fields you want. A document loader turns a file into something the model can read. An Extractor ties a loader to an LLM and runs the extraction. The README's basic example shows exactly this sequence: instantiate Extractor, call load_document_loader with DocumentLoaderPyPdf, call load_llm with a model name, then call extract with a path and the contract class.

Classification adds a second layer. You build a list of Classification objects, each carrying a name, a description, a contract and an extractor, then call extractor.classify on a document. The result is described in the README as a ClassificationResponse object with name and confidence fields. That is a routing decision made by the model, not a rule engine, so the confidence value is the only signal you get about whether the routing was sound.

The Process object handles multi-page documents. You load a splitter (the README uses ImageSplitter with a model name), load the file, call split with the classifications and a SplittingStrategy, then call extract. The strategy enum exposes LAZY and EAGER modes: lazy processes page by page, eager handles the document as a whole. The split_content result is a list of contract instances, and the README's example dispatches on isinstance to decide what each item is. That isinstance check is the real interface: your downstream code receives typed Python objects, not dictionaries.

Installing ExtractThinker and running a first extraction

Installation is a single pip command. The README gives no virtual environment step and no system dependency list beyond the Python version badge, which states Python 3.9 or newer. The package metadata in pyproject.toml is stricter: it allows Python from 3.9 up to but excluding 3.14.

bash
pip install extract_thinker

The first real use is a two-field invoice. Create a Pydantic-style contract, point an extractor at a PDF loader and a model, then call extract. The README's example uses gpt-4o-mini and loads the model name as a plain string, which is the same shape litellm expects, so any provider litellm supports should be reachable through the same call.

python
import os
from dotenv import load_dotenv
from extract_thinker import Extractor, DocumentLoaderPyPdf, Contract

load_dotenv()

class InvoiceContract(Contract):
    invoice_number: str
    invoice_date: str

extractor = Extractor()
extractor.load_document_loader(DocumentLoaderPyPdf())
extractor.load_llm("gpt-4o-mini")

result = extractor.extract("path_to_your_files/invoice.pdf", InvoiceContract)
print("Invoice Number:", result.invoice_number)
print("Invoice Date:", result.invoice_date)

What you should see is the two fields printed, or an exception if the model could not satisfy the contract. The README does not document what happens on a partial match, so treat the failure path as something you will discover rather than something the documentation promises. Batch processing exists too: the README shows extractor.extract_batch with a source and a response_model argument, though the snippet is truncated in the published README.

Where ExtractThinker is the wrong tool

The library is only as good as the model behind it. A contract with ten fields on a noisy scan is a prompt with ten extraction targets, and the README offers no retry policy, no validation loop and no confidence threshold for extraction (only classification returns a confidence value). If a field comes back wrong, the library has already handed you a typed object that looks correct. Nothing in the repository layout suggests a built-in verifier.

The dependency list is also heavier than the pip command implies. pyproject.toml pulls in litellm, instructor, pypdfium2, pillow, tiktoken, python-magic and playwright, plus a libmagic entry. Playwright is a browser automation package, which is a large install for a document extraction library and points to web page loading as one of the supported sources. python-magic needs the underlying libmagic system library, which is a known friction point on Windows. If your deployment target is a slim container, budget time for those system packages.

Finally, if your documents are machine-generated PDFs with a stable layout, an LLM is an expensive way to read them. A template-based parser will be faster, cheaper and deterministic. ExtractThinker earns its cost when the layout varies and the fields are semantic rather than positional.

How it differs from Docling and ContextGem

Docling and ContextGem appear alongside ExtractThinker in the same searches, and the three take different positions. Docling is a document conversion project: its job is to turn a PDF into structured text and layout information. It answers the question "what is in this document" without asking a model to fill a schema. ExtractThinker starts where that answer ends. It assumes you have text or an image and asks a model to map it onto your contract.

ContextGem sits closer to ExtractThinker in that it also targets structured extraction with LLMs, but the two organise the work differently. ExtractThinker's organising unit is the contract plus the loader, with classification and splitting as separate stages you compose. The practical difference for a team choosing between them is which abstraction you want to write against: a Pydantic model wired to a loader and a model name, or whatever object model the other library exposes. The README's own framing, an ORM for documents, is the clearest statement of ExtractThinker's bet: developers already understand models and sessions, so document extraction should look the same.

Version history, licence and what maintenance looks like

The last push to the default branch was on 2026-09-16, one day before this writing, and the repository is not archived. The most recent tagged release is v0.1.14 from 2025-06-09, with v0.1.13 in April 2025 and v0.1.12 in April 2025. That is a gap of roughly three months between the newest release and the latest commit, which is worth noting if you pin versions: the code on main is ahead of the newest tag, and the release notes are the only place to check what changed between them.

The licence is Apache-2.0, stated in the README badge and shipped as a LICENSE file at the repository root. Apache-2.0 permits commercial use and modification and includes an explicit patent grant, which matters if you are embedding the library in a product. It also requires that you preserve the licence and notice files in distributions. That is a description of the licence text, not legal advice; have your own counsel read it if the distinction matters to your product.

Upgrade cost is dominated by the dependency chain rather than the library's own API. Because litellm, instructor and pydantic are direct dependencies, a major version bump in any of them can force an upgrade here. Poetry is the build backend, and a poetry.lock file sits at the root, so reproducible installs are possible if you use the lock file rather than the loose requirements.txt, which lists a shorter and slightly different set of packages.

Editorial conclusion

Adopt ExtractThinker if your team writes Python, already pays for an LLM provider and wants Pydantic-typed output from PDFs, images and spreadsheets without building the loader, splitter and retry plumbing yourself. Skip it if you need a hosted service with a support contract, or if your documents are simple enough for a deterministic parser. Before committing, verify the licence file wording against your product, confirm the Python version range your runtime satisfies (the package metadata allows 3.9 up to but excluding 3.14), and check that the model name you plan to pass to load_llm is one your provider account can actually call.

Frequently asked questions

How do I install ExtractThinker?

Install it with pip install extract_thinker. The README states Python 3.9 or newer, and pyproject.toml allows Python from 3.9 up to but excluding 3.14.

Can ExtractThinker extract information from unstructured data?

That is its stated purpose: it uses LLMs to extract and classify structured data from documents, with Pydantic contracts defining the fields you want back. Loaders cover PDFs, images, spreadsheets and OCR services such as Tesseract, Azure Form Recognizer, AWS Textract and Google Document AI.

What is AI extraction in the context of ExtractThinker?

In this library it means sending a document to an LLM and receiving a typed object back, rather than parsing text with rules. You declare a Contract with the fields you need, and the extractor returns an instance of that contract.

Does ExtractThinker work with models other than OpenAI?

The README lists integration with OpenAI, Anthropic and Cohere among others, and the model is passed as a string to load_llm. The dependency list includes litellm, which is the layer that routes those calls.

How does ExtractThinker handle multi-page documents?

The README shows a Process object with a splitter, such as ImageSplitter, and a SplittingStrategy of LAZY or EAGER. Lazy processes page by page and eager handles the document as a whole, and the result is a list of contract instances.

Official sources

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

Community notes