Download docs/postprocessing.md from iapp/OpenThai2.0-OCR-Markdown: direct link, hf CLI and curl.
- Browser
- Download file 5.19 kB
-
https://huggingface.co/iapp/OpenThai2.0-OCR-Markdown/resolve/main/docs/postprocessing.md
- Command line
-
hf download hf://iapp/OpenThai2.0-OCR-Markdown/docs/postprocessing.md
-
curl -L -o postprocessing.md https://huggingface.co/iapp/OpenThai2.0-OCR-Markdown/resolve/main/docs/postprocessing.md
Parse documents and export tables
These helpers use predictions and page images; they do not load benchmark answers.
Downloaded helpers
With the native vLLM server running:
python -m pip install beautifulsoup4 Pillow numpy httpx
No serving plugin is required. Add the downloaded repository to Python's import path:
import sys
sys.path.insert(0, "./parse35")
from nemotron_parse.inference import DocumentParser
def main():
with DocumentParser(
base_url="http://localhost:8000/v1", model="nemotron-parse",
) as parser:
documents = parser.parse_many(
["one.png", "two.png"], mode="triple",
concurrency=128, triple_regions="union",
)
for document in documents:
print(document["markdown"])
print(document["blocks"])
if __name__ == "__main__":
main()
single parses each full page. double also refines predicted Table/Chart crops.
triple adds independent detection and refines the detector/parser region union.
parse_many overlaps parsing and detection, submits crops as they become ready,
and shares one concurrency window across stages. Put multiprocessing entry points
under the main guard. The one-page parse, parse_double and parse_triple
convenience methods execute their dependent stages serially.
The default alternatives merge retains differing overlapping table/chart hypotheses.
Use DocumentParser(merge_policy="guarded") for conservative replacement and a
single selected hypothesis; this can discard correct alternatives. Stage responses
remain available in document["stages"].
Convert an existing prediction
from nemotron_parse import postprocess_document, PostprocessOptions
from postprocessing import postprocess_text
options = PostprocessOptions(
infer_headers=True, render_charts=True,
split_chart_value_percent=True, relocate_chart_captions=True,
)
document = postprocess_document(raw_output, image_size=image.size, options=options)
table = next(b for b in document["blocks"] if b["class"] == "Table")
print(postprocess_text(table["text"], cls="Table", table_format="csv"))
print(postprocess_text(table["text"], cls="Table", table_format="json_hierarchical"))
Blocks retain class, normalized bbox, literal text and rendered content.
image_size=(width,height) adds clipped pixel boxes. Document Markdown uses
HTML tables to preserve merged cells. HTML and json_hierarchical preserve
cell spans; markdown, csv and record json are flat exports that expand spans.
latex retains the predicted table representation. Headerless tables retain
their first data row; duplicate column names are disambiguated.
Set any presentation option above to False to disable it. Caption association
moves existing text; value/percentage splitting separates existing predictions
and does not calculate values. Raw block text remains available. Malformed tables
are retained and reported in warnings rather than forced into a lossy row splitter.
For strict output schemas, select fields after a full-structure parse; prompt
switches can leave residual structural tokens.
Draw predicted boxes
Continue from the prediction conversion above to save an image overlay:
from PIL import ImageDraw
overlay = image.copy()
draw = ImageDraw.Draw(overlay)
for block in document["blocks"]:
if block.get("bbox_pixels"):
draw.rectangle(block["bbox_pixels"], outline="red", width=2)
overlay.save("prediction.png")
Use the same image dimensions supplied to postprocess_document. This recipe
draws the predicted boxes without changing their geometry or the source image.
Completion and prepared batches
Strict generation handling is the default. Token-limited, empty, failed or
filtered output raises GenerationError. If partial results are useful, pass
allow_partial=True: affected documents have complete=False and
generation_warnings; truncated crops are excluded from refinement. Transport
errors and empty responses still raise. Do not count partial pages as completed.
For repeated processing of the same page images:
prepared = parser.prepare(page_images, workers=8)
result = parser.parse_prepared(
prepared, mode="triple", concurrency=128, postprocess_workers=8,
triple_regions="union", schedule="pipelined", allow_partial=True,
)
print(result.metrics["inference_pages_per_second"])
print(result.metrics["complete_inference_pages_per_second"])
Run this inside the guarded main function while parser is open. Preparation is
reported separately. The inference clock includes model/HTTP calls, queueing and
dependent crop preparation; final rendering and serialization are reported
separately. Use pipeline rates when end-to-end merge/render cost matters. Stage
spans overlap and must not be added together.
For crop margins, generation controls, a loaded Transformers backend, CLI use,
and historical validation, see the extended reference.
The CLI can run from downloaded source as python -m nemotron_parse.inference;
installing the serving plugin is unnecessary for that invocation.