File size: 5,753 Bytes
59af62d
c2a765a
 
 
 
72b6c80
c2a765a
e62015b
c2a765a
e62015b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c2a765a
 
 
 
 
1d02976
 
 
 
d96e2e1
1d02976
 
 
 
 
 
 
 
c2a765a
74bbc85
c2a765a
74bbc85
c2a765a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d9eb7f6
 
 
c2a765a
 
 
 
 
 
74bbc85
c2a765a
 
 
 
 
 
4d86074
 
59af62d
 
4d86074
1d02976
 
59af62d
1d02976
 
59af62d
4d86074
 
1d02976
 
 
 
c2a765a
 
 
 
4debd81
 
c2a765a
 
4debd81
 
 
 
 
 
e62015b
 
4debd81
c2a765a
 
 
 
 
72b6c80
c2a765a
 
6e92dd9
c2a765a
 
d9eb7f6
 
1d02976
d9eb7f6
 
 
 
c2a765a
d9eb7f6
 
 
 
 
c2a765a
 
 
 
 
 
 
 
 
 
 
 
 
b2b415b
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import zipfile
from pathlib import Path

import gradio as gr

from model import extract, generate_template

templates_directory = Path(__file__).parent / "data" / "templates"
structured_json_templates = {
    "Basic receipt": (templates_directory / "basic-receipt.json").read_text(
        encoding="utf-8"
    ),
    "Invoice with line items": (
        templates_directory / "invoice-with-line-items.json"
    ).read_text(encoding="utf-8"),
    "Basic bank statement": (
        templates_directory / "basic-bank-statement.json"
    ).read_text(encoding="utf-8"),
    "Advanced bank statement": (
        templates_directory / "advanced-bank-statement.json"
    ).read_text(encoding="utf-8"),
    "Model task catalog": (
        templates_directory / "model-task-catalog.json"
    ).read_text(encoding="utf-8"),
    "Todo list": (templates_directory / "todo-list.json").read_text(
        encoding="utf-8"
    ),
}

default_structured_json_template = "Invoice with line items"


def download_agentskill(include_all_skills):
    skill_folders = (
        sorted(path for path in Path(".agents/skills").iterdir() if path.is_dir())
        if include_all_skills
        else [Path(".agents/skills/image-data-extractor")]
    )
    for skill_folder in skill_folders:
        with zipfile.ZipFile(
            f"{skill_folder.name}.zip", "w", compression=zipfile.ZIP_DEFLATED
        ) as archive:
            for path in skill_folder.rglob("*"):
                archive.write(path, path.relative_to(".agents/skills"))
    return [f"{skill_folder.name}.zip" for skill_folder in skill_folders]

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
            ) as template_accordion:
                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.Markdown(
                "## Install the agent skill\n"
                "Download the ZIP, extract it, and place its skill folders in your "
                "project's `.agents/skills/` directory. Agents should read the "
                "`SKILL.md` and use it whenever a task requires structured extraction "
                "from an image. Keep **Include All Skills** checked to download every "
                "skill as its own ZIP file."
            )
            include_all_skills = gr.Checkbox(
                label="Include All Skills",
                value=True,
            )
            download_agentskill_button = gr.Button("Download agent skill")
            download_agentskill_file = gr.File(
                label="Agent skill ZIPs",
                file_count="multiple",
            )

    gr.Examples(
        examples=[
            [
                preset,
                str(Path(__file__).parent / "data" / "samples" / filename),
                "",
                False,
            ]
            for preset, filename in [
                ("Basic receipt", "receipt-ocr-original.webp"),
                ("Invoice with line items", "invoice-with-items.png"),
                ("Advanced bank statement", "BankStatementChequing.png"),
                ("Basic bank statement", "bank statement blog image.webp"),
                ("Model task catalog", "tags.png"),
                ("Todo list", "task-list.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",
    )

    download_agentskill_button.click(
        download_agentskill,
        inputs=include_all_skills,
        outputs=download_agentskill_file,
        api_name="download_agentskill",
    )

    generate_template_button.click(
        lambda: gr.Accordion(open=True),
        outputs=template_accordion,
        api_visibility="private",
        show_progress="hidden",
    ).then(
        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()