Meet the Docling team at IBM TechXchange 2026 · Atlanta, GA · October 26–29, 2026See our sessions
DoclingDocling for IBM watsonx
Guides

Chunking

Split documents into retrieval-ready chunks and deliver them to Kafka or a vector database

RAG and semantic search work on chunks, pieces of a document small enough for an embedding model. Docling for IBM watsonx chunks documents along their structure:

  • a chunk never mixes two sections,
  • tables and lists stay whole whenever they fit,
  • every chunk carries its headings and page numbers, so answers can cite their source.

On the service, chunking is part of a batch request. You add chunking_options and pick a chunk target. The service then converts, chunks and delivers each chunk straight to your system:

TargetkindDelivers
Kafka (including Confluent Cloud)kafka_chunksOne message per chunk, for event-driven pipelines
OpenSearchopensearch_chunksIndexed chunks (embed them with an index ingest pipeline)
AstraDBastradb_chunksChunks with server-side embeddings

Example

Convert two PDFs and stream their chunks to a Kafka topic:

curl -X POST "${DOCLING_SERVICE_URL}/v1/convert/source/batch" \
  -H "X-Api-Key: ${DOCLING_SERVICE_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "sources": [
      { "kind": "http", "url": "https://arxiv.org/pdf/2408.09869" },
      { "kind": "http", "url": "https://arxiv.org/pdf/2206.01062" }
    ],
    "options": {
      "chunking_options": {
        "chunker": "hybrid",
        "tokenizer": "ibm-granite/granite-embedding-278m-multilingual",
        "max_tokens": 512
      }
    },
    "target": {
      "kind": "kafka_chunks",
      "bootstrap_servers": ["pkc-xxxxx.us-east-1.aws.confluent.cloud:9092"],
      "topic": "docs.chunks",
      "auth": { "kind": "sasl", "mechanism": "PLAIN", "username": "API_KEY", "password": "API_SECRET" },
      "headings_field": "headings",
      "page_field": "page_numbers"
    }
  }'

Each chunk arrives as a JSON record:

{
  "text": "DocLayNet: A Large Human-Annotated Dataset …\nThe dataset contains 80863 pages …",
  "doc_id": "a1b2c3…",
  "chunk_index": 4,
  "chunk_id": "9f8e7d…",
  "headings": ["3 The DocLayNet dataset"],
  "page_numbers": [2, 3],
  "metadata": { "origin": { … } }
}

Always send the chunker field explicitly, even for the default "hybrid". Without it the request is rejected with a 422 validation error. Some SDKs drop fields that equal their default value, so check the request your code actually sends.

Chunking options

OptionDefaultDescription
chunker(required)hybrid (recommended) or hierarchical
tokenizersentence-transformers/all-MiniLM-L6-v2Hugging Face model whose tokenizer counts tokens. Use the tokenizer of your embedding model. Hybrid only
max_tokenstaken from the tokenizerMaximum tokens per chunk. Hybrid only
merge_peerstrueMerge small consecutive chunks that share the same headings. Hybrid only
use_markdown_tablesfalseSerialize tables as Markdown tables instead of row, column = value triplets
use_markdown_imagesfalseInclude image references in chunks and flag those chunks with has_image
image_placeholder![IMAGE]Text that stands in for an image when use_markdown_images is off
include_raw_textfalseAlso include the raw chunk text next to the contextualized text

Which chunker?

  • hybrid first splits along the document structure, then splits or merges pieces so each fits max_tokens for your tokenizer. It is the right choice for embeddings.
  • hierarchical emits one chunk per structural element (paragraph, table, list) with its headings, and does not count tokens. Use it when you want to do your own grouping.

Picking tokenizer and max_tokens

Use the same model your pipeline will embed with. Set max_tokens to the model's input limit, or a bit lower to leave room for the headings that are added as context.

Embedding modeltokenizermax_tokens
IBM Granite Embedding 278M (watsonx.ai)ibm-granite/granite-embedding-278m-multilingual512
IBM Granite Embedding 30M Englishibm-granite/granite-embedding-30m-english512
all-MiniLM-L6-v2sentence-transformers/all-MiniLM-L6-v2256

The text field

Each chunk's text is contextualized: it starts with the chunk's headings, followed by the content. That gives the embedding model the context the chunk lives in, and it measurably improves retrieval. Use include_raw_text if you also need the bare content, for example for display.

Next steps

On this page