Skip to main content

DocAI Toolkit

Local OCR + Markdown + RAG with optional Hugging Face/custom endpoints. Renamed to avoid PyPI name collisions (docai-toolkit package import is docai_toolkit).

  • pdf_viewer_app.py: Tkinter UI to open PDFs, run OCR → Markdown, and “chat” via retrieval + generation.
  • docai_toolkit/: library for OCR (local Tesseract or remote endpoint), embedding/indexing (local or remote), and simple chat over FAISS.
  • Status: under active development; APIs and defaults may change as the AI ecosystem moves quickly.

Requirements

  • Python 3.11+ (tested on 3.11, 3.12 and 3.13)
  • Dependencies are split into extras so the viewer does not drag in the ML stack:
    • core (always installed): pypdf, reportlab
    • ocr: pytesseract, pdf2image (plus the tesseract-ocr and poppler system packages)
    • rag: langchain, langchain-community, sentence-transformers, faiss-cpu, huggingface-hub
    • llm: transformers, accelerate, bitsandbytes (only for local generation)
# viewer only
pip install .

# everything
pip install ".[all]"

# development (extras + pytest)
pip install -e ".[dev]"

# exact pinned set used by the Docker image
pip install -r requirements.txt

Usage

GUI Viewer

python pdf_viewer_app.py
  • Open: loads all pages of a PDF into the text area.
  • Save As: renders the text area content into a new PDF (requires reportlab).
  • OCR → Markdown: run OCR on a PDF and save Markdown to the configured output directory (local Tesseract or remote OCR endpoint via HF/custom).
  • Chat: build a quick FAISS index over a chosen Markdown file and query it with a selected HF model (remote endpoint or local HF pipeline).
  • Settings: set HF token, optional custom endpoints (OCR/embeddings/LLM), model choices, and output directory. Settings persist to ~/.docai/config.json. Env vars (HF_TOKEN, HUGGINGFACEHUB_API_TOKEN, DOC_AI_OUTPUT_DIR) are auto-read.

Triaging a mixed file tree

Before OCR/indexing a large, untrusted pile of files, separate real documents from media, archives, and renamed binaries. Classification checks each file two ways — extension and detected content type — and only keeps a file when both agree; anything that disagrees, is empty, unreadable, or unexpectedly large is quarantined for review rather than fed downstream.

docai-classify /path/to/tree --manifest manifest.json --doc-list docs.txt
  • --manifest: JSON report with per-file verdicts, reasons, and byte/count totals.
  • --doc-list: newline-separated paths of the kept documents, ready to pipe into OCR.

Kept types: .pdf .doc .docx .rtf .odt .txt .md. Content detection uses python-magic (pip install ".[classify]") when available, then the system file command, then a built-in signature sniff — so it runs with no extra deps but is more precise with libmagic installed.

Ingesting a corpus (OCR + index at scale)

build_index_from_markdown loads and embeds everything in one pass, which does not survive a large or interrupted run. docai-ingest OCRs PDFs concurrently, then adds their chunks to a FAISS index in batches, checkpointing the index and a ledger so a re-run resumes where it stopped (already-indexed files are skipped, not re-embedded).

docai-ingest --docs docs.txt --markdown-dir out/md --index out/faiss --workers 8
  • --docs: a file of PDF paths, one per line — e.g. the --doc-list from docai-classify.
  • OCR client and embeddings come from ~/.docai/config.json / env, same as the viewer.
  • --allow-dangerous-deserialization: required only to resume an existing index (it unpickles it); use it for indexes you created yourself.

Pipeline end to end: docai-classify a tree → feed its --doc-list to docai-ingest → query the index with chat_over_corpus.

Generation and embeddings: OpenAI-compatible endpoints

Remote generation and embeddings speak the OpenAI REST API (/v1/chat/completions, /v1/embeddings). Any server that implements it works through the same client — a local runner or a hosted gateway. Set the endpoint to the server's /v1 base URL and the model to the served model name.

Local on a laptop (Ollama) — cross-platform, CUDA and Apple-Metal:

ollama serve
ollama pull llama3.1
ollama pull nomic-embed-text
  • LLM Endpoint: http://localhost:11434/v1, LLM Model: llama3.1
  • Embedding Endpoint: http://localhost:11434/v1, Embedding Model: nomic-embed-text

Linux + NVIDIA, or corpus-scale batch (vLLM) — high throughput:

vllm serve mistralai/Mistral-7B-Instruct-v0.3   # serves an OpenAI API on :8000
  • LLM Endpoint: http://localhost:8000/v1, LLM Model: mistralai/Mistral-7B-Instruct-v0.3

Local embeddings on Apple Silicon / NVIDIA — with no embedding endpoint set, sentence-transformers runs in-process and EmbeddingConfig.device (auto by default) picks the device: CUDA if present, else Apple Metal (MPS), else CPU. Set it explicitly (cpu, cuda, cuda:0, mps) to override.

Hosted API — set the endpoint to the provider's /v1 base URL and put the key in the token field. Leaving the endpoint blank uses in-process sentence-transformers for embeddings and a local transformers pipeline for generation, no server required.

Endpoints must be https, except http is allowed for localhost — which is exactly where Ollama (:11434) and vLLM (:8000) listen, so the local token is never sent in cleartext. ~/.docai/config.json is written 0600, and a token picked up from the environment is not persisted to it.

Environment variables:

  • HF_TOKEN / HUGGINGFACEHUB_API_TOKEN / DOC_AI_HF_TOKEN: auth token (auto-loads into LLM + embeddings).
  • DOC_AI_OUTPUT_DIR: default output directory for OCR/Markdown.

Docker

Build:

docker build -t docai-toolkit .

Run (GUI requires X/Wayland forwarding; for headless tasks, override CMD):

docker run --rm -v $PWD:/data docai-toolkit python -m pytest -q
# or override to run OCR in batch using the library CLI you add

macOS GUI via XQuartz:

  1. Install/start XQuartz (brew install --cask xquartz; enable “Allow connections from network clients” in prefs and restart).
  2. Allow local clients: xhost +localhost
  3. Run:
docker run --rm -it \
  -e DISPLAY=host.docker.internal:0 \
  -v /tmp/.X11-unix:/tmp/.X11-unix \
  docai-toolkit

For day-to-day use, running natively is simpler; use the container when you need an isolated, reproducible environment.

Tests

Basic round-trip test for the viewer’s PDF writer:

pytest

reportlab must be installed for the test to run.

OCR + RAG (docai_toolkit/)

  • OCR: pluggable clients (RemoteOcrClient for a custom OCR endpoint, TesseractOcrClient local fallback) that turn PDFs into Markdown (ocr/pipeline.py).
  • RAG: build a FAISS index from Markdown (rag/index.py), then chat over it (rag/chat.py).
  • Transport: generation and embeddings use the OpenAI REST API (docai_toolkit/http_client.py), so Ollama, vLLM, llama.cpp, TGI, and hosted APIs are interchangeable.
  • Config: lightweight dataclasses in docai_toolkit/config.py; saved at ~/.docai/config.json.
  • Local retrieval: FAISS runs in-process; embeddings default to local sentence-transformers when no endpoint is set.

To experiment locally:

# OCR to Markdown (Tesseract fallback requires pytesseract + pdf2image installed)
python - <<'PY'
from pathlib import Path
from docai_toolkit.ocr import TesseractOcrClient, run_ocr_to_markdown
client = TesseractOcrClient()
md_path = run_ocr_to_markdown(Path("your.pdf"), Path("outputs"), client)
print("Saved:", md_path)
PY

# Build index + chat
# Local default needs sentence-transformers (+ transformers for local generation);
# or point at an OpenAI-compatible server (Ollama/vLLM/hosted) via the endpoint args.
python - <<'PY'
from pathlib import Path
from docai_toolkit.rag import (
    build_index_from_markdown,
    chat_over_corpus,
    load_index,
    SentenceTransformerEmbeddings,
)
index_path = Path("outputs/faiss_index")

# Served embeddings + generation (Ollama shown; drop the endpoint args for local):
db = build_index_from_markdown(
    [Path("outputs/your.md")],
    embedding_model="nomic-embed-text",
    embedding_endpoint="http://localhost:11434/v1",
    persist_path=index_path,
)
print(chat_over_corpus(
    db,
    "What is this document about?",
    model_id="llama3.1",
    endpoint="http://localhost:11434/v1",
))
# Later, for an index you created yourself (loading unpickles the docstore):
# db = load_index(index_path, SentenceTransformerEmbeddings("all-mpnet-base-v2"),
#                 allow_dangerous_deserialization=True)
PY

Case Study

This toolkit was architected as part of a consulting engagement to solve common document-centric workflow challenges: extraction, segmentation, text cleaning, OCR, and embedding preparation for AI models.

Full case study: Document Processing Pipeline Using docAI Toolkit

The Problem

Teams building RAG pipelines or document analytics typically stitch together custom scripts, ad-hoc processing, or partial library support—resulting in inconsistent, brittle pipelines.

The Solution

docAI provides a clean, modular toolkit for building AI-ready document processing flows:

  • Document loading — PDF, DOCX, Markdown
  • Page and text splitting — Configurable chunking
  • Preprocessing — Cleaning, normalization
  • OCR — Local (Tesseract) or remote (Hugging Face/custom endpoints)
  • Embedding preparation — Ready for FAISS, vector DBs, or ML pipelines

Example Workflow

Source documents (PDF, DOCX, MD)
        ↓
   docAI splits & preprocesses
        ↓
   Cleaned chunks → embedding model
        ↓
   Indexed for search / RAG / analytics

Benefits

  • Reduces bespoke glue code
  • Predictable interface for common document tasks
  • Easy integration into production systems

Need help building document pipelines or RAG systems?

→ Consulting Services
→ Book a call

License

CC BY-NC-SA 4.0 (see LICENSE).

Metadata

Release files for docai-toolkit 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for docai-toolkit 0.2.0
File Size Uploaded
docai_toolkit-0.2.0.tar.gz 36.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for docai-toolkit 0.2.0
File Interpreter ABI Platform
docai_toolkit-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 68.1 kB

Release files / docai_toolkit-0.2.0.tar.gz

Download URL docai_toolkit-0.2.0.tar.gz
Size 36.6 kB
Tags Source
SHA-256 checksum
How to use checksums
7c7c2bd0564934ef0589743b4dc5939fb5132844af131a55427b458012baaa77
BLAKE2b-256 checksum
How to use checksums
19529dfbd0517a405d4bca9dcb700e2fcb31e0682513459a22a0313801393629
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 6, 2026.

Transparency log

Release files / docai_toolkit-0.2.0-py3-none-any.whl

Download URL docai_toolkit-0.2.0-py3-none-any.whl
Size 31.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4d9443b605d0b6daef720938ed835a43cc268ab4b3d0ac47f2d88ec2251c9712
BLAKE2b-256 checksum
How to use checksums
8945ffa4e66f30491e69aa51ac9696f8e24ce169af0cdcb07dd75f5f22040c5f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 6, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page