Skip to main content

Extract hierarchical document graphs and baseline chunks from PDF

Project description

document2graph

Extract hierarchical document graphs and baseline chunks from PDF files. The package parses PDFs using Docling and produces two complementary representations:

  • Document graph — text, image, and table nodes connected by weighted structural edges, capturing the layout hierarchy of the document. Every graph is guaranteed to be connected: nodes without a resolvable parent are attached to a synthetic document root node.
  • Baseline chunks — flat, semantically merged chunks suitable for retrieval pipelines, with optional context enrichment.

Installation

pip install document2graph

Or from source:

pip install -e .

For development dependencies (pytest):

pip install -e ".[dev]"

Requires Python 3.11+.

Quick start

Configuration

Both extractors share the same ExtractorConfig:

from document2graph.models import ExtractorConfig
from docling.datamodel.pipeline_options import PdfPipelineOptions

config = ExtractorConfig(
    pdf_path="data/pdfs/",        # directory containing input PDFs
    data_path="data/output/",     # root directory for all output files
    save_json=True,               # write results to disk as JSON (default: True)
    document_type="report",       # arbitrary label stored in document metadata
    pdfPipelineOptions=PdfPipelineOptions(),  # optional Docling pipeline config
)

Metadata extraction

The metadata_config field controls how document metadata (title, authors, version, etc.) is located inside each PDF. Each field is described by a search string and an inclusive page range to search on. Fields set to None are skipped.

from document2graph.models import ExtractorConfig, MetadataExtractionConfig, MetadataFieldConfig

config = ExtractorConfig(
    pdf_path="data/pdfs/",
    data_path="data/output/",
    metadata_config=MetadataExtractionConfig(
        title_page=1,
        version=MetadataFieldConfig(label="edition", pages=(1, 1)),
        authors=MetadataFieldConfig(label="authors", pages=(1, 2)),
        institutions=MetadataFieldConfig(label="affiliations", pages=(1, 2)),
        bibliography=None,        # not present in this document type
        correspondence=MetadataFieldConfig(label="contact", pages=(2, 3)),
    ),
)

The default MetadataExtractionConfig() targets German-language Praxisempfehlungen PDFs (version on page 1, authors/institutions/bibliography/correspondence on page 2).

Edge weights

Every edge in the document graph carries a weight attribute reflecting the strength of the structural connection. The defaults can be overridden per category via edge_weights:

from document2graph.models import ExtractorConfig, EdgeWeightConfig

config = ExtractorConfig(
    pdf_path="data/pdfs/",
    data_path="data/output/",
    edge_weights=EdgeWeightConfig(
        section=1.0,             # heading -> subheading
        text=0.8,                # heading/body -> body text, subtext, footnotes
        list_item=0.6,           # anchor text -> grouped list item (bullets)
        media=0.9,               # referencing text -> image/table (matched via caption)
        unreferenced_media=0.3,  # fallback heading -> image/table without a caption match
        root=0.1,                # document root -> otherwise disconnected node
    ),
)

Connectivity guarantee

Each graph contains a synthetic root node (#/document-root, labelled with the document title). Any node whose parent cannot be resolved — as well as any component that would otherwise be disconnected — is attached to this root with the root edge weight, so every document graph is a single (weakly) connected component.

Extracted metadata is available on the Document object under the metadata sub-object:

result = extractor.run("my_document.pdf")
doc = result["document_metadata"]

print(doc.title)
print(doc.metadata.authors)
print(doc.metadata.version)

Document graph extraction

Processes every PDF in pdf_path and builds a NetworkX graph per document.

from document2graph.document2graph_extractor import DocumentGraphExtractor

extractor = DocumentGraphExtractor(config)

# Process all PDFs and save graphs + snippets to disk
extractor.generate_snippets()

# Or collect Snippet objects in memory as well
snippets = extractor.generate_snippets(return_snippets=True)

To process a single file and get the raw graph components:

result = extractor.run("my_document.pdf")

text_nodes   = result["text_nodes"]
image_nodes  = result["image_nodes"]
table_nodes  = result["table_nodes"]
edges        = result["edges"]        # list of (parent_id, child_id, weight) tuples
metadata     = result["document_metadata"]

Graphs are saved as .gexf files under <data_path>/nx_graphs/ and can be loaded with NetworkX:

import networkx as nx
G = nx.read_gexf("data/output/nx_graphs/my_document.gexf")

Baseline chunk extraction

Produces flat, retrieval-ready chunks using Docling's hybrid chunker.

from document2graph.baseline_extractor import BaselineExtractor

extractor = BaselineExtractor(config)

# Process all PDFs; saves JSON to disk
extractor.generate_baseline_chunks()

# Or return chunks in memory
all_chunks = extractor.generate_baseline_chunks(return_chunks=True)
# all_chunks["my_document.pdf"]["baseline"]  -> List[Chunk]
# all_chunks["my_document.pdf"]["enriched"]  -> List[Chunk] (context-enriched)

To process a single file:

chunks = extractor.extract_baseline_chunks(
    filename="my_document.pdf",
    baseline_description="Q1 report chunks",
    enrich=True,   # also produce context-enriched variants
)

Output structure

<data_path>/
├── raw_texts/          # intermediate Docling extraction output
├── nx_graphs/          # .gexf graph files (one per document)
├── snippets/           # <filename>_snippets.json (document graph output)
└── baseline_chunks/    # <filename>_baseline_chunks.json

Data models

Model Key fields
Snippet snippet_id, type (text/image/table), document_id, sequence_no, label, level, page_no, bbox, text
Chunk chunk_id, document_id, text, meta, baseline_description, embedding
Document document_id, document_type, filename, title, metadata: DocumentMetadata
DocumentMetadata version, authors, institutions, bibliography, correspondence
MetadataExtractionConfig title_page, version, authors, institutions, bibliography, correspondence (each a MetadataFieldConfig)
MetadataFieldConfig label (search string), pages (inclusive 1-based page range, e.g. (1, 3))
EdgeWeightConfig section, text, list_item, media, unreferenced_media, root (edge weights by category)

Running tests

pytest

Skip slow tests that download models:

pytest -m "not slow"

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

document2graph-0.1.0.tar.gz (21.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

document2graph-0.1.0-py3-none-any.whl (23.0 kB view details)

Uploaded Python 3

File details

Details for the file document2graph-0.1.0.tar.gz.

File metadata

  • Download URL: document2graph-0.1.0.tar.gz
  • Upload date:
  • Size: 21.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for document2graph-0.1.0.tar.gz
Algorithm Hash digest
SHA256 fe37d2364baee83a7ba0d853e7c5f78ad226b43273a0a4cdec8bd1e96a4db2c1
MD5 a5ada733d9bc306a0154443b145cb850
BLAKE2b-256 75d908c7f9dfa23a775494bcfb89411dd2829e670e582de2a6791ad78a33d9fc

See more details on using hashes here.

Provenance

The following attestation bundles were made for document2graph-0.1.0.tar.gz:

Publisher: python-publish.yml on mwalther10/document2graph

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file document2graph-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: document2graph-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 23.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for document2graph-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b24a51dff30c6162e22eeac7a34e34eadf442fba78b945d761097546997b5be8
MD5 ae3e242902b1332f176a7e08694028a2
BLAKE2b-256 ab05c495f7e8499b089bc0b3f19eca77df80d3718b89e0a82cbef990ce2aab79

See more details on using hashes here.

Provenance

The following attestation bundles were made for document2graph-0.1.0-py3-none-any.whl:

Publisher: python-publish.yml on mwalther10/document2graph

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page