A small local demo for checking the quality of parsed PDF output.
It takes JSON exported by Docling and creates:
- a small traceable JSON file with text blocks, page numbers, bounding boxes, and provenance
- a deterministic Markdown quality report that highlights missing fields, broken provenance, invalid bounding boxes, and layout/noise signals
- provenance-preserving JSONL chunk records from normalized parser output
This project does not try to replace Docling. Docling does the PDF parsing. This repo checks whether the parser output is structured and traceable for human review before downstream use.
It does not claim OCR quality, RAG answer quality, table reconstruction, legal extraction, compliance readiness, production extraction accuracy, or enterprise readiness.
Technical note: the traceable output is plain JSON. It is inspired by UIF, an internal block model with text, page numbers, bounding boxes, and provenance, but no separate schema repository is needed to use this demo.
The report answers practical questions such as:
- Does every extracted block have the basic fields a pipeline needs?
- Can each block be traced back to a source page and bounding box?
- Does the page contain layout noise that a human should review before using the output?
The seven current checks are:
- Required field coverage: are core fields such as
id,type,page_number,bbox, andreading_order_indexpresent? - Table output structure signals: do table-labeled normalized blocks contain visible table-output structure signals?
- Provenance completeness: can each block be traced back to Docling metadata and the source PDF?
- BBox sanity: are bounding boxes present, finite, and ordered correctly?
- Content vs noise ratio: how much looks like document content compared with headers, footers, images, or other secondary blocks?
- Text usefulness: are text blocks empty, suspiciously short, or duplicated?
- Text extraction health: is extracted text available in the normalized blocks for review, without judging whether the text is correct?
Text usefulness flags local text-quality issues such as empty body blocks, very short text, or repeated fragments.
Text extraction health summarizes whether the document contains enough extracted text overall for review.
The table output structure signal check flags table-labeled normalized blocks that lack obvious structured table-output
signals; it does not validate table reconstruction correctness against the PDF.
Structured table-output signals include normalized grid fields such as data_grid or rows, optional cells / html,
or delimiter-like content.text.
Warning-only checks can move the report to REVIEW; the report CLI still exits non-zero only for hard failures.
It also lists diagnostic noise/layout signals such as table-marker artifacts, headers/footers, and ambiguous image blocks. These signals are for review only; they do not add hard failures or warnings by themselves.
python -m venv .venv
. .venv/bin/activate
python -m pip install -e ".[dev]"Docling is only needed when you want to create the parser JSON from a PDF:
python -m pip install -e ".[docling]"The example uses:
Hansen, M.; Pomp, A.; Erki, K.; Meisen, T. "Data-Driven Recognition and Extraction of PDF Document Elements." Technologies 2019, 7(3), 65. https://doi.org/10.3390/technologies7030065
Download the PDF from the official article page:
https://www.mdpi.com/2227-7080/7/3/65
Then generate Docling JSON:
docling path/to/article.pdf --to json --image-export-mode placeholder --no-ocr --output tmp/doclingReplace article.json in the next command with the JSON filename generated by Docling.
Convert selected pages to normalized JSON:
python -m pdf_quality_report.convert \
--input tmp/docling/article.json \
--output examples/mdpi_pdf_elements/page_006/normalized_blocks.json \
--pages 6 \
--source-pdf path/to/article.pdfCreate a Markdown quality report:
python -m pdf_quality_report.report \
--input examples/mdpi_pdf_elements/page_006/normalized_blocks.json \
--output examples/mdpi_pdf_elements/page_006/quality_report.mdExport WARN and FAIL quality-check details as a human-reviewable findings list with source context when available:
python -m pdf_quality_report.review_findings \
--input examples/mdpi_pdf_elements/page_012/normalized_blocks.json \
--output /tmp/page_012_review_findings.mdUse --out as a short alias for --output. See Export Review Findings
for a short walkthrough.
review_findings counts WARN/FAIL detail items, or one check-level item when a warning or failure only has
metric-style details. It is not the number of WARN/FAIL checks. The command exits with 0 when the Markdown file is
written successfully, even if review findings exist; input or output errors return 1.
If the package entry point is installed:
pdf-quality-review-findings \
--input examples/mdpi_pdf_elements/page_012/normalized_blocks.json \
--output /tmp/page_012_review_findings.mdExport a static folder with the quality report, review findings, clean Markdown, chunk records, and chunk review Markdown:
python -m pdf_quality_report.review_bundle \
--input examples/mdpi_pdf_elements/page_012/normalized_blocks.json \
--output-dir /tmp/page_012_pqr_review_bundleThe command exits with 0 when all bundle files are written, even if the report decision is REVIEW or BLOCK.
Input or output errors return 1. See Export Review Bundle for a short
walkthrough.
Use --out-dir as a short alias for --output-dir.
If the package entry point is installed:
pdf-quality-review-bundle \
--input examples/mdpi_pdf_elements/page_012/normalized_blocks.json \
--output-dir /tmp/page_012_pqr_review_bundleExport normalized blocks to clean Markdown with source reference comments for downstream review or retrieval-oriented preparation:
python -m pdf_quality_report.to_markdown \
--input examples/mdpi_pdf_elements/page_012/normalized_blocks.json \
--output /tmp/page_012.mdUse --out as a short alias for --output. See Export Clean Markdown for a short walkthrough.
If the package entry point is installed:
pdf-quality-markdown \
--input examples/mdpi_pdf_elements/page_012/normalized_blocks.json \
--output /tmp/page_012.mdExport normalized blocks to JSONL chunk records with block IDs, page numbers, bounding-box references, heading context, source metadata, and citation-style display strings preserved for downstream review or lightweight retrieval-oriented experiments:
python -m pdf_quality_report.chunk \
--input examples/mdpi_pdf_elements/page_006/normalized_blocks.json \
--output /tmp/page_006_chunks.jsonlUse --out as a short alias for --output. See Export Chunk Records for a
short walkthrough.
If the package entry point is installed:
pdf-quality-chunk \
--input examples/mdpi_pdf_elements/page_006/normalized_blocks.json \
--output /tmp/page_006_chunks.jsonlBuild and render chunk records from normalized blocks as human-reviewable Markdown with source references and heading context:
python -m pdf_quality_report.chunk_review \
--input examples/mdpi_pdf_elements/page_006/normalized_blocks.json \
--output /tmp/page_006_chunk_review.mdUse --out as a short alias for --output. See Export Chunk Review Markdown
for a short walkthrough.
If the package entry point is installed:
pdf-quality-chunk-review \
--input examples/mdpi_pdf_elements/page_006/normalized_blocks.json \
--output /tmp/page_006_chunk_review.mdThis repository includes derived example outputs for page 6 and page 12 of the sample article:
examples/mdpi_pdf_elements/page_006/normalized_blocks.jsonexamples/mdpi_pdf_elements/page_006/quality_report.mdexamples/mdpi_pdf_elements/page_012/normalized_blocks.jsonexamples/mdpi_pdf_elements/page_012/quality_report.md
The source PDF itself is not committed. See examples/mdpi_pdf_elements/SOURCE.md for attribution and license details.
The tests use small synthetic Docling-style JSON fixtures, not the committed MDPI example files.
Documentation assets under docs/ explain the pipeline and a sample report layout. They do not change runtime behavior or widen claims beyond this README (see Publication policy).
docs/pqr_pipeline.svg— flow from PDF input through Docling to normalized blocks, six checks, GO/REVIEW/BLOCK, and exportsdocs/pqr_before_after.svg— illustrative raw parser JSON versus structured quality-report viewdocs/sample_report.html— open locally in a browser for a formatted sample (page 6 example)
Portfolio layer (same facts, presentation framing for proposals and embeds): docs/portfolio/README.md.
The simplified excerpt below comes from page 12 of the included MDPI research-paper example. A block is one extracted page element, such as text, a header, an image, or a caption. Later check sections and block-level warning details are not shown.
## Summary
- total_blocks: 82
- hard_failures: 0
- warnings: 2
- decision: REVIEW
## Interpretation
Why REVIEW? The hard structure checks passed, but warning checks need review in this report: Content vs Noise Ratio and Text Usefulness. Warnings are decision-level findings. Noise / Layout Signals provide supporting evidence and are counted separately.
- Content vs Noise Ratio is WARN: The report treats 79 blocks as possible main document text. The report treats 3 blocks as possible layout or noise elements.
- 2 blocks are typed as headers: p12-texts-555 and p12-texts-556. 1 block is typed as image: p12-pictures-14.
- Text Usefulness is WARN: This report found 22 very short extracted text values and 6 repeated-text groups.
- These findings come from extracted text blocks. Quoted values are the actual extracted text values, and block IDs show where they came from in the normalized output.
- In this report, very short means normalized text with 3 characters or fewer.
- Very short numeric fragments such as '111', '0.5', and '225' are common in chart ticks, figure labels, or repeated headers, footers, or page labels.
## Noise / Layout Signals
These signals identify page-layout elements that may need review before reusing the extracted text. They are supporting evidence and are counted separately from warning checks.
- table_marker_artifacts: 0
- running_furniture_blocks: 2
- visual_anchor_blocks: 1
- ambiguous_image_blocks: 1REVIEW means the hard structure checks passed, but warning details still need human review before Markdown export, retrieval-oriented preparation, or manual extraction.
Code in this repository is MIT licensed.
The sample article is third-party content distributed under CC BY 4.0 by MDPI. Derived example artifacts are provided for demonstration with attribution; they are not endorsed by MDPI or the article authors.