Chunking
Chunkingは、長文ドキュメントを、RAGパイプラインにおける検索および埋め込みに適した、より小さな単位(チャンク)に分割するプロセスです。分割方法、チャンクサイズ、オーバーラップは検索精度と回答品質に直接影響するため、RAGパイプライン設計における中核的なステップとして扱われます。
Chunking は、RAG において文書を retrieval および embedding に適したサイズの単位へ分割することであり、chunk が retrieval の最小単位であるため、分割の品質が答えの品質を大きく左右します。
一般的な手法には fixed-size、recursive、document-structure-based、semantic、contextual(late chunking を含む)があり、多くの場合、recursive splitting がバランスの取れたデフォルトです。
Pinecone は、開始点として 512-token の chunk に 50〜100 tokens の overlap を推奨しており、業界の経験則では 10〜20% の overlap が目安です。
chunk size は、embedding model の input length、コンテンツの種類、想定される query の形から決め、実際の corpus で benchmark して調整すべきです。
Anthropic の Contextual Retrieval は、embedding 前に各 chunk に説明的な context を付与することで、top-20 の chunk retrieval failure rate を最大 49% 削減します。
chunking とは何か
chunking とは、長いソーステキストを、RAG(retrieval-augmented generation)パイプライン内で embedding と vector search に適した小さな断片、つまり chunk に分割する作業です。retrieval step では、query に意味的に最も近い chunk を見つけて LLM に context として渡すため、chunk が retrieval と citation の最小単位になります。したがって、どのようにテキストを切るかが、retrieval accuracy と最終的な答えの品質の両方を直接左右します。
chunk が大きすぎると、複数のトピックが内部で混ざり合い、embedding の焦点がぼやけ、関係のない情報が context に入り込んで答えを希薄化します。chunk が小さすぎると、文や論旨が途中で切れ、context が失われ、実際に必要な情報が分散して retrieval で見落とされます。chunking の目的は、これら二つの極端の間で、意味が完全に保たれる単位を見つけることです。
chunking 手法の比較
実務で最もよく使われる chunking 手法を以下に示します。semantic chunkingはそれらの一分野であり、chunking はこれらすべての手法を含む包括的な概念です。
Strategy | Split basis | Strengths | Limitations |
|---|---|---|---|
Fixed-size | N tokens(または文字)ごとに一定間隔で分割し、必要に応じて overlap を設ける | 実装が最も सरल で、chunk サイズが均一になる | 文書構造を無視するため、文や論旨を途中で切ってしまう |
Recursive | 区切り文字を順に適用し(paragraph → line break → space → character)、目標サイズまで分割する | 外部モデルを使わずに文書構造を概ね保持でき、汎用的なデフォルトとして使える | 区切り文字に依存するため、構造が弱い文書では効果が限定的になる |
Document-based | 見出し、セクション、表、コードブロックなど、文書がすでに備えている構造を活用します | 法務、技術、API ドキュメントのように、構造が明確な資料に適しています | 構造が一貫しないプレーンテキストには適用しにくいです |
Semantic | 文埋め込みの類似度を使ってトピックが切り替わる境界を特定し、その位置で分割します | 自然な意味の境界に沿ってチャンクを形成します | チャンクサイズは大きく変動し、埋め込み計算によるコストも追加されます |
Contextual / late | 埋め込み前に文書コンテキストをチャンクに付与する、または文書全体を先に埋め込み、後から分割します | 周辺コンテキストを保持することで、検索精度を高めます | LLM 呼び出しまたは長文コンテキスト対応モデルが必要になり、コストと複雑さが増します |
推奨パラメータとエビデンス
Pinecone のチャンク分割ガイドでは512 トークンのチャンクに 50〜100 トークンのオーバーラップを出発点として推奨し、コンテンツが短く事実密度が高い場合は 128〜256 トークンのような小さめのチャンクを、コンテキストが重要な場合は 512〜1024 トークンのような大きめのチャンクを試すよう勧めています。オーバーラップ(隣接するチャンクが一部の内容を共有することで共通部分を持つ領域)は、チャンク境界でのコンテキスト損失を抑え、業界の経験則ではチャンクサイズの 10〜20% から始めるのが一般的です。
LangChain のRecursiveCharacterTextSplitterは、再帰的分割の標準実装であり、区切り文字リスト["\n\n", "\n", " ", ""]を優先順に適用します。まず段落を保持し、それでも長すぎる場合は改行、次に空白、最後に文字単位で分割し、できるだけ文書構造を維持します。公式ドキュメントの例パラメータは以下のとおりです。
from langchain_text_splitters import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=100, # maximum chunk size
chunk_overlap=20, # overlap between adjacent chunks
)
chunks = splitter.split_text(document)チャンクサイズに絶対的な正解はありません。使用する埋め込みモデルの入力長、コンテンツの種類、想定されるクエリの形に合わせて設定し、実際のコーパスでベンチマークして検証してください。文字数で切ると、埋め込みモデルのトークン上限とずれが生じることがあるため、分割に使う長さ関数は埋め込みモデルのトークナイザーに合わせるほうが安全です。
チャンク自体のコンテキスト不足を補うアプローチも、活発な研究分野です。AnthropicのContextual Retrievalでは、LLMを使って各チャンクごとに、そのチャンクが文書内のどこに位置するのかを説明するコンテキストを生成し、それを先頭に付加してから埋め込みます。発表によれば、このコンテキスト付き埋め込みだけで上位20件のチャンク検索失敗率が35%低下し(5.7% → 3.7%)、Contextual BM25と組み合わせると49%低下(5.7% → 2.9%)、さらに再ランキングを加えることで最大67%の削減が得られました。プロンプトキャッシュを使えば、チャンクコンテキストは文書トークン100万件あたり約$1.02で生成でき、コスト効率も高く保てます。別の手法として、Jina AIが提案したLate Chunking(arXiv:2409.04701, 2024)では、あらかじめチャンクに分割しません。代わりに、長文コンテキスト対応モデルで文書全体を埋め込み、その後にトークン埋め込みをチャンクにまとめることで、通常の分割時に失われるグローバルなコンテキストを保持します。
実装チェックリスト
再帰的分割をデフォルトとして採用し(文書タイプに対応した区切り文字を使い)、特別な理由がない限り、まずはここから始めてください。
まずは512トークンのチャンクに10〜20%のオーバーラップ(50〜100トークン)を設定し、その後調整してください。
分割長の関数は、埋め込みモデルのトークナイザーに合わせてトークン単位で測定してください。
見出し、表、コードなど明確な構造を持つ文書では、まず文書構造ベースの分割を検討してください。
追加コストをかけてセマンティックチャンクを導入する前に、自分のコーパスでのベンチマークにより、再帰的分割より実際に改善することを確認してください。
チャンクのコンテキスト不足が検索失敗の原因である場合は、コンテキスト付き埋め込みまたはLate Chunkingの導入を試してください。