Text splitters

Text splitters divide documents into retrievable DocumentChunk objects. The choice of splitter affects retrieval quality.

Available text splitters

Available text splitters

SplitterBest for
Character Text SplitterSimple text, quick prototyping
Token Text SplitterToken-aware chunking, LLM context management
Markdown Text SplitterMarkdown documents, structured content with headers
Separator Text SplitterCustom splitting logic, hierarchical text
Custom SplittersAny splitting strategy
i
Information

Each sub-chunk inherits the type and metadata of the chunk it comes from, such as page_number and any custom keys. Only its locator, start_offset, and end_offset change. Non-content chunks, such as summaries and image annotations, pass through unsplit.

Chunk size guidance

Chunk size guidance

Chunk size affects retrieval quality and LLM context usage. Choose it based on your use case:

LLM ContextChunk SizeOverlapUse case
4k tokens300-500 chars50-100 charsMemory-constrained, fast retrieval
8k tokens500-1000 chars100-200 charsBalanced retrieval quality
32k+ tokens1000-2000 chars200-500 charsRich context, complex retrieval
Code/technical500-1000 chars100-200 charsPreserve logical units
Legal/financial1000-2000 chars200-500 charsFull context for interpretation

Rule of thumb: ~400-600 characters ≈ 100-150 tokens. Adjust based on domain complexity and retrieval precision needs.

Chunk overlap benefits:

  • Prevents semantic boundaries from splitting related concepts
  • Improves context when chunks are used individually
  • Increases index size and query latency proportionally
Character text splitter

Character text splitter

CharacterTextSplitter splits text by character count, with no overlap. Use it for simple text and quick prototyping.

Example:

from mistralai.search.toolkit.ingestion.text_splitters import CharacterTextSplitter

splitter = CharacterTextSplitter(
    chunk_size=500,     # Characters per chunk
)
chunks = (await splitter.process(document)).chunks

Parameters:

ParameterTypeDefaultDescription
chunk_sizeint1000Maximum number of characters per chunk
Token text splitter

Token text splitter

TokenTextSplitter counts tokens with a Mistral tokenizer, for precise control over chunk size in tokens.

Example:

from mistral_common.tokens.tokenizers.mistral import MistralTokenizer
from mistralai.search.toolkit.ingestion.text_splitters import TokenTextSplitter

splitter = TokenTextSplitter(
    chunk_size=1000,                  # Tokens per chunk
    chunk_overlap=200,                # Token overlap
    tokenizer=MistralTokenizer.v1(),  # Embedding tokenizer
)

chunks = (await splitter.process(document)).chunks

Configuration options:

OptionTypeDefaultPurpose
chunk_sizeint512Target tokens per chunk
chunk_overlapint50Tokens of overlap between chunks
model_namestr"mistral-embed"Model whose tokenizer is resolved when tokenizer is unset
tokenizerMistralTokenizer | NoneNoneTokenizer instance; takes precedence over model_name

When to use:

  • Precise token budgeting for LLM context windows
  • Consistent chunks across different text densities
  • When working with specific token limits
Markdown text splitter

Markdown text splitter

MarkdownTextSplitter splits markdown documents at header boundaries. It splits on headers first, then runs a SeparatorTextSplitter on each section. Its configuration extends SeparatorTextSplitterConfig with configurable header levels.

Requirements:

Install the text-splitter-langchain extra:

uv add "mistralai-search-toolkit[text-splitter-langchain]"

Example:

from mistralai.search.toolkit.ingestion.text_splitters import MarkdownTextSplitter, MarkdownTextSplitterConfig

config = MarkdownTextSplitterConfig(
    headers_to_split_on=[
        ("#", "h1"),
        ("##", "h2"),
        ("###", "h3"),
    ],
    strip_headers=False,    # Keep headers in chunks
    chunk_size=1000,        # Inherited from SeparatorTextSplitterConfig
    chunk_overlap=200,      # Inherited from SeparatorTextSplitterConfig
)

splitter = MarkdownTextSplitter(config=config)
chunks = (await splitter.process(document)).chunks

Parameters (MarkdownTextSplitterConfig):

MarkdownTextSplitterConfig extends SeparatorTextSplitterConfig, adding:

ParameterTypeDefaultDescription
headers_to_split_onlist[tuple[str, str]][("#", "Header 1"), ("##", "Header 2"), ("###", "Header 3")]Markdown headers to split on. Each tuple is (header_prefix, label).
strip_headersboolFalseRemove header lines from chunk content

All parameters from SeparatorTextSplitterConfig are also available (chunk_size, chunk_max_size, chunk_overlap, chunk_separators, keep_separator, strip_whitespace).

Separator text splitter

Separator text splitter

SeparatorTextSplitter splits text recursively on a list of separators. Use it for custom document structures where you need control over split points.

Requirements:

Install the text-splitter-langchain extra:

uv add "mistralai-search-toolkit[text-splitter-langchain]"

Example:

from mistralai.search.toolkit.ingestion.text_splitters import SeparatorTextSplitter, SeparatorTextSplitterConfig

config = SeparatorTextSplitterConfig(
    chunk_size=1000,          # Target size (characters)
    chunk_max_size=1500,      # Maximum size (characters)
    chunk_overlap=200,        # Overlap (characters)
    chunk_separators=[        # Tried in order
        "\n\n",    # Paragraphs first
        "\n",      # Then lines
        ". ",      # Then sentences
        " ",       # Then words
        "",        # Finally characters
    ],
)

splitter = SeparatorTextSplitter(config=config)
chunks = (await splitter.process(document)).chunks

Parameters (SeparatorTextSplitterConfig):

ParameterTypeDefaultDescription
chunk_sizeint2048Target chunk size in characters
chunk_max_sizeint | NoneNoneMaximum chunk size, to avoid cutting inside a word. None uses chunk_size.
chunk_overlapint0Overlap between chunks in characters
chunk_separatorslist[str]["\n\n", "\n", ".", ", ", ",", " ", "\t"]Separators, tried from left to right
keep_separatorbool | "start" | "end""end"Whether and where to keep separators in chunks
strip_whitespaceboolFalseStrip leading and trailing whitespace from each chunk

Features:

  • Tries separators in order
  • Respects max size even if splitting fails
  • Merges small chunks when possible
  • Returns start/end offsets
Creating custom splitters

Creating custom splitters

Implement the TextSplitter protocol:

from mistralai.search.toolkit.context import IngestContext
from mistralai.search.toolkit.ingestion.text_splitters import TextSplitter
from mistralai.search.toolkit.ingestion.text_splitters.models import TextFragment

class ParagraphSplitter(TextSplitter):
    """Split text into chunks by paragraphs."""

    def __init__(self, max_paragraphs_per_chunk: int = 3):
        self.max_paragraphs_per_chunk = max_paragraphs_per_chunk

    def split_text(self, text: str, context: IngestContext = IngestContext()) -> list[TextFragment]:
        paragraphs = text.split("\n\n")
        fragments = []
        offset = 0

        for i in range(0, len(paragraphs), self.max_paragraphs_per_chunk):
            chunk_paragraphs = paragraphs[i:i + self.max_paragraphs_per_chunk]
            content = "\n\n".join(chunk_paragraphs)

            fragments.append(TextFragment(
                content=content,
                start_offset=offset,
                end_offset=offset + len(content),
            ))
            offset += len(content) + 2

        return fragments

splitter = ParagraphSplitter(max_paragraphs_per_chunk=3)
fragments = splitter.split_text("First paragraph.\n\nSecond paragraph.\n\nThird paragraph.")