skill.md
Type
Document
Status
Published
Created
Jul 9, 2026
Updated
Jul 9, 2026

skill.md — Docling Python Library Reference#

For AI coding agents: This is a self-contained reference for writing code that uses the Docling Python library. Use it to quickly find API patterns, class names, and configuration options.


1. Overview#

Docling is a Python SDK and CLI for converting documents into a structured, AI-ready format. It ingests PDF, DOCX, PPTX, XLSX, HTML, Markdown, images, LaTeX, EPUB, audio, and more , and produces a unified DoclingDocument — a schema-versioned JSON representation carrying all texts, tables, pictures, page layout, and provenance .

Key value propositions for gen AI use cases:

  • Structured extraction with provenance — every element (paragraph, table cell, figure) carries page_no and bounding-box coordinates traceable back to the source file
  • Table, formula, and code extraction — TableFormer models extract structured table grids; VLM models extract LaTeX formulas and code-language labels
  • RAG-ready chunkingHybridChunker produces DocChunk objects with tokenizer-aware splits, contextual headings, and three-layer provenance for citation
  • Multiple export targets — Markdown, HTML, JSON, plain text, DocTags (VLM training format), DocLang (LLM-compatible XML)
  • Integrations — official connectors for LangChain (langchain-docling) and LlamaIndex (llama-index-readers-docling)

Processing pipeline overview:

Input document
  └─► DocumentConverter
        ├─► Backend (parses raw format)
        ├─► Layout model (detects regions)
        ├─► Table structure model (extracts cell grids)
        ├─► OCR (handles scanned pages)
        └─► Enrichment models (code, formula, picture classification)
              └─► DoclingDocument
                    ├── export_to_markdown() / export_to_html() / etc.
                    └── HybridChunker ──► DocChunk[] ──► Vector store

2. Installation#

# Base install — supports all document formats (PDF, DOCX, PPTX, XLSX, HTML, images, etc.)
pip install docling

# VLM support — required for Granite Vision table structure, VLM pipeline presets,
# and picture description via local VLM models
pip install docling[vlm]

# ASR support — audio/video transcription pipeline
pip install docling[asr]

# HTML rendering — headless browser rendering for JavaScript-heavy pages
pip install docling[htmlrender]

# Chunking support in docling-core (HybridChunker + HuggingFace tokenizer)
pip install docling-core[chunking]

# Chunking with OpenAI/tiktoken tokenizer
pip install docling-core[chunking-openai]

LangChain integration :

pip install langchain-docling

LlamaIndex integration :

pip install llama-index-readers-docling llama-index-node-parser-docling

Note: VLM models (Granite Vision, CodeFormulaV2, etc.) are downloaded automatically from HuggingFace on first use. A CUDA GPU is recommended for practical performance, but CPU inference is supported .

3. Core Concepts#

DocumentConverter#

DocumentConverter is the main entry point for all document conversion . It accepts a format_options dict mapping InputFormat enum values to FormatOption instances.

from docling.document_converter import DocumentConverter, PdfFormatOption
from docling.datamodel.base_models import InputFormat
from docling.datamodel.pipeline_options import PdfPipelineOptions

# Default converter — all formats with default options
converter = DocumentConverter()

# Custom converter — PDF with specific options
converter = DocumentConverter(
    format_options={
        InputFormat.PDF: PdfFormatOption(
            pipeline_options=PdfPipelineOptions(do_ocr=True, do_table_structure=True)
        )
    }
)

# Convert a single document
result = converter.convert("path/to/document.pdf")
doc = result.document # DoclingDocument

Pipelines are cached by (pipeline_class, md5(pipeline_options)) — multiple formats sharing the same class and options reuse a single initialized pipeline .


DoclingDocument#

DoclingDocument is the canonical output — a Pydantic model backed by a schema-versioned JSON representation :

FieldTypeDescription
schema_namestrAlways "DoclingDocument"
versionstrSchema version (e.g. "1.10.0")
namestrWorking name
originDocumentOriginSource file: filename, mimetype, binary_hash, uri
bodyGroupItemRoot tree node for main content
furnitureGroupItemRoot node for headers/footers
groupslist[GroupItem]Structural containers
textslist[BaseTextItem]All text nodes (titles, headings, paragraphs, code, formulas)
pictureslist[PictureItem]Image/figure nodes
tableslist[TableItem]Table nodes (with structured cell grids)
pagesdict[str, PageItem]Page-number → layout/image mapping

InputFormat and OutputFormat Enums#

from docling.datamodel.base_models import InputFormat, OutputFormat

# InputFormat — 24 supported input types (cite:code_file:4b418ed6)
InputFormat.PDF # PDF documents
InputFormat.DOCX # Microsoft Word
InputFormat.PPTX # Microsoft PowerPoint
InputFormat.XLSX # Microsoft Excel
InputFormat.HTML # HTML pages
InputFormat.MD # Markdown (also: .txt, .text, .qmd, .rmd)
InputFormat.IMAGE # Images (PNG, JPEG, TIFF, BMP, WEBP)
InputFormat.CSV # CSV files
InputFormat.LATEX # LaTeX documents
InputFormat.EPUB # EPUB ebooks
InputFormat.AUDIO # Audio files (with ASR pipeline)
InputFormat.XML_DOCLANG # DocLang XML format
InputFormat.JSON_DOCLING # Docling JSON format (round-trip)
# ... and: ODT, ODS, ODP, XML_USPTO, XML_JATS, XML_XBRL, METS_GBS, VTT, EMAIL, BOXNOTE, ASCIIDOC

# OutputFormat
OutputFormat.MARKDOWN # Markdown
OutputFormat.JSON # JSON
OutputFormat.YAML # YAML
OutputFormat.HTML # HTML
OutputFormat.TEXT # Plain text
OutputFormat.DOCTAGS # DocTags (VLM training format)
OutputFormat.DOCLANG # DocLang XML (LLM-compatible)
OutputFormat.CHUNKS # Chunked output

FormatOption Hierarchy#

Each format has a named FormatOption subclass pre-wired with the correct pipeline and backend :

ClassFormats
PdfFormatOptionPDF
ImageFormatOptionImages
WordFormatOptionDOCX
PowerpointFormatOptionPPTX
ExcelFormatOptionXLSX
HTMLFormatOptionHTML
MarkdownFormatOptionMarkdown
AudioFormatOptionAudio
LatexFormatOptionLaTeX
EpubFormatOptionEPUB

Each FormatOption bundles: pipeline_cls, pipeline_options (controls ML models/OCR/enrichment), and backend_options (controls backend-specific parsing).


PipelineOptions Hierarchy#

PipelineOptions ← timeout, accelerator, artifacts_path
└── ConvertPipelineOptions ← picture classification/description, chart extraction
    └── PaginatedPipelineOptions ← images_scale, generate_page_images
        ├── PdfPipelineOptions ← OCR, table structure, layout, formula/code enrichment
        └── VlmPipelineOptions ← VLM-based holistic page understanding
AsrPipelineOptions ← speech recognition (audio)

4. Basic Usage Patterns#

Simple Conversion#

from docling.document_converter import DocumentConverter

converter = DocumentConverter()

# From a local file path
result = converter.convert("path/to/document.pdf")

# From a URL
result = converter.convert("https://arxiv.org/pdf/2408.09869")

doc = result.document # DoclingDocument
print(result.status) # ConversionStatus.SUCCESS / FAILURE / PARTIAL_SUCCESS

Batch Conversion#

from pathlib import Path
from docling.document_converter import DocumentConverter

converter = DocumentConverter()

sources = [
    "doc1.pdf",
    "https://example.com/report.docx",
    Path("slides.pptx"),
]

# convert_all returns an iterator of ConversionResult
for result in converter.convert_all(sources):
    if result.status.success:
        doc = result.document
        print(f"{result.input.file}: {len(doc.texts)} text items")

Export to Markdown#

md = doc.export_to_markdown()

# For scanned/image-based PDFs processed with full-page OCR,
# set traverse_pictures=True to include OCR text children (cite:page:53237f2f)
md = doc.export_to_markdown(traverse_pictures=True)

# Control image handling
from docling_core.types.doc import ImageRefMode
md = doc.export_to_markdown(image_mode=ImageRefMode.EMBEDDED) # base64 inline
md = doc.export_to_markdown(image_mode=ImageRefMode.REFERENCED) # file path

# Save directly to file
doc.save_as_markdown("output.md")

Export to JSON#

import json

# As a Python dict (cite:code_file:9f949ac5)
data = doc.export_to_dict()

# As a JSON string
json_str = doc.model_dump_json(indent=2)

# Save to file
doc.save_as_json("output.json")

# Save to file with embedded images
doc.save_as_json("output.json", image_mode=ImageRefMode.EMBEDDED)

Export to HTML#

html = doc.export_to_html()

# With MathML formulas (default: True)
html = doc.export_to_html(formula_to_mathml=True)

# Split by page
html = doc.export_to_html(split_page_view=True)

# Save to file
doc.save_as_html("output.html")

Export to Plain Text#

text = doc.export_to_text()

# Include scanned OCR text
text = doc.export_to_text(traverse_pictures=True)

# Filter to specific page
text = doc.export_to_text(page_no=2)

Export to DocTags (VLM training format)#

# DocTags is the XML-like token format used by vision models (cite:page:767e9838)
doctags = doc.export_to_doctags()

# With bounding-box location tokens
doctags = doc.export_to_doctags(add_location=True, add_page_index=True)

# Save to file
doc.save_as_doctags("output.doctags")

Export to DocLang (LLM-compatible XML)#

# DocLang is an XML semantic markup format for LLM/VLM compatibility (cite:page:01e08bae)
doclang_xml = doc.export_to_doclang()

# Save as .dclg.xml file
doc.save_as_doclang("output.dclg.xml")

# Save as .dclx archive (with embedded images)
doc.save_as_doclang_archive("output.dclx")

CLI Usage#

The docling CLI exposes a convert command :

# Basic conversion — outputs Markdown by default
docling convert document.pdf

# Specify output format(s)
docling convert document.pdf --to md --to json --output ./output/

# Multiple input files
docling convert doc1.pdf doc2.docx --to md

# From URL
docling convert https://arxiv.org/pdf/2408.09869 --to md

# Disable OCR, enable table extraction
docling convert document.pdf --no-ocr --tables --to md

# Force OCR on all pages
docling convert scanned.pdf --force-ocr --to md

# Select PDF backend
docling convert document.pdf --pdf-backend threaded_docling_parse --to md

# Enable enrichments
docling convert document.pdf --enrich-code --enrich-formula --to md

# With chunked output
docling convert document.pdf --to chunks --chunks-type hybrid \
    --chunks-tokenizer sentence-transformers/all-MiniLM-L6-v2 \
    --chunks-max-tokens 512

# Only process specific input formats
docling convert ./docs/ --from pdf --from docx --to md

# Progress tracking
docling convert document.pdf --progress --to md

# Set verbosity
docling convert document.pdf -vv --to md # debug logging

Key CLI flags :

FlagDescription
--from FORMATInput format filter (pdf, docx, pptx, etc.)
--to FORMATOutput format (md, json, html, text, doctags, chunks)
--output DIROutput directory
--pipeline PIPELINEPDF/image pipeline to use
--vlm-model MODELVLM preset for PDF/image
--ocr / --no-ocrEnable/disable OCR
--force-ocrOCR entire page, replacing existing text
--tables / --no-tablesEnable/disable table structure extraction
--ocr-engine ENGINEOCR engine selection
--ocr-lang LANGOCR language(s), comma-separated
--pdf-backend BACKENDPDF backend (docling_parse, pypdfium2, threaded_docling_parse)
--enrich-codeEnable code enrichment model
--enrich-formulaEnable formula enrichment model
--enrich-picture-classesEnable picture classification
--enrich-picture-descriptionEnable picture description
--enrich-chart-extractionEnable chart data extraction
--image-export-mode MODEImage export mode for HTML/MD/JSON outputs
--num-threads NNumber of threads
--device DEVICEAccelerator device (cpu, cuda, mps)
--document-timeout SECSPer-document processing timeout
--progressEnable progress tracking

5. Pipeline Configuration#

PdfPipelineOptions Reference#

from docling.datamodel.pipeline_options import PdfPipelineOptions
from docling.document_converter import DocumentConverter, PdfFormatOption
from docling.datamodel.base_models import InputFormat

# All options with their defaults
pipeline_options = PdfPipelineOptions(
    do_ocr=True, # Apply OCR to bitmap regions (default: True)
    force_full_page_ocr=False, # OCR entire page (overrides text layer)
    do_table_structure=True, # Extract table cell grids (default: True)
    do_code_enrichment=False, # VLM code language detection (requires [vlm])
    do_formula_enrichment=False, # VLM LaTeX formula extraction (requires [vlm])
    do_picture_classification=False,# Classify images (chart, logo, diagram, etc.)
    do_picture_description=False, # VLM-based image captioning
    images_scale=1.0, # Image resolution multiplier (CLI default 2.0)
    generate_page_images=False, # Extract page images
    generate_picture_images=False, # Extract picture images
    pdf_backend="docling_parse", # Backend: pypdfium2 | docling_parse | threaded_docling_parse
)

converter = DocumentConverter(
    format_options={
        InputFormat.PDF: PdfFormatOption(pipeline_options=pipeline_options)
    }
)

Runtime override: Only do_* flags can be changed at conversion time, and only from TrueFalse. All other options must be identical to those set at pipeline initialization .

# Disable table extraction for a specific conversion without reinitializing
result = converter.convert(
    "document.pdf",
    format_options={
        InputFormat.PDF: PdfFormatOption(
            pipeline_options=PdfPipelineOptions(do_table_structure=False)
        )
    }
)

OCR Configuration#

from docling.datamodel.pipeline_options import (
    PdfPipelineOptions,
    EasyOcrOptions,
    TesseractCliOcrOptions,
    TesseractOcrOptions,
    RapidOcrOptions,
    OcrMacOptions,
    OcrAutoOptions, # default: probes runtime for best engine
)

# EasyOCR — GPU-accelerated, 80+ languages (cite:page:41b5077b)
opts = PdfPipelineOptions()
opts.do_ocr = True
opts.ocr_options = EasyOcrOptions(
    lang=["en", "de", "fr"],
    use_gpu=True, # None = auto-detect
    confidence_threshold=0.5,
)

# Tesseract CLI
opts.ocr_options = TesseractCliOcrOptions(
    lang=["eng", "deu"], # ISO 639-2 codes
)

# RapidOCR (lightweight, ONNX-based)
opts.ocr_options = RapidOcrOptions(
    backend="onnxruntime", # onnxruntime | openvino | paddle | torch
)

# macOS Vision framework (Apple Silicon)
opts.ocr_options = OcrMacOptions(
    lang=["en-US", "de-DE"],
    recognition="accurate", # accurate | fast
)

# Force full-page OCR (ignores existing text layer)
opts.ocr_options = EasyOcrOptions(force_full_page_ocr=True)

Table Structure Configuration#

from docling.datamodel.pipeline_options import (
    PdfPipelineOptions,
    TableStructureOptions, # TableFormer V1
    TableStructureV2Options, # TableFormer V2
    GraniteVisionTableStructureOptions, # Granite Vision VLM (requires [vlm])
    TableFormerMode,
)

opts = PdfPipelineOptions()
opts.do_table_structure = True

# TableFormer V1 (default) — object-detection-based (cite:page:691dc513)
opts.table_structure_options = TableStructureOptions(
    do_cell_matching=True, # Match predictions to PDF text cells
    mode=TableFormerMode.ACCURATE, # ACCURATE | FAST
)

# TableFormer V2 — improved transformer-based model
opts.table_structure_options = TableStructureV2Options(
    do_cell_matching=True,
)

# Granite Vision — VLM-based, OTSL output (requires pip install docling[vlm])
opts.table_structure_options = GraniteVisionTableStructureOptions()

VLM Pipeline#

For holistic VLM-based document understanding (e.g., SmolDocling-style), use VlmPipelineOptions via the --pipeline vlm CLI flag or the vlm_pipeline_preset option :

from docling.datamodel.pipeline_options import (
    PdfPipelineOptions,
    CodeFormulaVlmOptions,
)
from docling.datamodel.vlm_engine_options import (
    TransformersVlmEngineOptions,
    MlxVlmEngineOptions, # Apple Silicon only
    VllmVlmEngineOptions, # vLLM server
    ApiVlmEngineOptions, # OpenAI-compatible API
)

# Code/formula enrichment with default preset (codeformulav2)
opts = PdfPipelineOptions(
    do_code_enrichment=True,
    do_formula_enrichment=True,
)

# Code/formula with Granite-Docling-258M preset
code_formula_opts = CodeFormulaVlmOptions.from_preset("granite_docling")
opts = PdfPipelineOptions(
    do_code_enrichment=True,
    do_formula_enrichment=True,
    code_formula_options=code_formula_opts,
)

# Code/formula with explicit MLX engine (Apple Silicon)
code_formula_opts = CodeFormulaVlmOptions.from_preset(
    "codeformulav2",
    engine_options=MlxVlmEngineOptions(),
)

# Using an OpenAI-compatible API endpoint
code_formula_opts = CodeFormulaVlmOptions.from_preset(
    "codeformulav2",
    engine_options=ApiVlmEngineOptions(
        url="http://localhost:11434", # e.g., Ollama
    ),
)

Format-Specific Backend Options#

from docling.document_converter import DocumentConverter, ExcelFormatOption, HTMLFormatOption
from docling.datamodel.backend_options import MsExcelBackendOptions, HTMLBackendOptions
from docling.datamodel.base_models import InputFormat

# XLSX — filter to specific sheets, parse charts (cite:page:3b5aff37)
converter = DocumentConverter(
    format_options={
        InputFormat.XLSX: ExcelFormatOption(
            backend_options=MsExcelBackendOptions(
                sheet_names=["Summary", "Q4"], # Only these sheets
                parse_charts=True,
                treat_singleton_as_text=True,
            )
        )
    }
)

# HTML — headless browser rendering for JavaScript-heavy pages
# (requires pip install docling[htmlrender])
converter = DocumentConverter(
    format_options={
        InputFormat.HTML: HTMLFormatOption(
            backend_options=HTMLBackendOptions(
                render_page=True, # Use headless browser
                fetch_images=True, # Fetch referenced images
            )
        )
    }
)

Progress Callbacks#

from docling.datamodel.progress_event import ProgressEvent
from docling.document_converter import DocumentConverter

def on_progress(event: ProgressEvent):
    print(f"{event.event_type}: {event.document_name}")

converter = DocumentConverter(progress_callback=on_progress)
result = converter.convert("document.pdf")

6. DoclingDocument API#

Building Documents Programmatically#

DoclingDocument supports a set of add_* builder methods for constructing documents from scratch . All methods append to the appropriate flat list, assign a JSON Pointer self_ref, and wire up parent–child links automatically.

from docling_core.types import DoclingDocument
from docling_core.types.doc import DocItemLabel
from docling_core.types.doc.document import (
    TableData, TableCell, ImageRef, ProvenanceItem,
)
from docling_core.types.doc.base import BoundingBox, CoordOrigin, Size

# Initialize an empty document
doc = DoclingDocument(name="My Document")

# Add page metadata
doc.add_page(page_no=1, size=Size(width=595.0, height=842.0))

# --- Text content ---

# Document title (stored in doc.texts)
doc.add_title(text="Quarterly Report 2024")

# Section headers (level 1–100)
sec = doc.add_heading(text="Introduction", level=1)

# Paragraph text
doc.add_text(label=DocItemLabel.PARAGRAPH, text="This report covers Q4 results.", parent=sec)

# Code block
doc.add_code(text='print("hello")', code_language="python")

# Mathematical formula (LaTeX)
doc.add_formula(text=r"\int_0^\infty e^{-x} dx = 1")

# List
list_grp = doc.add_list_group(parent=sec)
doc.add_list_item(text="Item one", enumerated=False, parent=list_grp)
doc.add_list_item(text="Item two", enumerated=False, parent=list_grp)

# Ordered list
ordered_grp = doc.add_list_group(parent=sec)
doc.add_list_item(text="First step", enumerated=True, marker="1.", parent=ordered_grp)
doc.add_list_item(text="Second step", enumerated=True, marker="2.", parent=ordered_grp)

# --- Tables ---

table_data = TableData(num_rows=2, num_cols=2)
cells = [
    TableCell(text="Name", row_span=1, col_span=1,
              start_row_offset_idx=0, end_row_offset_idx=1,
              start_col_offset_idx=0, end_col_offset_idx=1,
              column_header=True),
    TableCell(text="Value", row_span=1, col_span=1,
              start_row_offset_idx=0, end_row_offset_idx=1,
              start_col_offset_idx=1, end_col_offset_idx=2,
              column_header=True),
    TableCell(text="Revenue",row_span=1, col_span=1,
              start_row_offset_idx=1, end_row_offset_idx=2,
              start_col_offset_idx=0, end_col_offset_idx=1),
    TableCell(text="$1M", row_span=1, col_span=1,
              start_row_offset_idx=1, end_row_offset_idx=2,
              start_col_offset_idx=1, end_col_offset_idx=2),
]
table_data.table_cells = cells
# Add provenance (page + bounding box)
prov = ProvenanceItem(
    page_no=1,
    bbox=BoundingBox(l=50.0, t=200.0, r=400.0, b=300.0, coord_origin=CoordOrigin.BOTTOMLEFT),
    charspan=(0, 0),
)
table_item = doc.add_table(data=table_data, prov=prov)

# --- Export constructed document ---
print(doc.export_to_markdown())
print(doc.export_to_json())

Document-Level Utilities#

# Merge multiple documents (re-numbers pages, re-assigns refs)
merged = DoclingDocument.concatenate([doc1, doc2, doc3])

# Filter to specific pages
page_doc = doc.filter(page_nrs={1, 2})

# Delete items
doc.delete_items(node_items=[some_item])

Iterating Document Elements#

iterate_items() performs a depth-first traversal of the document tree and is the backbone for all export methods :

from docling_core.types.doc import ContentLayer
from docling_core.types.doc.document import (
    TextItem, TableItem, PictureItem, GroupItem, SectionHeaderItem
)

# Basic iteration — yields (NodeItem, nesting_level) tuples
# Default: ContentLayer.BODY only, groups excluded
for item, level in doc.iterate_items():
    if isinstance(item, TextItem):
        print(" " * level + item.text)
    elif isinstance(item, TableItem):
        print(" " * level + f"[TABLE: {item.data.num_rows}×{item.data.num_cols}]")
    elif isinstance(item, PictureItem):
        print(" " * level + "[PICTURE]")

# Include structural group nodes
for item, level in doc.iterate_items(with_groups=True):
    if isinstance(item, GroupItem):
        print(" " * level + f"[GROUP: {item.name}]")

# Include page headers/footers (FURNITURE layer)
for item, level in doc.iterate_items(
    included_content_layers={ContentLayer.BODY, ContentLayer.FURNITURE}
):
    ...

# Scanned PDFs: OCR text is stored as children of PictureItem
for item, level in doc.iterate_items(traverse_pictures=True):
    ...

# Restrict to a single page
for item, level in doc.iterate_items(page_no=3):
    ...

# Traverse a subtree
for item, level in doc.iterate_items(root=some_section_node):
    ...

Accessing Provenance#

Every document item carries a prov list with page and bounding-box information :

from docling_core.types.doc.document import ProvenanceItem

for item, _ in doc.iterate_items():
    for prov in item.prov:
        print(f"Page {prov.page_no}: bbox=({prov.bbox.l}, {prov.bbox.t}, {prov.bbox.r}, {prov.bbox.b})")
        print(f" charspan: {prov.charspan}") # (start, end) character offsets

# Access tables by index
for table in doc.tables:
    print(f"Table on page {table.prov[0].page_no if table.prov else 'unknown'}")
    # Export individual table
    df = table.export_to_dataframe(doc=doc)
    md = table.export_to_markdown(doc=doc)
    html = table.export_to_html(doc=doc)

# Access pictures
for pic in doc.pictures:
    if pic.prov:
        print(f"Picture on page {pic.prov[0].page_no}")
    if pic.meta and pic.meta.classification:
        print(f" Classification: {pic.meta.classification}")
    if pic.meta and pic.meta.description:
        print(f" Description: {pic.meta.description}")

Loading from DocTags Format#

DocTags is the XML-like token format emitted by VLMs (e.g., SmolDocling) :

from docling_core.types.doc.document import DocTagsDocument, DoclingDocument
from PIL import Image

# From per-page (tokens_str, PIL.Image) pairs
doctags_doc = DocTagsDocument.from_doctags_and_image_pairs([
    ("<title>My Doc</title><text>Hello world</text>", pil_image),
])
doc = DoclingDocument.load_from_doctags(doctags_doc, document_name="my_doc")

# Round-trip back to DocTags
doctags_str = doc.export_to_doctags()

7. Chunking for RAG#

Basic Setup#

# Requires: pip install docling-core[chunking]
from docling.chunking import HybridChunker
from docling_core.transforms.chunker.tokenizer.huggingface import HuggingFaceTokenizer
from transformers import AutoTokenizer

EMBED_MODEL = "sentence-transformers/all-MiniLM-L6-v2"

# The chunker tokenizer MUST match the embedding model's tokenizer (cite:page:ff0a9205)
tokenizer = HuggingFaceTokenizer(
    tokenizer=AutoTokenizer.from_pretrained(EMBED_MODEL),
    max_tokens=512, # optional; defaults to model max
)

chunker = HybridChunker(tokenizer=tokenizer)

Warning: HuggingFace Transformers may warn "Token indices sequence length is longer than the specified maximum sequence length" during HybridChunker initialization — this is a false alarm and can be safely ignored .


HybridChunker Constructor Parameters#

ParameterDefaultDescription
tokenizerHuggingFaceTokenizer("all-MiniLM-L6-v2")Controls token-count split boundaries
max_tokensderived from tokenizerHard token cap per chunk
merge_peersTrueMerge undersized sibling chunks
repeat_table_headerTrueRepeat header rows for split table chunks
omit_header_on_overflowFalseDrop header when row + header exceeds budget
serializer_providerChunkingSerializerProvider()Controls table serialization format


Chunking a Document#

from docling.document_converter import DocumentConverter

converter = DocumentConverter()
result = converter.convert("report.pdf")

chunks = list(chunker.chunk(result.document))

for chunk in chunks:
    print(chunk.text) # The chunk's plain text
    print(chunk.meta.headings) # Section headings in scope
    print(chunk.meta.origin) # DocumentOrigin: filename, mimetype, binary_hash

Contextualized Text for Embedding#

The text you embed should be the context-enriched form from chunker.contextualize(), which prepends in-scope section headings to chunk.text :

for chunk in chunker.chunk(doc):
    # Use this string for embedding — includes heading context
    embed_text = chunker.contextualize(chunk)
    # embed_text = "## Section Heading\n\nChunk body text..."

OpenAI Tokenizer#

# Requires: pip install docling-core[chunking-openai]
import tiktoken
from docling_core.transforms.chunker.tokenizer.openai import OpenAITokenizer

tokenizer = OpenAITokenizer(
    tokenizer=tiktoken.encoding_for_model("gpt-4o"),
    max_tokens=128 * 1024,
)

chunker = HybridChunker(tokenizer=tokenizer)

DocChunk Metadata and Provenance#

Every DocChunk carries a DocMeta with three-layer traceability :

DocChunk
  ├── text: str # chunk text content
  └── meta: DocMeta
        ├── doc_items: list[DocItem] # source nodes this chunk covers
        │ └── .prov: list[ProvenanceItem]
        │ ├── page_no: int # 1-indexed page
        │ ├── bbox: BoundingBox # l/t/r/b coordinates
        │ └── charspan: (int, int) # character offsets
        ├── headings: list[str] # section headings in scope
        └── origin: DocumentOrigin # filename, mimetype, binary_hash
for chunk in chunks:
    # Inspect provenance
    for item in chunk.meta.doc_items:
        for prov in item.prov:
            print(f" Page {prov.page_no}, bbox: {prov.bbox}")

    # Source file
    if chunk.meta.origin:
        print(f" File: {chunk.meta.origin.filename}")

Table Serialization Strategies#

The default TripletTableSerializer emits flat "**Column**, row = value" strings that lose cell-to-header bindings. For table-heavy documents, switch to MarkdownTableSerializer :

from docling_core.transforms.chunker.hierarchical_chunker import (
    ChunkingDocSerializer,
    ChunkingSerializerProvider,
)
from docling_core.transforms.serializer.markdown import MarkdownParams, MarkdownTableSerializer

class MDTableSerializerProvider(ChunkingSerializerProvider):
    def get_serializer(self, doc):
        return ChunkingDocSerializer(
            doc=doc,
            table_serializer=MarkdownTableSerializer(),
            params=MarkdownParams(compact_tables=True),
        )

chunker = HybridChunker(
    tokenizer=tokenizer,
    repeat_table_header=True, # Each chunk re-includes column headers
    serializer_provider=MDTableSerializerProvider(),
)

Why this matters: For RAG pipelines where 50%+ of chunks are tables, the serialization format is the dominant factor in embedding quality. The triplet format loses the column-to-value relationship; Markdown format preserves it .


End-to-End RAG Example#

from docling.document_converter import DocumentConverter
from docling.chunking import HybridChunker
from docling_core.transforms.chunker.tokenizer.huggingface import HuggingFaceTokenizer
from transformers import AutoTokenizer

EMBED_MODEL = "sentence-transformers/all-MiniLM-L6-v2"

# Step 1: Convert document
converter = DocumentConverter()
result = converter.convert("https://arxiv.org/pdf/2408.09869")
doc = result.document

# Step 2: Configure chunker with matching tokenizer
tokenizer = HuggingFaceTokenizer(
    tokenizer=AutoTokenizer.from_pretrained(EMBED_MODEL)
)
chunker = HybridChunker(tokenizer=tokenizer)

# Step 3: Chunk the document
chunks = list(chunker.chunk(doc))

# Step 4: Prepare embedding-ready texts with context
texts_to_embed = [chunker.contextualize(chunk) for chunk in chunks]

# Step 5: Build metadata for vector store
metadatas = []
for chunk in chunks:
    meta = {
        "headings": chunk.meta.headings,
        "filename": chunk.meta.origin.filename if chunk.meta.origin else None,
        "page_no": chunk.meta.doc_items[0].prov[0].page_no
                   if chunk.meta.doc_items and chunk.meta.doc_items[0].prov else None,
    }
    metadatas.append(meta)

# texts_to_embed and metadatas are now ready for any vector store
# e.g., for FAISS, Chroma, Milvus, Pinecone, etc.

8. Enrichments#

All enrichment models are disabled by default because they require additional model inference. Enable them individually in PdfPipelineOptions .

Note on do_ocr and do_table_structure: These two are enabled by default (True). All other enrichments (code, formula, picture classification/description, chart extraction) are disabled by default.

OCR#

from docling.datamodel.pipeline_options import PdfPipelineOptions, EasyOcrOptions

opts = PdfPipelineOptions(
    do_ocr=True, # Enable OCR for bitmap regions (default: True)
    ocr_options=EasyOcrOptions(
        force_full_page_ocr=False, # If True: OCR entire page, ignoring text layer
        lang=["en"],
    ),
)

Table Structure Extraction#

from docling.datamodel.pipeline_options import (
    PdfPipelineOptions, TableStructureV2Options
)

opts = PdfPipelineOptions(
    do_table_structure=True, # Extract structured cell grids (default: True)
    table_structure_options=TableStructureV2Options(
        do_cell_matching=True, # Match to PDF text cells
    ),
)

Code Enrichment#

Sets CodeItem.code_language (e.g., "python", "javascript") using the CodeFormulaVlmModel :

from docling.datamodel.pipeline_options import PdfPipelineOptions

opts = PdfPipelineOptions(
    do_code_enrichment=True, # VLM detects programming language
                               # Requires pip install docling[vlm]
)

Formula Enrichment#

Extracts LaTeX text from FORMULA-labeled TextItem elements :

opts = PdfPipelineOptions(
    do_formula_enrichment=True, # VLM produces LaTeX string
                                  # Requires pip install docling[vlm]
)

# After conversion, formulas are in TextItem elements:
for item, _ in doc.iterate_items():
    from docling_core.types.doc.document import TextItem
    from docling_core.types.doc import DocItemLabel
    if isinstance(item, TextItem) and item.label == DocItemLabel.FORMULA:
        print(item.text) # LaTeX string, e.g. "\int_0^\infty e^{-x} dx"

Picture Classification#

Classifies images by type: bar chart, pie chart, line chart, photograph, logo, diagram, chemistry structure, barcode, etc. :

from docling.datamodel.pipeline_options import PdfPipelineOptions, ConvertPipelineOptions

# do_picture_classification is on ConvertPipelineOptions (parent of PdfPipelineOptions)
opts = PdfPipelineOptions(
    do_picture_classification=True,
)

# After conversion, classification is in PictureItem.meta:
for pic in doc.pictures:
    if pic.meta and pic.meta.classification:
        for pred in pic.meta.classification:
            print(f" {pred.predicted_classes}") # list of (class, confidence)

Picture Description#

VLM-based image captioning stored in PictureItem.meta.description :

opts = PdfPipelineOptions(
    do_picture_classification=True, # Classification enables filtering
    do_picture_description=True,
    # Optional: only describe specific picture types
    picture_description_options=None, # use preset default
)

# After conversion:
for pic in doc.pictures:
    if pic.meta and pic.meta.description:
        print(pic.meta.description)

Chart Extraction#

Extracts chart data (bar, pie, line) into tabular format :

from docling.datamodel.pipeline_options import (
    PdfPipelineOptions, ChartExtractionModelKind
)

opts = PdfPipelineOptions(
    do_picture_classification=True,
    chart_extraction_model=ChartExtractionModelKind.GRANITE_VISION,
    # or: ChartExtractionModelKind.GRANITE_VISION_V4 (runs chart2csv, chart2code, chart2summary)
)

Combined Enrichment Example#

from docling.document_converter import DocumentConverter, PdfFormatOption
from docling.datamodel.base_models import InputFormat
from docling.datamodel.pipeline_options import (
    PdfPipelineOptions,
    EasyOcrOptions,
    TableStructureV2Options,
    ChartExtractionModelKind,
)

opts = PdfPipelineOptions(
    do_ocr=True,
    ocr_options=EasyOcrOptions(lang=["en"]),
    do_table_structure=True,
    table_structure_options=TableStructureV2Options(),
    do_code_enrichment=True,
    do_formula_enrichment=True,
    do_picture_classification=True,
    chart_extraction_model=ChartExtractionModelKind.GRANITE_VISION,
    generate_picture_images=True, # Store picture images in DoclingDocument
)

converter = DocumentConverter(
    format_options={InputFormat.PDF: PdfFormatOption(pipeline_options=opts)}
)
result = converter.convert("document.pdf")

Debug Visualization#

from docling.datamodel.settings import settings, DebugSettings, scoped

# Global debug output
settings.debug = DebugSettings(
    visualize_ocr=True,
    visualize_layout=True,
    visualize_tables=True,
    debug_output_path="/tmp/docling_debug",
)

# Scoped debug (restores settings after block)
with scoped(debug=DebugSettings(visualize_layout=True)):
    result = converter.convert("document.pdf")

9. Common Integration Patterns#

LangChain#

Install: pip install langchain-docling

from langchain_docling import DoclingLoader
from langchain_docling.loader import ExportType
from docling.chunking import HybridChunker
from docling_core.transforms.chunker.tokenizer.huggingface import HuggingFaceTokenizer
from transformers import AutoTokenizer

EMBED_MODEL = "sentence-transformers/all-MiniLM-L6-v2"

# Option A: DOC_CHUNKS — one LangChain Document per Docling chunk (recommended)
# Preserves document-native provenance (cite:page:ff0a9205)
loader = DoclingLoader(
    file_path=["https://arxiv.org/pdf/2408.09869"],
    export_type=ExportType.DOC_CHUNKS,
    chunker=HybridChunker(
        tokenizer=HuggingFaceTokenizer(
            tokenizer=AutoTokenizer.from_pretrained(EMBED_MODEL)
        )
    ),
)
splits = loader.load()
# Each split has split.metadata["dl_meta"] with DocMeta provenance

# Option B: MARKDOWN — one LangChain Document per file, then split externally
loader = DoclingLoader(
    file_path=["document.pdf"],
    export_type=ExportType.MARKDOWN,
)
docs = loader.load()
# Then use MarkdownHeaderTextSplitter or similar

# Ingest into a vector store
from langchain_community.vectorstores import FAISS
from langchain_huggingface import HuggingFaceEmbeddings

embeddings = HuggingFaceEmbeddings(model_name=EMBED_MODEL)
vector_store = FAISS.from_documents(splits, embeddings)

# Query
retriever = vector_store.as_retriever()
results = retriever.invoke("What are the key findings?")

LlamaIndex#

Install: pip install llama-index-readers-docling llama-index-node-parser-docling

The LlamaIndex integration provides two components :

  1. DoclingReader — converts documents and populates LlamaIndex Document objects
  2. DoclingNodeParser — parses Docling-format Document objects into Node objects for chunking/embedding
# Option A: Markdown export (simple, lossy)
from llama_index.readers.docling import DoclingReader

reader = DoclingReader()
documents = reader.load_data(
    file_path=["report.pdf", "https://arxiv.org/pdf/2408.09869"]
)
# Each document.text contains Markdown representation

# Option B: JSON export + DoclingNodeParser (lossless, preserves rich metadata)
from llama_index.readers.docling import DoclingReader
from llama_index.node_parser.docling import DoclingNodeParser

reader = DoclingReader(export_type=DoclingReader.ExportType.JSON)
node_parser = DoclingNodeParser()

documents = reader.load_data(file_path=["report.pdf"])
nodes = node_parser.get_nodes_from_documents(documents)
# Each node carries Docling metadata: page_no, bbox, headings, etc.

# Use with LlamaIndex pipeline
from llama_index.core import VectorStoreIndex
from llama_index.embeddings.huggingface import HuggingFaceEmbedding

embed_model = HuggingFaceEmbedding(model_name="sentence-transformers/all-MiniLM-L6-v2")
index = VectorStoreIndex(nodes, embed_model=embed_model)
query_engine = index.as_query_engine()
response = query_engine.query("Summarize the key findings.")

Direct Vector Store Integration (Without Framework)#

from docling.document_converter import DocumentConverter
from docling.chunking import HybridChunker
from docling_core.transforms.chunker.tokenizer.huggingface import HuggingFaceTokenizer
from transformers import AutoTokenizer
from sentence_transformers import SentenceTransformer

EMBED_MODEL = "sentence-transformers/all-MiniLM-L6-v2"

# Convert + chunk
converter = DocumentConverter()
chunker = HybridChunker(
    tokenizer=HuggingFaceTokenizer(
        tokenizer=AutoTokenizer.from_pretrained(EMBED_MODEL)
    )
)

doc = converter.convert("report.pdf").document
chunks = list(chunker.chunk(doc))

# Embed
embed_model = SentenceTransformer(EMBED_MODEL)
texts = [chunker.contextualize(c) for c in chunks]
embeddings = embed_model.encode(texts, normalize_embeddings=True)

# Store embeddings + metadata in your vector DB of choice
for chunk, embedding in zip(chunks, embeddings):
    metadata = {
        "text": chunk.text,
        "headings": chunk.meta.headings,
        "filename": chunk.meta.origin.filename if chunk.meta.origin else None,
        "page_no": chunk.meta.doc_items[0].prov[0].page_no
                   if chunk.meta.doc_items and chunk.meta.doc_items[0].prov else None,
    }
    # insert (embedding, metadata) into your vector store

10. Key Imports#

Quick-reference imports organized by use case. Copy the block(s) you need.

Core Conversion#

from docling.document_converter import (
    DocumentConverter,
    PdfFormatOption,
    ImageFormatOption,
    WordFormatOption,
    PowerpointFormatOption,
    ExcelFormatOption,
    HTMLFormatOption,
    MarkdownFormatOption,
    AudioFormatOption,
    LatexFormatOption,
    EpubFormatOption,
)
from docling.datamodel.base_models import InputFormat, OutputFormat

Pipeline Configuration#

from docling.datamodel.pipeline_options import (
    PdfPipelineOptions,
    PipelineOptions,
    # OCR engines
    EasyOcrOptions,
    TesseractCliOcrOptions,
    TesseractOcrOptions,
    RapidOcrOptions,
    OcrMacOptions,
    OcrAutoOptions,
    NemotronOcrOptions,
    # Table structure
    TableStructureOptions, # V1
    TableStructureV2Options, # V2
    GraniteVisionTableStructureOptions, # Granite Vision (requires [vlm])
    TableFormerMode,
    # VLM / enrichment
    CodeFormulaVlmOptions,
    ChartExtractionModelKind,
)
from docling.datamodel.vlm_engine_options import (
    TransformersVlmEngineOptions,
    MlxVlmEngineOptions,
    VllmVlmEngineOptions,
    ApiVlmEngineOptions,
)
from docling.datamodel.backend_options import (
    MsExcelBackendOptions,
    HTMLBackendOptions,
    LatexBackendOptions,
    EpubBackendOptions,
    MarkdownBackendOptions,
)

Document Model#

from docling_core.types import DoclingDocument
from docling_core.types.doc import (
    DocItemLabel,
    ContentLayer,
    ImageRefMode,
)
from docling_core.types.doc.document import (
    TextItem,
    TableItem,
    TableData,
    TableCell,
    PictureItem,
    SectionHeaderItem,
    GroupItem,
    ListItem,
    CodeItem,
    FormulaItem,
    ProvenanceItem,
    DocumentOrigin,
    ImageRef,
)
from docling_core.types.doc.base import BoundingBox, CoordOrigin, Size

Chunking#

from docling.chunking import HybridChunker
# or equivalently:
from docling_core.transforms.chunker.hybrid_chunker import HybridChunker

from docling_core.transforms.chunker.tokenizer.huggingface import HuggingFaceTokenizer
from docling_core.transforms.chunker.tokenizer.openai import OpenAITokenizer # requires [chunking-openai]
from docling_core.transforms.chunker.doc_chunk import DocChunk, DocMeta

# Table serialization for chunking
from docling_core.transforms.chunker.hierarchical_chunker import (
    ChunkingDocSerializer,
    ChunkingSerializerProvider,
)
from docling_core.transforms.serializer.markdown import MarkdownParams, MarkdownTableSerializer

Settings and Debug#

from docling.datamodel.settings import settings, DebugSettings, scoped
from docling.datamodel.progress_event import ProgressEvent

LangChain Integration#

from langchain_docling import DoclingLoader
from langchain_docling.loader import ExportType

LlamaIndex Integration#

from llama_index.readers.docling import DoclingReader
from llama_index.node_parser.docling import DoclingNodeParser