|
1 | 1 | # PDFStract |
2 | 2 |
|
3 | | -**The first layer in your RAG pipeline** — Extract, chunk, and prepare PDFs for AI. |
| 3 | +**The Data Preparation Layer for RAG** — Extract. Chunk. Embed. |
4 | 4 |
|
5 | 5 | [](https://pypi.org/project/pdfstract/) |
6 | 6 | [](https://pypi.org/project/pdfstract/) |
7 | 7 | [](https://github.com/AKSarav/pdfstract/blob/main/LICENSE) |
8 | 8 |
|
9 | | -PDFStract converts PDFs to text using 10+ extraction libraries and chunks them using 10+ methods — all through a simple Python API, CLI, or Web UI. |
| 9 | +**One unified API.** Switch between 10+ extraction libraries, 10+ chunking methods, and multiple embedding providers with a single parameter change. Focus on your RAG outcomes, not library dependencies. |
10 | 10 |
|
11 | 11 | ## Installation |
12 | 12 |
|
13 | 13 | ```bash |
14 | | -# Base (fast extractors) |
15 | | -pip install pdfstract |
16 | | - |
17 | | -# Standard (+ OCR support) |
18 | | -pip install pdfstract[standard] |
19 | | - |
20 | | -# Advanced (+ ML-powered extractors) |
21 | | -pip install pdfstract[advanced] |
22 | | - |
23 | | -# All libraries |
24 | | -pip install pdfstract[all] |
| 14 | +pip install pdfstract # Base - pymupdf4llm, markitdown |
| 15 | +pip install pdfstract[standard] # + OCR (pytesseract, unstructured) |
| 16 | +pip install pdfstract[advanced] # + ML-powered (marker, docling, paddleocr) |
| 17 | +pip install pdfstract[all] # Everything |
25 | 18 | ``` |
26 | 19 |
|
27 | | -## Quick Start — Python Module |
28 | | - |
29 | | -### Convert a PDF |
| 20 | +## Python API |
30 | 21 |
|
31 | 22 | ```python |
32 | 23 | from pdfstract import PDFStract |
33 | 24 |
|
34 | 25 | pdfstract = PDFStract() |
35 | | -text = pdfstract.convert('document.pdf', library='marker') |
36 | | -print(text) |
37 | | -``` |
38 | 26 |
|
39 | | -### Convert and Chunk for RAG |
40 | | - |
41 | | -```python |
42 | | -from pdfstract import PDFStract |
43 | | - |
44 | | -pdfstract = PDFStract() |
| 27 | +# Extract |
| 28 | +text = pdfstract.convert('document.pdf', library='auto') |
45 | 29 |
|
46 | | -# Extract text |
47 | | -text = pdfstract.convert('document.pdf', library='docling') |
48 | | - |
49 | | -# Chunk for embeddings |
| 30 | +# Chunk |
50 | 31 | chunks = pdfstract.chunk(text, chunker='semantic', chunk_size=512) |
51 | 32 |
|
52 | | -print(f"Created {chunks['total_chunks']} chunks") |
53 | | -for chunk in chunks['chunks']: |
54 | | - print(f"- {chunk['text'][:50]}...") |
| 33 | +# Embed |
| 34 | +vectors = pdfstract.embed_texts([c['text'] for c in chunks['chunks']]) |
| 35 | + |
| 36 | +# Combined pipelines |
| 37 | +result = pdfstract.convert_chunk('document.pdf', library='marker', chunker='token') |
| 38 | +result = pdfstract.convert_chunk_embed('document.pdf', embedding='sentence-transformers') |
55 | 39 | ``` |
56 | 40 |
|
57 | | -### List Available Libraries |
| 41 | +### Extract Examples |
58 | 42 |
|
59 | 43 | ```python |
60 | | -from pdfstract import PDFStract |
| 44 | +# Auto-select best available library |
| 45 | +text = pdfstract.convert('document.pdf', library='auto') |
61 | 46 |
|
62 | | -pdfstract = PDFStract() |
63 | | -print(pdfstract.list_available_libraries()) |
64 | | -# ['pymupdf4llm', 'markitdown', 'marker', 'docling', ...] |
| 47 | +# Use specific library |
| 48 | +text = pdfstract.convert('document.pdf', library='marker') |
| 49 | +text = pdfstract.convert('document.pdf', library='docling', output_format='json') |
| 50 | + |
| 51 | +# Batch processing |
| 52 | +results = pdfstract.batch_convert('./pdfs', library='pymupdf4llm', parallel_workers=4) |
65 | 53 |
|
66 | | -print(pdfstract.list_chunkers()) |
67 | | -# ['token', 'sentence', 'semantic', 'recursive', ...] |
| 54 | +# Async |
| 55 | +text = await pdfstract.convert_async('document.pdf', library='marker') |
68 | 56 | ``` |
69 | 57 |
|
70 | | -### Batch Processing |
| 58 | +### Chunk Examples |
71 | 59 |
|
72 | 60 | ```python |
73 | | -from pdfstract import PDFStract |
| 61 | +# Token-based chunking |
| 62 | +chunks = pdfstract.chunk(text, chunker='token', chunk_size=512, chunk_overlap=50) |
74 | 63 |
|
75 | | -pdfstract = PDFStract() |
| 64 | +# Semantic chunking |
| 65 | +chunks = pdfstract.chunk(text, chunker='semantic', chunk_size=1024) |
| 66 | + |
| 67 | +# Code-aware chunking |
| 68 | +chunks = pdfstract.chunk(code_text, chunker='code') |
76 | 69 |
|
77 | | -results = pdfstract.batch_convert( |
78 | | - pdf_directory='./pdfs', |
79 | | - library='pymupdf4llm', |
80 | | - parallel_workers=4 |
81 | | -) |
82 | | -print(f"Converted {results['success']} files") |
| 70 | +# Access results |
| 71 | +for chunk in chunks['chunks']: |
| 72 | + print(f"Chunk {chunk['chunk_id']}: {chunk['token_count']} tokens") |
83 | 73 | ``` |
84 | 74 |
|
85 | | -### Async Support |
| 75 | +### Embed Examples |
86 | 76 |
|
87 | 77 | ```python |
88 | | -import asyncio |
89 | | -from pdfstract import PDFStract |
| 78 | +# Embed multiple texts |
| 79 | +vectors = pdfstract.embed_texts(["First text", "Second text"], model='sentence-transformers') |
90 | 80 |
|
91 | | -async def process(): |
92 | | - pdfstract = PDFStract() |
93 | | - result = await pdfstract.convert_async('doc.pdf', library='marker') |
94 | | - return result |
| 81 | +# Embed single text |
| 82 | +vector = pdfstract.embed_text("Hello world", model='openai') |
95 | 83 |
|
96 | | -asyncio.run(process()) |
| 84 | +# List available providers |
| 85 | +providers = pdfstract.list_available_embeddings() |
97 | 86 | ``` |
98 | 87 |
|
99 | | -## Quick Start — CLI |
| 88 | +## CLI |
100 | 89 |
|
101 | 90 | ```bash |
102 | | -# List available libraries |
103 | | -pdfstract libs |
104 | | - |
105 | | -# Convert a PDF |
106 | | -pdfstract convert document.pdf --library marker --output result.md |
107 | | - |
108 | | -# Convert and chunk |
109 | | -pdfstract convert-chunk document.pdf --library docling --chunker semantic |
110 | | - |
111 | | -# Batch convert directory |
112 | | -pdfstract batch ./pdfs --library pymupdf4llm --parallel 4 --output ./converted |
113 | | - |
114 | | -# Compare libraries |
115 | | -pdfstract compare sample.pdf -l marker -l docling -l pymupdf4llm |
| 91 | +pdfstract convert document.pdf --library marker |
| 92 | +pdfstract convert-chunk document.pdf --chunker semantic |
| 93 | +pdfstract convert-chunk-embed document.pdf --embedding sentence-transformers |
| 94 | +pdfstract batch ./pdfs --parallel 4 |
116 | 95 | ``` |
117 | 96 |
|
118 | | -## Supported Libraries |
| 97 | +## What's Included |
119 | 98 |
|
120 | | -| Library | Type | Best For | |
121 | | -|---------|------|----------| |
122 | | -| **pymupdf4llm** | Fast | Simple PDFs, speed | |
123 | | -| **markitdown** | Balanced | General documents | |
124 | | -| **marker** | ML | Complex layouts | |
125 | | -| **docling** | ML | Document intelligence | |
126 | | -| **paddleocr** | OCR | Scanned PDFs | |
127 | | -| **unstructured** | Smart | Structured extraction | |
128 | | -| **pytesseract** | OCR | Classic OCR | |
129 | | -| **mineru** | ML | Best quality (Docker) | |
| 99 | +| Tier | Libraries | |
| 100 | +|------|-----------| |
| 101 | +| **Base** | pymupdf4llm, markitdown | |
| 102 | +| **Standard** | + pytesseract, unstructured | |
| 103 | +| **Advanced** | + marker, docling, paddleocr, deepseek | |
130 | 104 |
|
131 | | -## Supported Chunkers |
| 105 | +**Chunkers:** token, sentence, semantic, recursive, code, and more |
132 | 106 |
|
133 | | -| Chunker | Best For | |
134 | | -|---------|----------| |
135 | | -| **token** | Fixed-size chunks | |
136 | | -| **sentence** | Natural boundaries | |
137 | | -| **semantic** | Topic-coherent chunks | |
138 | | -| **recursive** | Structured documents | |
139 | | -| **code** | Source code | |
140 | | -| **fast** | High throughput | |
141 | | - |
142 | | -## Embeddings |
143 | | - |
144 | | -PDFStract can generate embeddings using multiple providers (OpenAI, Azure OpenAI, Google Generative, Ollama, Sentence-Transformers, Model2Vec). Use a `PDFStract()` instance and call `embed_text` / `embed_texts`, or use the CLI `pdfstract embeddings-list` and `pdfstract embed-text` commands. Hosted providers require API keys; local providers require installed models or running services. |
145 | | - |
146 | | -## Web UI & Docker |
147 | | - |
148 | | -```bash |
149 | | -git clone https://github.com/aksarav/pdfstract.git |
150 | | -cd pdfstract |
151 | | -make up |
152 | | -``` |
153 | | - |
154 | | -Open http://localhost:3000 for Web UI, http://localhost:8000 for API. |
| 107 | +**Embeddings:** OpenAI, Azure, Google, Ollama, Sentence Transformers |
155 | 108 |
|
156 | 109 | ## Documentation |
157 | 110 |
|
158 | | -📖 **[pdfstract.com](https://pdfstract.com)** — Full documentation, guides, and examples |
159 | | - |
160 | | -**Legacy:** [aksarav.github.io/pdfstract](https://aksarav.github.io/pdfstract) |
161 | | - |
162 | | -- [Installation Guide](https://aksarav.github.io/pdfstract/installation) |
163 | | -- [Python Module Reference](https://aksarav.github.io/pdfstract/api/overview) |
164 | | -- [CLI Guide](https://aksarav.github.io/pdfstract/cli/overview) |
165 | | -- [Web UI Guide](https://aksarav.github.io/pdfstract/web-ui/overview) |
166 | | - |
167 | | -## Links |
168 | | - |
169 | | -- **GitHub:** [github.com/aksarav/pdfstract](https://github.com/aksarav/pdfstract) |
170 | | -- **PyPI:** [pypi.org/project/pdfstract](https://pypi.org/project/pdfstract) |
171 | | -- **Issues:** [github.com/aksarav/pdfstract/issues](https://github.com/aksarav/pdfstract/issues) |
172 | | - |
173 | | -## License |
174 | | - |
175 | | -MIT License — see [LICENSE](https://github.com/aksarav/pdfstract/blob/main/LICENSE) |
176 | | - |
177 | | ---- |
178 | | - |
179 | | -**Made with ❤️ for AI RAG pipelines** |
| 111 | +📖 **[pdfstract.com](https://pdfstract.com)** — Full docs, guides, and API reference |
180 | 112 |
|
| 113 | +**GitHub:** [github.com/aksarav/pdfstract](https://github.com/aksarav/pdfstract) · [Issues](https://github.com/aksarav/pdfstract/issues) · [MIT License](https://github.com/aksarav/pdfstract/blob/main/LICENSE) |
0 commit comments