مفهوم اصلی
در یک سیستم RAG در محیط Production، اگرچه Vector Databaseها برای Vector Retrieval بهینه شدهاند، اما معمولاً برای افزایش کیفیت سیستم نیاز به بهینهسازیهای بیشتری وجود دارد.
یکی از مهمترین تکنیکها:
Chunking
است.
Chunking چیست؟
Chunking یعنی:
تقسیم کردن Documentهای متنی بزرگ موجود در Knowledge Base به بخشهای کوچکتر (Chunk).
به جای اینکه یک Document بزرگ به صورت یک Vector ذخیره شود، آن را به چند قسمت کوچکتر تقسیم میکنیم و هر قسمت یک Vector جداگانه دریافت میکند.
چرا از Chunking استفاده میکنیم؟
سه دلیل اصلی وجود دارد:
1. محدودیت Embedding Modelها
بسیاری از Embedding Modelها محدودیت دارند و نمیتوانند متنهای بسیار طولانی را به Vector تبدیل کنند.
بنابراین Documentهای بزرگ باید به بخشهای کوچکتر تقسیم شوند.
2. افزایش کیفیت Retrieval
اگر یک Document بسیار بزرگ را به یک Vector تبدیل کنیم:
- معنی کلی Document ذخیره میشود.
- اما جزئیات موضوعات داخل آن از بین میروند.
Chunking باعث میشود:
- Vectorها دقیقتر باشند.
- Retriever بتواند بخش مرتبطتر را پیدا کند.
3. کاهش حجم اطلاعات ارسالشده به LLM
بدون Chunking ممکن است کل Document به LLM ارسال شود.
نتیجه:
- Context Window سریع پر میشود.
- اطلاعات غیرمرتبط زیادی وارد Prompt میشود.
با Chunking:
فقط بخش مرتبط Document به LLM داده میشود.
مشکل Vector کردن Documentهای بزرگ
فرض کنید:
Knowledge Base شامل:
1000 کتاب
باشد.
اگر هر کتاب را به یک Vector تبدیل کنیم:
نتیجه:
1000 Vector
خواهد بود.
مشکل
یک Vector باید معنی کل کتاب را نمایش دهد.
اما یک کتاب شامل:
- فصلهای مختلف
- موضوعات مختلف
- صفحات مختلف
است.
در نتیجه:
Vector نمیتواند معنی دقیق یک فصل یا صفحه خاص را نشان دهد.
بلکه یک میانگین کلی از تمام محتوا ایجاد میکند.
نتیجه
کیفیت Search کاهش پیدا میکند.
همچنین Retriever به جای بخش مرتبط:
کل کتاب را برمیگرداند.
این موضوع باعث:
- پر شدن Context Window LLM
- افزایش اطلاعات غیرضروری
میشود.
راهحل: تقسیم Document به Chunk
به جای کتاب کامل:
آن را به بخشهای کوچکتر تقسیم میکنیم.
مثلاً:
- Page
- Paragraph
- Sentence
نتیجه:
به جای:
1000 Book
ممکن است داشته باشیم:
1,000,000 Paragraph
اما:
Vector Databaseها به راحتی میتوانند این حجم Vector را مدیریت کنند.
انتخاب اندازه Chunk (Chunk Size)
یکی از مهمترین تصمیمها:
اندازه مناسب Chunk چقدر باشد؟
Chunk خیلی بزرگ
مثلاً:
تقسیم در سطح Chapter
مشکلات:
- هنوز اطلاعات زیادی در یک Vector فشرده میشود.
- معنی دقیق موضوعات کوچکتر مشخص نیست.
- حجم زیادی وارد Context Window میشود.
Chunk خیلی کوچک
مثلاً:
تقسیم در سطح Word
مشکل:
Vectorها Context خود را از دست میدهند.
مثلاً:
یک کلمه بدون:
- جمله قبل
- جمله بعد
- موضوع پاراگراف
معنی کافی ندارد.
حتی Chunk در سطح Sentence نیز ممکن است بیش از حد کوچک باشد.
اندازه مناسب Chunk
هیچ اندازه ثابت و ایدهآلی برای همه پروژهها وجود ندارد.
هدف:
ایجاد تعادل بین:
- اطلاعات زیاد در یک Vector
- اطلاعات کم در یک Vector
است.
Fixed Size Chunking
سادهترین روش Chunking:
Fixed Size Chunking
است.
در این روش:
ابتدا اندازه Chunk مشخص میشود.
مثلاً:
250 Character
تقسیم:
Chunk 1:
Character 1 تا 250
Chunk 2:
Character 251 تا 500
Chunk 3:
Character 501 تا 750
و به همین ترتیب.
مشکل Fixed Size Chunking
مشکل این است که:
محل تقسیم همیشه منطقی نیست.
ممکن است:
- وسط یک کلمه قطع شود.
- دو بخش مرتبط یک پاراگراف از هم جدا شوند.
Overlap در Chunking
برای حل مشکل از:
Chunk Overlap
استفاده میشود.
یعنی:
بخشی از هر Chunk با Chunk قبلی و بعدی مشترک باشد.
مثال
Chunk Size:
250 Character
Overlap:
25 Character
تقسیم:
Chunk 1:
1 تا 250
Chunk 2:
226 تا 475
Chunk 3:
451 تا 700
در این مثال:
Overlap برابر:
10%
است.
مزایای Overlap
Overlap باعث میشود:
- کلمات در مرز Chunkها قطع نشوند.
- Context اطراف کلمات حفظ شود.
کلمات وسط Chunk:
- Context قبل و بعد را دارند.
کلمات نزدیک مرز:
- در دو Chunk ظاهر میشوند.
در نتیجه احتمال پیدا شدن همراه با Context مناسب بیشتر میشود.
تأثیر میزان Overlap
افزایش Overlap معمولاً:
باعث افزایش کیفیت Retrieval میشود.
اما هزینه دارد:
- تعداد Vectorها افزایش پیدا میکند.
- اطلاعات تکراری بیشتری ذخیره میشود.
Recursive Character Text Splitting
یک روش پویاتر:
Recursive Character Text Splitting
است.
ایده اصلی
به جای اندازه ثابت، متن بر اساس یک Character خاص تقسیم میشود.
مثال:
تقسیم بر اساس:
newline character
یعنی محل پایان پاراگرافها.
مزیت Recursive Splitting
این روش ساختار Document را بهتر حفظ میکند.
نتیجه:
- احتمال اینکه مفاهیم مرتبط در یک Chunk باقی بمانند بیشتر است.
محدودیت Recursive Splitting
اندازه Chunkها ثابت نیست.
ممکن است:
- بعضی Chunkها بسیار بزرگ شوند.
- بعضی Chunkها بسیار کوچک شوند.
بسته به محل قرارگیری جداکنندهها.
Chunking بر اساس نوع Document
اگر Knowledge Base شامل انواع مختلف Document باشد، میتوان روش متفاوتی برای هر نوع استفاده کرد.
مثال:
HTML
تقسیم بر اساس:
- Paragraph Tag
- Header Tag
Python Code
تقسیم بر اساس:
- Function Definition
Text Document
تقسیم بر اساس:
- Newline Character
Metadata در Chunking
اگر Documentها Metadata داشته باشند:
Chunkهای ساختهشده باید Metadata منبع اصلی را به ارث ببرند.
مثلاً:
Document اصلی:
- عنوان
- نویسنده
- تاریخ
Chunkها نیز باید این اطلاعات را داشته باشند.
همچنین میتوان اطلاعات مکان Chunk را اضافه کرد.
مثلاً:
- شماره صفحه
- موقعیت در Document
کتابخانههای Chunking
روشهایی مانند:
- Fixed Size Chunking با Overlap
- Character Splitting
آنقدر ساده هستند که میتوان آنها را دستی پیادهسازی کرد.
اما کتابخانههای آمادهای نیز برای این کار وجود دارند.
پیشنهاد شروع
برای شروع یک سیستم RAG:
پیشنهاد مناسب:
Chunk Size ≈ 500 characters
با:
Overlap = 50 تا 100 characters
است.
جمعبندی
- Chunking یعنی تقسیم Documentهای بزرگ به بخشهای کوچکتر.
- Chunking باعث افزایش کیفیت Retrieval و کاهش مصرف Context Window میشود.
- تبدیل یک Document کامل به یک Vector معمولاً باعث از دست رفتن جزئیات معنایی میشود.
- Chunk خیلی بزرگ باعث کاهش دقت میشود.
- Chunk خیلی کوچک باعث از دست رفتن Context میشود.
- Fixed Size Chunking سادهترین روش است.
- Overlap بین Chunkها باعث حفظ Context در مرزها میشود.
- Recursive Character Text Splitting ساختار Document را بهتر حفظ میکند.
- نوع Document میتواند روش Chunking مناسب را تعیین کند.
- نقطه شروع مناسب معمولاً Chunk حدود ۵۰۰ کاراکتر با ۵۰ تا ۱۰۰ کاراکتر Overlap است.