Table Structure Recognition#
Table structure recognition is the pipeline stage that takes a cropped table image (identified by the layout model) and produces a structured grid of typed cells with optional bounding-box provenance. Docling supports three pluggable backends, all sharing a common BaseTableStructureModel interface and a common OTSL intermediate representation.
Model Backends#
The backend is selected by setting pipeline_options.table_structure_options to the corresponding options class . All three are enabled via PdfPipelineOptions(do_table_structure=True) .
| Backend | Options class | kind discriminator | Install |
|---|---|---|---|
| TableFormer V1 | TableStructureOptions | docling_tableformer | default |
| TableFormer V2 | TableStructureV2Options | docling_tableformer_v2 | default |
| Granite Vision | GraniteVisionTableStructureOptions | granite_vision_table | pip install docling[vlm] |
TableFormer V1 — table_structure_model.py
Object-detection-based model from the docling-project/docling-models artifact repo (model_artifacts/tableformer). Controlled by :
do_cell_matching: bool = True— match predictions back to PDF text cells.mode: TableFormerMode—ACCURATE(default) orFAST.
Download: docling models download --model tableformer .
TableFormer V2 — table_structure_model_v2.py
Improved transformer-based model. Uses OTSL token sequences decoded with _decode_otsl_sequence(). Cell matching uses an intersection_over_self > 0.3 threshold to bind PDF text cells to predicted cell bounding boxes . Key option :
do_cell_matching: bool = True— note that setting thisTruecan break output when PDF cells span multiple table columns.
Download: docling models download --model tableformerv2 .
Granite Vision — table_structure_model_granite_vision.py
VLM-based backend using ibm-granite/granite-vision-4.1-4b . Sends a cropped table image to the model with the prompt <tables_otsl> and parses the OTSL string output . No separate cell-matching step — cell text comes directly from model output; bbox is always None on cells produced this way . Requires CUDA for practical performance; uses bfloat16 + optional flash_attention_2 .
OTSL: Open Table Structure Language#
OTSL is the shared intermediate representation for all three backends. It encodes table structure as a 2-D grid of typed tokens terminated by row separators :
| Token | Meaning |
|---|---|
ched | Column header cell |
rhed | Row header cell |
srow | Section row |
fcel | Full (content-bearing) cell |
ecel | Empty cell |
lcel | Left span extension (colspan) |
ucel | Up span extension (rowspan) |
xcel | Cross span extension (colspan + rowspan) |
nl | Row terminator |
Example sequence: <ched>Name<ched>Val<nl><fcel>Foo<fcel>42<nl> .
The OTSL parser handles three serialisation styles — closed <tag>text</tag>, open <tag>text<next> (ibm-granite output), and self-closing <tag/> — and optionally strips an outer <otsl>…</otsl> wrapper . The parsed output is a flat list[TableCell] plus num_rows/num_cols counts stored in Table.otsl_seq .
TableItem.export_to_otsl() in docling-core can re-serialize any parsed table back to OTSL, with an optional add_cell_location=True flag to embed bounding-box coordinates inline .
Cell Data Model#
Each cell is a TableCell with:
text— plain-text contentbbox— optional page-level bounding box (absent for Granite Vision output)row_span/col_spanandstart_/end_row/col_offset_idx— grid span indicescolumn_header,row_header,row_section— semantic role flags
RichTableCell extends this with a ref: RefItem pointer to a nested DocItem (e.g., an image or formatted text block). The 2-D grid is reconstructed by TableData.grid as a computed field .
Configuration Reference#
from docling.datamodel.pipeline_options import (
PdfPipelineOptions,
TableStructureOptions, # V1
TableStructureV2Options, # V2
GraniteVisionTableStructureOptions, # Granite Vision
TableFormerMode,
)
opts = PdfPipelineOptions()
opts.do_table_structure = True
# V1 — accurate mode
opts.table_structure_options = TableStructureOptions(
do_cell_matching=True,
mode=TableFormerMode.ACCURATE,
)
# V2
opts.table_structure_options = TableStructureV2Options(do_cell_matching=True)
# Granite Vision (requires pip install docling[vlm])
opts.table_structure_options = GraniteVisionTableStructureOptions()
Key Source Files#
| File | Purpose |
|---|---|
docling/models/stages/table_structure/table_structure_model.py | TableFormer V1 implementation |
docling/models/stages/table_structure/table_structure_model_v2.py | TableFormer V2 implementation |
docling/models/stages/table_structure/table_structure_model_granite_vision.py | Granite Vision VLM implementation + OTSL parser |
docling/models/base_table_model.py | BaseTableStructureModel abstract interface |
docling/datamodel/pipeline_options.py | All options classes and TableFormerMode enum |
docling_core/types/doc/document.py | TableCell, RichTableCell, TableData, TableItem.export_to_otsl() |