導入
固定長チャンクには、境界をまたぐ情報が分断されるという弱点がありました。隣り合うチャンクどうしを少しだけ重ねて切ると、境界のせいで意味が途切れるのを防げます。この重なりを**オーバーラップ(overlap、のりしろ)**と呼びます。
説明
def chunk_overlap(text, size, overlap):
step = size - overlap
return [text[i:i+size] for i in range(0, len(text), step)]
text = "Retrieval augmented generation splits documents into chunks for search."
chunks = chunk_overlap(text, 20, 5)
print("Number of chunks:", len(chunks))
for i, c in enumerate(chunks):
print(f"[{i}] {c!r}")
chunk_fixed との違いは1つだけです。先頭位置を進める幅を size ではなく step = size - overlap にしています。たとえば size=20, overlap=5 なら、次のチャンクの先頭は15文字先から始まる。つまり直前のチャンクの末尾5文字を、次のチャンクの先頭にもう一度含めているわけです。境界をまたぐ単語や文が、少なくともどちらか片方のチャンクには丸ごと収まりやすくなります。
トレードオフもあります。overlap を大きくするほど、チャンク同士の重複が増えてチャンクの総数が増え、索引のサイズや検索・保存のコストが上がります。その代わり、境界での情報の取りこぼしは減ります。逆に overlap=0 なら step = size となり、これは前のレッスンの固定長チャンクと完全に同じ動きになります。
やってみよう
overlap を 0・5・10 と変えて chunk_overlap(text, 20, overlap) を呼び、チャンク数がどう増えるか比べてみましょう。
演習
chunk_overlap(text, 20, 0) の結果が、レッスン6の chunk_fixed(text, 20) の結果と完全に一致することを、== を使って確認し、print で表示してください(chunk_fixed 関数も自分で定義してから比べてください)。
ヒント1を見る
2つの関数をどちらも定義してから、chunk_overlap(text, 20, 0) == chunk_fixed(text, 20) を print します。
ヒント2を見る
overlap=0 のとき step = size - 0 = size になるので、chunk_overlap は chunk_fixed と同じ計算になります。