Retrieval-Augmented Generation (RAG)

تسلط بر استراتژی‌های تکه‌بندی برای سیستم‌های RAG با وفاداری بالا

سیستم‌های تولید تقویت‌شده با بازیابی (RAG) به استاندارد صنعتی برای اتصال مدل‌های زبانی بزرگ (LLMs) به داده‌های خاص و اختصاصی تبدیل شده‌اند. با این حال، کیفیت یک سیستم RAG اغلب نه توسط خود LLM، بلکه توسط پیش‌پردازش داده‌های ورودی تعیین می‌شود. مهم‌ترین مرحله در این خط لوله تکه‌بندی (Chunking) است. اگر تکه‌های شما خیلی کوچک باشند، زمینه را از دست می‌دهید؛ اگر خیلی بزرگ باشند، مرتبطی معنایی رقیق می‌شود. انتخاب استراتژی تکه‌بندی مناسب، تفاوت بین یک دستیار مفید و یک ربات توهم‌ساز است.

چرا تکه‌بندی مهم است؟

مدل‌های زبانی بزرگ (LLMs) دارای پنجره زمینه محدودی هستند. پایگاه‌های داده برداری، امبدینگ‌ها (Embeddings) را ذخیره می‌کنند که معنای معنایی متن را نشان می‌دهند. برای اطمینان از اینکه جستجوی برداری بتواند مرتبط‌ترین اطلاعات را پیدا کند، باید اسناد را به تکه‌های قابل مدیریت تقسیم کنیم. هدف ایجاد تکه‌هایی است که خودکفا باشند اما در عین حال انسجام معنایی داشته باشند. یک سند که به درستی تکه‌بندی نشده باشد ممکن است یک جمله را نصف کند یا یک عنوان را از بدنه آن جدا کند که منجر به بازیابی‌های نامرتبط می‌شود.

۱. تکه‌بندی با اندازه ثابت: خط پایه

ساده‌ترین رویکرد، تکه‌بندی با اندازه ثابت است. این روش متن را به تکه‌هایی با تعداد مشخصی از کاراکترها یا توکن‌ها تقسیم می‌کند، اغلب با مقداری همپوشانی. این روش سریع و آسان برای پیاده‌سازی است، اما از انسجام ساختاری متن غافل می‌شود.


import textsplitter

def fixed_size_chunk(text, chunk_size=500, overlap=50):
    chunks = []
    for i in range(0, len(text), chunk_size - overlap):
        chunks.append(text[i : i + chunk_size])
    return chunks

# Example:
# text = "This is a very long document..."
# chunks = fixed_size_chunk(text)

۲. تقسیم‌بندی بازگشتی کاراکترها: رویکرد ساختاری

بیشتر سیستم‌های تولیدی از تقسیم‌بندی بازگشتی کاراکترها استفاده می‌کنند. این روش ابتدا سعی می‌کند متن را در مرزهای طبیعی (مانند پاراگراف‌ها یا جملات) تقسیم کند، قبل از اینکه به کاراکترها روی بیاورد. این روش سلسله‌مراتب متن را رعایت می‌کند: پاراگراف → جمله → کلمه → کاراکتر. این روش بهتر از روش‌های اندازه ثابت، معنا را حفظ می‌کند.


from langchain.text_splitter import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=200,
    length_function=len,
    separators=["\n\n", "\n", " ", ""]
)

# This splitter will try to keep paragraphs together, 
# then sentences, then words, and finally characters.
docs = splitter.split_documents([Document(page_content=raw_text)])

۳. تکه‌بندی معنایی: روش پیشرفته

تکه‌بندی معنایی از امبدینگ‌ها برای تشخیص جایی که معنای متن به طور قابل توجهی تغییر می‌کند، استفاده می‌کند. این روش شباهت کسینوسی بین جملات مجاور را تحلیل می‌کند. وقتی شباهت از یک آستانه پایین‌تر می‌آید، فرض می‌کند که موضوع جدیدی آغاز شده و یک شکاف تکه ایجاد می‌کند.

اگرچه این روش از نظر محاسباتی پرهزینه است، اما اغلب دقت بازیابی بالاتری را به ارمغان می‌آورد زیرا مفاهیم مرتبط را با هم گروه‌بندی می‌کند، صرف‌نظر از ساختار سند.


# Pseudocode for semantic chunking
def semantic_chunk(text, threshold=0.8):
    sentences = split_into_sentences(text)
    embeddings = get_embeddings(sentences)
    chunks = []
    current_chunk = [sentences[0]]
    
    for i in range(1, len(sentences)):
        sim = cosine_similarity(embeddings[i-1], embeddings[i])
        if sim < threshold:
            chunks.append(" ".join(current_chunk))
            current_chunk = [sentences[i]]
        else:
            current_chunk.append(sentences[i])
    chunks.append(" ".join(current_chunk))
    return chunks

بهترین روش‌ها برای پیاده‌سازی

  • همپوشانی کلیدی است: همیشه مقداری همپوشانی (۱۰-۲۰٪) بین تکه‌ها را شامل شوید تا از از دست رفتن زمینه در مرزها جلوگیری کنید.
  • به متادیتا احترام بگذارید: اگر داده‌های منبع شما ساختاریافته هستند (مانند JSON یا Markdown)، ابتدا آن‌ها را تجزیه کنید و بر اساس واحدهای منطقی (مثلاً برای هر نقطه پایانی API یا هر بخش) تکه‌بندی کنید.
  • آزمایش کنید: هیچ روش "مناسب برای همه" وجود ندارد. اندازه‌ها و استراتژی‌های مختلف تکه‌بندی را با استفاده از مجموعه داده پرسش‌های واقعی خود آزمایش کنید تا دقت بازیابی را اندازه بگیرید.

نتیجه‌گیری

تکه‌بندی فقط یک مرحله پیش‌پردازش نیست؛ بلکه یک جزء اصلی از معماری RAG شماست. با تقسیم‌بندی بازگشتی کاراکترها برای یک خط پایه محکم شروع کنید و اگر متوجه شدید که بازیابی‌های شما زمینه‌های ظریف را از دست می‌دهند، به تکه‌بندی معنایی روی بیاورید. با هم‌راستایی استراتژی تکه‌بندی خود با ساختار داده‌ها و معنای پرسش‌های کاربری خود، عملکرد و قابلیت اطمینان برنامه‌های هوش مصنوعی خود را به طور قابل توجهی بهبود خواهید بخشید.

Share: