HowdenParser 0.1.2__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.
- howdenparser-0.1.2/HowdenParser/__init__.py +3 -0
- howdenparser-0.1.2/HowdenParser/parser.py +137 -0
- howdenparser-0.1.2/PKG-INFO +28 -0
- howdenparser-0.1.2/README.md +1 -0
- howdenparser-0.1.2/parameter/__init__.py +3 -0
- howdenparser-0.1.2/parameter/huggingface.py +6 -0
- howdenparser-0.1.2/parameter/llamaparser.py +8 -0
- howdenparser-0.1.2/parameter/mistralocr.py +7 -0
- howdenparser-0.1.2/pyproject.toml +21 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from dotenv import load_dotenv
|
|
3
|
+
import os
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
load_dotenv()
|
|
7
|
+
|
|
8
|
+
class BaseParser(ABC):
|
|
9
|
+
@abstractmethod
|
|
10
|
+
def parse(self, text: str) -> dict:
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class MistralOCRParser(BaseParser):
|
|
15
|
+
def __init__(self, result_type: str, **kwargs) -> None:
|
|
16
|
+
from mistralai import Mistral
|
|
17
|
+
name = "MISTRAL-OCR-API-TOKEN"
|
|
18
|
+
api_key = os.getenv(name)
|
|
19
|
+
if not api_key:
|
|
20
|
+
raise EnvironmentError(f"Missing {name} in .env file.")
|
|
21
|
+
|
|
22
|
+
self.result_type = "md" if result_type.lower() in ("md", "markdown") else "text"
|
|
23
|
+
self.client = Mistral(api_key=api_key)
|
|
24
|
+
|
|
25
|
+
def parse(self, file_path: Path) -> str:
|
|
26
|
+
def upload_pdf(filename):
|
|
27
|
+
uploaded_pdf = self.client.files.upload(
|
|
28
|
+
file={
|
|
29
|
+
"file_name": filename,
|
|
30
|
+
"content": open(filename, "rb"),
|
|
31
|
+
},
|
|
32
|
+
purpose="ocr"
|
|
33
|
+
)
|
|
34
|
+
signed_url = self.client.files.get_signed_url(file_id=uploaded_pdf.id)
|
|
35
|
+
return signed_url.url
|
|
36
|
+
|
|
37
|
+
ocr_response = self.client.ocr.process(
|
|
38
|
+
model="mistral-ocr-latest",
|
|
39
|
+
document={
|
|
40
|
+
"type": "document_url",
|
|
41
|
+
"document_url": upload_pdf(file_path),
|
|
42
|
+
},
|
|
43
|
+
include_image_base64=True,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
return "\n".join(doc.markdown for doc in ocr_response.pages)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class LangChainParser(BaseParser):
|
|
50
|
+
def __init__(self, model_name: str):
|
|
51
|
+
from langchain.llms import OpenAI
|
|
52
|
+
self.model_name = model_name
|
|
53
|
+
self.model = OpenAI(model_name=model_name)
|
|
54
|
+
|
|
55
|
+
def parse(self, text: str) -> dict:
|
|
56
|
+
response = self.model(text)
|
|
57
|
+
return {"source": "LangChain", "output": response}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class LlamaParser(BaseParser):
|
|
61
|
+
def __init__(self, result_type: str, mode: bool, **kwargs) -> None:
|
|
62
|
+
from llama_parse import LlamaParse, ResultType
|
|
63
|
+
if result_type.lower() == "md" or result_type.lower() == "markdown":
|
|
64
|
+
self.result_type = ResultType.MD
|
|
65
|
+
name = "LLAMA-PARSER-API-TOKEN"
|
|
66
|
+
self.api_key = os.getenv(name)
|
|
67
|
+
if not self.api_key:
|
|
68
|
+
raise EnvironmentError(f"Missing {name} in .env file.")
|
|
69
|
+
|
|
70
|
+
self.parser = LlamaParse(
|
|
71
|
+
api_key=self.api_key,
|
|
72
|
+
result_type=self.result_type,
|
|
73
|
+
premium_mode=mode
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
def parse(self, file_path: Path) -> str:
|
|
77
|
+
documents = self.parser.load_data(str(file_path))
|
|
78
|
+
return "\n".join(doc.text for doc in documents)
|
|
79
|
+
|
|
80
|
+
class HuggingFaceParser(BaseParser):
|
|
81
|
+
def __init__(self, result_type: str, mode: bool, **kwargs) -> None:
|
|
82
|
+
from transformers import pipeline
|
|
83
|
+
|
|
84
|
+
if result_type.lower() in ("md", "markdown"):
|
|
85
|
+
self.result_type = "markdown"
|
|
86
|
+
else:
|
|
87
|
+
self.result_type = "text"
|
|
88
|
+
|
|
89
|
+
name = "HF-API-TOKEN"
|
|
90
|
+
self.api_key = os.getenv(name)
|
|
91
|
+
if not self.api_key:
|
|
92
|
+
raise EnvironmentError(f"Missing {name} in .env file.")
|
|
93
|
+
|
|
94
|
+
# OCR + text extraction pipeline
|
|
95
|
+
# Example model: microsoft/layoutlmv3-base-finetuned-docvqa
|
|
96
|
+
self.parser = pipeline(
|
|
97
|
+
task="document-question-answering",
|
|
98
|
+
model="impira/layoutlm-document-qa",
|
|
99
|
+
use_auth_token=self.api_key
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
def parse(self, file_path: Path) -> str:
|
|
103
|
+
import fitz # PyMuPDF for PDF → images
|
|
104
|
+
|
|
105
|
+
pdf_doc = fitz.open(file_path)
|
|
106
|
+
output_parts = []
|
|
107
|
+
|
|
108
|
+
for page in pdf_doc:
|
|
109
|
+
pix = page.get_pixmap(dpi=200)
|
|
110
|
+
img_bytes = pix.tobytes("png")
|
|
111
|
+
response = self.parser(img_bytes, question="Extract all text")
|
|
112
|
+
if response and "answer" in response[0]:
|
|
113
|
+
output_parts.append(response[0]["answer"])
|
|
114
|
+
|
|
115
|
+
if self.result_type == "markdown":
|
|
116
|
+
# Here you could add rules to format into markdown
|
|
117
|
+
return "\n\n".join(output_parts)
|
|
118
|
+
else:
|
|
119
|
+
return " ".join(output_parts)
|
|
120
|
+
|
|
121
|
+
# === Step 3: Dynamic factory using string input ===
|
|
122
|
+
class ParserFactory:
|
|
123
|
+
@staticmethod
|
|
124
|
+
def get_parser(parser_type: str, **kwargs) -> BaseParser:
|
|
125
|
+
provider = parser_type.partition(":")[0].lower()
|
|
126
|
+
model = parser_type.partition(":")[2]
|
|
127
|
+
if provider == "langchain":
|
|
128
|
+
return LangChainParser(model_name=model)
|
|
129
|
+
elif provider == "llamaparser":
|
|
130
|
+
return LlamaParser(**kwargs)
|
|
131
|
+
elif provider == "huggingface":
|
|
132
|
+
return HuggingFaceParser(model_name=model, **kwargs)
|
|
133
|
+
elif provider == "mistralocr":
|
|
134
|
+
return MistralOCRParser(**kwargs)
|
|
135
|
+
else:
|
|
136
|
+
raise ValueError(f"Unknown parser type: {parser_type}")
|
|
137
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: HowdenParser
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: A simple configuration manager with Pydantic and JSON export.
|
|
5
|
+
License: MIT
|
|
6
|
+
Keywords: config,configuration,pydantic,json
|
|
7
|
+
Author: JesperThoftIllemannJ
|
|
8
|
+
Author-email: jesper.jaeger@howdendanmark.dk
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 2
|
|
11
|
+
Classifier: Programming Language :: Python :: 2.7
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.4
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.5
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.6
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Project-URL: Documentation, https://github.com/yourusername/config
|
|
24
|
+
Project-URL: Homepage, https://github.com/yourusername/config
|
|
25
|
+
Project-URL: Repository, https://github.com/yourusername/config
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
.\build.ps1
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.\build.ps1
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [ "poetry-core>=2.0.0,<3.0.0",]
|
|
3
|
+
build-backend = "poetry.core.masonry.api"
|
|
4
|
+
|
|
5
|
+
[tool.poetry]
|
|
6
|
+
name = "HowdenParser"
|
|
7
|
+
version = "0.1.2"
|
|
8
|
+
description = "A simple configuration manager with Pydantic and JSON export."
|
|
9
|
+
authors = [ "JesperThoftIllemannJ <jesper.jaeger@howdendanmark.dk>",]
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
keywords = [ "config", "configuration", "pydantic", "json",]
|
|
13
|
+
homepage = "https://github.com/yourusername/config"
|
|
14
|
+
repository = "https://github.com/yourusername/config"
|
|
15
|
+
documentation = "https://github.com/yourusername/config"
|
|
16
|
+
[[tool.poetry.packages]]
|
|
17
|
+
include = "HowdenParser"
|
|
18
|
+
|
|
19
|
+
[[tool.poetry.packages]]
|
|
20
|
+
include = "parameter"
|
|
21
|
+
|