Spaces:
Sleeping
Sleeping
electblake commited on
Commit ·
60d4ffd
1
Parent(s): b443080
refactor(gradio): focus app on structured extraction
Browse filesRemove the content task and Markdown outputs so the Space exposes one structured extraction pipeline with one JSON result. Update examples and documentation to match the simplified API.
- README.md +3 -3
- app/gradio.py +14 -36
README.md
CHANGED
|
@@ -10,14 +10,14 @@ app_file: app.py
|
|
| 10 |
pinned: false
|
| 11 |
models:
|
| 12 |
- numind/NuExtract3
|
| 13 |
-
short_description: Extract
|
| 14 |
---
|
| 15 |
|
| 16 |
# NuMark
|
| 17 |
|
| 18 |
-
NuMark is a Gradio app for extracting
|
| 19 |
|
| 20 |
-
Upload a receipt, invoice, or other document image, optionally add accompanying text, and choose
|
| 21 |
|
| 22 |
The inference function uses Hugging Face ZeroGPU dynamic GPU allocation. Select ZeroGPU in the Space hardware settings before launching the app.
|
| 23 |
|
|
|
|
| 10 |
pinned: false
|
| 11 |
models:
|
| 12 |
- numind/NuExtract3
|
| 13 |
+
short_description: Extract structured JSON from documents with NuExtract3.
|
| 14 |
---
|
| 15 |
|
| 16 |
# NuMark
|
| 17 |
|
| 18 |
+
NuMark is a Gradio app for extracting structured JSON from document images with [NuExtract3](https://huggingface.co/numind/NuExtract3).
|
| 19 |
|
| 20 |
+
Upload a receipt, invoice, or other document image, optionally add accompanying text, and choose a JSON template for schema-guided structured extraction.
|
| 21 |
|
| 22 |
The inference function uses Hugging Face ZeroGPU dynamic GPU allocation. Select ZeroGPU in the Space hardware settings before launching the app.
|
| 23 |
|
app/gradio.py
CHANGED
|
@@ -262,7 +262,7 @@ def run_nuextract(messages, **chat_template_kwargs):
|
|
| 262 |
)[0].strip()
|
| 263 |
|
| 264 |
|
| 265 |
-
def extract(image, text,
|
| 266 |
result = run_nuextract(
|
| 267 |
[
|
| 268 |
{
|
|
@@ -273,21 +273,18 @@ def extract(image, text, mode, template, enable_thinking):
|
|
| 273 |
],
|
| 274 |
}
|
| 275 |
],
|
| 276 |
-
mode=
|
| 277 |
template=template,
|
| 278 |
enable_thinking=enable_thinking,
|
| 279 |
)
|
| 280 |
|
| 281 |
-
|
| 282 |
-
return result, result, gr.skip()
|
| 283 |
-
|
| 284 |
-
return gr.skip(), gr.skip(), json.loads(result)
|
| 285 |
|
| 286 |
|
| 287 |
with gr.Blocks(title="NuMarkApp") as demo:
|
| 288 |
gr.Markdown(
|
| 289 |
"# NuMarkApp\n"
|
| 290 |
-
"Extract
|
| 291 |
"[numind/NuExtract3](https://huggingface.co/numind/NuExtract3)."
|
| 292 |
)
|
| 293 |
with gr.Row():
|
|
@@ -298,11 +295,6 @@ with gr.Blocks(title="NuMarkApp") as demo:
|
|
| 298 |
placeholder="Add text to process alongside the image",
|
| 299 |
lines=3,
|
| 300 |
)
|
| 301 |
-
mode = gr.Radio(
|
| 302 |
-
["content", "structured"],
|
| 303 |
-
value="content",
|
| 304 |
-
label="Task",
|
| 305 |
-
)
|
| 306 |
enable_thinking = gr.Checkbox(label="Enable thinking")
|
| 307 |
template_preset = gr.Dropdown(
|
| 308 |
choices=list(structured_json_templates),
|
|
@@ -317,22 +309,13 @@ with gr.Blocks(title="NuMarkApp") as demo:
|
|
| 317 |
lines=18,
|
| 318 |
info="Used for structured extraction. Edit the example to match your document.",
|
| 319 |
)
|
| 320 |
-
run = gr.Button("Extract", variant="primary")
|
| 321 |
-
with gr.Column()
|
| 322 |
-
|
| 323 |
-
|
| 324 |
-
|
| 325 |
-
|
| 326 |
-
|
| 327 |
-
)
|
| 328 |
-
with gr.Accordion("Markdown preview (optional)", open=False):
|
| 329 |
-
markdown_preview = gr.Markdown()
|
| 330 |
-
with gr.Tab("Structured"):
|
| 331 |
-
structured_output = gr.JSON(
|
| 332 |
-
label="Structured JSON",
|
| 333 |
-
open=True,
|
| 334 |
-
show_indices=True,
|
| 335 |
-
)
|
| 336 |
|
| 337 |
gr.Examples(
|
| 338 |
examples=[
|
|
@@ -345,7 +328,6 @@ with gr.Blocks(title="NuMarkApp") as demo:
|
|
| 345 |
/ "receipt-ocr-original.webp"
|
| 346 |
),
|
| 347 |
"",
|
| 348 |
-
"structured",
|
| 349 |
False,
|
| 350 |
],
|
| 351 |
[
|
|
@@ -357,7 +339,6 @@ with gr.Blocks(title="NuMarkApp") as demo:
|
|
| 357 |
/ "invoice-with-items.png"
|
| 358 |
),
|
| 359 |
"",
|
| 360 |
-
"structured",
|
| 361 |
False,
|
| 362 |
],
|
| 363 |
[
|
|
@@ -369,7 +350,6 @@ with gr.Blocks(title="NuMarkApp") as demo:
|
|
| 369 |
/ "BankStatementChequing.png"
|
| 370 |
),
|
| 371 |
"",
|
| 372 |
-
"structured",
|
| 373 |
False,
|
| 374 |
],
|
| 375 |
[
|
|
@@ -381,7 +361,6 @@ with gr.Blocks(title="NuMarkApp") as demo:
|
|
| 381 |
/ "bank statement blog image.webp"
|
| 382 |
),
|
| 383 |
"",
|
| 384 |
-
"structured",
|
| 385 |
False,
|
| 386 |
],
|
| 387 |
*[
|
|
@@ -389,7 +368,6 @@ with gr.Blocks(title="NuMarkApp") as demo:
|
|
| 389 |
default_structured_json_template,
|
| 390 |
str(path),
|
| 391 |
"",
|
| 392 |
-
"content",
|
| 393 |
False,
|
| 394 |
]
|
| 395 |
for path in sorted(
|
|
@@ -402,7 +380,7 @@ with gr.Blocks(title="NuMarkApp") as demo:
|
|
| 402 |
)
|
| 403 |
],
|
| 404 |
],
|
| 405 |
-
inputs=[template_preset, image, text,
|
| 406 |
)
|
| 407 |
|
| 408 |
template_preset.change(
|
|
@@ -413,8 +391,8 @@ with gr.Blocks(title="NuMarkApp") as demo:
|
|
| 413 |
|
| 414 |
run.click(
|
| 415 |
extract,
|
| 416 |
-
inputs=[image, text,
|
| 417 |
-
outputs=
|
| 418 |
api_name="extract",
|
| 419 |
)
|
| 420 |
|
|
|
|
| 262 |
)[0].strip()
|
| 263 |
|
| 264 |
|
| 265 |
+
def extract(image, text, template, enable_thinking):
|
| 266 |
result = run_nuextract(
|
| 267 |
[
|
| 268 |
{
|
|
|
|
| 273 |
],
|
| 274 |
}
|
| 275 |
],
|
| 276 |
+
mode="structured",
|
| 277 |
template=template,
|
| 278 |
enable_thinking=enable_thinking,
|
| 279 |
)
|
| 280 |
|
| 281 |
+
return json.loads(result)
|
|
|
|
|
|
|
|
|
|
| 282 |
|
| 283 |
|
| 284 |
with gr.Blocks(title="NuMarkApp") as demo:
|
| 285 |
gr.Markdown(
|
| 286 |
"# NuMarkApp\n"
|
| 287 |
+
"Extract structured JSON from an image and optional text using "
|
| 288 |
"[numind/NuExtract3](https://huggingface.co/numind/NuExtract3)."
|
| 289 |
)
|
| 290 |
with gr.Row():
|
|
|
|
| 295 |
placeholder="Add text to process alongside the image",
|
| 296 |
lines=3,
|
| 297 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 298 |
enable_thinking = gr.Checkbox(label="Enable thinking")
|
| 299 |
template_preset = gr.Dropdown(
|
| 300 |
choices=list(structured_json_templates),
|
|
|
|
| 309 |
lines=18,
|
| 310 |
info="Used for structured extraction. Edit the example to match your document.",
|
| 311 |
)
|
| 312 |
+
run = gr.Button("Extract structured JSON", variant="primary")
|
| 313 |
+
with gr.Column():
|
| 314 |
+
structured_output = gr.JSON(
|
| 315 |
+
label="Structured JSON",
|
| 316 |
+
open=True,
|
| 317 |
+
show_indices=True,
|
| 318 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 319 |
|
| 320 |
gr.Examples(
|
| 321 |
examples=[
|
|
|
|
| 328 |
/ "receipt-ocr-original.webp"
|
| 329 |
),
|
| 330 |
"",
|
|
|
|
| 331 |
False,
|
| 332 |
],
|
| 333 |
[
|
|
|
|
| 339 |
/ "invoice-with-items.png"
|
| 340 |
),
|
| 341 |
"",
|
|
|
|
| 342 |
False,
|
| 343 |
],
|
| 344 |
[
|
|
|
|
| 350 |
/ "BankStatementChequing.png"
|
| 351 |
),
|
| 352 |
"",
|
|
|
|
| 353 |
False,
|
| 354 |
],
|
| 355 |
[
|
|
|
|
| 361 |
/ "bank statement blog image.webp"
|
| 362 |
),
|
| 363 |
"",
|
|
|
|
| 364 |
False,
|
| 365 |
],
|
| 366 |
*[
|
|
|
|
| 368 |
default_structured_json_template,
|
| 369 |
str(path),
|
| 370 |
"",
|
|
|
|
| 371 |
False,
|
| 372 |
]
|
| 373 |
for path in sorted(
|
|
|
|
| 380 |
)
|
| 381 |
],
|
| 382 |
],
|
| 383 |
+
inputs=[template_preset, image, text, enable_thinking],
|
| 384 |
)
|
| 385 |
|
| 386 |
template_preset.change(
|
|
|
|
| 391 |
|
| 392 |
run.click(
|
| 393 |
extract,
|
| 394 |
+
inputs=[image, text, template, enable_thinking],
|
| 395 |
+
outputs=structured_output,
|
| 396 |
api_name="extract",
|
| 397 |
)
|
| 398 |
|