إنتقل إلى المحتوى الرئيسي

الفصل 2: استراتيجيات تقسيم النص

مقدمة​

تقسيم النص (chunking) حاسم لأداء RAG. يؤثّر حجم الـ chunk والاستراتيجية المناسبة كثيرًا في جودة الاسترجاع ودقة التوليد.

لماذا يهم الـ Chunking​

مشكلات غياب الـ chunking:

  • الوثائق الكاملة أكبر من اللازم
  • يعيد الاسترجاع محتوى غير ذي صلة
  • يهدر نافذة سياق LLM

المعاملات الأساسية​

حجم الـ Chunk​

عدد الأحرف أو الـ tokens لكل chunk:

حجم الـ Chunkالمزاياالعيوب
صغير (256)استرجاع دقيققد يفقد السياق
متوسط (512-1024)متوازنمناسب لمعظم الحالات
كبير (2000+)سياق أكثراسترجاع أقل دقة

تداخل الـ Chunk​

نص مشترك بين chunks متتالية:

Chunk 1: [_______________]
Chunk 2: [_______________]
^overlap^

لماذا التداخل؟

  • يمنع قطع الجمل في منتصف الفكرة
  • يحافظ على السياق عبر حدود الـ chunks
  • نموذجيًا: 10-20% من حجم الـ chunk

استراتيجيات التقسيم​

1. التقسيم التكراري بالأحرف​

المقاربة الأكثر شيوعًا - تقسّم حسب تسلسل فواصل:

from langchain.text_splitter import RecursiveCharacterTextSplitter

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

chunks = splitter.split_documents(documents)

تسلسل الفواصل:

  1. أسطر فارغة مزدوجة (فقرات)
  2. أسطر جديدة مفردة
  3. نقاط (جمل)
  4. مسافات (كلمات)
  5. أحرف (الملاذ الأخير)

2. التقسيم القائم على الـ Tokens​

يستخدم عدد الـ tokens الفعلي (مهم لحدود LLM):

from langchain.text_splitter import TokenTextSplitter

splitter = TokenTextSplitter(
chunk_size=500, # tokens, not characters
chunk_overlap=50,
encoding_name="cl100k_base" # GPT-4 tokenizer
)

3. التقسيم بالجمل​

يحافظ على حدود الجمل:

from langchain.text_splitter import SentenceTransformersTokenTextSplitter

splitter = SentenceTransformersTokenTextSplitter(
chunk_overlap=50,
tokens_per_chunk=256
)

4. التقسيم الدلالي​

يقسّم بناءً على التشابه الدلالي:

from langchain_experimental.text_splitter import SemanticChunker
from langchain.embeddings import OpenAIEmbeddings

splitter = SemanticChunker(
OpenAIEmbeddings(),
breakpoint_threshold_type="percentile"
)

# Chunks based on semantic similarity
semantic_chunks = splitter.split_documents(documents)

5. التقسيم حسب عناوين Markdown​

يحترم بنية الوثيقة:

from langchain.text_splitter import MarkdownHeaderTextSplitter

headers_to_split_on = [
("#", "Header 1"),
("##", "Header 2"),
("###", "Header 3"),
]

splitter = MarkdownHeaderTextSplitter(
headers_to_split_on=headers_to_split_on
)

اختيار حجم الـ Chunk​

def optimal_chunk_size(embedding_model, llm_context_window, top_k):
"""
Calculate optimal chunk size
"""
# Leave room for prompt template and response
available_tokens = llm_context_window * 0.6

# Divide by number of chunks to retrieve
chunk_tokens = available_tokens / top_k

# Convert to characters (roughly 4 chars per token)
return int(chunk_tokens * 4)

# Example: GPT-4 with 8K context, retrieving 5 chunks
optimal = optimal_chunk_size(
embedding_model="text-embedding-3-small",
llm_context_window=8192,
top_k=5
)
# Result: ~3900 characters per chunk

جدول المقارنة​

الاستراتيجيةالأنسب لـجودة الـ Chunk
Recursive Characterغرض عامجيدة
Token-Basedإدارة سياق LLMممتازة
Sentenceأنظمة الأسئلة والأجوبةجيدة
Semanticمحتوى متغيّرممتازة
Markdown Headersوثائق منظّمةممتازة

أفضل الممارسات​

  1. ابدأ بالافتراضيات - 1000 حرف، تداخل 200
  2. اختبر أحجامًا مختلفة - قيّم جودة الاسترجاع
  3. طابق المحتوى - الوثائق التقنية قد تحتاج chunks أكبر
  4. راعِ embeddings - لبعض النماذج حدود tokens قصوى
  5. احفظ metadata - تتبّع مصدر الـ chunk وموضعه
# Production chunking pipeline
def chunk_documents(documents, chunk_size=1000, overlap=200):
splitter = RecursiveCharacterTextSplitter(
chunk_size=chunk_size,
chunk_overlap=overlap,
length_function=len,
add_start_index=True # Track position
)

chunks = splitter.split_documents(documents)

# Add chunk index to metadata
for i, chunk in enumerate(chunks):
chunk.metadata["chunk_index"] = i
chunk.metadata["total_chunks"] = len(chunks)

return chunks

ملخص​

  • حجم الـ chunk يؤثّر في دقة الاسترجاع مقابل السياق
  • التداخل يمنع فقدان المعلومات عند الحدود
  • الاستراتيجية ينبغي أن تطابق نوع وثيقتك
  • اختبر وكرّر لإيجاد الإعدادات المثلى

الخطوات التالية​

تابع إلى الفصل 3: أنواع الملفات للتعرّف على التعامل مع الوثائق المعقّدة.