Chunking Modes
Seven document modes plus dedicated spreadsheet modes — what each one emits, which parameter it reads, and how to pick.
The mode argument controls how a document is segmented. Document formats
support seven modes; spreadsheet and delimited formats have their own set.
Document modes
| Mode | What it does |
|---|---|
default | Each format's natural element-level strategy (DOCX normalizes to structural). |
structural | One chunk per paragraph / heading / table / list. |
section | Content under a heading grouped into one chunk. |
semantic | Adjacent blocks merged while an eleven-signal ladder says they're the same idea. |
sliding_window | Overlapping windows for dense retrieval. |
sentence | A fixed number of sentences per chunk. |
page_aware | Chunks aligned to the document's pages or slides. |
Applies to DOCX (+ DOCM/DOTX/DOTM), DOC, PDF, PPTX (+ POTX/POTM/PPSX/PPSM), PPT, Markdown, HTML, TXT, MSG, EML/MBOX, ODT/ODP, JSON/JSONL/NDJSON, RTF, EPUB, and IPYNB.
A mode never gives you only its own content_type
mode="section" does not mean every chunk is content_type: "section". Most
formats keep headings, tables and code blocks as their own typed chunks
alongside the mode's chunks, and the exact set differs per format. Each mode
page below states the set it really emits — read it before you write
if chunk.content_type == mode.
Pick your mode
| I want to… | Best mode |
|---|---|
| Index every paragraph and heading individually | default / structural |
| Keep the body under a heading in one chunk | section |
| Feed coherent passages to an LLM or embedding model | semantic |
| Enforce a fixed sentence count per chunk | sentence |
| Build overlapping chunks for dense retrieval | sliding_window |
| Cite a real page or slide number | page_aware (on a format that has pages — see the table) |
Default recommendation
Start with semantic when feeding an LLM and section when building a
document search index. Use default/structural when you need
fine-grained, element-level control.
Mode parameters
These are the four knobs the source-agnostic entry points (get_chunks /
getChunks / chunks_rs::get_chunks) accept.
| Parameter | Default | Read by |
|---|---|---|
window_size | 3 | sliding_window (must be > 0) |
overlap | 1 | sliding_window (must be < window_size) |
sentences_per_chunk | 3 | sentence — and spreadsheets/CSV in row mode, see below |
paragraphs_per_page | 15 | page_aware — units per page for formats with no page breaks; slides per chunk for PPTX; rows per chunk for CSV/TSV |
Spreadsheet & delimited modes
Spreadsheets (XLSX / XLS / XLSM / XLSB / ODS / XLTX / XLTM) support six modes;
CSV / TSV support three (plus default, an alias for row). Passing an
unsupported mode raises immediately, and the engine names the set it accepts:
mode must be one of ['default', 'page_aware', 'row', 'semantic', 'sheet', 'sliding_window', 'table'] for XLSX, got: 'nope'
mode must be one of ['default', 'page_aware', 'row', 'sliding_window'] for CSV, got: 'nope'| Mode | Spreadsheets | CSV / TSV | content_type emitted |
|---|---|---|---|
row (= default) | yes | yes | row_document (spreadsheet) / row_group (CSV) |
table | yes | — | table_region |
sheet | yes | — | sheet |
sliding_window | yes | yes | row_window |
page_aware | yes | yes | sheet_region (spreadsheet) / row_group (CSV) |
semantic | yes | — | semantic_group |
table is not XLSX-only: it works for every extension in the spreadsheet
family — .xlsx, .xls, .xlsm, .xlsb, .ods, .xltx, .xltm — all
routed through the same calamine-backed chunker.
Rows per chunk through the unified entry point
There is no rows_per_chunk argument on get_chunks. The row count is derived
from the two document parameters, and the derivation is not the same for
spreadsheets and CSV:
| Format | row mode rows per chunk | page_aware rows per chunk |
|---|---|---|
| CSV / TSV | max(sentences_per_chunk, 1) → 3 at defaults | paragraphs_per_page → 15 at defaults |
| XLSX family | sentences_per_chunk, except 3 → 1 (see below) → 1 at defaults | whole-sheet regions capped at 2,000 chars |
`sentences_per_chunk == 3` is a sentinel for spreadsheets
For the spreadsheet extensions the value 3 — the API's own default — is
read as "the caller did not ask" and mapped to rows_per_chunk = 1. Every
other value passes through unchanged. The consequence: a deliberate
sentences_per_chunk=3 is unreachable through get_chunks for a
spreadsheet. You will get 1 row per chunk, not 3. If you genuinely want 3
rows per chunk, call the format-specific chunker (chunk_xlsx in Python,
chunks_rs::formats::xlsx::chunk_with_options in Rust) and set
rows_per_chunk directly.
CSV has no sentinel: sentences_per_chunk=3 really does mean 3 rows there.
Where the “10” comes from
You may have seen rows_per_chunk = 10 documented as the CSV default. That is
the default of the format-specific chunk_csv() helper (and of
ChunkOptions::default() in Rust) — it is not what the unified entry point
uses. Through get_chunks / getChunks, CSV rows-per-chunk defaults to
3.
Other spreadsheet & delimited parameters
Reachable only through the format-specific chunkers, not get_chunks:
| Parameter | Default | Notes |
|---|---|---|
rows_per_chunk | 10 (chunk_csv / ChunkOptions) | Rows per row chunk. |
max_chunk_chars | 2000 | Cap for table / sheet / page_aware chunks (spreadsheets). |
include_headers | true | Repeat the header row in each chunk. |
sheet_names | all | Restrict to specific worksheets. |
skip_empty_rows | true | Drop blank rows. |
serialize_as | key_value | How a row is rendered (spreadsheets). |
delimiter | auto-detected | , \t ; | (CSV/TSV). |
encoding | auto | auto / utf-8 / utf-8-bom / latin-1 / windows-1252 (CSV). auto tries UTF-8 strictly, then detects exactly as the .txt path does: BOMs, BOM-less UTF-16 from the NUL pattern, then a statistical charset detector for 8-bit encodings (so a windows-1251 or Big5 file decodes as itself, not as Windows-1252) — so a latin-1 CSV reads like a latin-1 .txt instead of raising. Naming an encoding explicitly still forces it. HTML needs no parameter: it reads its own <meta charset> (see Error Handling). |
See the API Reference for the full signatures, and Metadata Reference for the keys each mode writes.