File size: 5,191 Bytes
874752d | 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 | # 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](serving.md#native-dflash2) running:
```bash
python -m pip install beautifulsoup4 Pillow numpy httpx
```
No serving plugin is required. Add the downloaded repository to Python's import path:
```python
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
```python
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:
```python
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:
```python
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](postprocessing-reference.md).
The CLI can run from downloaded source as `python -m nemotron_parse.inference`;
installing the serving plugin is unnecessary for that invocation.
|