Heading Hierarchy Configuration#
Overview#
By default, Docling's PDF layout model flags regions as SECTION_HEADER without assigning a level, leaving every heading at level=1 (a flat hierarchy). HeadingHierarchyOptions enables the HeadingHierarchyModel to run after the reading-order stage and infer proper SectionHeaderItem.level values from three signals in order of precedence:
- PDF bookmarks — the document's own outline/ToC, most authoritative
- Numbering patterns — outline numbering like
PART I → 1. → 1.1 → (a) → (i) - Font style — font size approximated from parsed PDF cell heights, as a last resort
The feature is disabled by default (enabled=False).
Configuration: HeadingHierarchyOptions#
Defined in pipeline_options.py and nested under PdfPipelineOptions.heading_hierarchy_options.
| Field | Default | Description |
|---|---|---|
enabled | False | Master switch — must be True to run inference |
use_bookmarks | True | Use PDF outline as authoritative heading signal |
use_numbering | True | Infer levels from legal/outline numbering schemes |
use_style | True | Infer levels from font size (requires generate_parsed_pages=True) |
numbering_schemes | None | Override scheme precedence order (see below) |
max_level | 6 | Levels deeper than this are clamped |
bookmark_match_threshold | 0.8 | Minimum fuzzy-title similarity for a bookmark to be authoritative |
Important: use_style requires PdfPipelineOptions.generate_parsed_pages=True. Without it, style inference is silently skipped but numbering still applies.
Inference Signals in Detail#
1. Bookmarks (_infer_from_bookmarks)#
Reads ConversionResult._pdf_outline (populated before pipeline stages start) and fuzzily matches each bookmark to detected headings or list-items by title (via SequenceMatcher) and page number.
Key behaviors:
- Both the heading text and a marker-stripped version are compared, so
"1.1 Definitions"matches a bookmark titled"Definitions". - A bookmark-matched list-item is promoted to a
SectionHeaderItemin place — fixing common layout-model misclassifications. - Unmatched bookmarks fall back to numbering/style; partial outlines don't degrade other inference.
- Raw bookmark depths are compressed into contiguous 1-based levels.
2. Numbering (_infer_from_numbering)#
Parses each heading's leading marker with _parse_marker and assigns levels based on scheme family rank and dotted-decimal depth.
Default scheme order (highest → lowest):
part > chapter > article > roman_u > arabic (+ dotted by depth) > alpha_u > alpha_l > roman_l
Supported marker families:
part—PART I,TITLE I,BOOK Ichapter—CHAPTER 1article—ARTICLE 1,SECTION 2,Clause,§ 1.2roman_u/roman_l—I.,(ii)arabic/dotted—1.,1.2,1.2.3alpha_u/alpha_l—A.,(a)
Single-letter ambiguous markers (e.g., I.) are resolved by scanning other markers in the document for context.
Override the scheme order via numbering_schemes:
HeadingHierarchyOptions(numbering_schemes=["arabic", "roman_u"])
# Arabic now outranks Roman
3. Style (_infer_from_style)#
Uses the median height of parsed PDF textline_cells overlapping the heading's bounding box as a font-size proxy. Sizes are rounded and bucketed; larger size → lower level number (higher in hierarchy). Only applies to headings that have no bookmark or numbering match.
Integration in the PDF Pipeline#
HeadingHierarchyModel is constructed with the options and called after ReadingOrderModel during _assemble_document. The __call__ method pulls _pdf_outline from the ConversionResult and collected parsed pages, delegates to assign_heading_levels, then clears the transient outline.
assign_heading_levels also accepts a bare DoclingDocument without a pipeline, making it reusable in tests and offline tooling.
Quick Start#
from docling.datamodel.pipeline_options import PdfPipelineOptions, HeadingHierarchyOptions
options = PdfPipelineOptions(
heading_hierarchy_options=HeadingHierarchyOptions(
enabled=True,
use_bookmarks=True,
use_numbering=True,
use_style=True,
max_level=4,
),
generate_parsed_pages=True, # required for use_style
)
Source References#
| File | Purpose |
|---|---|
docling/datamodel/pipeline_options.py | HeadingHierarchyOptions definition |
docling/models/stages/heading_hierarchy/heading_hierarchy_model.py | Full model + inference functions |
tests/test_heading_hierarchy.py | Behavioral tests covering all three inference paths |