Doclingdocling 2.127.0 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
26 small wins to finish your pathNext lesson

Chunks that fit

Lesson 22's chunks are whatever size the document made them. An embedding model has a hard limit, and a chunk over it is silently truncated.

HybridChunker starts from the hierarchical chunks and does two more passes: it splits anything too long, then merges neighbours that are too short and share the same headings.

Example
from docling.chunking import HybridChunker
from docling.document_converter import DocumentConverter

document = DocumentConverter().convert("shipping.md").document
chunker = HybridChunker(max_tokens=20)
for chunk in chunker.chunk(document):
    print(repr(chunker.contextualize(chunk))[:70])

Three chunks where lesson 22 gave two. The list of bullets was over twenty tokens once its headings were counted, so it was split, and each half kept the headings.

Counting the tokens

Example
for chunk in chunker.chunk(document):
    text = chunker.contextualize(chunk)
    print(chunker.tokenizer.count_tokens(text), "tokens")

All three are inside the limit, and the count includes the headings because those are part of what gets embedded. Tokens are not words: a token is a piece of a word, and the tokenizer decides where the pieces are.

Whose tokenizer

Example
print(type(chunker.tokenizer).__name__)
print(HybridChunker().tokenizer.get_max_tokens())

With no arguments the chunker uses a Hugging Face tokenizer with a limit of 256, matching a common small embedding model. Downloading that tokenizer is the one thing in this part that touches the network, and it happens once. Pass your own so the count matches the model you are really going to embed with; a limit that does not match is how text goes missing without an error.

The merging pass

Two short paragraphs under the same heading come back as one chunk, because two tiny chunks make two weak search results where one would be strong. Pass merge_peers=False to keep them apart, and repeat_table_header=True, which is the default, to put a wide table's header row on the front of every piece it gets cut into.

Example
print(HybridChunker(max_tokens=20).merge_peers)
print(HybridChunker(max_tokens=20).repeat_table_header)
Pick max_tokens from the model, not from taste. It is the embedding model's input limit. Setting it larger does not make the model read more; it makes the model read the first part and ignore the rest.
Try it yourself
  • Chunk with max_tokens=12 and count how many chunks you get.
  • Chunk returns.pdf at 30 tokens and check the page numbers still survive in meta.doc_items.
  • Set max_tokens to 5 and read what happens to a sentence that cannot fit.

This is what real progress feels like.