pdf-autofillr-doc-upload
Extract structured data from any document format using an LLM, then optionally fill a blank PDF via the mapper module.
Supported document formats
| Format | Extension |
|---|---|
.pdf |
|
| Word | .docx |
| PowerPoint | .pptx |
| Excel | .xlsx, .xls |
| CSV | .csv |
| JSON | .json |
| Markdown | .md, .markdown |
| Plain text | .txt |
| HTML | .html, .htm |
| XML | .xml |
Supported LLM providers (via LiteLLM)
Any model LiteLLM supports — OpenAI, Anthropic, Groq, Ollama, AWS Bedrock, Azure OpenAI, Google Vertex AI, and more.
Installation
# Step 1 — create venv
python -m venv venv
.\venv\Scripts\activate # Windows
# source venv/bin/activate # Linux/Mac
# Step 2 — install litellm (pinned)
pip install "litellm==1.59.12" --no-cache-dir
# Step 3 — install mapper (from sibling modules3/mapper/)
pip install -e ../mapper --no-cache-dir --no-deps
pip install PyMuPDF tiktoken pydantic pydantic-settings python-dotenv tenacity requests aiohttp httpx numpy tqdm python-json-logger --no-cache-dir
# Step 4 — install extractor
pip install -e . --no-cache-dir --no-deps
pip install python-docx python-pptx openpyxl --no-cache-dir
# Verify
python -c "import pdf_autofillr_doc_upload; print('extractor ok')"
python -c "import pdf_autofillr_mapper; print('mapper ok')"
Setup
1. Copy sample configs
python -c "import pdf_autofillr_doc_upload; pdf_autofillr_doc_upload.copy_sample_configs('.')"
2. Create .env
cp .env.example .env
# Edit .env — set DOC_UPLOAD_LLM_MODEL and DOC_UPLOAD_LLM_API_KEY at minimum
Minimal .env:
DOC_UPLOAD_LLM_MODEL=openai/gpt-4.1-mini
DOC_UPLOAD_LLM_API_KEY=sk-...
DOC_UPLOAD_STORAGE=local
DOC_UPLOAD_DATA_PATH=./extractor_data
DOC_UPLOAD_CONFIG_PATH=./configs
# Required to run the FastAPI server — see "FastAPI server" below.
AUTH_TOKEN=change-me-to-a-long-random-secret
Running
Interactive local runner
python -m entrypoints.local
Non-interactive (single document)
python -m entrypoints.local --document investor.pdf --schema configs/form_keys.json --output output/filled.json
CLI
doc-upload-cli --document investor.pdf --schema configs/form_keys.json --output filled.json --report
FastAPI server
doc-upload-server
# or
uvicorn entrypoints.fastapi_app:app --reload --port 8001
Authentication is required. Set AUTH_TOKEN to a strong secret before
starting the server — every request must send it as the X-API-Key header,
or the server responds with a config error. (For local-only experimentation
you can instead set DOC_UPLOAD_ALLOW_INSECURE_NO_AUTH=true, but never do
this in a deployment reachable by anyone else.)
Then POST to http://localhost:8001/extract:
{
"document_path": "/path/to/investor_profile.pdf",
"schema_path": "configs/form_keys.json"
}
with header X-API-Key: <your AUTH_TOKEN>.
document_path and schema_path must resolve inside DOC_UPLOAD_DATA_PATH,
DOC_UPLOAD_CONFIG_PATH, or a directory listed in
DOC_UPLOAD_ALLOWED_DOCUMENT_ROOTS (comma-separated). Paths outside those
directories — including via .. traversal or symlinks — are rejected with
HTTP 400. If your documents live somewhere else (e.g. an uploads folder),
add that folder to DOC_UPLOAD_ALLOWED_DOCUMENT_ROOTS rather than removing
the restriction.
Storage backends
| Value | Description |
|---|---|
local |
Local filesystem (default, for dev) |
s3 |
AWS S3 |
gcp |
Google Cloud Storage |
azure |
Azure Blob Storage |
Set DOC_UPLOAD_STORAGE=s3 and the matching bucket env vars.
PDF Filling (mapper integration)
Set DOC_UPLOAD_PDF_FILLER=mapper and the Lambda URL:
DOC_UPLOAD_PDF_FILLER=mapper
DOC_UPLOAD_FILL_PDF_LAMBDA_URL=https://xyz.lambda-url.us-east-1.on.aws
DOC_UPLOAD_PDF_API_KEY=my-api-key
The client runs extraction and embed-file preparation in parallel, then calls fill_pdf once both complete — identical to the Lambda main.py pipeline.
Telemetry
| Value | Description |
|---|---|
off |
Disabled (default, zero overhead) |
local |
Append events to ./extractor_telemetry/events.jsonl |
managed |
(stub) HTTP POST to DOC_UPLOAD_TELEMETRY_ENDPOINT |
Field values are never included in telemetry. Only metadata (counts, latencies, file extensions) is logged. Job IDs are one-way SHA-256 hashed.
Entrypoints
| File | Use case |
|---|---|
entrypoints/local.py |
Interactive development REPL |
entrypoints/cli.py |
doc-upload-cli command |
entrypoints/server.py |
doc-upload-server (uvicorn) |
entrypoints/fastapi_app.py |
FastAPI app (mount or standalone) |
entrypoints/aws_lambda.py |
AWS Lambda handler |
entrypoints/gcp_function.py |
GCP Cloud Functions handler |
entrypoints/azure_function.py |
Azure Functions handler |
Programmatic API
from pdf_autofillr_doc_upload import DocUploadClient
client = DocUploadClient()
# Extract only
result = client.run(
document_path="investor_profile.pdf",
schema_path="configs/form_keys.json",
output_path="output/filled.json",
)
print(result["output_flat"]) # flat dot-notation dict
print(result["output_nested"]) # nested dict matching schema
# Extract + fill PDF
result = client.run(
document_path="investor_profile.pdf",
schema_path="configs/form_keys.json",
user_id="42",
pdf_doc_id="99",
session_id="sess_abc",
investor_type="Individual",
)
Module structure
extractor/
├── pyproject.toml
├── .env.example
├── README.md
├── config_samples/
│ └── form_keys.json
├── entrypoints/
│ ├── local.py ← interactive REPL
│ ├── cli.py ← doc-upload-cli
│ ├── server.py ← doc-upload-server
│ ├── fastapi_app.py ← FastAPI app
│ ├── aws_lambda.py ← AWS Lambda
│ ├── gcp_function.py ← GCP Cloud Functions
│ └── azure_function.py ← Azure Functions
└── src/pdf_autofillr_doc_upload/
├── __init__.py
├── client.py ← DocUploadClient (main API)
├── config/
│ └── settings.py ← all env var config
├── storage/
│ ├── base.py ← abstract interface
│ ├── local_storage.py
│ ├── s3_storage.py
│ ├── gcp_storage.py
│ ├── azure_storage.py
│ └── factory.py
├── extraction/
│ ├── document_reader.py ← PDF/DOCX/PPTX/XLSX/CSV/JSON/MD/HTML/XML
│ ├── llm_client.py ← LiteLLM wrapper
│ └── extractor.py ← full pipeline
├── pdf/
│ ├── interface.py
│ ├── api_handler.py ← HTTP client for Lambda
│ └── mapper_filler.py ← mapper integration
├── logging/
│ └── logger.py ← ExecutionLogger
├── telemetry/
│ ├── collector.py
│ └── config.py
└── managed/
└── __init__.py ← stub for future managed service
Metadata
Release files for pdf-autofillr-doc-upload 0.1.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pdf_autofillr_doc_upload-0.1.6.tar.gz | 370.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pdf_autofillr_doc_upload-0.1.6-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 429.7 kB
Release files / pdf_autofillr_doc_upload-0.1.6.tar.gz
| Download URL | pdf_autofillr_doc_upload-0.1.6.tar.gz |
|---|---|
| Size | 370.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cc58da82495a3881bdc09aa6e291ec2256a57bef9d2f3139057fdc48dd9ec22f
|
|
BLAKE2b-256 checksum How to use checksums |
8e7e1c783981e95d25bd9134a2d9e3139aaff96f3b71fe234accb564ee727329
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.6
|
Release files / pdf_autofillr_doc_upload-0.1.6-py3-none-any.whl
| Download URL | pdf_autofillr_doc_upload-0.1.6-py3-none-any.whl |
|---|---|
| Size | 59.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dc833e6322d64515705906202aa9b52cd22664aee09765dbe2eb8aeb6fc6b71a
|
|
BLAKE2b-256 checksum How to use checksums |
f26b7454ff11e0368b9e752bdfd79436894ec2c68885156b39cfb4aae9877763
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.6
|