10 行で書くと#
from docling.chunking import HybridChunker
from docling.document_converter import DocumentConverter
doc = DocumentConverter().convert("https://arxiv.org/pdf/2408.09869").document
chunker = HybridChunker(max_tokens=256) # 埋め込みモデルに合わせる
for chunk in chunker.chunk(doc):
text = chunker.contextualize(chunk) # 見出し + 本文:これを埋め込む
pages = {p.page_no for item in chunk.meta.doc_items for p in item.prov}
print(len(text), chunk.meta.headings, sorted(pages))各チャンクには meta.headings(章のパス)と meta.doc_items(ページ番号とバウンディングボックス付きの元要素)が付きます。ページ上の正確な位置に戻れる引用を表示するのに十分な情報です。
実際のチャンクを見る#
9 ページの Docling テクニカルレポートを変換し、docling-core 2.106.0 で 3 通りにチャンク化しました。実際の出力を見てください。色は要素の種類、バーは上限に対する各チャンクのサイズ、赤は上限超過を表します。
計測結果#
docling.org が docling-core 2.106.0 で分割。最後の区間は 512 以上をすべて含みます。
データ表を表示
| トークン数 | 階層型 | ハイブリッド · 256 トークン | ハイブリッド · 512 トークン |
|---|---|---|---|
| 0–63 | 13 | 2 | 0 |
| 64–127 | 27 | 10 | 4 |
| 128–191 | 10 | 10 | 6 |
| 192–255 | 5 | 24 | 3 |
| 256–319 | 2 | 2 | 5 |
| 320–383 | 0 | 0 | 3 |
| 384–447 | 0 | 0 | 4 |
| 448–511 | 2 | 0 | 4 |
| 512+ | 2 | 0 | 1 |
| チャンカー | チャンク数 | 平均トークン | 最大 | 256 トークン超 |
|---|---|---|---|---|
| HierarchicalChunker | 61 | 144 | 1,102(参考文献リスト) | 61 中 5(うち 2 つは 512 超) |
HybridChunker、max_tokens=256(既定) | 48 | 182 | 256 | なし |
HybridChunker、max_tokens=512 | 30 | 290 | 512 | 30 中 16(設計どおり:上限は 512) |
チャンカーの違い#
HierarchicalChunker
文書要素(段落・リスト・表)ごとに 1 チャンクで、見出しのパスが付きます。トークンを意識しないため、長い表やリストはどれだけ大きくても 1 チャンク。構造の確認には良いですが、埋め込みにはリスクがあります。
HybridChunker
階層チャンクから出発し、max_tokens を超えるものをトークナイザーで分割し、見出しが同じ小さな隣接チャンクを結合します(merge_peers=True)。分割が必要な表はヘッダーを繰り返します(repeat_table_header=True)。
HybridChunker の設定
| パラメーター | 既定値 | 意味 |
|---|---|---|
tokenizer | all-MiniLM-L6-v2 のトークナイザー | トークン数を数える。埋め込みモデルのトークナイザーを使う |
max_tokens | トークナイザー自身の上限(ここでは 256) | 見出しを含むチャンクごとの上限 |
merge_peers | True | 見出しが同じ小さな兄弟チャンクを結合 |
repeat_table_header | True | 表を分割したときにヘッダー行を繰り返す |
omit_header_on_overflow | False | 見出しの文脈だけで上限を超える場合は省く |
always_emit_headings | False | 空の章にも見出しだけのチャンクを出す |
既定値は docling-core 2.106.0 の HybridChunker のモデルフィールドから取得しました。
埋め込みモデルのトークナイザーを使う
from docling.chunking import HybridChunker
from docling_core.transforms.chunker.tokenizer.huggingface import HuggingFaceTokenizer
from transformers import AutoTokenizer
EMBED_MODEL = "intfloat/multilingual-e5-small" # 実際に埋め込みに使うモデル
tokenizer = HuggingFaceTokenizer(
tokenizer=AutoTokenizer.from_pretrained(EMBED_MODEL),
max_tokens=512,
)
chunker = HybridChunker(tokenizer=tokenizer)OpenAI の埋め込みモデル向けには、docling-core に tiktoken を使う OpenAITokenizer ラッパーもあります(docling-core[chunking-openai] をインストール)。
コマンドラインでチャンク化#
docling convert report.pdf --to chunks --chunks-max-tokens 512 --output chunks/
docling convert report.pdf --to chunks --chunks-type hierarchical
docling convert report.pdf --to chunks --chunks-tokenizer intfloat/multilingual-e5-smallフレームワークのローダー#
LangChain
langchain-docling 3.0 以降、基本パッケージは docling-serve 用の軽量クライアントです。ローカル変換には local エクストラが必要です。
pip install "langchain-docling[local]"from langchain_docling import DoclingLoader
from langchain_docling.loader import ExportType
loader = DoclingLoader(
file_path=["https://arxiv.org/pdf/2408.09869"],
export_type=ExportType.DOC_CHUNKS, # 既定。または ExportType.MARKDOWN
)
docs = loader.load() # チャンクごとに LangChain の Document
print(docs[0].metadata.keys())LlamaIndex
pip install llama-index-readers-docling llama-index-node-parser-doclingfrom llama_index.node_parser.docling import DoclingNodeParser
from llama_index.readers.docling import DoclingReader
reader = DoclingReader(export_type=DoclingReader.ExportType.JSON)
docs = reader.load_data(file_path="https://arxiv.org/pdf/2408.09869")
nodes = DoclingNodeParser().get_nodes_from_documents(documents=docs)JSON エクスポートと DoclingNodeParser を組み合わせると、ノードのメタデータに見出しとページの出典が残ります。
Haystack ほか
docling-haystack は Haystack のコンバーターコンポーネントを提供します。Docling の README は統合先として Crew AI も挙げており、docling-mcp は変換機能を MCP 対応エージェント向けのツールとして公開します。
実践的なアドバイス#
- 各ベクトルに
doc_itemsの出典を保存すれば、回答でページと位置を引用できます。 - 埋め込むのは文脈付きテキスト、表示するのは元のテキスト。見出しは検索に役立ち、ユーザーが見たいのは本文です。
- DoclingDocument の JSON を残す。新しいトークナイザーで再チャンク化するとき、JSON からなら一瞬、PDF からだと時間がかかります。
- 表を確認する。表は行ごとにシリアライズされます(テストでは “Caption, human human = 84-89. …” のような形)。数値に依存する回答なら、表に関する質問で検索を個別にテストしてください。
- 日本語文書はトークナイザーに注意。英語向けトークナイザーでは同じ文章でもトークン数が大きく変わることがあります。日本語を扱える埋め込みモデルのトークナイザーで数えてください。
よくある質問
RAG に最適な Docling のチャンカーは?
ほとんどの場合 HybridChunker です。文書構造から出発し(HierarchicalChunker と同じ)、トークン上限を超えるものを分割し、見出しが同じ小さな隣接チャンクを結合します。テスト論文ではすべてのチャンクが上限内に収まり、HierarchicalChunker では最大 1,102 トークンになりました。
Docling の HybridChunker の max_tokens はいくつにする?
埋め込みモデルの最大入力長にし、そのモデルのトークナイザーを渡します。既定では sentence-transformers/all-MiniLM-L6-v2 のトークナイザーと上限 256 を使います。512 や 8,192 トークンのモデルなら max_tokens もそれに合わせて上げます。
Docling の contextualize() は何をする?
見出しのパスを先頭に付けたチャンクのテキストを返します(例:段落の前に「1 Introduction」)。文脈付きのテキストを埋め込むと、ベクトルがどの章の文章かを知っているため、検索精度が上がることが多いです。
表はどのようにチャンク化される?
表は行ごとにシリアライズされ、収まる限りまとめて保たれます。トークン上限を超えると HybridChunker が分割し、既定で各部分にヘッダーを繰り返します(repeat_table_header=True)。
Docling の CLI でチャンクを得られる?
はい:docling convert file.pdf --to chunks --chunks-max-tokens 512。構造だけで分ける場合は --chunks-type hierarchical、トークナイザーの指定は --chunks-tokenizer です。
出典
- docling-core 2.106.0 のチャンカー(docling_core/transforms/chunker)
- 公式ドキュメント:チャンキングの概念
- PyPI の langchain-docling 3.0.0
- PyPI の llama-index-readers-docling と llama-index-node-parser-docling
- PyPI の docling-haystack