Skip to content

Repository files navigation


ScaleDP

An Open-Source Library for Processing Documents using AI/ML in Apache Spark.

GitHubStabRiseCodacy Badgepre-commitPoetryCode style: blackDocumentation Status


Source Code: https://github.com/StabRise/ScaleDP

Quickstart: 1.QuickStart.ipynb

Documentations: https://scaledp.stabrise.com

Tutorials: https://github.com/StabRise/ScaleDP-Tutorials

Change Log


Welcome to the ScaleDP library

ScaleDP is library allows you to process documents using AI/ML capabilities and scale it using Apache Spark.

LLM (Large Language Models) and VLM (Vision Language Models) models are used to extract data from text and images in combination with OCR engines.

Discover pre-trained models for your projects or play with the thousands of models hosted on the Hugging Face Hub.

Key features

Document processing:

  • ✅ Loading PDF documents/Images to the Spark DataFrame (using Spark PDF Datasource and as binaryFile)
  • ✅ Extraction text/images from PDF documents/Images
  • ✅ Zero-Shot extraction structured data from text/images using LLM and ML models
  • ✅ Possibility run as REST API service without Spark Session for have minimum processing latency
  • ✅ Support Streaming mode for processing documents in real-time

LLM:

Support OpenAI compatible API for call LLM/VLM models (GPT, Gemini, GROQ, etc.)

  • OCR Images/PDF documents using Vision LLM models
  • Extract data from the image using Vision LLM models
  • Extract data from the text/images using LLM models
  • Extract data using DSPy framework
  • NER using LLM's
  • Visualize results

NLP:

  • Extract data from the text/images using NLP models from the Hugging Face Hub
  • NER using classical ML models

OCR:

Support various open-source OCR engines:

CV:

  • Object detection on images using YOLO models
  • Text detection on images

Installation

Prerequisites

  • Python 3.10 or higher
  • Apache Spark 3.5 or higher
  • Java 8

Installation using pip

Install the ScaleDP package with pip:

pip install scaledp

Installation using Docker

Build image:

 docker build -t scaledp .

Run container:

 docker run -p 8888:8888 scaledp:latest

Open Jupyter Notebook in your browser:

 http://localhost:8888

Qiuckstart

Start a Spark session with ScaleDP:

fromscaledpimport*spark=ScaleDPSession()
spark

Read example image file:

image_example=files('resources/images/Invoice.png')
df=spark.read.format("binaryFile") \
.load(image_example)
df.show_image("content")

Output:

Zero-Shot data Extraction from the Image:

frompydanticimportBaseModelimportjsonclassItems(BaseModel):
date: stritem: strnote: strdebit: strclassInvoiceSchema(BaseModel):
hospital: strtax_id: straddress: stremail: strphone: stritems: list[Items]
total: strpipeline=PipelineModel(stages=[
DataToImage(
inputCol="content",
outputCol="image"
),
LLMVisualExtractor(
inputCol="image",
outputCol="invoice",
model="gemini-1.5-flash",
apiKey="",
apiBase="https://generativelanguage.googleapis.com/v1beta/",
schema=json.dumps(InvoiceSchema.model_json_schema())
)
])
result=pipeline.transform(df).cache()

Show the extracted json:

result.show_json("invoice")

Let's show Invoice as Structured Data in Data Frame

result.select("invoice.data.*").show()

Output:

+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+
| hospital| tax_id| address| email| phone| items| total|
+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+
|Hope Haven Hospital|26-123123|855 Howard Street...|hopedutton@hopeha...|(123) 456-1238|[{10/21/2022, App...|1024.50|
+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+

Schema:

result.printSchema()
root
|-- path: string (nullable = true)
|-- modificationTime: timestamp (nullable = true)
|-- length: long (nullable = true)
|-- image: struct (nullable = true)
| |-- path: string (nullable = false)
| |-- resolution: integer (nullable = false)
| |-- data: binary (nullable = false)
| |-- imageType: string (nullable = false)
| |-- exception: string (nullable = false)
| |-- height: integer (nullable = false)
| |-- width: integer (nullable = false)
|-- invoice: struct (nullable = true)
| |-- path: string (nullable = false)
| |-- json_data: string (nullable = true)
| |-- type: string (nullable = false)
| |-- exception: string (nullable = false)
| |-- processing_time: double (nullable = false)
| |-- data: struct (nullable = true)
| | |-- hospital: string (nullable = false)
| | |-- tax_id: string (nullable = false)
| | |-- address: string (nullable = false)
| | |-- email: string (nullable = false)
| | |-- phone: string (nullable = false)
| | |-- items: array (nullable = false)
| | | |-- element: struct (containsNull = false)
| | | | |-- date: string (nullable = false)
| | | | |-- item: string (nullable = false)
| | | | |-- note: string (nullable = false)
| | | | |-- debit: string (nullable = false)
| | |-- total: string (nullable = false)

NER using model from the HuggingFace models Hub

Define pipeline for extract text from the image and run NER:

pipeline=PipelineModel(stages=[
DataToImage(inputCol="content", outputCol="image"),
TesseractOcr(inputCol="image", outputCol="text", psm=PSM.AUTO, keepInputData=True),
Ner(model="obi/deid_bert_i2b2", inputCol="text", outputCol="ner", keepInputData=True),
ImageDrawBoxes(inputCols=["image", "ner"], outputCol="image_with_boxes", lineWidth=3, padding=5, displayDataList=['entity_group'])
])
result=pipeline.transform(df).cache()
result.show_text("text")

Output:

Show NER results:

result.show_ner(limit=20)

Output:

+------------+-------------------+----------+-----+---+--------------------+
|entity_group| score| word|start|end| boxes|
+------------+-------------------+----------+-----+---+--------------------+
| HOSP| 0.991257905960083| Hospital| 0| 8|[{Hospital:, 0.94...|
| LOC| 0.999171257019043| Dutton| 10| 16|[{Dutton,, 0.9609...|
| LOC| 0.9992585778236389| MI| 18| 20|[{MI, 0.93335297,...|
| ID| 0.6838774085044861| 26| 29| 31|[{26-123123, 0.90...|
| PHONE| 0.4669836759567261| -| 31| 32|[{26-123123, 0.90...|
| PHONE| 0.7790696024894714| 123123| 32| 38|[{26-123123, 0.90...|
| HOSP|0.37445762753486633| HOPE| 39| 43|[{HOPE, 0.9525460...|
| HOSP| 0.9503226280212402| HAVEN| 44| 49|[{HAVEN, 0.952546...|
| LOC| 0.9975488185882568|855 Howard| 59| 69|[{855, 0.94682700...|
| LOC| 0.9984399676322937| Street| 70| 76|[{Street, 0.95823...|
| HOSP| 0.3670221269130707| HOSPITAL| 77| 85|[{HOSPITAL, 0.959...|
| LOC| 0.9990363121032715| Dutton| 86| 92|[{Dutton,, 0.9647...|
| LOC| 0.999313473701477| MI 49316| 94|102|[{MI, 0.94589012,...|
| PHONE| 0.9830010533332825| ( 123 )| 110|115|[{(123), 0.595334...|
| PHONE| 0.9080978035926819| 456| 116|119|[{456-1238, 0.955...|
| PHONE| 0.9378324151039124| -| 119|120|[{456-1238, 0.955...|
| PHONE| 0.8746233582496643| 1238| 120|124|[{456-1238, 0.955...|
| PATIENT|0.45354968309402466|hopedutton| 132|142|[{hopedutton@hope...|
| EMAIL|0.17805588245391846| hopehaven| 143|152|[{hopedutton@hope...|
| HOSP| 0.505658745765686| INVOICE| 157|164|[{INVOICE, 0.9661...|
+------------+-------------------+----------+-----+---+--------------------+

Visualize NER results:

result.visualize_ner(labels_list=["DATE", "LOC"])

Original image with NER results:

result.show_image("image_with_boxes")

Ocr engines

Bbox levelSupport GPUSeparate model for text detectionProcessing time 1 page (CPU/GPU) secsSupport Handwritten Text
Tesseract OCRcharacternono0.2/nonot good
Tesseract OCR CLIcharacternono0.2/nonot good
Easy OCRwordyesyes
Surya OCRlineyesyes
DocTRwordyesyes

Projects used the ScaleDP

  • PDF Redaction - Free AI-powered tool for redact PDF files (remove sensitive information) online.
  • frontiersin.org - Reviewer Recommendation System for academic articles using ScaleDP and LLM models.
  • dayme.tech - Data extraction from scanned receipts using ScaleDP and LLM models.
  • curie.is - Curie used ScaleDP for document preprocessing and analysis data in documents.

Disclaimer

This project is not affiliated with, endorsed by, or connected to the Apache Software Foundation or Apache Spark.

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - StabRise/ScaleDP: ScaleDP is an Open-Source extension of Apache Spark for Document Processing · GitHub
Skip to content

Repository files navigation


ScaleDP

An Open-Source Library for Processing Documents using AI/ML in Apache Spark.

GitHubStabRiseCodacy Badgepre-commitPoetryCode style: blackDocumentation Status


Source Code: https://github.com/StabRise/ScaleDP

Quickstart: 1.QuickStart.ipynb

Documentations: https://scaledp.stabrise.com

Tutorials: https://github.com/StabRise/ScaleDP-Tutorials

Change Log


Welcome to the ScaleDP library

ScaleDP is library allows you to process documents using AI/ML capabilities and scale it using Apache Spark.

LLM (Large Language Models) and VLM (Vision Language Models) models are used to extract data from text and images in combination with OCR engines.

Discover pre-trained models for your projects or play with the thousands of models hosted on the Hugging Face Hub.

Key features

Document processing:

  • ✅ Loading PDF documents/Images to the Spark DataFrame (using Spark PDF Datasource and as binaryFile)
  • ✅ Extraction text/images from PDF documents/Images
  • ✅ Zero-Shot extraction structured data from text/images using LLM and ML models
  • ✅ Possibility run as REST API service without Spark Session for have minimum processing latency
  • ✅ Support Streaming mode for processing documents in real-time

LLM:

Support OpenAI compatible API for call LLM/VLM models (GPT, Gemini, GROQ, etc.)

  • OCR Images/PDF documents using Vision LLM models
  • Extract data from the image using Vision LLM models
  • Extract data from the text/images using LLM models
  • Extract data using DSPy framework
  • NER using LLM's
  • Visualize results

NLP:

  • Extract data from the text/images using NLP models from the Hugging Face Hub
  • NER using classical ML models

OCR:

Support various open-source OCR engines:

CV:

  • Object detection on images using YOLO models
  • Text detection on images

Installation

Prerequisites

  • Python 3.10 or higher
  • Apache Spark 3.5 or higher
  • Java 8

Installation using pip

Install the ScaleDP package with pip:

pip install scaledp

Installation using Docker

Build image:

 docker build -t scaledp .

Run container:

 docker run -p 8888:8888 scaledp:latest

Open Jupyter Notebook in your browser:

 http://localhost:8888

Qiuckstart

Start a Spark session with ScaleDP:

fromscaledpimport*spark=ScaleDPSession()
spark

Read example image file:

image_example=files('resources/images/Invoice.png')
df=spark.read.format("binaryFile") \
.load(image_example)
df.show_image("content")

Output:

Zero-Shot data Extraction from the Image:

frompydanticimportBaseModelimportjsonclassItems(BaseModel):
date: stritem: strnote: strdebit: strclassInvoiceSchema(BaseModel):
hospital: strtax_id: straddress: stremail: strphone: stritems: list[Items]
total: strpipeline=PipelineModel(stages=[
DataToImage(
inputCol="content",
outputCol="image"
),
LLMVisualExtractor(
inputCol="image",
outputCol="invoice",
model="gemini-1.5-flash",
apiKey="",
apiBase="https://generativelanguage.googleapis.com/v1beta/",
schema=json.dumps(InvoiceSchema.model_json_schema())
)
])
result=pipeline.transform(df).cache()

Show the extracted json:

result.show_json("invoice")

Let's show Invoice as Structured Data in Data Frame

result.select("invoice.data.*").show()

Output:

+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+
| hospital| tax_id| address| email| phone| items| total|
+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+
|Hope Haven Hospital|26-123123|855 Howard Street...|hopedutton@hopeha...|(123) 456-1238|[{10/21/2022, App...|1024.50|
+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+

Schema:

result.printSchema()
root
|-- path: string (nullable = true)
|-- modificationTime: timestamp (nullable = true)
|-- length: long (nullable = true)
|-- image: struct (nullable = true)
| |-- path: string (nullable = false)
| |-- resolution: integer (nullable = false)
| |-- data: binary (nullable = false)
| |-- imageType: string (nullable = false)
| |-- exception: string (nullable = false)
| |-- height: integer (nullable = false)
| |-- width: integer (nullable = false)
|-- invoice: struct (nullable = true)
| |-- path: string (nullable = false)
| |-- json_data: string (nullable = true)
| |-- type: string (nullable = false)
| |-- exception: string (nullable = false)
| |-- processing_time: double (nullable = false)
| |-- data: struct (nullable = true)
| | |-- hospital: string (nullable = false)
| | |-- tax_id: string (nullable = false)
| | |-- address: string (nullable = false)
| | |-- email: string (nullable = false)
| | |-- phone: string (nullable = false)
| | |-- items: array (nullable = false)
| | | |-- element: struct (containsNull = false)
| | | | |-- date: string (nullable = false)
| | | | |-- item: string (nullable = false)
| | | | |-- note: string (nullable = false)
| | | | |-- debit: string (nullable = false)
| | |-- total: string (nullable = false)

NER using model from the HuggingFace models Hub

Define pipeline for extract text from the image and run NER:

pipeline=PipelineModel(stages=[
DataToImage(inputCol="content", outputCol="image"),
TesseractOcr(inputCol="image", outputCol="text", psm=PSM.AUTO, keepInputData=True),
Ner(model="obi/deid_bert_i2b2", inputCol="text", outputCol="ner", keepInputData=True),
ImageDrawBoxes(inputCols=["image", "ner"], outputCol="image_with_boxes", lineWidth=3, padding=5, displayDataList=['entity_group'])
])
result=pipeline.transform(df).cache()
result.show_text("text")

Output:

Show NER results:

result.show_ner(limit=20)

Output:

+------------+-------------------+----------+-----+---+--------------------+
|entity_group| score| word|start|end| boxes|
+------------+-------------------+----------+-----+---+--------------------+
| HOSP| 0.991257905960083| Hospital| 0| 8|[{Hospital:, 0.94...|
| LOC| 0.999171257019043| Dutton| 10| 16|[{Dutton,, 0.9609...|
| LOC| 0.9992585778236389| MI| 18| 20|[{MI, 0.93335297,...|
| ID| 0.6838774085044861| 26| 29| 31|[{26-123123, 0.90...|
| PHONE| 0.4669836759567261| -| 31| 32|[{26-123123, 0.90...|
| PHONE| 0.7790696024894714| 123123| 32| 38|[{26-123123, 0.90...|
| HOSP|0.37445762753486633| HOPE| 39| 43|[{HOPE, 0.9525460...|
| HOSP| 0.9503226280212402| HAVEN| 44| 49|[{HAVEN, 0.952546...|
| LOC| 0.9975488185882568|855 Howard| 59| 69|[{855, 0.94682700...|
| LOC| 0.9984399676322937| Street| 70| 76|[{Street, 0.95823...|
| HOSP| 0.3670221269130707| HOSPITAL| 77| 85|[{HOSPITAL, 0.959...|
| LOC| 0.9990363121032715| Dutton| 86| 92|[{Dutton,, 0.9647...|
| LOC| 0.999313473701477| MI 49316| 94|102|[{MI, 0.94589012,...|
| PHONE| 0.9830010533332825| ( 123 )| 110|115|[{(123), 0.595334...|
| PHONE| 0.9080978035926819| 456| 116|119|[{456-1238, 0.955...|
| PHONE| 0.9378324151039124| -| 119|120|[{456-1238, 0.955...|
| PHONE| 0.8746233582496643| 1238| 120|124|[{456-1238, 0.955...|
| PATIENT|0.45354968309402466|hopedutton| 132|142|[{hopedutton@hope...|
| EMAIL|0.17805588245391846| hopehaven| 143|152|[{hopedutton@hope...|
| HOSP| 0.505658745765686| INVOICE| 157|164|[{INVOICE, 0.9661...|
+------------+-------------------+----------+-----+---+--------------------+

Visualize NER results:

result.visualize_ner(labels_list=["DATE", "LOC"])

Original image with NER results:

result.show_image("image_with_boxes")

Ocr engines

Bbox levelSupport GPUSeparate model for text detectionProcessing time 1 page (CPU/GPU) secsSupport Handwritten Text
Tesseract OCRcharacternono0.2/nonot good
Tesseract OCR CLIcharacternono0.2/nonot good
Easy OCRwordyesyes
Surya OCRlineyesyes
DocTRwordyesyes

Projects used the ScaleDP

  • PDF Redaction - Free AI-powered tool for redact PDF files (remove sensitive information) online.
  • frontiersin.org - Reviewer Recommendation System for academic articles using ScaleDP and LLM models.
  • dayme.tech - Data extraction from scanned receipts using ScaleDP and LLM models.
  • curie.is - Curie used ScaleDP for document preprocessing and analysis data in documents.

Disclaimer

This project is not affiliated with, endorsed by, or connected to the Apache Software Foundation or Apache Spark.

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - StabRise/ScaleDP: ScaleDP is an Open-Source extension of Apache Spark for Document Processing · GitHub
Skip to content

Repository files navigation


ScaleDP

An Open-Source Library for Processing Documents using AI/ML in Apache Spark.

GitHubStabRiseCodacy Badgepre-commitPoetryCode style: blackDocumentation Status


Source Code: https://github.com/StabRise/ScaleDP

Quickstart: 1.QuickStart.ipynb

Documentations: https://scaledp.stabrise.com

Tutorials: https://github.com/StabRise/ScaleDP-Tutorials

Change Log


Welcome to the ScaleDP library

ScaleDP is library allows you to process documents using AI/ML capabilities and scale it using Apache Spark.

LLM (Large Language Models) and VLM (Vision Language Models) models are used to extract data from text and images in combination with OCR engines.

Discover pre-trained models for your projects or play with the thousands of models hosted on the Hugging Face Hub.

Key features

Document processing:

  • ✅ Loading PDF documents/Images to the Spark DataFrame (using Spark PDF Datasource and as binaryFile)
  • ✅ Extraction text/images from PDF documents/Images
  • ✅ Zero-Shot extraction structured data from text/images using LLM and ML models
  • ✅ Possibility run as REST API service without Spark Session for have minimum processing latency
  • ✅ Support Streaming mode for processing documents in real-time

LLM:

Support OpenAI compatible API for call LLM/VLM models (GPT, Gemini, GROQ, etc.)

  • OCR Images/PDF documents using Vision LLM models
  • Extract data from the image using Vision LLM models
  • Extract data from the text/images using LLM models
  • Extract data using DSPy framework
  • NER using LLM's
  • Visualize results

NLP:

  • Extract data from the text/images using NLP models from the Hugging Face Hub
  • NER using classical ML models

OCR:

Support various open-source OCR engines:

CV:

  • Object detection on images using YOLO models
  • Text detection on images

Installation

Prerequisites

  • Python 3.10 or higher
  • Apache Spark 3.5 or higher
  • Java 8

Installation using pip

Install the ScaleDP package with pip:

pip install scaledp

Installation using Docker

Build image:

 docker build -t scaledp .

Run container:

 docker run -p 8888:8888 scaledp:latest

Open Jupyter Notebook in your browser:

 http://localhost:8888

Qiuckstart

Start a Spark session with ScaleDP:

fromscaledpimport*spark=ScaleDPSession()
spark

Read example image file:

image_example=files('resources/images/Invoice.png')
df=spark.read.format("binaryFile") \
.load(image_example)
df.show_image("content")

Output:

Zero-Shot data Extraction from the Image:

frompydanticimportBaseModelimportjsonclassItems(BaseModel):
date: stritem: strnote: strdebit: strclassInvoiceSchema(BaseModel):
hospital: strtax_id: straddress: stremail: strphone: stritems: list[Items]
total: strpipeline=PipelineModel(stages=[
DataToImage(
inputCol="content",
outputCol="image"
),
LLMVisualExtractor(
inputCol="image",
outputCol="invoice",
model="gemini-1.5-flash",
apiKey="",
apiBase="https://generativelanguage.googleapis.com/v1beta/",
schema=json.dumps(InvoiceSchema.model_json_schema())
)
])
result=pipeline.transform(df).cache()

Show the extracted json:

result.show_json("invoice")

Let's show Invoice as Structured Data in Data Frame

result.select("invoice.data.*").show()

Output:

+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+
| hospital| tax_id| address| email| phone| items| total|
+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+
|Hope Haven Hospital|26-123123|855 Howard Street...|hopedutton@hopeha...|(123) 456-1238|[{10/21/2022, App...|1024.50|
+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+

Schema:

result.printSchema()
root
|-- path: string (nullable = true)
|-- modificationTime: timestamp (nullable = true)
|-- length: long (nullable = true)
|-- image: struct (nullable = true)
| |-- path: string (nullable = false)
| |-- resolution: integer (nullable = false)
| |-- data: binary (nullable = false)
| |-- imageType: string (nullable = false)
| |-- exception: string (nullable = false)
| |-- height: integer (nullable = false)
| |-- width: integer (nullable = false)
|-- invoice: struct (nullable = true)
| |-- path: string (nullable = false)
| |-- json_data: string (nullable = true)
| |-- type: string (nullable = false)
| |-- exception: string (nullable = false)
| |-- processing_time: double (nullable = false)
| |-- data: struct (nullable = true)
| | |-- hospital: string (nullable = false)
| | |-- tax_id: string (nullable = false)
| | |-- address: string (nullable = false)
| | |-- email: string (nullable = false)
| | |-- phone: string (nullable = false)
| | |-- items: array (nullable = false)
| | | |-- element: struct (containsNull = false)
| | | | |-- date: string (nullable = false)
| | | | |-- item: string (nullable = false)
| | | | |-- note: string (nullable = false)
| | | | |-- debit: string (nullable = false)
| | |-- total: string (nullable = false)

NER using model from the HuggingFace models Hub

Define pipeline for extract text from the image and run NER:

pipeline=PipelineModel(stages=[
DataToImage(inputCol="content", outputCol="image"),
TesseractOcr(inputCol="image", outputCol="text", psm=PSM.AUTO, keepInputData=True),
Ner(model="obi/deid_bert_i2b2", inputCol="text", outputCol="ner", keepInputData=True),
ImageDrawBoxes(inputCols=["image", "ner"], outputCol="image_with_boxes", lineWidth=3, padding=5, displayDataList=['entity_group'])
])
result=pipeline.transform(df).cache()
result.show_text("text")

Output:

Show NER results:

result.show_ner(limit=20)

Output:

+------------+-------------------+----------+-----+---+--------------------+
|entity_group| score| word|start|end| boxes|
+------------+-------------------+----------+-----+---+--------------------+
| HOSP| 0.991257905960083| Hospital| 0| 8|[{Hospital:, 0.94...|
| LOC| 0.999171257019043| Dutton| 10| 16|[{Dutton,, 0.9609...|
| LOC| 0.9992585778236389| MI| 18| 20|[{MI, 0.93335297,...|
| ID| 0.6838774085044861| 26| 29| 31|[{26-123123, 0.90...|
| PHONE| 0.4669836759567261| -| 31| 32|[{26-123123, 0.90...|
| PHONE| 0.7790696024894714| 123123| 32| 38|[{26-123123, 0.90...|
| HOSP|0.37445762753486633| HOPE| 39| 43|[{HOPE, 0.9525460...|
| HOSP| 0.9503226280212402| HAVEN| 44| 49|[{HAVEN, 0.952546...|
| LOC| 0.9975488185882568|855 Howard| 59| 69|[{855, 0.94682700...|
| LOC| 0.9984399676322937| Street| 70| 76|[{Street, 0.95823...|
| HOSP| 0.3670221269130707| HOSPITAL| 77| 85|[{HOSPITAL, 0.959...|
| LOC| 0.9990363121032715| Dutton| 86| 92|[{Dutton,, 0.9647...|
| LOC| 0.999313473701477| MI 49316| 94|102|[{MI, 0.94589012,...|
| PHONE| 0.9830010533332825| ( 123 )| 110|115|[{(123), 0.595334...|
| PHONE| 0.9080978035926819| 456| 116|119|[{456-1238, 0.955...|
| PHONE| 0.9378324151039124| -| 119|120|[{456-1238, 0.955...|
| PHONE| 0.8746233582496643| 1238| 120|124|[{456-1238, 0.955...|
| PATIENT|0.45354968309402466|hopedutton| 132|142|[{hopedutton@hope...|
| EMAIL|0.17805588245391846| hopehaven| 143|152|[{hopedutton@hope...|
| HOSP| 0.505658745765686| INVOICE| 157|164|[{INVOICE, 0.9661...|
+------------+-------------------+----------+-----+---+--------------------+

Visualize NER results:

result.visualize_ner(labels_list=["DATE", "LOC"])

Original image with NER results:

result.show_image("image_with_boxes")

Ocr engines

Bbox levelSupport GPUSeparate model for text detectionProcessing time 1 page (CPU/GPU) secsSupport Handwritten Text
Tesseract OCRcharacternono0.2/nonot good
Tesseract OCR CLIcharacternono0.2/nonot good
Easy OCRwordyesyes
Surya OCRlineyesyes
DocTRwordyesyes

Projects used the ScaleDP

  • PDF Redaction - Free AI-powered tool for redact PDF files (remove sensitive information) online.
  • frontiersin.org - Reviewer Recommendation System for academic articles using ScaleDP and LLM models.
  • dayme.tech - Data extraction from scanned receipts using ScaleDP and LLM models.
  • curie.is - Curie used ScaleDP for document preprocessing and analysis data in documents.

Disclaimer

This project is not affiliated with, endorsed by, or connected to the Apache Software Foundation or Apache Spark.

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - StabRise/ScaleDP: ScaleDP is an Open-Source extension of Apache Spark for Document Processing · GitHub
Skip to content

Repository files navigation


ScaleDP

An Open-Source Library for Processing Documents using AI/ML in Apache Spark.

GitHubStabRiseCodacy Badgepre-commitPoetryCode style: blackDocumentation Status


Source Code: https://github.com/StabRise/ScaleDP

Quickstart: 1.QuickStart.ipynb

Documentations: https://scaledp.stabrise.com

Tutorials: https://github.com/StabRise/ScaleDP-Tutorials

Change Log


Welcome to the ScaleDP library

ScaleDP is library allows you to process documents using AI/ML capabilities and scale it using Apache Spark.

LLM (Large Language Models) and VLM (Vision Language Models) models are used to extract data from text and images in combination with OCR engines.

Discover pre-trained models for your projects or play with the thousands of models hosted on the Hugging Face Hub.

Key features

Document processing:

  • ✅ Loading PDF documents/Images to the Spark DataFrame (using Spark PDF Datasource and as binaryFile)
  • ✅ Extraction text/images from PDF documents/Images
  • ✅ Zero-Shot extraction structured data from text/images using LLM and ML models
  • ✅ Possibility run as REST API service without Spark Session for have minimum processing latency
  • ✅ Support Streaming mode for processing documents in real-time

LLM:

Support OpenAI compatible API for call LLM/VLM models (GPT, Gemini, GROQ, etc.)

  • OCR Images/PDF documents using Vision LLM models
  • Extract data from the image using Vision LLM models
  • Extract data from the text/images using LLM models
  • Extract data using DSPy framework
  • NER using LLM's
  • Visualize results

NLP:

  • Extract data from the text/images using NLP models from the Hugging Face Hub
  • NER using classical ML models

OCR:

Support various open-source OCR engines:

CV:

  • Object detection on images using YOLO models
  • Text detection on images

Installation

Prerequisites

  • Python 3.10 or higher
  • Apache Spark 3.5 or higher
  • Java 8

Installation using pip

Install the ScaleDP package with pip:

pip install scaledp

Installation using Docker

Build image:

 docker build -t scaledp .

Run container:

 docker run -p 8888:8888 scaledp:latest

Open Jupyter Notebook in your browser:

 http://localhost:8888

Qiuckstart

Start a Spark session with ScaleDP:

fromscaledpimport*spark=ScaleDPSession()
spark

Read example image file:

image_example=files('resources/images/Invoice.png')
df=spark.read.format("binaryFile") \
.load(image_example)
df.show_image("content")

Output:

Zero-Shot data Extraction from the Image:

frompydanticimportBaseModelimportjsonclassItems(BaseModel):
date: stritem: strnote: strdebit: strclassInvoiceSchema(BaseModel):
hospital: strtax_id: straddress: stremail: strphone: stritems: list[Items]
total: strpipeline=PipelineModel(stages=[
DataToImage(
inputCol="content",
outputCol="image"
),
LLMVisualExtractor(
inputCol="image",
outputCol="invoice",
model="gemini-1.5-flash",
apiKey="",
apiBase="https://generativelanguage.googleapis.com/v1beta/",
schema=json.dumps(InvoiceSchema.model_json_schema())
)
])
result=pipeline.transform(df).cache()

Show the extracted json:

result.show_json("invoice")

Let's show Invoice as Structured Data in Data Frame

result.select("invoice.data.*").show()

Output:

+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+
| hospital| tax_id| address| email| phone| items| total|
+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+
|Hope Haven Hospital|26-123123|855 Howard Street...|hopedutton@hopeha...|(123) 456-1238|[{10/21/2022, App...|1024.50|
+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+

Schema:

result.printSchema()
root
|-- path: string (nullable = true)
|-- modificationTime: timestamp (nullable = true)
|-- length: long (nullable = true)
|-- image: struct (nullable = true)
| |-- path: string (nullable = false)
| |-- resolution: integer (nullable = false)
| |-- data: binary (nullable = false)
| |-- imageType: string (nullable = false)
| |-- exception: string (nullable = false)
| |-- height: integer (nullable = false)
| |-- width: integer (nullable = false)
|-- invoice: struct (nullable = true)
| |-- path: string (nullable = false)
| |-- json_data: string (nullable = true)
| |-- type: string (nullable = false)
| |-- exception: string (nullable = false)
| |-- processing_time: double (nullable = false)
| |-- data: struct (nullable = true)
| | |-- hospital: string (nullable = false)
| | |-- tax_id: string (nullable = false)
| | |-- address: string (nullable = false)
| | |-- email: string (nullable = false)
| | |-- phone: string (nullable = false)
| | |-- items: array (nullable = false)
| | | |-- element: struct (containsNull = false)
| | | | |-- date: string (nullable = false)
| | | | |-- item: string (nullable = false)
| | | | |-- note: string (nullable = false)
| | | | |-- debit: string (nullable = false)
| | |-- total: string (nullable = false)

NER using model from the HuggingFace models Hub

Define pipeline for extract text from the image and run NER:

pipeline=PipelineModel(stages=[
DataToImage(inputCol="content", outputCol="image"),
TesseractOcr(inputCol="image", outputCol="text", psm=PSM.AUTO, keepInputData=True),
Ner(model="obi/deid_bert_i2b2", inputCol="text", outputCol="ner", keepInputData=True),
ImageDrawBoxes(inputCols=["image", "ner"], outputCol="image_with_boxes", lineWidth=3, padding=5, displayDataList=['entity_group'])
])
result=pipeline.transform(df).cache()
result.show_text("text")

Output:

Show NER results:

result.show_ner(limit=20)

Output:

+------------+-------------------+----------+-----+---+--------------------+
|entity_group| score| word|start|end| boxes|
+------------+-------------------+----------+-----+---+--------------------+
| HOSP| 0.991257905960083| Hospital| 0| 8|[{Hospital:, 0.94...|
| LOC| 0.999171257019043| Dutton| 10| 16|[{Dutton,, 0.9609...|
| LOC| 0.9992585778236389| MI| 18| 20|[{MI, 0.93335297,...|
| ID| 0.6838774085044861| 26| 29| 31|[{26-123123, 0.90...|
| PHONE| 0.4669836759567261| -| 31| 32|[{26-123123, 0.90...|
| PHONE| 0.7790696024894714| 123123| 32| 38|[{26-123123, 0.90...|
| HOSP|0.37445762753486633| HOPE| 39| 43|[{HOPE, 0.9525460...|
| HOSP| 0.9503226280212402| HAVEN| 44| 49|[{HAVEN, 0.952546...|
| LOC| 0.9975488185882568|855 Howard| 59| 69|[{855, 0.94682700...|
| LOC| 0.9984399676322937| Street| 70| 76|[{Street, 0.95823...|
| HOSP| 0.3670221269130707| HOSPITAL| 77| 85|[{HOSPITAL, 0.959...|
| LOC| 0.9990363121032715| Dutton| 86| 92|[{Dutton,, 0.9647...|
| LOC| 0.999313473701477| MI 49316| 94|102|[{MI, 0.94589012,...|
| PHONE| 0.9830010533332825| ( 123 )| 110|115|[{(123), 0.595334...|
| PHONE| 0.9080978035926819| 456| 116|119|[{456-1238, 0.955...|
| PHONE| 0.9378324151039124| -| 119|120|[{456-1238, 0.955...|
| PHONE| 0.8746233582496643| 1238| 120|124|[{456-1238, 0.955...|
| PATIENT|0.45354968309402466|hopedutton| 132|142|[{hopedutton@hope...|
| EMAIL|0.17805588245391846| hopehaven| 143|152|[{hopedutton@hope...|
| HOSP| 0.505658745765686| INVOICE| 157|164|[{INVOICE, 0.9661...|
+------------+-------------------+----------+-----+---+--------------------+

Visualize NER results:

result.visualize_ner(labels_list=["DATE", "LOC"])

Original image with NER results:

result.show_image("image_with_boxes")

Ocr engines

Bbox levelSupport GPUSeparate model for text detectionProcessing time 1 page (CPU/GPU) secsSupport Handwritten Text
Tesseract OCRcharacternono0.2/nonot good
Tesseract OCR CLIcharacternono0.2/nonot good
Easy OCRwordyesyes
Surya OCRlineyesyes
DocTRwordyesyes

Projects used the ScaleDP

  • PDF Redaction - Free AI-powered tool for redact PDF files (remove sensitive information) online.
  • frontiersin.org - Reviewer Recommendation System for academic articles using ScaleDP and LLM models.
  • dayme.tech - Data extraction from scanned receipts using ScaleDP and LLM models.
  • curie.is - Curie used ScaleDP for document preprocessing and analysis data in documents.

Disclaimer

This project is not affiliated with, endorsed by, or connected to the Apache Software Foundation or Apache Spark.

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - StabRise/ScaleDP: ScaleDP is an Open-Source extension of Apache Spark for Document Processing · GitHub
Skip to content

Repository files navigation


ScaleDP

An Open-Source Library for Processing Documents using AI/ML in Apache Spark.

GitHubStabRiseCodacy Badgepre-commitPoetryCode style: blackDocumentation Status


Source Code: https://github.com/StabRise/ScaleDP

Quickstart: 1.QuickStart.ipynb

Documentations: https://scaledp.stabrise.com

Tutorials: https://github.com/StabRise/ScaleDP-Tutorials

Change Log


Welcome to the ScaleDP library

ScaleDP is library allows you to process documents using AI/ML capabilities and scale it using Apache Spark.

LLM (Large Language Models) and VLM (Vision Language Models) models are used to extract data from text and images in combination with OCR engines.

Discover pre-trained models for your projects or play with the thousands of models hosted on the Hugging Face Hub.

Key features

Document processing:

  • ✅ Loading PDF documents/Images to the Spark DataFrame (using Spark PDF Datasource and as binaryFile)
  • ✅ Extraction text/images from PDF documents/Images
  • ✅ Zero-Shot extraction structured data from text/images using LLM and ML models
  • ✅ Possibility run as REST API service without Spark Session for have minimum processing latency
  • ✅ Support Streaming mode for processing documents in real-time

LLM:

Support OpenAI compatible API for call LLM/VLM models (GPT, Gemini, GROQ, etc.)

  • OCR Images/PDF documents using Vision LLM models
  • Extract data from the image using Vision LLM models
  • Extract data from the text/images using LLM models
  • Extract data using DSPy framework
  • NER using LLM's
  • Visualize results

NLP:

  • Extract data from the text/images using NLP models from the Hugging Face Hub
  • NER using classical ML models

OCR:

Support various open-source OCR engines:

CV:

  • Object detection on images using YOLO models
  • Text detection on images

Installation

Prerequisites

  • Python 3.10 or higher
  • Apache Spark 3.5 or higher
  • Java 8

Installation using pip

Install the ScaleDP package with pip:

pip install scaledp

Installation using Docker

Build image:

 docker build -t scaledp .

Run container:

 docker run -p 8888:8888 scaledp:latest

Open Jupyter Notebook in your browser:

 http://localhost:8888

Qiuckstart

Start a Spark session with ScaleDP:

fromscaledpimport*spark=ScaleDPSession()
spark

Read example image file:

image_example=files('resources/images/Invoice.png')
df=spark.read.format("binaryFile") \
.load(image_example)
df.show_image("content")

Output:

Zero-Shot data Extraction from the Image:

frompydanticimportBaseModelimportjsonclassItems(BaseModel):
date: stritem: strnote: strdebit: strclassInvoiceSchema(BaseModel):
hospital: strtax_id: straddress: stremail: strphone: stritems: list[Items]
total: strpipeline=PipelineModel(stages=[
DataToImage(
inputCol="content",
outputCol="image"
),
LLMVisualExtractor(
inputCol="image",
outputCol="invoice",
model="gemini-1.5-flash",
apiKey="",
apiBase="https://generativelanguage.googleapis.com/v1beta/",
schema=json.dumps(InvoiceSchema.model_json_schema())
)
])
result=pipeline.transform(df).cache()

Show the extracted json:

result.show_json("invoice")

Let's show Invoice as Structured Data in Data Frame

result.select("invoice.data.*").show()

Output:

+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+
| hospital| tax_id| address| email| phone| items| total|
+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+
|Hope Haven Hospital|26-123123|855 Howard Street...|hopedutton@hopeha...|(123) 456-1238|[{10/21/2022, App...|1024.50|
+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+

Schema:

result.printSchema()
root
|-- path: string (nullable = true)
|-- modificationTime: timestamp (nullable = true)
|-- length: long (nullable = true)
|-- image: struct (nullable = true)
| |-- path: string (nullable = false)
| |-- resolution: integer (nullable = false)
| |-- data: binary (nullable = false)
| |-- imageType: string (nullable = false)
| |-- exception: string (nullable = false)
| |-- height: integer (nullable = false)
| |-- width: integer (nullable = false)
|-- invoice: struct (nullable = true)
| |-- path: string (nullable = false)
| |-- json_data: string (nullable = true)
| |-- type: string (nullable = false)
| |-- exception: string (nullable = false)
| |-- processing_time: double (nullable = false)
| |-- data: struct (nullable = true)
| | |-- hospital: string (nullable = false)
| | |-- tax_id: string (nullable = false)
| | |-- address: string (nullable = false)
| | |-- email: string (nullable = false)
| | |-- phone: string (nullable = false)
| | |-- items: array (nullable = false)
| | | |-- element: struct (containsNull = false)
| | | | |-- date: string (nullable = false)
| | | | |-- item: string (nullable = false)
| | | | |-- note: string (nullable = false)
| | | | |-- debit: string (nullable = false)
| | |-- total: string (nullable = false)

NER using model from the HuggingFace models Hub

Define pipeline for extract text from the image and run NER:

pipeline=PipelineModel(stages=[
DataToImage(inputCol="content", outputCol="image"),
TesseractOcr(inputCol="image", outputCol="text", psm=PSM.AUTO, keepInputData=True),
Ner(model="obi/deid_bert_i2b2", inputCol="text", outputCol="ner", keepInputData=True),
ImageDrawBoxes(inputCols=["image", "ner"], outputCol="image_with_boxes", lineWidth=3, padding=5, displayDataList=['entity_group'])
])
result=pipeline.transform(df).cache()
result.show_text("text")

Output:

Show NER results:

result.show_ner(limit=20)

Output:

+------------+-------------------+----------+-----+---+--------------------+
|entity_group| score| word|start|end| boxes|
+------------+-------------------+----------+-----+---+--------------------+
| HOSP| 0.991257905960083| Hospital| 0| 8|[{Hospital:, 0.94...|
| LOC| 0.999171257019043| Dutton| 10| 16|[{Dutton,, 0.9609...|
| LOC| 0.9992585778236389| MI| 18| 20|[{MI, 0.93335297,...|
| ID| 0.6838774085044861| 26| 29| 31|[{26-123123, 0.90...|
| PHONE| 0.4669836759567261| -| 31| 32|[{26-123123, 0.90...|
| PHONE| 0.7790696024894714| 123123| 32| 38|[{26-123123, 0.90...|
| HOSP|0.37445762753486633| HOPE| 39| 43|[{HOPE, 0.9525460...|
| HOSP| 0.9503226280212402| HAVEN| 44| 49|[{HAVEN, 0.952546...|
| LOC| 0.9975488185882568|855 Howard| 59| 69|[{855, 0.94682700...|
| LOC| 0.9984399676322937| Street| 70| 76|[{Street, 0.95823...|
| HOSP| 0.3670221269130707| HOSPITAL| 77| 85|[{HOSPITAL, 0.959...|
| LOC| 0.9990363121032715| Dutton| 86| 92|[{Dutton,, 0.9647...|
| LOC| 0.999313473701477| MI 49316| 94|102|[{MI, 0.94589012,...|
| PHONE| 0.9830010533332825| ( 123 )| 110|115|[{(123), 0.595334...|
| PHONE| 0.9080978035926819| 456| 116|119|[{456-1238, 0.955...|
| PHONE| 0.9378324151039124| -| 119|120|[{456-1238, 0.955...|
| PHONE| 0.8746233582496643| 1238| 120|124|[{456-1238, 0.955...|
| PATIENT|0.45354968309402466|hopedutton| 132|142|[{hopedutton@hope...|
| EMAIL|0.17805588245391846| hopehaven| 143|152|[{hopedutton@hope...|
| HOSP| 0.505658745765686| INVOICE| 157|164|[{INVOICE, 0.9661...|
+------------+-------------------+----------+-----+---+--------------------+

Visualize NER results:

result.visualize_ner(labels_list=["DATE", "LOC"])

Original image with NER results:

result.show_image("image_with_boxes")

Ocr engines

Bbox levelSupport GPUSeparate model for text detectionProcessing time 1 page (CPU/GPU) secsSupport Handwritten Text
Tesseract OCRcharacternono0.2/nonot good
Tesseract OCR CLIcharacternono0.2/nonot good
Easy OCRwordyesyes
Surya OCRlineyesyes
DocTRwordyesyes

Projects used the ScaleDP

  • PDF Redaction - Free AI-powered tool for redact PDF files (remove sensitive information) online.
  • frontiersin.org - Reviewer Recommendation System for academic articles using ScaleDP and LLM models.
  • dayme.tech - Data extraction from scanned receipts using ScaleDP and LLM models.
  • curie.is - Curie used ScaleDP for document preprocessing and analysis data in documents.

Disclaimer

This project is not affiliated with, endorsed by, or connected to the Apache Software Foundation or Apache Spark.

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - StabRise/ScaleDP: ScaleDP is an Open-Source extension of Apache Spark for Document Processing · GitHub
Skip to content

Repository files navigation


ScaleDP

An Open-Source Library for Processing Documents using AI/ML in Apache Spark.

GitHubStabRiseCodacy Badgepre-commitPoetryCode style: blackDocumentation Status


Source Code: https://github.com/StabRise/ScaleDP

Quickstart: 1.QuickStart.ipynb

Documentations: https://scaledp.stabrise.com

Tutorials: https://github.com/StabRise/ScaleDP-Tutorials

Change Log


Welcome to the ScaleDP library

ScaleDP is library allows you to process documents using AI/ML capabilities and scale it using Apache Spark.

LLM (Large Language Models) and VLM (Vision Language Models) models are used to extract data from text and images in combination with OCR engines.

Discover pre-trained models for your projects or play with the thousands of models hosted on the Hugging Face Hub.

Key features

Document processing:

  • ✅ Loading PDF documents/Images to the Spark DataFrame (using Spark PDF Datasource and as binaryFile)
  • ✅ Extraction text/images from PDF documents/Images
  • ✅ Zero-Shot extraction structured data from text/images using LLM and ML models
  • ✅ Possibility run as REST API service without Spark Session for have minimum processing latency
  • ✅ Support Streaming mode for processing documents in real-time

LLM:

Support OpenAI compatible API for call LLM/VLM models (GPT, Gemini, GROQ, etc.)

  • OCR Images/PDF documents using Vision LLM models
  • Extract data from the image using Vision LLM models
  • Extract data from the text/images using LLM models
  • Extract data using DSPy framework
  • NER using LLM's
  • Visualize results

NLP:

  • Extract data from the text/images using NLP models from the Hugging Face Hub
  • NER using classical ML models

OCR:

Support various open-source OCR engines:

CV:

  • Object detection on images using YOLO models
  • Text detection on images

Installation

Prerequisites

  • Python 3.10 or higher
  • Apache Spark 3.5 or higher
  • Java 8

Installation using pip

Install the ScaleDP package with pip:

pip install scaledp

Installation using Docker

Build image:

 docker build -t scaledp .

Run container:

 docker run -p 8888:8888 scaledp:latest

Open Jupyter Notebook in your browser:

 http://localhost:8888

Qiuckstart

Start a Spark session with ScaleDP:

fromscaledpimport*spark=ScaleDPSession()
spark

Read example image file:

image_example=files('resources/images/Invoice.png')
df=spark.read.format("binaryFile") \
.load(image_example)
df.show_image("content")

Output:

Zero-Shot data Extraction from the Image:

frompydanticimportBaseModelimportjsonclassItems(BaseModel):
date: stritem: strnote: strdebit: strclassInvoiceSchema(BaseModel):
hospital: strtax_id: straddress: stremail: strphone: stritems: list[Items]
total: strpipeline=PipelineModel(stages=[
DataToImage(
inputCol="content",
outputCol="image"
),
LLMVisualExtractor(
inputCol="image",
outputCol="invoice",
model="gemini-1.5-flash",
apiKey="",
apiBase="https://generativelanguage.googleapis.com/v1beta/",
schema=json.dumps(InvoiceSchema.model_json_schema())
)
])
result=pipeline.transform(df).cache()

Show the extracted json:

result.show_json("invoice")

Let's show Invoice as Structured Data in Data Frame

result.select("invoice.data.*").show()

Output:

+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+
| hospital| tax_id| address| email| phone| items| total|
+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+
|Hope Haven Hospital|26-123123|855 Howard Street...|hopedutton@hopeha...|(123) 456-1238|[{10/21/2022, App...|1024.50|
+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+

Schema:

result.printSchema()
root
|-- path: string (nullable = true)
|-- modificationTime: timestamp (nullable = true)
|-- length: long (nullable = true)
|-- image: struct (nullable = true)
| |-- path: string (nullable = false)
| |-- resolution: integer (nullable = false)
| |-- data: binary (nullable = false)
| |-- imageType: string (nullable = false)
| |-- exception: string (nullable = false)
| |-- height: integer (nullable = false)
| |-- width: integer (nullable = false)
|-- invoice: struct (nullable = true)
| |-- path: string (nullable = false)
| |-- json_data: string (nullable = true)
| |-- type: string (nullable = false)
| |-- exception: string (nullable = false)
| |-- processing_time: double (nullable = false)
| |-- data: struct (nullable = true)
| | |-- hospital: string (nullable = false)
| | |-- tax_id: string (nullable = false)
| | |-- address: string (nullable = false)
| | |-- email: string (nullable = false)
| | |-- phone: string (nullable = false)
| | |-- items: array (nullable = false)
| | | |-- element: struct (containsNull = false)
| | | | |-- date: string (nullable = false)
| | | | |-- item: string (nullable = false)
| | | | |-- note: string (nullable = false)
| | | | |-- debit: string (nullable = false)
| | |-- total: string (nullable = false)

NER using model from the HuggingFace models Hub

Define pipeline for extract text from the image and run NER:

pipeline=PipelineModel(stages=[
DataToImage(inputCol="content", outputCol="image"),
TesseractOcr(inputCol="image", outputCol="text", psm=PSM.AUTO, keepInputData=True),
Ner(model="obi/deid_bert_i2b2", inputCol="text", outputCol="ner", keepInputData=True),
ImageDrawBoxes(inputCols=["image", "ner"], outputCol="image_with_boxes", lineWidth=3, padding=5, displayDataList=['entity_group'])
])
result=pipeline.transform(df).cache()
result.show_text("text")

Output:

Show NER results:

result.show_ner(limit=20)

Output:

+------------+-------------------+----------+-----+---+--------------------+
|entity_group| score| word|start|end| boxes|
+------------+-------------------+----------+-----+---+--------------------+
| HOSP| 0.991257905960083| Hospital| 0| 8|[{Hospital:, 0.94...|
| LOC| 0.999171257019043| Dutton| 10| 16|[{Dutton,, 0.9609...|
| LOC| 0.9992585778236389| MI| 18| 20|[{MI, 0.93335297,...|
| ID| 0.6838774085044861| 26| 29| 31|[{26-123123, 0.90...|
| PHONE| 0.4669836759567261| -| 31| 32|[{26-123123, 0.90...|
| PHONE| 0.7790696024894714| 123123| 32| 38|[{26-123123, 0.90...|
| HOSP|0.37445762753486633| HOPE| 39| 43|[{HOPE, 0.9525460...|
| HOSP| 0.9503226280212402| HAVEN| 44| 49|[{HAVEN, 0.952546...|
| LOC| 0.9975488185882568|855 Howard| 59| 69|[{855, 0.94682700...|
| LOC| 0.9984399676322937| Street| 70| 76|[{Street, 0.95823...|
| HOSP| 0.3670221269130707| HOSPITAL| 77| 85|[{HOSPITAL, 0.959...|
| LOC| 0.9990363121032715| Dutton| 86| 92|[{Dutton,, 0.9647...|
| LOC| 0.999313473701477| MI 49316| 94|102|[{MI, 0.94589012,...|
| PHONE| 0.9830010533332825| ( 123 )| 110|115|[{(123), 0.595334...|
| PHONE| 0.9080978035926819| 456| 116|119|[{456-1238, 0.955...|
| PHONE| 0.9378324151039124| -| 119|120|[{456-1238, 0.955...|
| PHONE| 0.8746233582496643| 1238| 120|124|[{456-1238, 0.955...|
| PATIENT|0.45354968309402466|hopedutton| 132|142|[{hopedutton@hope...|
| EMAIL|0.17805588245391846| hopehaven| 143|152|[{hopedutton@hope...|
| HOSP| 0.505658745765686| INVOICE| 157|164|[{INVOICE, 0.9661...|
+------------+-------------------+----------+-----+---+--------------------+

Visualize NER results:

result.visualize_ner(labels_list=["DATE", "LOC"])

Original image with NER results:

result.show_image("image_with_boxes")

Ocr engines

Bbox levelSupport GPUSeparate model for text detectionProcessing time 1 page (CPU/GPU) secsSupport Handwritten Text
Tesseract OCRcharacternono0.2/nonot good
Tesseract OCR CLIcharacternono0.2/nonot good
Easy OCRwordyesyes
Surya OCRlineyesyes
DocTRwordyesyes

Projects used the ScaleDP

  • PDF Redaction - Free AI-powered tool for redact PDF files (remove sensitive information) online.
  • frontiersin.org - Reviewer Recommendation System for academic articles using ScaleDP and LLM models.
  • dayme.tech - Data extraction from scanned receipts using ScaleDP and LLM models.
  • curie.is - Curie used ScaleDP for document preprocessing and analysis data in documents.

Disclaimer

This project is not affiliated with, endorsed by, or connected to the Apache Software Foundation or Apache Spark.

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - StabRise/ScaleDP: ScaleDP is an Open-Source extension of Apache Spark for Document Processing · GitHub
Skip to content

Repository files navigation


ScaleDP

An Open-Source Library for Processing Documents using AI/ML in Apache Spark.

GitHubStabRiseCodacy Badgepre-commitPoetryCode style: blackDocumentation Status


Source Code: https://github.com/StabRise/ScaleDP

Quickstart: 1.QuickStart.ipynb

Documentations: https://scaledp.stabrise.com

Tutorials: https://github.com/StabRise/ScaleDP-Tutorials

Change Log


Welcome to the ScaleDP library

ScaleDP is library allows you to process documents using AI/ML capabilities and scale it using Apache Spark.

LLM (Large Language Models) and VLM (Vision Language Models) models are used to extract data from text and images in combination with OCR engines.

Discover pre-trained models for your projects or play with the thousands of models hosted on the Hugging Face Hub.

Key features

Document processing:

  • ✅ Loading PDF documents/Images to the Spark DataFrame (using Spark PDF Datasource and as binaryFile)
  • ✅ Extraction text/images from PDF documents/Images
  • ✅ Zero-Shot extraction structured data from text/images using LLM and ML models
  • ✅ Possibility run as REST API service without Spark Session for have minimum processing latency
  • ✅ Support Streaming mode for processing documents in real-time

LLM:

Support OpenAI compatible API for call LLM/VLM models (GPT, Gemini, GROQ, etc.)

  • OCR Images/PDF documents using Vision LLM models
  • Extract data from the image using Vision LLM models
  • Extract data from the text/images using LLM models
  • Extract data using DSPy framework
  • NER using LLM's
  • Visualize results

NLP:

  • Extract data from the text/images using NLP models from the Hugging Face Hub
  • NER using classical ML models

OCR:

Support various open-source OCR engines:

CV:

  • Object detection on images using YOLO models
  • Text detection on images

Installation

Prerequisites

  • Python 3.10 or higher
  • Apache Spark 3.5 or higher
  • Java 8

Installation using pip

Install the ScaleDP package with pip:

pip install scaledp

Installation using Docker

Build image:

 docker build -t scaledp .

Run container:

 docker run -p 8888:8888 scaledp:latest

Open Jupyter Notebook in your browser:

 http://localhost:8888

Qiuckstart

Start a Spark session with ScaleDP:

fromscaledpimport*spark=ScaleDPSession()
spark

Read example image file:

image_example=files('resources/images/Invoice.png')
df=spark.read.format("binaryFile") \
.load(image_example)
df.show_image("content")

Output:

Zero-Shot data Extraction from the Image:

frompydanticimportBaseModelimportjsonclassItems(BaseModel):
date: stritem: strnote: strdebit: strclassInvoiceSchema(BaseModel):
hospital: strtax_id: straddress: stremail: strphone: stritems: list[Items]
total: strpipeline=PipelineModel(stages=[
DataToImage(
inputCol="content",
outputCol="image"
),
LLMVisualExtractor(
inputCol="image",
outputCol="invoice",
model="gemini-1.5-flash",
apiKey="",
apiBase="https://generativelanguage.googleapis.com/v1beta/",
schema=json.dumps(InvoiceSchema.model_json_schema())
)
])
result=pipeline.transform(df).cache()

Show the extracted json:

result.show_json("invoice")

Let's show Invoice as Structured Data in Data Frame

result.select("invoice.data.*").show()

Output:

+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+
| hospital| tax_id| address| email| phone| items| total|
+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+
|Hope Haven Hospital|26-123123|855 Howard Street...|hopedutton@hopeha...|(123) 456-1238|[{10/21/2022, App...|1024.50|
+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+

Schema:

result.printSchema()
root
|-- path: string (nullable = true)
|-- modificationTime: timestamp (nullable = true)
|-- length: long (nullable = true)
|-- image: struct (nullable = true)
| |-- path: string (nullable = false)
| |-- resolution: integer (nullable = false)
| |-- data: binary (nullable = false)
| |-- imageType: string (nullable = false)
| |-- exception: string (nullable = false)
| |-- height: integer (nullable = false)
| |-- width: integer (nullable = false)
|-- invoice: struct (nullable = true)
| |-- path: string (nullable = false)
| |-- json_data: string (nullable = true)
| |-- type: string (nullable = false)
| |-- exception: string (nullable = false)
| |-- processing_time: double (nullable = false)
| |-- data: struct (nullable = true)
| | |-- hospital: string (nullable = false)
| | |-- tax_id: string (nullable = false)
| | |-- address: string (nullable = false)
| | |-- email: string (nullable = false)
| | |-- phone: string (nullable = false)
| | |-- items: array (nullable = false)
| | | |-- element: struct (containsNull = false)
| | | | |-- date: string (nullable = false)
| | | | |-- item: string (nullable = false)
| | | | |-- note: string (nullable = false)
| | | | |-- debit: string (nullable = false)
| | |-- total: string (nullable = false)

NER using model from the HuggingFace models Hub

Define pipeline for extract text from the image and run NER:

pipeline=PipelineModel(stages=[
DataToImage(inputCol="content", outputCol="image"),
TesseractOcr(inputCol="image", outputCol="text", psm=PSM.AUTO, keepInputData=True),
Ner(model="obi/deid_bert_i2b2", inputCol="text", outputCol="ner", keepInputData=True),
ImageDrawBoxes(inputCols=["image", "ner"], outputCol="image_with_boxes", lineWidth=3, padding=5, displayDataList=['entity_group'])
])
result=pipeline.transform(df).cache()
result.show_text("text")

Output:

Show NER results:

result.show_ner(limit=20)

Output:

+------------+-------------------+----------+-----+---+--------------------+
|entity_group| score| word|start|end| boxes|
+------------+-------------------+----------+-----+---+--------------------+
| HOSP| 0.991257905960083| Hospital| 0| 8|[{Hospital:, 0.94...|
| LOC| 0.999171257019043| Dutton| 10| 16|[{Dutton,, 0.9609...|
| LOC| 0.9992585778236389| MI| 18| 20|[{MI, 0.93335297,...|
| ID| 0.6838774085044861| 26| 29| 31|[{26-123123, 0.90...|
| PHONE| 0.4669836759567261| -| 31| 32|[{26-123123, 0.90...|
| PHONE| 0.7790696024894714| 123123| 32| 38|[{26-123123, 0.90...|
| HOSP|0.37445762753486633| HOPE| 39| 43|[{HOPE, 0.9525460...|
| HOSP| 0.9503226280212402| HAVEN| 44| 49|[{HAVEN, 0.952546...|
| LOC| 0.9975488185882568|855 Howard| 59| 69|[{855, 0.94682700...|
| LOC| 0.9984399676322937| Street| 70| 76|[{Street, 0.95823...|
| HOSP| 0.3670221269130707| HOSPITAL| 77| 85|[{HOSPITAL, 0.959...|
| LOC| 0.9990363121032715| Dutton| 86| 92|[{Dutton,, 0.9647...|
| LOC| 0.999313473701477| MI 49316| 94|102|[{MI, 0.94589012,...|
| PHONE| 0.9830010533332825| ( 123 )| 110|115|[{(123), 0.595334...|
| PHONE| 0.9080978035926819| 456| 116|119|[{456-1238, 0.955...|
| PHONE| 0.9378324151039124| -| 119|120|[{456-1238, 0.955...|
| PHONE| 0.8746233582496643| 1238| 120|124|[{456-1238, 0.955...|
| PATIENT|0.45354968309402466|hopedutton| 132|142|[{hopedutton@hope...|
| EMAIL|0.17805588245391846| hopehaven| 143|152|[{hopedutton@hope...|
| HOSP| 0.505658745765686| INVOICE| 157|164|[{INVOICE, 0.9661...|
+------------+-------------------+----------+-----+---+--------------------+

Visualize NER results:

result.visualize_ner(labels_list=["DATE", "LOC"])

Original image with NER results:

result.show_image("image_with_boxes")

Ocr engines

Bbox levelSupport GPUSeparate model for text detectionProcessing time 1 page (CPU/GPU) secsSupport Handwritten Text
Tesseract OCRcharacternono0.2/nonot good
Tesseract OCR CLIcharacternono0.2/nonot good
Easy OCRwordyesyes
Surya OCRlineyesyes
DocTRwordyesyes

Projects used the ScaleDP

  • PDF Redaction - Free AI-powered tool for redact PDF files (remove sensitive information) online.
  • frontiersin.org - Reviewer Recommendation System for academic articles using ScaleDP and LLM models.
  • dayme.tech - Data extraction from scanned receipts using ScaleDP and LLM models.
  • curie.is - Curie used ScaleDP for document preprocessing and analysis data in documents.

Disclaimer

This project is not affiliated with, endorsed by, or connected to the Apache Software Foundation or Apache Spark.

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - StabRise/ScaleDP: ScaleDP is an Open-Source extension of Apache Spark for Document Processing · GitHub
Skip to content

Repository files navigation


ScaleDP

An Open-Source Library for Processing Documents using AI/ML in Apache Spark.

GitHubStabRiseCodacy Badgepre-commitPoetryCode style: blackDocumentation Status


Source Code: https://github.com/StabRise/ScaleDP

Quickstart: 1.QuickStart.ipynb

Documentations: https://scaledp.stabrise.com

Tutorials: https://github.com/StabRise/ScaleDP-Tutorials

Change Log


Welcome to the ScaleDP library

ScaleDP is library allows you to process documents using AI/ML capabilities and scale it using Apache Spark.

LLM (Large Language Models) and VLM (Vision Language Models) models are used to extract data from text and images in combination with OCR engines.

Discover pre-trained models for your projects or play with the thousands of models hosted on the Hugging Face Hub.

Key features

Document processing:

  • ✅ Loading PDF documents/Images to the Spark DataFrame (using Spark PDF Datasource and as binaryFile)
  • ✅ Extraction text/images from PDF documents/Images
  • ✅ Zero-Shot extraction structured data from text/images using LLM and ML models
  • ✅ Possibility run as REST API service without Spark Session for have minimum processing latency
  • ✅ Support Streaming mode for processing documents in real-time

LLM:

Support OpenAI compatible API for call LLM/VLM models (GPT, Gemini, GROQ, etc.)

  • OCR Images/PDF documents using Vision LLM models
  • Extract data from the image using Vision LLM models
  • Extract data from the text/images using LLM models
  • Extract data using DSPy framework
  • NER using LLM's
  • Visualize results

NLP:

  • Extract data from the text/images using NLP models from the Hugging Face Hub
  • NER using classical ML models

OCR:

Support various open-source OCR engines:

CV:

  • Object detection on images using YOLO models
  • Text detection on images

Installation

Prerequisites

  • Python 3.10 or higher
  • Apache Spark 3.5 or higher
  • Java 8

Installation using pip

Install the ScaleDP package with pip:

pip install scaledp

Installation using Docker

Build image:

 docker build -t scaledp .

Run container:

 docker run -p 8888:8888 scaledp:latest

Open Jupyter Notebook in your browser:

 http://localhost:8888

Qiuckstart

Start a Spark session with ScaleDP:

fromscaledpimport*spark=ScaleDPSession()
spark

Read example image file:

image_example=files('resources/images/Invoice.png')
df=spark.read.format("binaryFile") \
.load(image_example)
df.show_image("content")

Output:

Zero-Shot data Extraction from the Image:

frompydanticimportBaseModelimportjsonclassItems(BaseModel):
date: stritem: strnote: strdebit: strclassInvoiceSchema(BaseModel):
hospital: strtax_id: straddress: stremail: strphone: stritems: list[Items]
total: strpipeline=PipelineModel(stages=[
DataToImage(
inputCol="content",
outputCol="image"
),
LLMVisualExtractor(
inputCol="image",
outputCol="invoice",
model="gemini-1.5-flash",
apiKey="",
apiBase="https://generativelanguage.googleapis.com/v1beta/",
schema=json.dumps(InvoiceSchema.model_json_schema())
)
])
result=pipeline.transform(df).cache()

Show the extracted json:

result.show_json("invoice")

Let's show Invoice as Structured Data in Data Frame

result.select("invoice.data.*").show()

Output:

+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+
| hospital| tax_id| address| email| phone| items| total|
+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+
|Hope Haven Hospital|26-123123|855 Howard Street...|hopedutton@hopeha...|(123) 456-1238|[{10/21/2022, App...|1024.50|
+-------------------+---------+--------------------+--------------------+--------------+--------------------+-------+

Schema:

result.printSchema()
root
|-- path: string (nullable = true)
|-- modificationTime: timestamp (nullable = true)
|-- length: long (nullable = true)
|-- image: struct (nullable = true)
| |-- path: string (nullable = false)
| |-- resolution: integer (nullable = false)
| |-- data: binary (nullable = false)
| |-- imageType: string (nullable = false)
| |-- exception: string (nullable = false)
| |-- height: integer (nullable = false)
| |-- width: integer (nullable = false)
|-- invoice: struct (nullable = true)
| |-- path: string (nullable = false)
| |-- json_data: string (nullable = true)
| |-- type: string (nullable = false)
| |-- exception: string (nullable = false)
| |-- processing_time: double (nullable = false)
| |-- data: struct (nullable = true)
| | |-- hospital: string (nullable = false)
| | |-- tax_id: string (nullable = false)
| | |-- address: string (nullable = false)
| | |-- email: string (nullable = false)
| | |-- phone: string (nullable = false)
| | |-- items: array (nullable = false)
| | | |-- element: struct (containsNull = false)
| | | | |-- date: string (nullable = false)
| | | | |-- item: string (nullable = false)
| | | | |-- note: string (nullable = false)
| | | | |-- debit: string (nullable = false)
| | |-- total: string (nullable = false)

NER using model from the HuggingFace models Hub

Define pipeline for extract text from the image and run NER:

pipeline=PipelineModel(stages=[
DataToImage(inputCol="content", outputCol="image"),
TesseractOcr(inputCol="image", outputCol="text", psm=PSM.AUTO, keepInputData=True),
Ner(model="obi/deid_bert_i2b2", inputCol="text", outputCol="ner", keepInputData=True),
ImageDrawBoxes(inputCols=["image", "ner"], outputCol="image_with_boxes", lineWidth=3, padding=5, displayDataList=['entity_group'])
])
result=pipeline.transform(df).cache()
result.show_text("text")

Output:

Show NER results:

result.show_ner(limit=20)

Output:

+------------+-------------------+----------+-----+---+--------------------+
|entity_group| score| word|start|end| boxes|
+------------+-------------------+----------+-----+---+--------------------+
| HOSP| 0.991257905960083| Hospital| 0| 8|[{Hospital:, 0.94...|
| LOC| 0.999171257019043| Dutton| 10| 16|[{Dutton,, 0.9609...|
| LOC| 0.9992585778236389| MI| 18| 20|[{MI, 0.93335297,...|
| ID| 0.6838774085044861| 26| 29| 31|[{26-123123, 0.90...|
| PHONE| 0.4669836759567261| -| 31| 32|[{26-123123, 0.90...|
| PHONE| 0.7790696024894714| 123123| 32| 38|[{26-123123, 0.90...|
| HOSP|0.37445762753486633| HOPE| 39| 43|[{HOPE, 0.9525460...|
| HOSP| 0.9503226280212402| HAVEN| 44| 49|[{HAVEN, 0.952546...|
| LOC| 0.9975488185882568|855 Howard| 59| 69|[{855, 0.94682700...|
| LOC| 0.9984399676322937| Street| 70| 76|[{Street, 0.95823...|
| HOSP| 0.3670221269130707| HOSPITAL| 77| 85|[{HOSPITAL, 0.959...|
| LOC| 0.9990363121032715| Dutton| 86| 92|[{Dutton,, 0.9647...|
| LOC| 0.999313473701477| MI 49316| 94|102|[{MI, 0.94589012,...|
| PHONE| 0.9830010533332825| ( 123 )| 110|115|[{(123), 0.595334...|
| PHONE| 0.9080978035926819| 456| 116|119|[{456-1238, 0.955...|
| PHONE| 0.9378324151039124| -| 119|120|[{456-1238, 0.955...|
| PHONE| 0.8746233582496643| 1238| 120|124|[{456-1238, 0.955...|
| PATIENT|0.45354968309402466|hopedutton| 132|142|[{hopedutton@hope...|
| EMAIL|0.17805588245391846| hopehaven| 143|152|[{hopedutton@hope...|
| HOSP| 0.505658745765686| INVOICE| 157|164|[{INVOICE, 0.9661...|
+------------+-------------------+----------+-----+---+--------------------+

Visualize NER results:

result.visualize_ner(labels_list=["DATE", "LOC"])

Original image with NER results:

result.show_image("image_with_boxes")

Ocr engines

Bbox levelSupport GPUSeparate model for text detectionProcessing time 1 page (CPU/GPU) secsSupport Handwritten Text
Tesseract OCRcharacternono0.2/nonot good
Tesseract OCR CLIcharacternono0.2/nonot good
Easy OCRwordyesyes
Surya OCRlineyesyes
DocTRwordyesyes

Projects used the ScaleDP

  • PDF Redaction - Free AI-powered tool for redact PDF files (remove sensitive information) online.
  • frontiersin.org - Reviewer Recommendation System for academic articles using ScaleDP and LLM models.
  • dayme.tech - Data extraction from scanned receipts using ScaleDP and LLM models.
  • curie.is - Curie used ScaleDP for document preprocessing and analysis data in documents.

Disclaimer

This project is not affiliated with, endorsed by, or connected to the Apache Software Foundation or Apache Spark.