StructureAwareChunker

On this page

Module: chunks.structure_aware_chunker
Import: from zerda.chunks import StructureAwareChunker


Table of Contents


Purpose

StructureAwareChunker parses document structure (Markdown headings, HTML tags, paragraph breaks) and creates chunks that respect those natural boundaries. A chapter never gets split mid-paragraph if avoidable; code blocks and tables are always kept intact.

Use when:

  • Input is Markdown documentation or HTML pages
  • You need chunk boundaries aligned with heading/section structure
  • Preserving code blocks and tables is critical

Algorithm

code · 10 lines
1. DocumentStructureParser.detect_document_type(text) → DocumentType
2. DocumentStructureParser.parse(text, doc_type) → List[StructuredSection]
3. _merge_small_sections(): merge short sections with next (unless code/table/header)
4. For each section:
   - Code block? → one chunk (ChunkType.CODE_BLOCK)
   - Table?      → one chunk (ChunkType.TABLE)
   - List?       → one chunk (ChunkType.LIST_ITEM)
   - Header node? → one chunk (ChunkType.HEADER)
   - Normal text? → _split_large_section() → one or more SECTION chunks
5. _finalize() sets position and total_chunks

Constructor

Python · 9 lines
StructureAwareChunker(
    config: Optional[ChunkConfig] = None,
    *,
    max_chunk_size: int = 1024,
    min_chunk_size: int = 50,
    language: str = "auto",
    split_on_headers: bool = True,
    preserve_code_blocks: bool = True,
)

Parameters

ParameterTypeDefaultDescription
configChunkConfig | NoneNoneIf provided, reads max_chunk_size, min_chunk_size, split_on_headers, preserve_code_blocks from config.
max_chunk_sizeint1024Sections larger than this are sentence-split further
min_chunk_sizeint50Sections smaller than this are merged with the next
languagestr"auto"Stored in chunk metadata
split_on_headersboolTrueWhether headings open new chunks
preserve_code_blocksboolTrueKeep code blocks as single chunks

Public Methods

Inherited from BaseChunker:

chunk(text, doc_id="", source="") → List[DocumentChunk]

chunk_documents(documents) → List[DocumentChunk]


Document Type Detection

DocumentStructureParser.detect_document_type() uses heuristics:

SignalDetected Type
<html>, <div>, <p> tagsHTML
# headers, ```, **bold**MARKDOWN
Arabic char ratio > 20%ARABIC
DefaultPLAIN_TEXT

Section Handling Rules

Section TypeAction
is_code_block=True + preserve_code_blocks=TrueOne CODE_BLOCK chunk, no splitting
is_table=TrueOne TABLE chunk
is_list=TrueOne LIST_ITEM chunk
extra["is_heading_node"]=TrueOne HEADER chunk
Normal text ≤ max_chunk_sizeOne SECTION chunk
Normal text > max_chunk_sizeSentence-split into multiple SECTION chunks
Length < min_chunk_sizeMerged with adjacent section text

Chunk Types Produced

ChunkTypeWhen
HEADERMarkdown # heading / HTML <h1>–<h6>
CODE_BLOCKMarkdown ``` block / HTML <pre>
TABLEHTML <table>
LIST_ITEMHTML <ul>/<ol>
SECTIONNormal paragraph/section text

Metadata Set

Each chunk gets:

Python · 6 lines
metadata.section        # heading text of parent section
metadata.heading_level  # 0-6 (0 = body, 1 = H1, ...)
metadata.is_header      # True for HEADER chunks
metadata.chunk_type     # ChunkType enum value
metadata.document_type  # detected DocumentType
metadata.extra          # {"tag": "p"} for HTML, {"is_heading_node": True} for headers

Examples

Markdown Document

Python · 9 lines
from zerda.chunks import StructureAwareChunker

md = """
# Introduction
This is the intro section.

## Installation
```bash
pip install chunks

Usage

Python · 8 lines
Use the library like this.
"""

chunker = StructureAwareChunker()
chunks = chunker.chunk(md, source="docs.md")

for c in chunks:
    print(c.metadata.chunk_type.value, "|", c.metadata.section, "|", c.text[:40])

HTML Document

Python · 10 lines
html = """
<html><body>
<h1>Getting Started</h1>
<p>Welcome to the tutorial.</p>
<ul><li>Step one</li><li>Step two</li></ul>
</body></html>
"""

chunker = StructureAwareChunker()
chunks = chunker.chunk(html, source="page.html")

With Configuration

Python · 9 lines
from zerda.chunks import StructureAwareChunker, ChunkConfig

config = ChunkConfig(
    max_chunk_size=800,
    min_chunk_size=100,
    preserve_code_blocks=True,
    split_on_headers=True,
)
chunker = StructureAwareChunker(config=config)

Disabling Code Block Preservation

Python · 2 lines
# Split large code blocks like any other text
chunker = StructureAwareChunker(preserve_code_blocks=False)

Best Practices

  • Always use for Markdown docs, API references, and HTML pages.
  • Set split_on_headers=True (default) to ensure each section is independently retrievable.
  • Inspect metadata.section to filter chunks from a specific heading during retrieval.
  • Use ChunkMode.HYBRID when sections may be long prose that also benefits from semantic splitting.

Common Mistakes

MistakeFix
Passing plain text with no structureWorks correctly — falls back to paragraph splitting.
Large max_chunk_size with no min_chunk_sizeShort heading nodes create tiny, uninformative chunks. Set min_chunk_size appropriately.

Related pages