electblake
refactor(app): rename to Image Data Extractor
74bbc85
Raw
History Blame
9.27 kB
from pathlib import Path
import gradio as gr
from model import extract, generate_template
structured_json_templates = {
"Basic receipt": """{
"merchant": "verbatim-string",
"purchase_date": "date",
"purchase_time": "time",
"total": "number",
"currency": "currency",
"item_count": "integer",
"paid": "boolean",
"payment_method": ["cash", "credit-card", "debit-card", "other"],
"items": ["verbatim-string"]
}""",
"Advanced receipt": """{
"merchant": {
"name": "verbatim-string",
"address": "verbatim-string",
"phone": "phone-number"
},
"purchase_date": "date",
"purchase_time": "time",
"store_number": "verbatim-string",
"operator_number": "verbatim-string",
"terminal_number": "verbatim-string",
"transaction_number": "verbatim-string",
"items": [
{
"description": "verbatim-string",
"sku": "verbatim-string",
"quantity": "number",
"unit": "unit-code",
"unit_price": "number",
"discount": "number",
"line_total": "number",
"tax_code": "verbatim-string"
}
],
"item_count": "integer",
"subtotal": "number",
"tax": "number",
"total": "number",
"currency": "currency",
"payment_method": ["cash", "credit-card", "debit-card", "other"],
"card_last_four": "verbatim-string",
"amount_tendered": "number",
"change_due": "number"
}""",
"Basic bank statement": """{
"financial_institution": "verbatim-string",
"account_holder": "verbatim-string",
"account_number": "verbatim-string",
"statement_period": {
"start_date": "date",
"end_date": "date"
},
"opening_balance": "number",
"closing_balance": "number",
"currency": "currency",
"transaction_count": "integer",
"transactions": [
{
"date": "date",
"description": "verbatim-string",
"transaction_type": ["debit", "credit", "other"],
"amount": "number",
"balance": "number"
}
]
}""",
"Advanced bank statement": """{
"financial_institution": {
"name": "verbatim-string",
"address": "verbatim-string",
"phone": "phone-number",
"website": "url"
},
"account_holder": {
"name": "verbatim-string",
"address": "verbatim-string"
},
"account": {
"type": "verbatim-string",
"number": "verbatim-string",
"branch_number": "verbatim-string",
"transit_number": "verbatim-string",
"routing_number": "verbatim-string",
"iban": "iban",
"bic": "bic"
},
"statement_period": {
"start_date": "date",
"end_date": "date"
},
"summary": {
"opening_balance": "number",
"total_credits": "number",
"total_debits": "number",
"total_fees": "number",
"total_interest": "number",
"closing_balance": "number",
"currency": "currency"
},
"transaction_count": "integer",
"transactions": [
{
"transaction_date": "date",
"posting_date": "date",
"description": "verbatim-string",
"reference_number": "verbatim-string",
"category": [
"deposit",
"withdrawal",
"transfer",
"payment",
"purchase",
"fee",
"interest",
"refund",
"other"
],
"debit": "number",
"credit": "number",
"balance": "number",
"currency": "currency"
}
]
}""",
"Invoice with line items": """{
"document_type": "verbatim-string",
"vendor": {
"name": "verbatim-string",
"address": "verbatim-string",
"email": "email-address",
"phone": "phone-number"
},
"invoice_number": "verbatim-string",
"invoice_date": "verbatim-string",
"line_items": [
{
"description": "verbatim-string",
"category": ["product", "service", "shipping", "tax", "other"],
"quantity": "integer",
"unit_price": "number",
"unit": "unit-code",
"amount": "number"
}
],
"subtotal": "number",
"tax": "number",
"total": "number",
"currency": "currency"
}""",
"Advanced global record": """{
"summary": "string",
"reference_text": "verbatim-string",
"sequence_number": "integer",
"amount": "number",
"effective_date": "date",
"effective_time": "time",
"signed_at": "date-time",
"term": "duration",
"active": "boolean",
"country": "country",
"currency": "currency",
"language": "language",
"language_tag": "language-tag",
"script": "script",
"website": "url",
"email": "email-address",
"phone": "phone-number",
"iban": "iban",
"bic": "bic",
"measurement_unit": "unit-code",
"regions": {
"us": "region:US",
"fr": "region:FR",
"ie": "region:IE",
"gb": "region:GB",
"it": "region:IT",
"es": "region:ES",
"de": "region:DE",
"pt": "region:PT",
"ca": "region:CA",
"mx": "region:MX",
"br": "region:BR",
"au": "region:AU",
"jp": "region:JP",
"kr": "region:KR"
},
"contacts": [
{
"name": "verbatim-string",
"role": "string",
"email": "email-address"
}
],
"status": ["draft", "active", "expired", "unknown"],
"applicable_labels": [["legal", "financial", "technical", "personal"]],
"keywords": ["string"]
}""",
}
default_structured_json_template = "Invoice with line items"
with gr.Blocks(title="Image Data Extractor") as demo:
gr.Markdown(
"# Image Data Extractor\n"
"Extract structured JSON from an image and optional text using "
"[numind/NuExtract3](https://huggingface.co/numind/NuExtract3)."
)
with gr.Row():
with gr.Column():
image = gr.Image(label="Document image", type="pil", height=430)
text = gr.Textbox(
label="Document text (optional)",
placeholder="Add text to process alongside the image",
lines=3,
)
enable_thinking = gr.Checkbox(label="Enable thinking")
template_preset = gr.Dropdown(
choices=list(structured_json_templates),
value=default_structured_json_template,
label="JSON template preset",
info="Choose a starting structure, then edit it below.",
)
generate_template_button = gr.Button("Generate template from Image")
with gr.Accordion("Structured JSON template", open=False):
template = gr.Textbox(
label="Structured JSON template",
value=structured_json_templates[default_structured_json_template],
lines=18,
info="Used for structured extraction. Edit the example to match your document.",
)
run = gr.Button("Extract Image Data", variant="primary")
with gr.Column():
structured_output = gr.JSON(
label="Structured JSON",
open=True,
show_indices=True,
)
gr.Examples(
examples=[
[
"Basic receipt",
str(
Path(__file__).parent
/ "data"
/ "samples"
/ "receipt-ocr-original.webp"
),
"",
False,
],
[
"Invoice with line items",
str(
Path(__file__).parent
/ "data"
/ "samples"
/ "invoice-with-items.png"
),
"",
False,
],
[
"Advanced bank statement",
str(
Path(__file__).parent
/ "data"
/ "samples"
/ "BankStatementChequing.png"
),
"",
False,
],
[
"Basic bank statement",
str(
Path(__file__).parent
/ "data"
/ "samples"
/ "bank statement blog image.webp"
),
"",
False,
],
*[
[
default_structured_json_template,
str(path),
"",
False,
]
for path in sorted(
path
for path in (Path(__file__).parent / "data" / "samples").glob(
"*.png"
)
if path.name
not in {"BankStatementChequing.png", "invoice-with-items.png"}
)
],
],
inputs=[template_preset, image, text, enable_thinking],
)
template_preset.change(
structured_json_templates.__getitem__,
inputs=template_preset,
outputs=template,
api_name="select_structured_json_template",
)
generate_template_button.click(
generate_template,
inputs=image,
outputs=template,
api_name="generate_template",
)
run.click(
extract,
inputs=[image, text, template, enable_thinking],
outputs=structured_output,
api_name="extract",
)
if __name__ == "__main__":
demo.launch()