What is pdf-craft?
pdf-craft is a PDF-centered conversion library. It turns PDFs into Markdown or EPUB, and can translate the converted content or write a translated result back to PDF. It is especially useful for scanned documents: pages that are otherwise only readable as images become searchable, editable Markdown or EPUB.
The pipeline is designed for books and academic or technical documents, including body text, tables of contents, footnotes, tables, formulas, and images. OCR can run entirely on a compatible local GPU, or use a vendor service that supplies remote compute. Translation uses a separate text LLM.
Online Version
Want to try the workflow before installing anything? Open Inkora - PDF Craft, the online version of the same core experience. Upload a PDF in your browser and see the main workflow in action.
Installation
If you are getting started, use the standard installation:
pip install pdf-craft
This includes vendor OCR, Markdown/EPUB rendering, and PDF translation. Vendor OCR uses remote compute, so your machine does not need CUDA; you provide the service URL, model name, and API key in the OCR configuration.
Only install the local extra when you explicitly want to run OCR models on your own NVIDIA GPU. If you are unsure, use the standard installation above:
pip install "pdf-craft[local]"
Local OCR also requires a CUDA-compatible PyTorch build, model storage, and enough GPU memory. Before processing PDFs, install Poppler; see the Installation Guide for the supported Python versions and complete system setup. If something goes wrong, start with the Troubleshooting Guide.
Quick Start
The following example converts a scanned PDF into a Markdown file. Replace the example OCR endpoint, model name, and API key with your own service configuration.
from pdf_craft import DeepSeekOCRVendorConfig, PDFCraft, PDFOptions
craft = PDFCraft(pdf=PDFOptions(ocr=DeepSeekOCRVendorConfig(
base_url="https://example.com/v1",
api_key="your-api-key",
model="deepseek-ocr",
)))
craft.convert_pdf_to_markdown(
"input.pdf", "output.md",
)
The conversion uses a temporary working directory automatically and removes it
when the conversion finishes or fails. Pass package_path only when you want to
keep the intermediate work for debugging or reuse.
For the complete PDF conversion workflow and customization options, see the PDF Translation Guide and API Reference.
Advanced Features
PDF → EPUB
To produce an EPUB instead of Markdown, call convert_pdf_to_epub. This complete
example also shows how to set the book title and author metadata:
from pdf_craft import BookMeta, DeepSeekOCRVendorConfig, PDFCraft, PDFOptions
ocr_config = DeepSeekOCRVendorConfig(
base_url="https://example.com/v1",
api_key="your-api-key",
model="deepseek-ocr",
)
craft = PDFCraft(pdf=PDFOptions(ocr=ocr_config))
craft.convert_pdf_to_epub(
"input.pdf", "output.epub",
book_meta=BookMeta(title="Book title", authors=["Author"]),
)
If book_meta is omitted, pdf-craft tries to read the metadata from the source PDF.
PDF → translated Markdown or EPUB
To translate while converting, pass a TranslationStep to either conversion method.
The translator is a chapter transformer: it sends chapter text to your text LLM and
returns the translated chapter. The same step can be used for Markdown and EPUB output.
from pdf_craft import TranslationStep
translation = TranslationStep(translator)
craft.convert_pdf_to_markdown("input.pdf", "translated.md", steps=[translation])
craft.convert_pdf_to_epub("input.pdf", "translated.epub", steps=[translation])
PDF → translated PDF
Use the PDF translation workflow when you want to keep the original PDF layout. It extracts the page content, translates it, and writes the result back into the matching source pages. OCR and translation use separate configurations.
from pdf_craft import DeepSeekOCRVendorConfig, PDFCraft, PDFOptions
craft = PDFCraft(pdf=PDFOptions(ocr=DeepSeekOCRVendorConfig(
base_url="https://example.com/v1",
api_key="your-ocr-api-key",
model="deepseek-ocr",
)))
# Placeholder only: replace this with your text LLM call.
def translator(text: str) -> str:
return text
package = craft.extract_pdf("input.pdf", "work/cache")
craft.translate_pdf("input.pdf", package, "translated.pdf", translator)
EPUB → translated EPUB
If you already have an EPUB, translate it directly by providing the target language and a text LLM:
from pdf_craft import LLM, PDFCraft, SubmitKind
llm = LLM(
key="your-api-key",
url="https://api.openai.com/v1",
model="gpt-4.1-mini",
token_encoding="o200k_base",
)
PDFCraft().translate_epub(
"input.epub", "translated.epub",
target_language="zh", submit=SubmitKind.REPLACE, llm=llm,
)
REPLACE creates a target-language-only edition. Use APPEND_BLOCK to keep the
original and append the translation as a separate block, or APPEND_TEXT to place
the translation directly after the original text. See the EPUB translation guide
for prompts, retries, concurrency, caching, progress callbacks, and failure handling.
OCR Backends and Model Cache
OCR turns page images into text. pdf-craft offers six backends; choose the runtime location first, then choose the model family:
- No CUDA or minimal local setup: choose vendor OCR. Pages are sent to a remote service and processed with its compute resources, so you need network access, a service URL, and credentials.
- A compatible NVIDIA GPU and local execution: choose local OCR. Models are cached locally and run on your GPU, which keeps processing on your machine but requires CUDA, VRAM, and model files.
DeepSeek OCR and DeepSeek OCR 2 are from DeepSeek; Unlimited OCR is from Baidu. Each model family has local and vendor configurations:
| Backend | Owner | Runs on | Choose it when | You need |
|---|---|---|---|---|
DeepSeekOCRLocalConfig |
DeepSeek | Local GPU | You want local DeepSeek OCR | CUDA, VRAM, model cache |
DeepSeekOCR2LocalConfig |
DeepSeek | Local GPU | You want local DeepSeek OCR 2 | CUDA, VRAM, model cache; base is the verified preset |
UnlimitedOCRLocalConfig |
Baidu | Local GPU | You want local Unlimited OCR | CUDA, VRAM, model cache |
DeepSeekOCRVendorConfig |
DeepSeek | Remote service | You do not have CUDA or prefer remote DeepSeek OCR | URL, model, API key, network |
DeepSeekOCR2VendorConfig |
DeepSeek | Remote service | You prefer remote DeepSeek OCR 2 | URL, model, API key, network |
UnlimitedOCRVendorConfig |
Baidu | Remote service | You prefer remote Unlimited OCR | URL, credentials, network |
If you simply want to get the workflow running, start with the vendor you already
have credentials for. Choose local OCR when you specifically want local execution.
The library accepts these configuration objects through PDFOptions(ocr=...) and
does not read environment variables. See the OCR Backend Guide
for detailed configuration examples.
Unlimited OCR local supports base and gundam. DeepSeek OCR 2 local is verified
with base; an explicit tiny selection fails early with a clear message.
Model Cache and Common Parameters
Local OCR models are downloaded from Hugging Face by default. You can pre-download
one into a chosen cache directory and then run with local_only=True:
from pdf_craft import DeepSeekOCRLocalConfig, predownload_models
predownload_models(
ocr=DeepSeekOCRLocalConfig(models_cache_path="models"),
revision=None,
)
ocr_size supports tiny, small, base, large, and gundam, although presets
vary by backend. Markdown defaults to toc_assumed=False; EPUB defaults to
toc_assumed=True. Complex chapter hierarchies can use an optional toc_llm.
Related Projects
- Wiki Graph: turn a converted EPUB or Markdown book into structured summaries, chapter topology, and a knowledge graph.
License
This project is licensed under the MIT License. See the LICENSE file for details.
Since v1.0.0, pdf-craft has used DeepSeek OCR under the MIT license and removed
the previous AGPL-3.0 dependency. The project still receives easydict transitively
through the OCR stack under the LGPLv3 license. Thanks to the community for their
support and contributions.
Acknowledgments
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pdf_craft-2.0.0.tar.gz.
File metadata
- Download URL: pdf_craft-2.0.0.tar.gz
- Upload date:
- Size: 137.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
57a24902b65f5cadb29eca83a027b5a18648223fee67247b6a3f1ec24b354216
|
|
| MD5 |
89e44cf0fd19415264e30612904c93ea
|
|
| BLAKE2b-256 |
540f2e416418ab49734f0be77707aceaf9a8da4bc1142b7411b86c2fe778deb1
|
Provenance
The following attestation bundles were made for pdf_craft-2.0.0.tar.gz:
Publisher:
release.yml on oomol-lab/pdf-craft
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pdf_craft-2.0.0.tar.gz -
Subject digest:
57a24902b65f5cadb29eca83a027b5a18648223fee67247b6a3f1ec24b354216 - Sigstore transparency entry: 2580103058
- Sigstore integration time:
-
Permalink:
oomol-lab/pdf-craft@407244148c5f099c5d8b0afdf7976a6309e3b93d -
Branch / Tag:
refs/heads/main - Owner: https://github.com/oomol-lab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@407244148c5f099c5d8b0afdf7976a6309e3b93d -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file pdf_craft-2.0.0-py3-none-any.whl.
File metadata
- Download URL: pdf_craft-2.0.0-py3-none-any.whl
- Upload date:
- Size: 182.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1aa61facd19430b2326afd9e430e8de907b9ffeb0c17ee11f033ba1d5f26b79a
|
|
| MD5 |
bcb3921b2089835bc0151bba3021f842
|
|
| BLAKE2b-256 |
80c52b91f9b6e235c3cb89440d9060babcefcfb03cb006dc925aa187f5094411
|
Provenance
The following attestation bundles were made for pdf_craft-2.0.0-py3-none-any.whl:
Publisher:
release.yml on oomol-lab/pdf-craft
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pdf_craft-2.0.0-py3-none-any.whl -
Subject digest:
1aa61facd19430b2326afd9e430e8de907b9ffeb0c17ee11f033ba1d5f26b79a - Sigstore transparency entry: 2580103064
- Sigstore integration time:
-
Permalink:
oomol-lab/pdf-craft@407244148c5f099c5d8b0afdf7976a6309e3b93d -
Branch / Tag:
refs/heads/main - Owner: https://github.com/oomol-lab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@407244148c5f099c5d8b0afdf7976a6309e3b93d -
Trigger Event:
workflow_dispatch
-
Statement type: