チャンク分割
Chunking
概要(サマリー)
チャンク分割とは、長い資料を、検索やLLMへ渡しやすい大きさの断片(チャンク)に分けることである。
本を1冊ごとではなく、見出しや段落の単位で索引カードにする作業に近い。RAGでは、この断片をエンベディングに変換し、ベクトルデータベースへ入れておく。質問が来たら、近い断片だけを探してモデルへ渡す。
Anthropicは、知識ベースを通常は数百トークン以内の断片へ分ける、とRAGの前処理を説明している。小さくすれば検索はしやすいが、断片だけでは「誰の、いつの話か」が消える。
詳細解説
なぜ丸ごと渡さないのか
資料全体がコンテキストウィンドウに収まるなら、分割せずに渡すほうが単純なことがある。検索も、断片のつなぎ合わせも要らない。
資料が窓に入らない、または毎回は一部しか要らないときは、全部を貼れない。チャンク分割は、そのための前処理である。質問のたびに本を先頭から読ませず、関係のありそうなページだけを開く。
流れは次のようになる。
- 文書を断片へ分ける
- 各断片をエンベディングへ変換する
- 変換したベクトルを、ベクトル検索用の保存先へ入れる
- 質問に近い断片を探す
- 見つけた断片を、回答用のプロンプトへ添える
分割は、質問が来てから毎回やるものではない。資料を登録するときに済ませておく。
切れ方で意味が変わる
文字数だけで機械的に切ると、文の途中や、表の見出しと数値の間で分かれる。コードなら、関数の途中で切れる。
Anthropicが示した問題は、断片だけだと主語が消えることである。「売上が前期より3%増えた」という文だけでは、どの会社の、いつの数字か分からない。検索でも、回答でも、その断片を正しく使いにくい。
切れ目は、見出し、段落、関数、話者の交代など、意味の境目に寄せる。前後が必要な箇所は、隣の断片と少し重ねる。重ねを overlap と呼ぶことがある。重ねを大きくすると、同じ文が何枚も索引に入り、費用とノイズが増える。
大きさのトレードオフ
小さすぎると、定義と例外規定が別の断片になり、片方だけが検索に引っかかる。大きすぎると、関係の薄い文章まで一緒に返り、窓を圧迫する。
数百トークンというのは、Anthropicが従来のRAGを説明するときの目安であり、すべての資料の最適値ではない。マニュアル、ソースコード、チャットログでは、適した大きさが違う。同じ質問集で、大きさだけを変えて検索結果を比べる。
返す枚数も結果を変える。関係する断片を多く渡すほど当たりは入りやすいが、モデルが読み飛ばす量も増える。
プロンプトを小分けにすることとは別
出力が途中で切れるので、依頼文をいくつかに分けて送り直すことがある。それも「分割」だが、ここでいうチャンク分割ではない。
チャンク分割は、検索用の索引を作るための資料の切り方である。会話がその場の窓に入らないから依頼を分けることとは、保存の有無も、再利用のしかたも違う。
断片に文脈を戻す
切ったあとに、「この断片は文書のどの部分か」を説明する短い文を、断片の先頭へ足す方法がある。Anthropicはこれを Contextual Retrieval の一部として紹介している。本文の「売上は3%増」だけでは足りないとき、会社名や期間を断片側へ書いてからエンベディングを作る。
この説明文もトークンになる。すべての断片へ長い要約を付けると、索引の作成費用が増える。まず境目と重ねを整え、取りこぼしが残る資料だけ、この一手を検討する。
chunks = [
{
"source": "manual/shipping.md",
"heading": "返品できる期間",
"text": "到着日から14日以内であれば、未使用の商品を返品できる。"
}
]
source と heading を断片と一緒に保存しておくと、検索結果をモデルへ渡すときに出典を添えられる。本文だけを保存すると、あとからどのファイルの記述か分からなくなる。
AIコーディングとの関係
リポジトリ全体を1つのプロンプトへ貼れないとき、ファイル単位や関数単位が自然なチャンクになる。文字数でコードの途中を切ると、定義だけ、または呼び出しだけが検索に残る。
AIに分割処理を書かせるときは、区切りの優先順位を指定する。見出し、空行、関数の境界の順で切り、どうしても長い箇所だけ文字数で分割する、という条件が扱いやすい。
検索で当たった断片を、そのまま修正対象だと思わない。断片は索引である。適用前に、元ファイルの前後を開いて確認する。
よくある勘違い
コンテキストウィンドウを広げる機能?
広げない。窓に入らない資料から、渡す部分を選ぶための準備である。窓の上限そのものは変わらない。
小さく切るほど正確?
検索の単位は細かくなるが、周囲の条件が落ちる。小さすぎる断片は、例外規定を切り離して誤った回答の材料になる。
一度決めればすべての文書で同じ?
マニュアルとソースコードでは、意味の境目が違う。大きさ、重ね、区切りは、資料の種類ごとに調整する。
質問のたびに分割し直す?
通常は、資料を登録するときに分割して保存する。質問のたびに全文書を切り直すと、待ち時間と費用が増えるだけになる。
まとめ
- チャンク分割は、長い資料を検索しやすい断片へ分ける前処理である
- RAGでは、断片をエンベディングにしてベクトルの索引へ入れる
- 文字数だけで切ると、主語や見出しが落ちて検索も回答も不安定になる
- 小さすぎると条件が分離し、大きすぎると無関係な文章まで返る
- 資料全体が窓に収まるなら、分割しないほうが単純なことがある
情報ソース
より詳しくAIに聞いてみよう
- チャンク分割を、本の索引カードのたとえで説明してください。
- 断片が小さすぎるときと大きすぎるときの失敗を、それぞれ具体例で教えてください。
- 資料全体が窓に収まるのに、分割しないほうがよい理由を説明してください。
- コードを関数の途中で切らない分割ルールを、初心者向けに整理してください。
- AIに、Markdownの見出しを優先して分割する処理の条件を書かせてください。