【比較】RAGのチャンク・ウィンドウ・オーバーラップの違い¶
概要¶
RAG(Retrieval-Augmented Generation)の前処理では、文書を検索・埋め込みできる単位に分割します。ここで「チャンク」「チャンクサイズ(ウィンドウ)」「オーバーラップ」という似た用語が立て続けに出てきて混同しがちです。整理すると、チャンクは文書を分割した 1 単位(埋め込み・インデックス・検索の最小ピース)、チャンクサイズ(ウィンドウ)は 1 チャンクに入れるテキスト量の上限、オーバーラップは隣り合うチャンク同士で重複させる部分で、境界をまたいで文脈が切れるのを和らげるためのものです。
最大の落とし穴は、この「チャンクサイズ(ウィンドウ)」を LLM の「コンテキストウィンドウ(context window)」と取り違えることです。前者は文書分割の設計値(あなたが決めるインデックス側の値)、後者はモデルが 1 リクエストで参照できる最大トークン数(モデル側の上限)で、レイヤーがまったく違います。チャンクが小さすぎると文脈が落ちて検索しても意味が通らず、大きすぎると 1 チャンクに無関係な内容が混ざって検索の関連度が薄まる――というトレードオフを、この 3 語の違いとともに押さえるのが本記事のねらいです。
例えるなら:本を付箋ページに分けて索引を作る¶
- チャンク … 本を「検索しやすい一塊」に切り分けた付箋ページ 1 枚。索引に登録する単位。
- チャンクサイズ(ウィンドウ) … 付箋 1 枚にどれだけの文章を載せるかの上限(短冊の大きさ)。
- オーバーラップ … 隣の付箋と数行だけ内容を重ねて貼る運用。ページ境界で話が途切れて意味不明にならないための“のりしろ”。
- (対比)LLM のコンテキストウィンドウ … 付箋を渡される“読み手”が一度に机に広げて読める最大ページ数。本の切り方とは別の、読み手側の制約。
詳細比較¶
| 比較軸 | チャンク(chunk) | チャンクサイズ/ウィンドウ(chunk size) | オーバーラップ(chunk overlap) |
|---|---|---|---|
| 何か | 文書を分割した 1 単位(埋め込み・索引・検索の最小ピース) | 1 チャンクに入れるテキスト量の上限値 | 隣接チャンク間で重複させる部分(長さ) |
| 役割 | ベクトル化して検索対象として登録される実体 | 各チャンクの粒度を決める設定値 | 境界で文脈が分断され情報が落ちるのを緩和 |
| 単位 | (概念。実体は分割後のテキスト断片) | 文字数 or トークン数(スプリッタ依存) | 文字数 or トークン数(チャンクサイズと同単位) |
| 誰が決めるか | 分割結果として生成される | 人間が前処理で設定 | 人間が前処理で設定(通常チャンクサイズより小さく) |
| 大きすぎると | (該当せず) | 1 チャンクに無関係内容が混在し検索の関連度が希薄化 | 重複過多で索引が肥大・冗長、検索ノイズ増 |
| 小さすぎると | (該当せず) | 文脈が断片化し単体で意味が通らない/必要情報が分散 | 0 だと境界で文意が切れ情報欠落 |
| コストへの影響 | チャンク数=埋め込み・ベクトル保存件数 | 大きいほど 1 件あたりの情報量大/件数減 | 大きいほど総トークン・保存量が増える |
| LLM コンテキストウィンドウとの関係 | 検索でヒットしたチャンク群を後段でプロンプトに詰める | 文書分割の設計値(モデルの入力上限とは別物) | 同上(モデルの入力上限とは無関係に決める) |
よくある誤解¶
- 誤解1:「チャンクサイズ(ウィンドウ)= LLM のコンテキストウィンドウ」 — 別物です。チャンクサイズは文書を分割するときに人間が決める前処理の設定値(スプリッタの
chunk_size)。LLM のコンテキストウィンドウは「言語モデルが応答生成時に参照できる全テキスト(応答自身を含む)」というモデル側のトークン上限で、Anthropic の定義でもモデルの“ワーキングメモリ”として説明されます。検索でヒットした複数チャンクを最終的にプロンプトへ詰める段で初めてコンテキストウィンドウの制約に当たるのであって、分割サイズそのものとは別レイヤーです。混同すると「コンテキストが 20 万トークンあるからチャンクも 20 万にする」のような筋違いの設計になります。 - 誤解2:「チャンクは大きいほど検索精度が上がる(文脈が多いから良い)」 — 単純には上がりません。チャンクを大きくすると 1 チャンクに複数トピックが混在し、埋め込みが“ぼやけて”クエリとの関連度が薄まる(検索でヒットしにくい/ノイズが増える)ことがあります。逆に小さすぎると単体で意味が通らず必要情報が分散します。最適点はデータと用途で変わるトレードオフで、「大きければ良い/小さければ良い」と一方向に言い切れません。
- 誤解3:「オーバーラップは無駄な重複だから 0 にすべき」 — 0 にすると、文・段落・論理のつながりがチャンク境界でちょうど切れたときに情報が欠落します。LangChain も「オーバーラップはチャンク間で文脈が分割されることによる情報の損失を緩和する」と説明しています。一方で大きすぎると索引が肥大しトークン・保存コストと検索の冗長性が増えるため、“ゼロか過大か”ではなく適度な重複(一般にチャンクサイズより十分小さく)を取るのが定石です。
- 誤解4:「チャンクサイズの数字は常に『文字数』」 — スプリッタ依存です。文字ベースのスプリッタ(例: 文字長で測る分割)と、トークン数で測るスプリッタ(例: LlamaIndex の
TokenTextSplitterは raw token count で一定サイズに分割)があり、chunk_size=1024が文字なのかトークンなのかで実際の粒度が大きく変わります。課金・コンテキスト見積もりはトークンで効くため、どの単位で測っているかを必ず確認します。
実務での選び分け¶
- 検索の関連度が低い/無関係な箇所がヒットする → まずチャンクサイズを疑う。大きすぎてトピック混在なら小さく、断片的すぎて意味が通らないなら大きく。データの構造(見出し・段落・コード)に沿った分割(構造的・意味的分割)も検討。
- 回答が境界でちぐはぐ・前提が抜ける → オーバーラップ不足を疑う。境界で切れる文脈をまたげる程度に重複を増やす(増やしすぎは索引肥大・コスト増とのトレードオフ)。
- ベクトルDB のコスト/件数が膨らむ → チャンク数(=埋め込み件数)とオーバーラップ量を見直す。重複過多は保存・トークンコストに直撃。
- 「コンテキストに入りきらない」エラー → これはチャンクサイズではなく、ヒット件数 × チャンク長を最終プロンプトに詰めすぎている問題。再ランク・件数制御・要約圧縮で“モデルのコンテキストウィンドウ”側の制約に対処する(分割サイズの問題と切り分ける)。
- 単位の取り違え防止 → スプリッタが文字基準かトークン基準かを最初に確認し、見積もり(課金・コンテキスト)はトークンで揃える。
ひとことまとめ¶
チャンクは「文書を分割した検索の 1 単位」、チャンクサイズ(ウィンドウ)は「1 チャンクの量の上限という設計値」、オーバーラップは「境界で文脈が切れないための重複(のりしろ)」。これらは前処理で人間が決めるインデックス側の値であり、モデルが 1 リクエストで読める上限である LLM のコンテキストウィンドウとは別レイヤー、と切り分けると混同しません。小さすぎれば文脈喪失・大きすぎれば関連度希薄というトレードオフを、データと用途で調整します。
出典・参考¶
- LangChain Docs「Recursive text splitter」(
chunk_size=チャンクの最大サイズ、chunk_overlap=チャンク間の目標重複で、文脈がチャンク間で分割されることによる情報損失を緩和する): https://docs.langchain.com/oss/python/integrations/splitters/recursive_text_splitter - LlamaIndex Docs「Node Parser Modules」(
TokenTextSplitterは raw token count に従って一定のチャンクサイズに分割。SentenceSplitter/TokenTextSplitterはchunk_sizeとchunk_overlapを持つ): https://developers.llamaindex.ai/python/framework/module_guides/loading/node_parsers/modules/ - Anthropic Docs「Context windows」(コンテキストウィンドウは言語モデルが応答生成時に参照できる全テキスト=応答自身を含む“ワーキングメモリ”で、学習データとは別。モデル側のトークン上限): https://platform.claude.com/docs/en/docs/build-with-claude/context-windows