فراتر از RAG ساده: پیادهسازی قطعهبندی معنایی، جستجوی ترکیبی (BM25 + Dense) و بازرتبهبندی در محیط تولید

دموی اولیه RAG به طرز فریبندهای ساده است. چند سند را قطعهبندی میکنید، آنها را Embedding میکنید، بردارها را ذخیره میکنید، Top-k را با شباهت کسینوسی بازیابی میکنید و زمینه را به یک LLM میدهید. در یک اثبات مفهوم، این فوقالعاده به نظر میرسد. در محیط تولید، به طور خطرناکی شکننده است.
خطوط لوله RAG ساده به دلایل قابل پیشبینی و در سطح مهندسی شکست میخورند:
شباهت برداری با ارتباط سند یکسان نیست — یک قطعه از نظر معنایی نزدیک ممکن است در واقع به سؤال پاسخ ندهد
قطعهبندی با اندازه ثابت، زمینه ساختاری را از بین میبرد — تقسیم هر ۵۰۰ توکن، جدولها را قطع میکند، بندها را از شرایطشان جدا میکند و کد را از مستنداتش جدا میکند
جستجوی برداری خالص نمیتواند شناسههای دقیق را مدیریت کند — شماره قطعات، کدهای خطا و بندهای قرارداد نیازمند دقت واژگانی هستند که Embeddingها اغلب از دست میدهند
بدون لایه اعتبارسنجی، نویز به مدل میرسد — نتایج رتبهبالا ممکن است ناقص، منقضی یا متناقض باشند
این مقاله پاسخ معماری را بررسی میکند:
قطعهبندی مرزهای معنایی، بازیابی ترکیبی (BM25 + Embeddingهای Dense) و بازرتبهبندی با Cross-Encoder — دیسیپلینهای تولیدی که سیستمهای RAG که کار میکنند را از سیستمهای RAG که در دمو تأثیرگذار هستند اما تحت ترافیک واقعی سازمانی شکست میخورند جدا میکند.
بخش ۱ — چرا قطعهبندی ساده شکست میخورد: مشکل فشردهسازی Embedding
پایه هر سیستم RAG، استراتژی قطعهبندی است. و شایعترین رویکرد — قطعهبندی با اندازه ثابت — فعالانه کیفیت بازیابی را کاهش میدهد.
واقعیت فشردهسازی Embedding
مدلهای Embedding یک قطعه کامل را با یک بردار ثابت نمایش میدهند. این یک مشکل بنیادی ایجاد میکند:
بخش سند:
"احراز هویت از توکنهای OAuth با انقضا استفاده میکند..."
"محدودیتهای نرخ به ازای هر کلید API با Backoff اعمال میشود..."
قطعه با اندازه ثابت (۵۰۰ توکن):
حاوی هر دو محتوای احراز هویت و محدودیت نرخ
Embedding برای این قطعه:
{ OAuth، توکنها، احراز هویت، محدودیتهای نرخ، تلاش مجدد }
← "میانگین" معنایی چند موضوع
پرسوجو: "محدودیتهای نرخ چگونه مدیریت میشوند؟"
نتیجه جستجوی شباهت:
تطابق ضعیف — Embedding توسط محتوای احراز هویت رقیق شدهپیامد مهندسی: Embedding دیگر یک ایده منسجم را نمایش نمیدهد. یک ترکیب فشرده از موضوعات نامرتبط را نمایش میدهد — و جستجوی شباهت مبهم و غیرقابل اعتماد میشود.
مشکل تخریب ساختاری
قطعهبندی با اندازه ثابت به ویژه برای اسناد سازمانی ساختاریافته مخرب است:
| ساختار سند | شکست قطعهبندی با اندازه ثابت |
|---|---|
| جدولها | سرصفحهها را از داده جدا میکند — اعداد معنای خود را از دست میدهند |
| بندهای حقوقی | شرایط را از استثناهایشان جدا میکند |
| کد + Docstring | کد را از مستندات جدا میکند |
| چیدمانهای چند-ستونی | متن آشفته و غیرقابل خواندن تولید میکند |
| بخشهای سلسلهمراتبی | زمینه والد-فرزند را از دست میدهد |
یک قطعه که در داخل سند اصلی خود واضح به نظر میرسد، اغلب وقتی به تنهایی بازیابی میشود مبهم میشود.
بخش ۲ — قطعهبندی معنایی: تقسیم بر اساس معنا، نه تعداد توکن
قطعهبندی معنایی مشکل فشردهسازی را با تقسیم اسناد در امتداد مرزهای معنا حل میکند — نه محدودیتهای توکن دلبخواهی.
چگونه قطعهبندی معنایی کار میکند
فرآیند جملات را Embedding میکند و شباهت معنایی بین واحدهای مجاور را اندازه میگیرد:
گام ۱: تقسیمبندی جمله سند را به جملات گسسته تقسیم کنید (NLTK، spaCy) گام ۲: تولید Embedding هر جمله را با یک مدل Embedding کنید (sentence-transformers) گام ۳: پروفایل شباهت شباهت کسینوسی بین Embeddingهای جملات متوالی را محاسبه کنید گام ۴: تشخیص مرز شباهت بالا → همان موضوع (ادامه قطعه) افت شدید → انتقال موضوع (درج مرز) گام ۵: مونتاژ قطعه جملات بین مرزها را به قطعات منسجم ادغام کنید اختیاری: ۱-۳ جمله همپوشانی برای حفظ زمینه در لبهها
مقایسه استراتژیهای قطعهبندی
| جنبه | قطعهبندی با اندازه ثابت | قطعهبندی معنایی |
|---|---|---|
| سرعت پردازش | سریع — محاسبه حداقلی | کندتر — نیازمند Embedding + شباهت |
| اندازه قطعه | قابل پیشبینی (N توکن) | متغیر (با محتوا سازگار میشود) |
| حفظ زمینه | پایین — تقسیمها معنا را نادیده میگیرند | بالا — ساختار منطقی را حفظ میکند |
| Recall بازیابی | پایینتر — Embeddingهای رقیق | بالاتر — Embeddingهای موضوع-خالص |
| الزام همپوشانی | ضروری (از دست دادن اطلاعات) | حداقلی (ایدهها دست نخورده میمانند) |
| بهترین کاربرد | محتوای پرحجم و یکنواخت | RAG که کیفیت پاسخ مهم است |
تنظیم آستانه بر اساس نوع سند
آستانه شباهت، حساسیت مرز را تعیین میکند:
| نوع سند | آستانه توصیهشده | منطق |
|---|---|---|
| مستندات فنی | ۰.۷-۰.۸ | تغییرات مکرر موضوع، قطعات دانهای مورد نیاز |
| محتوای روایی | ۰.۵-۰.۶ | حفظ زمینه در قطعات طولانیتر |
| حقوقی/قانونی | ۰.۶-۰.۷ | تعادل بین دقت بند و زمینه |
بهترین شیوههای تولید
از پیادهسازیهای RAG تولیدی:
مدلهای Embedding مناسب دامنه انتخاب کنید —
all-mpnet-base-v2برای اسناد فنی،all-MiniLM-L6-v2برای متن عمومیپنجرههای همپوشانی اضافه کنید — ۱-۳ جمله در مرزها از از دست دادن اطلاعات جلوگیری میکند
قطعات را با فراداده برچسبگذاری کنید — سرصفحههای بخش، شماره صفحات، نوع سند سیگنالهای بازیابی فراتر از شباهت معنایی ایجاد میکنند
هرگز از مرزهای بخش عبور نکنید — یکپارچگی ساختاری غیرقابل مذاکره است
۳۰۰-۵۰۰ توکن را برای مدلهای کلاس MiniLM هدف بگیرید — این نقطه شیرین برای خلوص معنایی است
اصل مهندسی: یک مدل Embedding ضعیفتر با قطعات معنایی تمیز، از یک مدل قویتر با قطعات اندازه-ثابت رقیق بهتر عمل میکند.
بخش ۳ — جستجوی ترکیبی: چرا بازیابی فقط-برداری شکست میخورد
حتی با قطعهبندی کامل، بازیابی فقط-برداری نقاط کور ساختاری دارد.
شکاف واژگانی
انواع مختلف پرسوجو نیازمند مسیرهای بازیابی اساساً متفاوت هستند:
| نوع پرسوجو | مثال | جستجوی برداری | جستجوی واژگانی |
|---|---|---|---|
| مفهومی گسترده | “سیاست کار از راه دور ما چیست؟” | ✅ قوی | ⚠️ ضعیف |
| شناسه دقیق | “کد خطا E-4021” | ❌ ضعیف | ✅ قوی |
| شماره قطعه | “PN-8842-A” | ❌ ضعیف | ✅ قوی |
| بند قرارداد | “بخش ۷.۳(b)” | ❌ ضعیف | ✅ قوی |
| بازنویسی معنایی | “چگونه رمز عبورم را بازنشانی کنم؟” | ✅ قوی | ⚠️ ضعیف |
مشکل اصلی: جستجوی برداری خالص به طور روتین تطابقهای شناسه دقیق را بیش از حد پایین رتبهبندی میکند، وقتی قطعات اطراف از زبان مشابه استفاده میکنند.
BM25: پایه واژگانی
BM25 (Best Matching 25) الگوریتم رتبهبندی واژگانی استاندارد صنعت است. اسناد را بر اساس اینها امتیاز میدهد:
فراوانی اصطلاح — چند بار اصطلاحات پرسوجو در سند ظاهر میشوند
فراوانی معکوس سند — این اصطلاحات چقدر در مجموعه نادر هستند
نرمالسازی طول سند — از سوگیری به سمت اسناد طولانیتر جلوگیری میکند
چرا BM25 برای RAG سازمانی مهم است: اصطلاحات دقیق، شناسهها و اصطلاحات تخصصی حفظ میشوند — بدون فشردهسازی معنایی، بدون تقریب Embedding.
پیادهسازی جستجوی ترکیبی
پایگاههای داده برداری مدرن، بازیابی ترکیبی را به صورت بومی پشتیبانی میکنند. Milvus به عنوان مثال، به BM25 و Embeddingهای Dense در یک مجموعه واحد اجازه میدهد:
# اسکیما با فیلدهای Dense و Sparse (BM25) schema.add_field(field_name="text", datatype=DataType.VARCHAR, enable_analyzer=True, enable_match=True) schema.add_field(field_name="sparse_bm25", datatype=DataType.SPARSE_FLOAT_VECTOR) schema.add_field(field_name="dense", datatype=DataType.FLOAT_VECTOR, dim=1536) # تابع BM25 متن را به صورت خودکار به بردارهای Sparse تبدیل میکند bm25_function = Function( name="bm25", function_type=FunctionType.BM25, input_field_names=["text"], output_field_names="sparse_bm25", ) # ایندکس هر دو فیلد index_params.add_index(field_name="dense", index_type="IVF_FLAT", metric_type="IP") index_params.add_index(field_name="sparse_bm25", index_type="SPARSE_WAND", metric_type="BM25")
Reciprocal Rank Fusion (RRF): ادغام رتبهبندیها
امتیازات Dense و Sparse روی مقیاسهای غیرقابل مقایسه زندگی میکنند. جمع یا میانگین امتیازهای خام بیمعنی است — یک سیگنال غالب میشود.
RRF رتبهبندیها را ادغام میکند، نه امتیازها:
def reciprocal_rank_fusion(rankings, k=60): """ادغام لیستهای رتبهبندیشده از شناسههای سند به یک رتبهبندی با امتیاز RRF.""" scores = {} for ranking in rankings: for rank, doc_id in enumerate(ranking, start=1): scores[doc_id] = scores.get(doc_id, 0.0) + 1.0 / (k + rank) return scores
چگونه کار میکند: هر سند یک امتیاز بر اساس موقعیت رتبه خود در هر رتبهبندی انباشته میکند. سندی که در هر دو جستجو رتبه بالا دارد، برنده میشود. ثابت k=60 از مقاله اصلی RRF، تأثیر رتبههای بسیار بالا را کاهش میدهد.
وزندهی سازگار با پرسوجو: تکامل بعدی
RRF استاتیک (α = ۰.۵) فرض میکند که BM25 و Dense برای هر پرسوجو به یک اندازه ارزشمند هستند. این نادرست است:
| پرسوجو | سیگنال بهینه | مشکل با α=۰.۵ ثابت |
|---|---|---|
| پرسوجوی کلیدواژهای بالینی | BM25 | کموزن کردن واژگانی |
| سؤال مبتنی بر بازنویسی | Dense | کموزن کردن معنایی |
سیستمهای سازگار با پرسوجو یک Router آموزش میدهند تا وزنهای ادغام به ازای هر پرسوجو را پیشبینی کند:
# RRF وزندار با آلفای آموختهشده به ازای هر پرسوجو score(d) = α · 1/(60 + rank_bm25(d)) + (1−α) · 1/(60 + rank_dense(d)) # α از ویژگیهای پرسوجو آموخته میشود (طول، آمار IDF، اطمینان بازیابنده)
نتایج بنچمارک در ۵ مجموعه داده BEIR، ۲۲۵ پرسوجوی نگهداشتهشده:
| روش | NDCG@100 | MRR@100 | Recall@100 |
|---|---|---|---|
| BM25 | ۰.۳۲۷ | ۰.۳۶۲ | ۰.۵۱۳ |
| Dense (BGE-M3) | ۰.۴۲۰ | ۰.۴۴۹ | ۰.۶۴۴ |
| RRF استاتیک (α=۰.۵) | ۰.۴۰۴ | ۰.۴۳۱ | ۰.۶۴۱ |
| wRRF Strong (XGBoost) | ۰.۴۲۴ | ۰.۴۵۳ | ۰.۶۵۱ |
| wRRF MoE (SVR) | ۰.۴۲۶ | ۰.۴۶۲ | ۰.۶۴۷ |
| سقف Oracle | ۰.۴۸۷ | — | — |
بینش مهندسی: ادغام سازگار به طور قابل توجهی از RRF استاتیک در NDCG بهتر عمل میکند (p ≤ ۰.۰۱۸). یک Router ارزان ۱۶-ویژگی از نظر آماری غیرقابل تشخیص از Routerهای گران مبتنی بر Embedding عمل میکند — با ~۱ms سربار استنتاج.
بخش ۴ — بازرتبهبندی با Cross-Encoder: لایه دقت
بازیابی ترکیبی Recall را بهبود میبخشد. اما نتایج رتبهبالا همیشه آنهایی نیستند که واقعاً به سؤال پاسخ میدهند.
محدودیت Bi-Encoder
Embeddingهای Bi-Encoder اسناد را در زمان ایندکس، بدون دانش از پرسوجوهای آینده به بردار فشرده میکنند. این دو مشکل ایجاد میکند:
از دست دادن اطلاعات از طریق فشردهسازی — اسناد پیچیده به نقاط میانگین در فضای برداری تبدیل میشوند
نمایشهای مستقل از پرسوجو — Embeddingها نمیتوانند سیگنالهای ارتباط خاص پرسوجو را ثبت کنند
پیامد: بازیابی Top-k اغلب اسنادی را شامل میشود که از نظر موضوعی مرتبط اما واقعاً مرتبط با سؤال خاص نیستند.
Cross-Encoder: پردازش مشترک پرسوجو-سند
Cross-Encoder پرسوجو و سند را به صورت مشترک در یک پاس رو به جلو پردازش میکند:
Bi-Encoder:
پرسوجو → Embedding Q ─┐
├─→ شباهت کسینوسی
سند → Embedding D ─┘
(موازی، کدگذاری مستقل)
Cross-Encoder:
پرسوجو + سند → شبکه عصبی → امتیاز ارتباط
(کدگذاری مشترک، توجه اشتراکی)این پردازش مشترک روابط معنایی ریزدانه را ثبت میکند که Bi-Encoder از دست میدهد.
چرا Cross-Encoder یک گام دوم است
Cross-Encoder از نظر محاسباتی گران است — به صورت درجه دوم با طول ورودی مقیاس میشود و باید برای هر جفت پرسوجو-سند اجرا شود. الگوی تولیدی:
گام ۱: بازیابی ترکیبی (BM25 + Dense) → بازیابی ۵۰-۱۰۰ نامزد (سریع، Recall بالا) گام ۲: بازرتبهبندی با Cross-Encoder → امتیازدهی مجدد نامزدها با پردازش مشترک پرسوجو-سند → نگهداشتن ۱۰ تای برتر (کند، دقت بالا)
قانون: “بسیاری را بازیابی کنید، بر روی چندی بازرتبهبندی کنید”.
انتخاب مدل
| مدل | تأخیر | کیفیت | کاربرد |
|---|---|---|---|
ms-marco-MiniLM-L6-v2 | ~۵۰ms | خوب | پیشفرض، حجم بالا |
BAAI/bge-reranker-large | ~۱۰۰ms | بهتر | بازیابی حیاتی از نظر کیفیت |
cohere rerank-v4.0-pro | ~۲۰۰ms | بهترین | سازمانی، مبتنی بر API |
پیادهسازی بازرتبهبندی
from sentence_transformers import CrossEncoder reranker = CrossEncoder("cross-encoder/ms-marco-MiniLM-L6-v2") def rerank(query, candidates, top_k=10): # کوتاهسازی برای کارایی (۲۰۰-۴۰۰ کاراکتر) pairs = [(query, doc["content"][:400]) for doc in candidates] scores = reranker.predict(pairs) scored_docs = sorted(zip(candidates, scores), key=lambda x: x[1], reverse=True) return [{"doc": doc, "score": float(score)} for doc, score in scored_docs[:top_k]]
تأثیر بنچمارک: افزودن یک Cross-Encoder بازرتبهبند به طور مداوم بهبودهای عظیم در دقت پاسخ نهایی در سیستمهای تولیدی را به ارمغان میآورد.
بخش ۵ — خط لوله کامل تولید
ترکیب هر سه تکنیک در یک معماری منسجم:
┌─────────────────────────────────────────────────────────────────┐
│ فاز Ingestion │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ بارگذار │───▶│ قطعهبندی │───▶│ ایندکس ترکیبی │ │
│ │ سند │ │ معنایی │ │ (Dense + BM25) │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ فاز بازیابی │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ پرسوجو │───▶│ بازیابی │───▶│ ادغام RRF │ │
│ │ │ │ موازی │ │ (ترکیب رتبهها) │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌────────┐ ┌────────┐ ┌─────────────┐ │
│ │ BM25 │ │ Dense │ │ ۵۰-۱۰۰ │ │
│ │ Top-K │ │ Top-K │ │ نامزد │ │
│ └────────┘ └────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ فاز بازرتبهبندی │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Cross- │───▶│ امتیازدهی │───▶│ ۵-۱۰ │ │
│ │ Encoder │ │ اسناد │ │ نتیجه برتر │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────┐
│ مولد LLM │
│ (زمینهسازی │
│ تقویتشده) │
└─────────────────┘اصول مهندسی
| لایه | اصل | منطق |
|---|---|---|
| Ingestion | قطعهبندی معنایی، نه اندازه ثابت | حفظ معنا، بهبود کیفیت Embedding |
| بازیابی | ترکیبی (BM25 + Dense) | پوشش هر دو پرسوجوی تطابق دقیق و معنایی |
| ادغام | RRF (مبتنی بر رتبه، نه امتیاز) | امتیازها در روشهای بازیابی غیرقابل مقایسه هستند |
| بازرتبهبندی | Cross-Encoder به عنوان پاس دوم | پردازش مشترک پرسوجو-سند برای دقت |
| فیلتر | بسیاری را بازیابی، بر روی چندی بازرتبهبندی | تعادل Recall و دقت |
بخش ۶ — چه زمانی از این معماری استفاده کنیم (و چه زمانی نه)
از قطعهبندی معنایی + جستجوی ترکیبی + بازرتبهبندی استفاده کنید وقتی:
✅ اسناد ساختار دارند (سرفصلها، جداول، بخشها)
✅ پرسوجوها شامل هر دو سؤال مفهومی و شناسه دقیق هستند
✅ دقت پاسخ حیاتی است (سازمانی، حقوقی، پزشکی، فنی)
✅ پایگاه دانش بزرگ و ناهمگن است
✅ بودجه تأخیر اجازه بازرتبهبندی را میدهد (~۵۰-۲۰۰ms سربار)
استفاده نکنید وقتی:
❌ اسناد یکنواخت و بدون ساختار هستند (لاگها، رونوشتها) — اندازه ثابت ممکن است کافی باشد
❌ تأخیر بسیار محدود است — بازرتبهبندی سربار اضافه میکند
❌ مجموعه کوچک است — جستجوی برداری ساده ممکن است کافی باشد
❌ زیرساخت Embedding وجود ندارد — با BM25 شروع کنید
RAG ساده یک خط پایه سریع برای نمونه اولیه است. RAG تولیدی یک دیسیپلین مهندسی سیستم است.
نتیجهگیری — از نمونه اولیه تا دیسیپلین تولیدی
شکاف بین یک دموی RAG و یک سیستم RAG تولیدی یک تکنیک واحد نیست. مجموعهای از دیسیپلینهای مهندسی است:
قطعهبندی معنایی تقسیم با شمارش توکن را با مرزهای حفظ معنا جایگزین میکند
بازیابی ترکیبی نقاط کور هر دو جستجوی واژگانی و معنایی را پوشش میدهد
Reciprocal Rank Fusion رتبهبندیهای غیرقابل مقایسه را بدون وزندهی دلبخواهی ادغام میکند
بازرتبهبندی با Cross-Encoder نویز را قبل از رسیدن به مدل فیلتر میکند
اینها پالایشهای اختیاری نیستند. آنها معماری حداقل قابل اجرا برای سیستمهای RAG هستند که باید تحت ترافیک واقعی سازمانی کار کنند.
سؤال این نیست که آیا سیستم RAG شما میتواند اسناد را بازیابی کند. سؤال این است که آیا میتواند اسناد درست را بازیابی کند — به طور قابل اعتماد، در مقیاس، تحت فشار.
شباهت برداری با ارتباط سند یکسان نیست. بازیابی با تولید یکسان نیست. و یک نمونه اولیه یک سیستم تولیدی نیست.
یادداشت نویسنده
این مقاله الگوهای معماری توسعهیافته در هنگام ساخت Binesh AI — یک چارچوب LLM قابل آموزش سفارشی با خطوط لوله RAG، قطعهبندی معنایی و بازیابی چندمرحلهای — را بازتاب میدهد. برای همکاری در معماری RAG سازمانی، از طریق صفحه تماس با من در ارتباط باشید.