ocr-llm 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
ocr_llm-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Shehryar Sohail
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,10 @@
1
+ include README.md
2
+ include LICENSE
3
+ include requirements.txt
4
+ include requirements-dev.txt
5
+ recursive-include llm_ocr *.py
6
+ recursive-exclude tests *
7
+ recursive-exclude htmlcov *
8
+ exclude test.ipynb
9
+ exclude Resume.pdf
10
+
ocr_llm-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,308 @@
1
+ Metadata-Version: 2.4
2
+ Name: ocr-llm
3
+ Version: 1.0.0
4
+ Summary: Convert PDFs to markdown using Large Language Models (LLMs) with vision capabilities
5
+ Author-email: Shehryar Sohail <hafizshehryar88@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Shehryar718/llm-ocr
8
+ Project-URL: Repository, https://github.com/Shehryar718/llm-ocr
9
+ Project-URL: Issues, https://github.com/Shehryar718/llm-ocr/issues
10
+ Keywords: ocr,pdf,markdown,llm,vision,gemini,openai,ai
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Classifier: Topic :: Text Processing :: Markup :: Markdown
20
+ Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
21
+ Requires-Python: >=3.9
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: pdf2image>=1.16.0
25
+ Requires-Dist: Pillow>=11.0.0
26
+ Requires-Dist: google-genai>=1.0.0
27
+ Requires-Dist: openai>=2.0.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
30
+ Requires-Dist: pytest-asyncio>=1.0.0; extra == "dev"
31
+ Requires-Dist: pytest-cov>=6.5.0; extra == "dev"
32
+ Requires-Dist: pytest-mock>=3.14.0; extra == "dev"
33
+ Requires-Dist: black>=24.0.0; extra == "dev"
34
+ Requires-Dist: isort>=6.0.0; extra == "dev"
35
+ Requires-Dist: flake8>=7.0.0; extra == "dev"
36
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
37
+ Requires-Dist: ruff>=0.10.0; extra == "dev"
38
+ Dynamic: license-file
39
+
40
+ # LLM OCR
41
+
42
+ [![PyPI](https://img.shields.io/pypi/v/ocr-llm)](https://pypi.org/project/ocr-llm/)
43
+ [![Python](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11-blue)](https://pypi.org/project/ocr-llm/)
44
+ [![License](https://img.shields.io/badge/license-MIT-blue)](https://github.com/Shehryar718/llm-ocr/blob/main/LICENSE)
45
+
46
+ Convert PDFs to markdown using Large Language Models (LLMs) with vision capabilities.
47
+
48
+ ## Features
49
+
50
+ - 🔍 High-quality OCR using vision-capable LLMs
51
+ - 📄 Batch processing of multiple PDF pages
52
+ - 🔌 Multiple provider support (Gemini, OpenAI)
53
+ - ⚙️ Configurable processing settings
54
+ - 🔄 Automatic retry logic for transient errors
55
+ - 📝 Clean markdown output
56
+
57
+ ## Installation
58
+
59
+ ```bash
60
+ pip install ocr-llm
61
+ ```
62
+
63
+ ### System Dependencies
64
+
65
+ You also need to install poppler (required for PDF processing):
66
+
67
+ ```bash
68
+ # macOS
69
+ brew install poppler
70
+
71
+ # Ubuntu/Debian
72
+ sudo apt-get install poppler-utils
73
+
74
+ # Fedora/RHEL
75
+ sudo yum install poppler-utils
76
+ ```
77
+
78
+ ### Dependencies
79
+
80
+ The library requires:
81
+
82
+ - **System**: `poppler-utils` for PDF processing
83
+ - **Python**:
84
+ - `google-genai` for Gemini provider
85
+ - `openai` for OpenAI provider
86
+ - `pdf2image` and `Pillow` for PDF processing
87
+
88
+ ## Quick Start
89
+
90
+ ### Using OpenAI
91
+
92
+ ```python
93
+ import asyncio
94
+ from llm_ocr import LLMOCR, OpenAI
95
+
96
+ async def main():
97
+ # Initialize OpenAI provider
98
+ provider = OpenAI(
99
+ api_key="your-api-key", # Or set OPENAI_API_KEY env var
100
+ model=OpenAI.GPT_4O_MINI
101
+ )
102
+
103
+ # Create OCR processor
104
+ async with LLMOCR(provider) as ocr:
105
+ # Convert PDF to markdown
106
+ markdown = await ocr.convert(
107
+ "document.pdf",
108
+ output_path="output.md"
109
+ )
110
+ print(markdown)
111
+
112
+ asyncio.run(main())
113
+ ```
114
+
115
+ ### Using Gemini
116
+
117
+ ```python
118
+ import asyncio
119
+ from llm_ocr import LLMOCR, Gemini
120
+
121
+ async def main():
122
+ # Initialize Gemini provider
123
+ provider = Gemini(
124
+ api_key="your-api-key", # Or set GEMINI_API_KEY env var
125
+ model=Gemini.FLASH_2_5 # Or Gemini.PRO_2_5 for best quality
126
+ )
127
+
128
+ # Create OCR processor
129
+ async with LLMOCR(provider) as ocr:
130
+ # Convert PDF to markdown
131
+ markdown = await ocr.convert(
132
+ "document.pdf",
133
+ output_path="output.md"
134
+ )
135
+ print(markdown)
136
+
137
+ asyncio.run(main())
138
+ ```
139
+
140
+ ## Available Models
141
+
142
+ ### OpenAI
143
+
144
+ - `OpenAI.GPT_4O`
145
+ - `OpenAI.GPT_4O_MINI` (default)
146
+
147
+ Additional models: `O1`, `O3`, `O4_MINI`, `GPT_5`, `GPT_5_MINI`, `GPT_4_1`, and more.
148
+
149
+ > See `llm_ocr/providers/openai.py` for the complete list.
150
+
151
+ ### Gemini
152
+
153
+ - `Gemini.PRO_2_5`
154
+ - `Gemini.FLASH_2_5` (default)
155
+
156
+ Additional models: `PRO_2_0`, `FLASH_2_0`.
157
+
158
+ > See `llm_ocr/providers/gemini.py` for the complete list.
159
+
160
+ ## Configuration
161
+
162
+ Customize the OCR processing with `OCRConfig`:
163
+
164
+ ```python
165
+ from llm_ocr import LLMOCR, OpenAI, OCRConfig
166
+
167
+ config = OCRConfig(
168
+ dpi=300, # Higher DPI for better quality
169
+ max_pages=10, # Limit number of pages to process
170
+ llm_batch_size=2, # Send 2 pages to LLM at once
171
+ convert_to_grayscale=True, # Convert images to grayscale
172
+ max_retries=3, # Retry failed requests
173
+ retry_delay=1.0, # Wait 1 second between retries
174
+ include_page_markers=True, # Add page markers in output
175
+ )
176
+
177
+ provider = OpenAI()
178
+ ocr = LLMOCR(provider, config=config)
179
+ ```
180
+
181
+ ### Configuration Options
182
+
183
+ | Option | Default | Description |
184
+ | ---------------------- | ------- | ------------------------------------------ |
185
+ | `dpi` | 200 | DPI for PDF to image conversion (72-600) |
186
+ | `max_pages` | None | Maximum number of pages to process |
187
+ | `batch_size` | 5 | PDF to image conversion batch size |
188
+ | `llm_batch_size` | 1 | Number of pages to send to LLM at once |
189
+ | `thread_count` | 4 | Number of threads for PDF conversion |
190
+ | `convert_to_grayscale` | False | Convert images to grayscale |
191
+ | `optimize_png` | True | Optimize PNG compression |
192
+ | `use_cropbox` | True | Use PDF cropbox for conversion |
193
+ | `max_retries` | 3 | Maximum retry attempts for failed requests |
194
+ | `retry_delay` | 1.0 | Delay between retries in seconds |
195
+ | `include_page_markers` | False | Add page markers in markdown output |
196
+
197
+ ## Advanced Usage
198
+
199
+ ### Custom Provider Parameters
200
+
201
+ Pass additional parameters to the LLM provider:
202
+
203
+ ```python
204
+ # OpenAI with custom parameters
205
+ provider = OpenAI(
206
+ model=OpenAI.GPT_4O,
207
+ max_tokens=4000,
208
+ temperature=0.0,
209
+ )
210
+
211
+ # Gemini with custom parameters
212
+ provider = Gemini(
213
+ model=Gemini.PRO_2_5,
214
+ temperature=0.0,
215
+ )
216
+ ```
217
+
218
+ ### Processing Multiple Documents
219
+
220
+ ```python
221
+ import asyncio
222
+ from pathlib import Path
223
+ from llm_ocr import LLMOCR, OpenAI
224
+
225
+ async def process_documents():
226
+ provider = OpenAI()
227
+
228
+ async with LLMOCR(provider) as ocr:
229
+ pdf_files = Path("pdfs").glob("*.pdf")
230
+
231
+ for pdf_file in pdf_files:
232
+ output_file = pdf_file.with_suffix(".md")
233
+ await ocr.convert(pdf_file, output_path=output_file)
234
+ print(f"Converted {pdf_file.name} -> {output_file.name}")
235
+
236
+ asyncio.run(process_documents())
237
+ ```
238
+
239
+ ### Without Context Manager
240
+
241
+ If you prefer not to use the context manager:
242
+
243
+ ```python
244
+ import asyncio
245
+ from llm_ocr import LLMOCR, OpenAI
246
+
247
+ async def main():
248
+ provider = OpenAI()
249
+ ocr = LLMOCR(provider)
250
+
251
+ try:
252
+ markdown = await ocr.convert("document.pdf")
253
+ print(markdown)
254
+ finally:
255
+ await ocr.aclose() # Don't forget to close!
256
+
257
+ asyncio.run(main())
258
+ ```
259
+
260
+ ## Environment Variables
261
+
262
+ Set API keys via environment variables:
263
+
264
+ ```bash
265
+ # For OpenAI
266
+ export OPENAI_API_KEY="your-openai-api-key"
267
+
268
+ # For Gemini
269
+ export GEMINI_API_KEY="your-gemini-api-key"
270
+ ```
271
+
272
+ Then use providers without passing API keys:
273
+
274
+ ```python
275
+ # API key read from environment variable
276
+ provider = OpenAI() # Uses OPENAI_API_KEY
277
+ # or
278
+ provider = Gemini() # Uses GEMINI_API_KEY
279
+ ```
280
+
281
+ ## Error Handling
282
+
283
+ The library uses a fail-fast approach with automatic retries:
284
+
285
+ ```python
286
+ import asyncio
287
+ from llm_ocr import LLMOCR, OpenAI, OCRConfig
288
+
289
+ async def main():
290
+ provider = OpenAI()
291
+ config = OCRConfig(
292
+ max_retries=5, # Retry up to 5 times
293
+ retry_delay=2.0, # Wait 2 seconds between retries
294
+ )
295
+
296
+ async with LLMOCR(provider, config) as ocr:
297
+ try:
298
+ markdown = await ocr.convert("document.pdf")
299
+ print(markdown)
300
+ except Exception as e:
301
+ print(f"Failed to process document: {e}")
302
+
303
+ asyncio.run(main())
304
+ ```
305
+
306
+ ## License
307
+
308
+ See LICENSE file for details.
@@ -0,0 +1,269 @@
1
+ # LLM OCR
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/ocr-llm)](https://pypi.org/project/ocr-llm/)
4
+ [![Python](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11-blue)](https://pypi.org/project/ocr-llm/)
5
+ [![License](https://img.shields.io/badge/license-MIT-blue)](https://github.com/Shehryar718/llm-ocr/blob/main/LICENSE)
6
+
7
+ Convert PDFs to markdown using Large Language Models (LLMs) with vision capabilities.
8
+
9
+ ## Features
10
+
11
+ - 🔍 High-quality OCR using vision-capable LLMs
12
+ - 📄 Batch processing of multiple PDF pages
13
+ - 🔌 Multiple provider support (Gemini, OpenAI)
14
+ - ⚙️ Configurable processing settings
15
+ - 🔄 Automatic retry logic for transient errors
16
+ - 📝 Clean markdown output
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ pip install ocr-llm
22
+ ```
23
+
24
+ ### System Dependencies
25
+
26
+ You also need to install poppler (required for PDF processing):
27
+
28
+ ```bash
29
+ # macOS
30
+ brew install poppler
31
+
32
+ # Ubuntu/Debian
33
+ sudo apt-get install poppler-utils
34
+
35
+ # Fedora/RHEL
36
+ sudo yum install poppler-utils
37
+ ```
38
+
39
+ ### Dependencies
40
+
41
+ The library requires:
42
+
43
+ - **System**: `poppler-utils` for PDF processing
44
+ - **Python**:
45
+ - `google-genai` for Gemini provider
46
+ - `openai` for OpenAI provider
47
+ - `pdf2image` and `Pillow` for PDF processing
48
+
49
+ ## Quick Start
50
+
51
+ ### Using OpenAI
52
+
53
+ ```python
54
+ import asyncio
55
+ from llm_ocr import LLMOCR, OpenAI
56
+
57
+ async def main():
58
+ # Initialize OpenAI provider
59
+ provider = OpenAI(
60
+ api_key="your-api-key", # Or set OPENAI_API_KEY env var
61
+ model=OpenAI.GPT_4O_MINI
62
+ )
63
+
64
+ # Create OCR processor
65
+ async with LLMOCR(provider) as ocr:
66
+ # Convert PDF to markdown
67
+ markdown = await ocr.convert(
68
+ "document.pdf",
69
+ output_path="output.md"
70
+ )
71
+ print(markdown)
72
+
73
+ asyncio.run(main())
74
+ ```
75
+
76
+ ### Using Gemini
77
+
78
+ ```python
79
+ import asyncio
80
+ from llm_ocr import LLMOCR, Gemini
81
+
82
+ async def main():
83
+ # Initialize Gemini provider
84
+ provider = Gemini(
85
+ api_key="your-api-key", # Or set GEMINI_API_KEY env var
86
+ model=Gemini.FLASH_2_5 # Or Gemini.PRO_2_5 for best quality
87
+ )
88
+
89
+ # Create OCR processor
90
+ async with LLMOCR(provider) as ocr:
91
+ # Convert PDF to markdown
92
+ markdown = await ocr.convert(
93
+ "document.pdf",
94
+ output_path="output.md"
95
+ )
96
+ print(markdown)
97
+
98
+ asyncio.run(main())
99
+ ```
100
+
101
+ ## Available Models
102
+
103
+ ### OpenAI
104
+
105
+ - `OpenAI.GPT_4O`
106
+ - `OpenAI.GPT_4O_MINI` (default)
107
+
108
+ Additional models: `O1`, `O3`, `O4_MINI`, `GPT_5`, `GPT_5_MINI`, `GPT_4_1`, and more.
109
+
110
+ > See `llm_ocr/providers/openai.py` for the complete list.
111
+
112
+ ### Gemini
113
+
114
+ - `Gemini.PRO_2_5`
115
+ - `Gemini.FLASH_2_5` (default)
116
+
117
+ Additional models: `PRO_2_0`, `FLASH_2_0`.
118
+
119
+ > See `llm_ocr/providers/gemini.py` for the complete list.
120
+
121
+ ## Configuration
122
+
123
+ Customize the OCR processing with `OCRConfig`:
124
+
125
+ ```python
126
+ from llm_ocr import LLMOCR, OpenAI, OCRConfig
127
+
128
+ config = OCRConfig(
129
+ dpi=300, # Higher DPI for better quality
130
+ max_pages=10, # Limit number of pages to process
131
+ llm_batch_size=2, # Send 2 pages to LLM at once
132
+ convert_to_grayscale=True, # Convert images to grayscale
133
+ max_retries=3, # Retry failed requests
134
+ retry_delay=1.0, # Wait 1 second between retries
135
+ include_page_markers=True, # Add page markers in output
136
+ )
137
+
138
+ provider = OpenAI()
139
+ ocr = LLMOCR(provider, config=config)
140
+ ```
141
+
142
+ ### Configuration Options
143
+
144
+ | Option | Default | Description |
145
+ | ---------------------- | ------- | ------------------------------------------ |
146
+ | `dpi` | 200 | DPI for PDF to image conversion (72-600) |
147
+ | `max_pages` | None | Maximum number of pages to process |
148
+ | `batch_size` | 5 | PDF to image conversion batch size |
149
+ | `llm_batch_size` | 1 | Number of pages to send to LLM at once |
150
+ | `thread_count` | 4 | Number of threads for PDF conversion |
151
+ | `convert_to_grayscale` | False | Convert images to grayscale |
152
+ | `optimize_png` | True | Optimize PNG compression |
153
+ | `use_cropbox` | True | Use PDF cropbox for conversion |
154
+ | `max_retries` | 3 | Maximum retry attempts for failed requests |
155
+ | `retry_delay` | 1.0 | Delay between retries in seconds |
156
+ | `include_page_markers` | False | Add page markers in markdown output |
157
+
158
+ ## Advanced Usage
159
+
160
+ ### Custom Provider Parameters
161
+
162
+ Pass additional parameters to the LLM provider:
163
+
164
+ ```python
165
+ # OpenAI with custom parameters
166
+ provider = OpenAI(
167
+ model=OpenAI.GPT_4O,
168
+ max_tokens=4000,
169
+ temperature=0.0,
170
+ )
171
+
172
+ # Gemini with custom parameters
173
+ provider = Gemini(
174
+ model=Gemini.PRO_2_5,
175
+ temperature=0.0,
176
+ )
177
+ ```
178
+
179
+ ### Processing Multiple Documents
180
+
181
+ ```python
182
+ import asyncio
183
+ from pathlib import Path
184
+ from llm_ocr import LLMOCR, OpenAI
185
+
186
+ async def process_documents():
187
+ provider = OpenAI()
188
+
189
+ async with LLMOCR(provider) as ocr:
190
+ pdf_files = Path("pdfs").glob("*.pdf")
191
+
192
+ for pdf_file in pdf_files:
193
+ output_file = pdf_file.with_suffix(".md")
194
+ await ocr.convert(pdf_file, output_path=output_file)
195
+ print(f"Converted {pdf_file.name} -> {output_file.name}")
196
+
197
+ asyncio.run(process_documents())
198
+ ```
199
+
200
+ ### Without Context Manager
201
+
202
+ If you prefer not to use the context manager:
203
+
204
+ ```python
205
+ import asyncio
206
+ from llm_ocr import LLMOCR, OpenAI
207
+
208
+ async def main():
209
+ provider = OpenAI()
210
+ ocr = LLMOCR(provider)
211
+
212
+ try:
213
+ markdown = await ocr.convert("document.pdf")
214
+ print(markdown)
215
+ finally:
216
+ await ocr.aclose() # Don't forget to close!
217
+
218
+ asyncio.run(main())
219
+ ```
220
+
221
+ ## Environment Variables
222
+
223
+ Set API keys via environment variables:
224
+
225
+ ```bash
226
+ # For OpenAI
227
+ export OPENAI_API_KEY="your-openai-api-key"
228
+
229
+ # For Gemini
230
+ export GEMINI_API_KEY="your-gemini-api-key"
231
+ ```
232
+
233
+ Then use providers without passing API keys:
234
+
235
+ ```python
236
+ # API key read from environment variable
237
+ provider = OpenAI() # Uses OPENAI_API_KEY
238
+ # or
239
+ provider = Gemini() # Uses GEMINI_API_KEY
240
+ ```
241
+
242
+ ## Error Handling
243
+
244
+ The library uses a fail-fast approach with automatic retries:
245
+
246
+ ```python
247
+ import asyncio
248
+ from llm_ocr import LLMOCR, OpenAI, OCRConfig
249
+
250
+ async def main():
251
+ provider = OpenAI()
252
+ config = OCRConfig(
253
+ max_retries=5, # Retry up to 5 times
254
+ retry_delay=2.0, # Wait 2 seconds between retries
255
+ )
256
+
257
+ async with LLMOCR(provider, config) as ocr:
258
+ try:
259
+ markdown = await ocr.convert("document.pdf")
260
+ print(markdown)
261
+ except Exception as e:
262
+ print(f"Failed to process document: {e}")
263
+
264
+ asyncio.run(main())
265
+ ```
266
+
267
+ ## License
268
+
269
+ See LICENSE file for details.
@@ -0,0 +1,18 @@
1
+ """llm-ocr: Convert PDFs to markdown using LLMs."""
2
+
3
+ from .config.settings import OCRConfig
4
+ from .core.base import LLMProvider
5
+ from .core.processor import LLMOCR
6
+
7
+ # Import providers
8
+ from .providers.gemini import Gemini
9
+ from .providers.openai import OpenAI
10
+
11
+ __version__ = "1.0.0"
12
+ __all__ = [
13
+ "LLMOCR",
14
+ "OCRConfig",
15
+ "LLMProvider",
16
+ "Gemini",
17
+ "OpenAI",
18
+ ]
File without changes
@@ -0,0 +1,29 @@
1
+ from dataclasses import dataclass
2
+ from typing import Optional
3
+
4
+
5
+ @dataclass
6
+ class OCRConfig:
7
+ """Configuration for OCR processing."""
8
+
9
+ dpi: int = 200
10
+ max_pages: Optional[int] = None
11
+ batch_size: int = 5 # PDF to image conversion batch size
12
+ llm_batch_size: int = 1 # Number of pages to send to LLM at once
13
+ thread_count: int = 4
14
+ convert_to_grayscale: bool = False
15
+ optimize_png: bool = True
16
+ use_cropbox: bool = True
17
+ max_retries: int = 3
18
+ retry_delay: float = 1.0
19
+ output_format: str = "markdown"
20
+ include_page_markers: bool = False
21
+
22
+ def validate(self):
23
+ """Validate configuration."""
24
+ if self.dpi < 72 or self.dpi > 600:
25
+ raise ValueError("DPI must be between 72 and 600")
26
+ if self.batch_size < 1:
27
+ raise ValueError("Batch size must be at least 1")
28
+ if self.llm_batch_size < 1:
29
+ raise ValueError("LLM batch size must be at least 1")
File without changes
@@ -0,0 +1,48 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import List
3
+
4
+
5
+ class LLMProvider(ABC):
6
+ """Abstract base class for LLM providers."""
7
+
8
+ def __init__(self, api_key: str, model: str, **kwargs):
9
+ """
10
+ Initialize the LLM provider.
11
+
12
+ Args:
13
+ api_key: API key for the provider
14
+ model: Model identifier/name
15
+ **kwargs: Additional provider-specific parameters
16
+ """
17
+ self.api_key = api_key
18
+ self.model = model
19
+ self.kwargs = kwargs
20
+
21
+ @abstractmethod
22
+ async def generate_content(
23
+ self,
24
+ prompt: str,
25
+ image_bytes_list: List[bytes],
26
+ ) -> str:
27
+ """
28
+ Generate content from images and prompt.
29
+
30
+ Args:
31
+ prompt: The instruction prompt
32
+ image_bytes_list: List of PNG image bytes (one or more pages)
33
+
34
+ Returns:
35
+ Generated text content
36
+ """
37
+ pass
38
+
39
+ @abstractmethod
40
+ async def aclose(self):
41
+ """Close and cleanup resources."""
42
+ pass
43
+
44
+ @property
45
+ @abstractmethod
46
+ def name(self) -> str:
47
+ """Return the provider name."""
48
+ pass