doclingr turns messy documents — PDF, DOCX, PPTX, HTML, images — into structured, AI-ready data. It wraps the Docling Python library through reticulate, giving you layout-aware parsing, table extraction and retrieval-ready chunking with a small, tidy R API.
This vignette walks the full path: document → structure → tables → chunks → embeddings, i.e. everything you need to stand up a retrieval-augmented generation (RAG) corpus from R.
doclingr needs the Docling Python package. Install it once into a managed environment, then restart R:
docling_convert() runs Docling’s understanding pipeline
over a file path or URL and returns a lightweight handle:
doc <- docling_convert("https://arxiv.org/pdf/2408.09869")
doc
#> <docling_document>
#> source: https://arxiv.org/pdf/2408.09869
#> pages: 9
#> tables: 5
#> figures: 3Tune the pipeline when you need to. OCR and the accurate table model cost time; turn them down for born-digital documents or large batches:
Render the understood document into the format your downstream tools expect:
Every detected table comes back as a tibble, in document order:
Pull figure captions and pages, and optionally save the images
(requires images = TRUE at conversion time):
docling_chunk() splits the document into context-rich
chunks. The default hybrid chunker is token-aware: match its tokenizer
to your embedding model and set a budget so chunks fit your model’s
context.
chunks <- docling_chunk(
doc,
tokenizer = "BAAI/bge-small-en-v1.5",
max_tokens = 512
)
chunks
#> # A tibble: 84 x 7
#> chunk_id text raw_text n_chars headings pages n_doc_items
#> <int> <chr> <chr> <int> <list> <list> <int>
#> 1 1 "Docling: ..." "Docling..." 412 <chr [2]> <int [1]> 3
#> ...Each chunk’s text is contextualized — enriched
with its heading path and table context — which is the form you
typically embed. The unmodified text is kept in
raw_text.
doclingr is deliberately provider-agnostic about embeddings: you
supply a function that maps a character vector to vectors, and
docling_embed() handles batching and tidy assembly. Here is
a sketch against an OpenAI-style API:
embed_api <- function(texts) {
# Call your embedding endpoint; return a matrix with one row per text.
# e.g. httr2 -> a list of vectors, or a matrix.
}
corpus <- doc |>
docling_chunk(tokenizer = "BAAI/bge-small-en-v1.5", max_tokens = 512) |>
docling_embed(embed_api, batch_size = 64)
corpus
#> # ... your chunks plus `embedding` (list-column) and `n_dim`At this point corpus is a tidy table of chunks with
their headings, pages and embeddings — ready to write to a vector store,
a database, or an in-memory nearest-neighbor index for RAG.
as_json(doc) when you need the full structural
detail Docling captured.corpus (for example with
arrow::write_parquet()) to avoid re-converting and
re-embedding.