rasgapdf 0.2.3__tar.gz → 0.2.4__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.
- {rasgapdf-0.2.3 → rasgapdf-0.2.4}/PKG-INFO +44 -1
- {rasgapdf-0.2.3 → rasgapdf-0.2.4}/README.md +43 -0
- {rasgapdf-0.2.3 → rasgapdf-0.2.4}/pyproject.toml +1 -1
- {rasgapdf-0.2.3 → rasgapdf-0.2.4}/rasgapdf/__init__.py +24 -3
- rasgapdf-0.2.4/rasgapdf/integrations/__init__.py +6 -0
- rasgapdf-0.2.4/rasgapdf/integrations/langchain.py +185 -0
- rasgapdf-0.2.4/rasgapdf/integrations/llama_index.py +73 -0
- {rasgapdf-0.2.3 → rasgapdf-0.2.4}/rasgapdf/librasgapdf.so +0 -0
- {rasgapdf-0.2.3 → rasgapdf-0.2.4}/rasgapdf/rasgapdf.dll +0 -0
- {rasgapdf-0.2.3 → rasgapdf-0.2.4}/rasgapdf.egg-info/PKG-INFO +44 -1
- {rasgapdf-0.2.3 → rasgapdf-0.2.4}/rasgapdf.egg-info/SOURCES.txt +4 -1
- {rasgapdf-0.2.3 → rasgapdf-0.2.4}/rasgapdf.egg-info/dependency_links.txt +0 -0
- {rasgapdf-0.2.3 → rasgapdf-0.2.4}/rasgapdf.egg-info/top_level.txt +0 -0
- {rasgapdf-0.2.3 → rasgapdf-0.2.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rasgapdf
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Ultra-fast 2D spatial PDF parser powered by pure Rust — extract exact [x0, y0, x1, y1] bounding boxes, text blocks, tables, images & vector paths in milliseconds for RAG & LLMs
|
|
5
5
|
Author: Messias Martins
|
|
6
6
|
Project-URL: Homepage, https://martinsmessias.github.io/rasgapdf/
|
|
@@ -191,6 +191,33 @@ print(manifest["written"], "files written")
|
|
|
191
191
|
|
|
192
192
|
---
|
|
193
193
|
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## 🦜️🔗 AI Framework Integrations (LangChain & LlamaIndex)
|
|
197
|
+
|
|
198
|
+
### 🦜️ LangChain Document Loader
|
|
199
|
+
`python
|
|
200
|
+
from rasgapdf import RasgaPDFLoader
|
|
201
|
+
|
|
202
|
+
# 1 Document per page with markdown tables:
|
|
203
|
+
loader = RasgaPDFLoader('document.pdf', mode='pages')
|
|
204
|
+
docs = loader.load()
|
|
205
|
+
|
|
206
|
+
# Spatial RAG: 1 Document per block/table with exact [x0, y0, x1, y1] coordinates:
|
|
207
|
+
spatial_loader = RasgaPDFLoader('document.pdf', mode='elements')
|
|
208
|
+
chunks = spatial_loader.load()
|
|
209
|
+
for chunk in chunks:
|
|
210
|
+
print(chunk.metadata['bbox'], chunk.page_content[:40])
|
|
211
|
+
`
|
|
212
|
+
|
|
213
|
+
### 🦙 LlamaIndex Reader
|
|
214
|
+
`python
|
|
215
|
+
from rasgapdf import RasgaPDFReader
|
|
216
|
+
|
|
217
|
+
reader = RasgaPDFReader(mode='pages')
|
|
218
|
+
documents = reader.load_data('financial_report.pdf')
|
|
219
|
+
`
|
|
220
|
+
|
|
194
221
|
## 📄 License
|
|
195
222
|
|
|
196
223
|
GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later). Copyright (c) 2026 Messias Martins.
|
|
@@ -198,3 +225,19 @@ GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later). Copyright (
|
|
|
198
225
|
RasgaPDF embeds and links against [MuPDF](https://mupdf.com/) (Artifex Software),
|
|
199
226
|
which is distributed under the AGPL-3.0. That is why this project is licensed
|
|
200
227
|
under the same terms.
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## 💼 Commercial & Enterprise Licensing (AGPL-3.0 Waiver)
|
|
232
|
+
|
|
233
|
+
Need to use **RasgaPDF** in closed-source commercial software, proprietary SaaS platforms, private cloud environments, or corporate applications without releasing your source code under the AGPL-3.0?
|
|
234
|
+
|
|
235
|
+
A **Commercial / Enterprise License** is available directly from the author:
|
|
236
|
+
|
|
237
|
+
- **Complete AGPL-3.0 Exemption:** Keep your intellectual property, backend code, and SaaS infrastructure 100% closed-source and proprietary.
|
|
238
|
+
- **Enterprise SLA & Support:** Direct architecture advisory, guaranteed response times, and priority bug resolution.
|
|
239
|
+
- **On-Premise & Air-Gapped Appliances:** Ready-to-deploy private Docker containers for confidential banking, healthcare, and legal compliance (LGPD / GDPR).
|
|
240
|
+
- **Custom Spatial Features:** Tailored table extractors for bank statements, invoices, and court proceedings.
|
|
241
|
+
|
|
242
|
+
📬 **Inquiries & Licensing:**
|
|
243
|
+
[👉 **Click here to Request a Commercial License & Pricing**](mailto:messiasads2017@gmail.com?subject=RasgaPDF%20Commercial%20License%20Inquiry) with details about your organization, use case, and estimated volume.
|
|
@@ -163,6 +163,33 @@ print(manifest["written"], "files written")
|
|
|
163
163
|
|
|
164
164
|
---
|
|
165
165
|
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## 🦜️🔗 AI Framework Integrations (LangChain & LlamaIndex)
|
|
169
|
+
|
|
170
|
+
### 🦜️ LangChain Document Loader
|
|
171
|
+
`python
|
|
172
|
+
from rasgapdf import RasgaPDFLoader
|
|
173
|
+
|
|
174
|
+
# 1 Document per page with markdown tables:
|
|
175
|
+
loader = RasgaPDFLoader('document.pdf', mode='pages')
|
|
176
|
+
docs = loader.load()
|
|
177
|
+
|
|
178
|
+
# Spatial RAG: 1 Document per block/table with exact [x0, y0, x1, y1] coordinates:
|
|
179
|
+
spatial_loader = RasgaPDFLoader('document.pdf', mode='elements')
|
|
180
|
+
chunks = spatial_loader.load()
|
|
181
|
+
for chunk in chunks:
|
|
182
|
+
print(chunk.metadata['bbox'], chunk.page_content[:40])
|
|
183
|
+
`
|
|
184
|
+
|
|
185
|
+
### 🦙 LlamaIndex Reader
|
|
186
|
+
`python
|
|
187
|
+
from rasgapdf import RasgaPDFReader
|
|
188
|
+
|
|
189
|
+
reader = RasgaPDFReader(mode='pages')
|
|
190
|
+
documents = reader.load_data('financial_report.pdf')
|
|
191
|
+
`
|
|
192
|
+
|
|
166
193
|
## 📄 License
|
|
167
194
|
|
|
168
195
|
GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later). Copyright (c) 2026 Messias Martins.
|
|
@@ -170,3 +197,19 @@ GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later). Copyright (
|
|
|
170
197
|
RasgaPDF embeds and links against [MuPDF](https://mupdf.com/) (Artifex Software),
|
|
171
198
|
which is distributed under the AGPL-3.0. That is why this project is licensed
|
|
172
199
|
under the same terms.
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## 💼 Commercial & Enterprise Licensing (AGPL-3.0 Waiver)
|
|
204
|
+
|
|
205
|
+
Need to use **RasgaPDF** in closed-source commercial software, proprietary SaaS platforms, private cloud environments, or corporate applications without releasing your source code under the AGPL-3.0?
|
|
206
|
+
|
|
207
|
+
A **Commercial / Enterprise License** is available directly from the author:
|
|
208
|
+
|
|
209
|
+
- **Complete AGPL-3.0 Exemption:** Keep your intellectual property, backend code, and SaaS infrastructure 100% closed-source and proprietary.
|
|
210
|
+
- **Enterprise SLA & Support:** Direct architecture advisory, guaranteed response times, and priority bug resolution.
|
|
211
|
+
- **On-Premise & Air-Gapped Appliances:** Ready-to-deploy private Docker containers for confidential banking, healthcare, and legal compliance (LGPD / GDPR).
|
|
212
|
+
- **Custom Spatial Features:** Tailored table extractors for bank statements, invoices, and court proceedings.
|
|
213
|
+
|
|
214
|
+
📬 **Inquiries & Licensing:**
|
|
215
|
+
[👉 **Click here to Request a Commercial License & Pricing**](mailto:messiasads2017@gmail.com?subject=RasgaPDF%20Commercial%20License%20Inquiry) with details about your organization, use case, and estimated volume.
|
|
@@ -2,7 +2,8 @@ import os
|
|
|
2
2
|
import sys
|
|
3
3
|
import json
|
|
4
4
|
import ctypes
|
|
5
|
-
from
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Dict, Any, List, Optional, Union
|
|
6
7
|
|
|
7
8
|
def _find_library() -> str:
|
|
8
9
|
lib_name = "librasgapdf.so" if sys.platform != "win32" else "rasgapdf.dll"
|
|
@@ -251,7 +252,7 @@ def parse_raw_bytes(data: bytes) -> Dict[str, Any]:
|
|
|
251
252
|
_lib.rasgapdf_free_string(res_ptr)
|
|
252
253
|
|
|
253
254
|
|
|
254
|
-
def extract_text(data_or_path: bytes
|
|
255
|
+
def extract_text(data_or_path: Union[bytes, str]) -> str:
|
|
255
256
|
"""
|
|
256
257
|
🚀 Extrai o texto completo do PDF em ordem natural de blocos de leitura
|
|
257
258
|
diretamente de `bytes` ou caminho de arquivo.
|
|
@@ -339,4 +340,24 @@ def extract_images_bytes(data: bytes, output_dir: str) -> Dict[str, Any]:
|
|
|
339
340
|
finally:
|
|
340
341
|
_lib.rasgapdf_free_string(res_ptr)
|
|
341
342
|
|
|
342
|
-
|
|
343
|
+
def __getattr__(name: str):
|
|
344
|
+
if name == "RasgaPDFLoader":
|
|
345
|
+
from .integrations.langchain import RasgaPDFLoader
|
|
346
|
+
return RasgaPDFLoader
|
|
347
|
+
if name == "RasgaPDFReader":
|
|
348
|
+
from .integrations.llama_index import RasgaPDFReader
|
|
349
|
+
return RasgaPDFReader
|
|
350
|
+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
__all__ = [
|
|
354
|
+
"parse_raw",
|
|
355
|
+
"parse_raw_bytes",
|
|
356
|
+
"parse_pdf",
|
|
357
|
+
"extract_text",
|
|
358
|
+
"extract_images",
|
|
359
|
+
"extract_images_bytes",
|
|
360
|
+
"version",
|
|
361
|
+
"RasgaPDFLoader",
|
|
362
|
+
"RasgaPDFReader",
|
|
363
|
+
]
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"""Official LangChain Document Loader for RasgaPDF.
|
|
2
|
+
|
|
3
|
+
Ultra-fast 2D spatial PDF loading with exact bounding boxes, structured tables,
|
|
4
|
+
and zero-loss layout preservation for RAG pipelines.
|
|
5
|
+
"""
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any, Dict, Iterator, List, Optional, Union
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
from langchain_core.document_loaders import BaseLoader
|
|
12
|
+
from langchain_core.documents import Document
|
|
13
|
+
except ImportError:
|
|
14
|
+
# Standalone fallback when langchain_core is not installed
|
|
15
|
+
class BaseLoader:
|
|
16
|
+
def load(self) -> List["Document"]:
|
|
17
|
+
return list(self.lazy_load())
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class Document:
|
|
21
|
+
page_content: str
|
|
22
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class RasgaPDFLoader(BaseLoader):
|
|
26
|
+
"""LangChain Document Loader powered by RasgaPDF.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
file_path_or_bytes: Path to PDF file or raw bytes of a PDF.
|
|
30
|
+
mode: Extraction granularity:
|
|
31
|
+
- "pages" (default): One Document per page with layout-preserved text & markdown tables.
|
|
32
|
+
- "elements": One Document per spatial element (blocks and tables) with exact 2D bounding boxes.
|
|
33
|
+
- "text": A single Document containing the entire normalized text stream.
|
|
34
|
+
detect_tables: Whether to detect and reconstruct physical 2D tables. Default True.
|
|
35
|
+
markdown_tables: Format tables as Markdown matrices inside page content. Default True.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def __init__(
|
|
39
|
+
self,
|
|
40
|
+
file_path_or_bytes: Union[str, Path, bytes],
|
|
41
|
+
mode: str = "pages",
|
|
42
|
+
detect_tables: bool = True,
|
|
43
|
+
markdown_tables: bool = True,
|
|
44
|
+
):
|
|
45
|
+
self.file_input = file_path_or_bytes
|
|
46
|
+
self.mode = mode
|
|
47
|
+
self.detect_tables = detect_tables
|
|
48
|
+
self.markdown_tables = markdown_tables
|
|
49
|
+
self.source = str(file_path_or_bytes) if not isinstance(file_path_or_bytes, (bytes, bytearray)) else "bytes_stream"
|
|
50
|
+
|
|
51
|
+
def lazy_load(self) -> Iterator[Document]:
|
|
52
|
+
import rasgapdf
|
|
53
|
+
|
|
54
|
+
if self.mode == "text":
|
|
55
|
+
text = rasgapdf.extract_text(self.file_input)
|
|
56
|
+
yield Document(
|
|
57
|
+
page_content=text,
|
|
58
|
+
metadata={"source": self.source, "mode": "text"},
|
|
59
|
+
)
|
|
60
|
+
return
|
|
61
|
+
|
|
62
|
+
doc = rasgapdf.parse_pdf(self.file_input, detect_tables=self.detect_tables)
|
|
63
|
+
pages = doc.get("pages", [])
|
|
64
|
+
|
|
65
|
+
if self.mode == "elements":
|
|
66
|
+
for page in pages:
|
|
67
|
+
page_num = page.get("page_number", 1)
|
|
68
|
+
width = page.get("width", 0.0)
|
|
69
|
+
height = page.get("height", 0.0)
|
|
70
|
+
|
|
71
|
+
# 1. Text blocks
|
|
72
|
+
for block in page.get("text_blocks", []):
|
|
73
|
+
lines_text = [line.get("text", "") for line in block.get("lines", []) if line.get("text")]
|
|
74
|
+
content = "\n".join(lines_text).strip()
|
|
75
|
+
if content:
|
|
76
|
+
yield Document(
|
|
77
|
+
page_content=content,
|
|
78
|
+
metadata={
|
|
79
|
+
"source": self.source,
|
|
80
|
+
"page": page_num,
|
|
81
|
+
"type": "text_block",
|
|
82
|
+
"bbox": block.get("bbox", {}),
|
|
83
|
+
"reading_order": block.get("reading_order", 0),
|
|
84
|
+
"page_width": width,
|
|
85
|
+
"page_height": height,
|
|
86
|
+
},
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# 2. Tables
|
|
90
|
+
for t_idx, table in enumerate(page.get("tables", [])):
|
|
91
|
+
table_md = self._format_table_markdown(table) if self.markdown_tables else "\n".join(
|
|
92
|
+
["\t".join([str(c) for c in row]) if isinstance(row, list) else str(row) for row in table.get("rows", [])]
|
|
93
|
+
)
|
|
94
|
+
if table_md.strip():
|
|
95
|
+
yield Document(
|
|
96
|
+
page_content=table_md,
|
|
97
|
+
metadata={
|
|
98
|
+
"source": self.source,
|
|
99
|
+
"page": page_num,
|
|
100
|
+
"type": "table",
|
|
101
|
+
"table_id": table.get("table_id", t_idx),
|
|
102
|
+
"bbox": table.get("bbox", {}),
|
|
103
|
+
"row_count": table.get("row_count", len(table.get("rows", []))),
|
|
104
|
+
"col_count": table.get("col_count", 0),
|
|
105
|
+
"page_width": width,
|
|
106
|
+
"page_height": height,
|
|
107
|
+
},
|
|
108
|
+
)
|
|
109
|
+
return
|
|
110
|
+
|
|
111
|
+
# Default mode: "pages"
|
|
112
|
+
for page in pages:
|
|
113
|
+
page_num = page.get("page_number", 1)
|
|
114
|
+
parts = []
|
|
115
|
+
|
|
116
|
+
# Add text blocks
|
|
117
|
+
for block in page.get("text_blocks", []):
|
|
118
|
+
lines_text = [line.get("text", "") for line in block.get("lines", []) if line.get("text")]
|
|
119
|
+
text = "\n".join(lines_text).strip()
|
|
120
|
+
if text:
|
|
121
|
+
parts.append(text)
|
|
122
|
+
|
|
123
|
+
# Add formatted tables
|
|
124
|
+
for table in page.get("tables", []):
|
|
125
|
+
if self.markdown_tables:
|
|
126
|
+
table_str = self._format_table_markdown(table)
|
|
127
|
+
else:
|
|
128
|
+
table_str = "\n".join(
|
|
129
|
+
["\t".join([str(c) for c in row]) if isinstance(row, list) else str(row) for row in table.get("rows", [])]
|
|
130
|
+
)
|
|
131
|
+
if table_str:
|
|
132
|
+
parts.append(table_str)
|
|
133
|
+
|
|
134
|
+
page_content = "\n\n".join(parts).strip()
|
|
135
|
+
yield Document(
|
|
136
|
+
page_content=page_content,
|
|
137
|
+
metadata={
|
|
138
|
+
"source": self.source,
|
|
139
|
+
"page": page_num,
|
|
140
|
+
"total_pages": len(pages),
|
|
141
|
+
"width": page.get("width", 0.0),
|
|
142
|
+
"height": page.get("height", 0.0),
|
|
143
|
+
"block_count": len(page.get("text_blocks", [])),
|
|
144
|
+
"table_count": len(page.get("tables", [])),
|
|
145
|
+
},
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
def load(self) -> List[Document]:
|
|
149
|
+
return list(self.lazy_load())
|
|
150
|
+
|
|
151
|
+
@staticmethod
|
|
152
|
+
def _format_table_markdown(table: Dict[str, Any]) -> str:
|
|
153
|
+
rows = table.get("rows", [])
|
|
154
|
+
headers = table.get("headers", [])
|
|
155
|
+
if not rows and not headers:
|
|
156
|
+
return ""
|
|
157
|
+
|
|
158
|
+
matrix = []
|
|
159
|
+
if headers and isinstance(headers, list):
|
|
160
|
+
matrix.append([str(h).replace("\n", " ").strip() for h in headers])
|
|
161
|
+
|
|
162
|
+
for row in rows:
|
|
163
|
+
if isinstance(row, list):
|
|
164
|
+
row_cells = [str(c).replace("\n", " ").strip() for c in row]
|
|
165
|
+
elif isinstance(row, dict):
|
|
166
|
+
row_cells = [str(c.get("text", "")).replace("\n", " ").strip() for c in row.get("cells", [])]
|
|
167
|
+
else:
|
|
168
|
+
row_cells = [str(row)]
|
|
169
|
+
matrix.append(row_cells)
|
|
170
|
+
|
|
171
|
+
if not matrix:
|
|
172
|
+
return ""
|
|
173
|
+
|
|
174
|
+
max_cols = max(len(r) for r in matrix)
|
|
175
|
+
for r in matrix:
|
|
176
|
+
while len(r) < max_cols:
|
|
177
|
+
r.append("")
|
|
178
|
+
|
|
179
|
+
md_lines = []
|
|
180
|
+
header = matrix[0]
|
|
181
|
+
md_lines.append("| " + " | ".join(header) + " |")
|
|
182
|
+
md_lines.append("| " + " | ".join(["---"] * max_cols) + " |")
|
|
183
|
+
for r in matrix[1:]:
|
|
184
|
+
md_lines.append("| " + " | ".join(r) + " |")
|
|
185
|
+
return "\n".join(md_lines)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""Official LlamaIndex Reader for RasgaPDF.
|
|
2
|
+
|
|
3
|
+
High-throughput 2D spatial PDF reader for LlamaIndex indexers and agents.
|
|
4
|
+
"""
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any, Dict, List, Optional, Union
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
from llama_index.core.readers.base import BaseReader
|
|
11
|
+
from llama_index.core.schema import Document
|
|
12
|
+
except ImportError:
|
|
13
|
+
class BaseReader:
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class Document:
|
|
18
|
+
text: str
|
|
19
|
+
extra_info: Dict[str, Any] = field(default_factory=dict)
|
|
20
|
+
|
|
21
|
+
@property
|
|
22
|
+
def metadata(self) -> Dict[str, Any]:
|
|
23
|
+
return self.extra_info
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class RasgaPDFReader(BaseReader):
|
|
27
|
+
"""LlamaIndex Reader powered by RasgaPDF.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
mode: Granularity mode:
|
|
31
|
+
- "pages" (default): Returns one Document per PDF page.
|
|
32
|
+
- "elements": Returns one Document per text block or table with exact bounding boxes.
|
|
33
|
+
detect_tables: Detect and extract physical tables. Default True.
|
|
34
|
+
markdown_tables: Format tables as Markdown. Default True.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
mode: str = "pages",
|
|
40
|
+
detect_tables: bool = True,
|
|
41
|
+
markdown_tables: bool = True,
|
|
42
|
+
):
|
|
43
|
+
self.mode = mode
|
|
44
|
+
self.detect_tables = detect_tables
|
|
45
|
+
self.markdown_tables = markdown_tables
|
|
46
|
+
|
|
47
|
+
def load_data(
|
|
48
|
+
self,
|
|
49
|
+
file: Union[str, Path, bytes],
|
|
50
|
+
extra_info: Optional[Dict[str, Any]] = None,
|
|
51
|
+
) -> List[Document]:
|
|
52
|
+
from .langchain import RasgaPDFLoader
|
|
53
|
+
|
|
54
|
+
loader = RasgaPDFLoader(
|
|
55
|
+
file_path_or_bytes=file,
|
|
56
|
+
mode=self.mode,
|
|
57
|
+
detect_tables=self.detect_tables,
|
|
58
|
+
markdown_tables=self.markdown_tables,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
base_meta = extra_info or {}
|
|
62
|
+
docs = []
|
|
63
|
+
|
|
64
|
+
for doc in loader.lazy_load():
|
|
65
|
+
meta = {**base_meta, **doc.metadata}
|
|
66
|
+
try:
|
|
67
|
+
# Use official llama_index Document if available
|
|
68
|
+
from llama_index.core.schema import Document as LlamaDoc
|
|
69
|
+
docs.append(LlamaDoc(text=doc.page_content, extra_info=meta))
|
|
70
|
+
except ImportError:
|
|
71
|
+
docs.append(Document(text=doc.page_content, extra_info=meta))
|
|
72
|
+
|
|
73
|
+
return docs
|
|
Binary file
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rasgapdf
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Ultra-fast 2D spatial PDF parser powered by pure Rust — extract exact [x0, y0, x1, y1] bounding boxes, text blocks, tables, images & vector paths in milliseconds for RAG & LLMs
|
|
5
5
|
Author: Messias Martins
|
|
6
6
|
Project-URL: Homepage, https://martinsmessias.github.io/rasgapdf/
|
|
@@ -191,6 +191,33 @@ print(manifest["written"], "files written")
|
|
|
191
191
|
|
|
192
192
|
---
|
|
193
193
|
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## 🦜️🔗 AI Framework Integrations (LangChain & LlamaIndex)
|
|
197
|
+
|
|
198
|
+
### 🦜️ LangChain Document Loader
|
|
199
|
+
`python
|
|
200
|
+
from rasgapdf import RasgaPDFLoader
|
|
201
|
+
|
|
202
|
+
# 1 Document per page with markdown tables:
|
|
203
|
+
loader = RasgaPDFLoader('document.pdf', mode='pages')
|
|
204
|
+
docs = loader.load()
|
|
205
|
+
|
|
206
|
+
# Spatial RAG: 1 Document per block/table with exact [x0, y0, x1, y1] coordinates:
|
|
207
|
+
spatial_loader = RasgaPDFLoader('document.pdf', mode='elements')
|
|
208
|
+
chunks = spatial_loader.load()
|
|
209
|
+
for chunk in chunks:
|
|
210
|
+
print(chunk.metadata['bbox'], chunk.page_content[:40])
|
|
211
|
+
`
|
|
212
|
+
|
|
213
|
+
### 🦙 LlamaIndex Reader
|
|
214
|
+
`python
|
|
215
|
+
from rasgapdf import RasgaPDFReader
|
|
216
|
+
|
|
217
|
+
reader = RasgaPDFReader(mode='pages')
|
|
218
|
+
documents = reader.load_data('financial_report.pdf')
|
|
219
|
+
`
|
|
220
|
+
|
|
194
221
|
## 📄 License
|
|
195
222
|
|
|
196
223
|
GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later). Copyright (c) 2026 Messias Martins.
|
|
@@ -198,3 +225,19 @@ GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later). Copyright (
|
|
|
198
225
|
RasgaPDF embeds and links against [MuPDF](https://mupdf.com/) (Artifex Software),
|
|
199
226
|
which is distributed under the AGPL-3.0. That is why this project is licensed
|
|
200
227
|
under the same terms.
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## 💼 Commercial & Enterprise Licensing (AGPL-3.0 Waiver)
|
|
232
|
+
|
|
233
|
+
Need to use **RasgaPDF** in closed-source commercial software, proprietary SaaS platforms, private cloud environments, or corporate applications without releasing your source code under the AGPL-3.0?
|
|
234
|
+
|
|
235
|
+
A **Commercial / Enterprise License** is available directly from the author:
|
|
236
|
+
|
|
237
|
+
- **Complete AGPL-3.0 Exemption:** Keep your intellectual property, backend code, and SaaS infrastructure 100% closed-source and proprietary.
|
|
238
|
+
- **Enterprise SLA & Support:** Direct architecture advisory, guaranteed response times, and priority bug resolution.
|
|
239
|
+
- **On-Premise & Air-Gapped Appliances:** Ready-to-deploy private Docker containers for confidential banking, healthcare, and legal compliance (LGPD / GDPR).
|
|
240
|
+
- **Custom Spatial Features:** Tailored table extractors for bank statements, invoices, and court proceedings.
|
|
241
|
+
|
|
242
|
+
📬 **Inquiries & Licensing:**
|
|
243
|
+
[👉 **Click here to Request a Commercial License & Pricing**](mailto:messiasads2017@gmail.com?subject=RasgaPDF%20Commercial%20License%20Inquiry) with details about your organization, use case, and estimated volume.
|
|
@@ -6,4 +6,7 @@ rasgapdf/rasgapdf.dll
|
|
|
6
6
|
rasgapdf.egg-info/PKG-INFO
|
|
7
7
|
rasgapdf.egg-info/SOURCES.txt
|
|
8
8
|
rasgapdf.egg-info/dependency_links.txt
|
|
9
|
-
rasgapdf.egg-info/top_level.txt
|
|
9
|
+
rasgapdf.egg-info/top_level.txt
|
|
10
|
+
rasgapdf/integrations/__init__.py
|
|
11
|
+
rasgapdf/integrations/langchain.py
|
|
12
|
+
rasgapdf/integrations/llama_index.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|