در سیستمهای RAG، کاربران پرسشها را با همان لحن، ساختار و واژگانی که در مستندات پایگاه دانش شما ثبت شده مطرح نمیکنند. یک ناهماهنگی جزئی در انتخاب کلمات یا مطرحکردن پرسشی چندبخشی و مبهم، باعث میشود الگوریتمهای جستجوی معنایی و BM25 سند هدف را پیدا نکنند و سیستم اصلاً نتواند پاسخ مناسب را در اختیار مدل تولیدگر بگذارد.
لایه بازنویسی پرسش (Query Rewriting) با بهرهگیری از تکنیکهایی مثل HyDE، گسترش چندپرسشی و تجزیه، پرسش خام کاربر را پیش از ارسال به بازیاب دگرگون میکند؛ با تولید یک پاسخ فرضی یا تفکیک آن به چند زیرپرسش، بردار جستجو درست در همان جایی از فضای امبدینگ مینشیند که مستندات واقعی قرار دارند.
در این درس هر سه استراتژی را با کدهای پایتون و یک Mock LLM آفلاین پیادهسازی میکنیم و نتایج را با ترکیب متقابل رتبهها (RRF) مقایسه خواهیم کرد تا بتوانید خط لوله بازیابی خود را به صورت عملیاتی بهینهسازی کنید.
پرسشی که کاربر مینویسد، لزوماً همان پرسشی نیست که بازیاب شما میخواهد. بازنویسی، پیش از بازیابی این شکاف را پر میکند تا نمایه چیزی شبیه به ساختار خودِ پاسخ را ببیند.
اهداف یادگیری
- پیادهسازی امبدینگ فرضی سند (Hypothetical Document Embeddings یا HyDE): تولید پاسخ ساختگی، ساخت امبدینگ آن و بازیابی بر اساس این بردار بهجای بردار پرسش.
- پیادهسازی گسترش چندپرسشی (Multi-query expansion): بازنویسی یک پرسش به N عبارت معادل، بازیابی با تکتک آنها و merge کردن اجتماع نتایج با ادغام متقابل رتبهها (Reciprocal Rank Fusion یا RRF).
- پیادهسازی تجزیه پرسش (Query decomposition): شکستن یک پرسش پیچیده به چند زیرپرسش، بازیابی به ازای هر زیرپرسش و سپس merge کردن نتایج.
- مقایسهی سربهسر (Head to head) این سه بازنویس روی دادههای نمونه (Fixture) و تحلیل زمان برتری هر استراتژی.
- اتصال یک مدل زبانی ساختگی (Mock LLM) با خروجیهای قطعی و منطبق بر نمونهها تا حلقهی بازنویس بهصورت کاملاً آفلاین اجرا شود.
صورت مسئله
کاربری مینویسد: «تیم ما وقتی آپلودها شکست میخورند و بودجه تمام شده چه کاری انجام میدهد؟». در مجموعهاسناد (Corpus)، متنی هست که میگوید: «تابع AbortMultipartOnFail یک آپلود چندبخشی در حال اجرای S3 را متوقف کرده و هنگام شکست آپلود، بودجهی تلاش مجدد به ازای هر باکت را کاهش میدهد». پرسش و سند هیچ عبارت اسمی مشترکی ندارند. در نتیجه BM25 کاملاً آن را از دست میدهد. بایانکودر (Bi-encoder) سند را در رتبهی سوم یا چهارم میگذارد؛ چون بردار پرسش در ناحیهای از فضای امبدینگ مینشیند که اسناد تسکهای لغوشده را ترجیح میدهد، نه سند آپلودهای متوقفشده را. بازرتبهبندی دومرحلهای درس 66 میتواند این پاسخ را به شرطی نجات دهد که جزو N نتیجهی برتر باشد؛ ولی اگر اصلاً به N نتیجهی اول نرسد، بازرتبهبند هرگز آن را نخواهد دید.
راهحل این است که پرسش را پیش از رسیدن به بازیاب بازنویسی کنیم. مقالهی سال 2023 با عنوان «بازیابی متراکم صفر-نمونه دقیق بدون برچسبهای ارتباط» (Gao و همکاران) روش HyDE را معرفی کرد: از مدل زبانی بخواهید سندی را بنویسد که میتواند به پرسش پاسخ دهد، سپس امبدینگ آن سند فرضی را بسازید و از همین بردار برای بازیابی استفاده کنید. سند فرضی دقیقاً در ناحیهی درستی از فضای امبدینگ مینشیند؛ چون با لحن و ادبیات اسناد مجموعه نوشته شده است، در حالی که بردار پرسش اولیه چنین ویژگیای نداشت.
دو روش همخانواده در کنار HyDE به کار میروند. «گسترش چندپرسشی» (اصطلاحی که در GraphRAG مایکروسافت مطرح شد) N بازنویسی مختلف از پرسش میسازد، با هر یک بازیابی انجام میدهد و خروجیها را ترکیب میکند. «تجزیه» (که با عنوان تجزیهی زیرپرسش در کارهای 2024 پروژهی Stanford DSPy فراگیر شد) پرسش «تیم ما وقتی آپلودها شکست میخورند و بودجه تمام شده چه کاری انجام میدهد؟» را به دو پرسش میشکند: «وقتی یک آپلود شکست میخورد چه رخ میدهد؟» و «وقتی بودجهی تلاش مجدد تمام میشود چه میشود؟». حاصل کار: دو بار بازیابی، یک نتیجهی ترکیبشده و دسترسی به هر دو تکهی پاسخ.
در این درس هر سه روش را پیاده میکنیم و آنها را روی مجموعهاسناد نمونه اجرا خواهیم کرد.
مبانی مفهومی
سازوکار دقیق HyDE
روش HyDE بردار پرسش کاربر را با بردار یک سند فرضیِ تولیدشده توسط مدل زبانی جایگزین میکند. پرامپت آن بسیار کوتاه است:
You are a domain expert. Write a one-paragraph passage that answers the question
below. Use the same vocabulary and phrasing the documentation in this domain would
use. Do not refuse. Do not say you do not know.
Question: {user_query}
Passage:
پاسخ مدل زبانی از نظر فکتهای واقعی غلط است، چون مدل، اسناد شما را ندیده است. این اصلاً اهمیتی ندارد. بازیاب کاری با درستی فکتها ندارد، بلکه توزیع توکنها برایش مهم است. متن فرضی شامل کلماتی مثل «abort» ،«multipart» ،«bucket» و «budget» است؛ چون یک سند فنی دربارهی این موضوع دقیقاً چنین کلماتی دارد. وقتی امبدینگ این متن را میسازید، بردار آن درست در نزدیکی سند واقعی مینشیند.
در محیط عملیاتی (پروداکشن)، طول سند فرضی را به دو یا سه جمله محدود میکنید. متنهای طولانیتر نویز بیشتری جذب میکنند؛ متنهای کوتاهتر هم سیگنال واژگانیِ مورد نیاز HyDE را از دست میدهند.
سازوکار دقیق گسترش چندپرسشی
از پرسش کاربر N بازنویسی بسازید. سادهترین پرامپت ممکن این است:
Rewrite the following question in {N} different ways. Each rewrite must preserve
the original intent. Number them 1 to {N}. Do not add explanations.
به ازای هر عبارت بازنویسیشده، k نتیجهی برتر را بازیابی کنید. سپس N فهرست رتبهبندیشده را با RRF (همان الگوریتم درس 65) merge کنید؛ روشی ارزان، موازی و قطعی.
روش چندپرسشی زمانی برنده است که نحوهی بیان کاربر فقط یکی از چندین شکل ممکن برای طرح پرسش باشد و هر کدام از بازنویسیها بتوانند سوال را شفافتر بپرسند. اما وقتی همهی بازنویسیها به یک اندازه ضعیف باشند — چون پرسش اولیه ساختار مبهمی داشته — این روش شکست میخورد.
سازوکار دقیق تجزیه
یک بازیابی منفرد نمیتواند پرسشی چندوجهی را پوشش دهد. در تجزیه، از مدل زبانی میخواهیم سوال را به چند زیرپرسش بشکند تا سیستم برای هر زیرپرسش بازیابی جداگانهای انجام دهد. پرامپت:
The following question may require information from multiple distinct topics.
Decompose it into a list of sub-questions. Each sub-question must be answerable
independently. If the question is already atomic, return it unchanged.
Question: {user_query}
بازیابی را به ازای هر زیرپرسش اجرا کنید و نتایج را merge کنید. تجزیه ابزار مناسبی برای سوالاتی است که شامل حروف ربط، مقایسههای چندبندی یا دو موضوع نامرتبط هستند. برای سوالات تکموضوعی و اتمیک (Atomic) اصلاً ابزار مناسبی نیست؛ آنجا وظیفهی تجزیهکننده این است که همان پرسش واحد را برگرداند و زیرپرسش ساختگی تولید نکند.
چرا به هر سه روش نیاز داریم؟
این سه تکنیک مکمل یکدیگرند. روش HyDE شکاف توکنیِ میان پرسش و اسناد را پر میکند. روش چندپرسشی تنوع نگارشی را پوشش میدهد و روش تجزیه از پس پرسشهای چندموضوعی برمیآید. یک سیستم در محیط عملیاتی (پروداکشن) هر سه را پیاده میکند و استراتژی مناسب را به ازای هر پرسش برمیگزیند (سیستم سرتاسری درس 69 بخش انتخابگر را نشان میدهد).
مدل زبانی ساختگی (Mock LLM)
این درس بهصورت آفلاین اجرا میشود. مدل ساختگی ما یک جدول جستجو (Lookup Table) کوچک بر اساس پرسش کاربر است، به همراه یک طرح پشتیبان (Fallback) برای پرسشهایی که قبلاً ندیده است. این جدول جستجو شامل موارد زیر است:
- برای هر پرسش موجود در دادههای نمونه: یک متن فرضی، سه بازنویسی و یک تجزیه.
- برای پرسشهای ناشناخته: یک تبدیل قطعی؛ کلمات کلیدی پرسش را استخراج میکند، آنها را با جدول مترادفها گسترش میدهد و نتیجه را برمیگرداند.
آنچه اهمیت دارد ساختار و رفتار این مدل ساختگی است، نه دادههای آن. در محیط عملیاتی (پروداکشن)، این بخش را با فراخوانی یک مدل واقعی جایگزین میکنید، بدون اینکه نیازی به تغییر بازیاب باشد.
پیادهسازی
فایل code/main.py این بخشها را پیادهسازی میکند:
MockLLM: همان جایگزین قطعی که در بالا توضیح دادیم.HyDERewriter: مدل زبانی را برای نوشتن سند فرضی فراخوانی میکند و خروجی را در قالبRewriteResultشامل متن فرضی و پرسش مورد نظر بازیاب برمیگرداند.MultiQueryRewriter: مدل را برای تولید N بازنویسی فراخوانی میکند و لیستی از پرسشها را تحویل میدهد.DecomposeRewriter: مدل را برای تجزیه فراخوانی کرده و زیرپرسشها را برمیگرداند.retrieve_with_rewriter: یک بازنویس و یک بازیاب میگیرد، بازنویسیها را اجرا کرده و نتایج را ترکیب میکند.- دمویی که سه بازنویس را روی نمونهها اجرا میکند و نشان میدهد کدام استراتژی توانسته سند پاسخ اصلی (Gold) را زودتر پیدا کند.
ساختار بازیاب مستقیماً از درس 65 برداشته شده است (ترکیب هیبرید BM25 و بازیابی متراکم (Dense retrieval)). ترکیب نتایج نیز با همان RRF انجام میشود. تنها بخش جدید، اینترفیس کوچک بازنویس است.
کد را اجرا کنید:
python3 code/main.py
خروجی شامل رتبهبندی به ازای هر استراتژی و یک خلاصهی نهایی است. روش HyDE در پرسشی که ناهماهنگی بیانی دارد برنده میشود. روش چندپرسشی روی پرسشهایی با تنوع بیانی پیروز میشود و روش تجزیه روی پرسشهای چندموضوعی بهترین عملکرد را دارد. حالت بدون بازنویس (طرح پشتیبان) حداقل در یکی از این سه حالت شکست میخورد.
حالتهای شکستی که دمو پنهان میکند
روش HyDE شناسههای اختصاصی اسناد را بهاشتباه توهم میزند. مدل یک نام تابع ساختگی تولید میکند. در نتیجه امتیاز BM25 متن فرضی برای سند درست به شدت سقوط میکند؛ چرا که نام ساختگی به توکنی با وزن بالا تبدیل میشود که اصلاً در نمایه وجود ندارد. برای حل این مشکل، طول متن فرضی را محدود کنید و در ترکیب نتایج، وزن کمتری به BM25 بدهید.
بازنویسیهای چندپرسشی همگرا میشوند. یک مدل ضعیف سه نگارش تقریباً یکسان تولید میکند. در نتیجه هر N بازیابی همان نتایج top-k یکسان را برمیگردانند و merge کردن با RRF هیچ بهبودی نسبت به یک بازیابی ساده ایجاد نمیکند. دستور شفافی برای ایجاد تنوع در پرامپت قرار دهید و موارد تکراری را با ضریب جاکارد (Jaccard) شناسایی کنید.
تجزیه، پرسش را بیش از حد خرد میکند. تجزیهکننده یک پرسش اتمیک را به چند بخش میشکند. تمام بازیابیها سند یکسانی را اما با رتبهی پایینتر پیدا میکنند؛ در نتیجه خروجی ادغامشده از نتیجهی پرسش اولیه هم ضعیفتر میشود. این مشکل را پیش از توزیع موازی (Fan-out)، با یک مرحله بررسی «آیا این زیرپرسشها به اندازهی کافی متمایزند؟» برطرف کنید.
تاخیر سیستم ضرب میشود. روش HyDE به اندازهی یک فراخوانی مدل هزینه دارد. روش چندپرسشی نیازمند یک فراخوانی مدل برای ساخت N بازنویسی و سپس N مرحله بازیابی است. روش تجزیه یک فراخوانی برای خرد کردن پرسش و سپس M مرحله بازیابی نیاز دارد. بازیابیها بهصورت موازی اجرا میشوند؛ اما فراخوانی مدل زبانی، کف تاخیر (Latency) سیستم را مشخص میکند.
الگوهای کاربردی
الگوهای استفاده در محیط عملیاتی (پروداکشن):
- انتخاب استراتژی بر اساس طول پرسش: پرسشهای کوتاه و اتمیک به روش چندپرسشی، پرسشهای پیچیده و چندبندی به تجزیه، و پرسشهای پر از اصطلاحات تخصصی به HyDE سپرده میشوند.
- کش کردن خروجی بازنویس با هشِ پرسش؛ چون بسیاری از پرسشها تکرار میشوند.
- اجرای موازی هر سه روش و ترکیب نتایج حاصل در یک مجموعه با RRF. هزینهی این کار سه فراخوانی مدل زبانی و یک مرحله ترکیب نتایج است؛ در عوض پوشش نهایی، اجتماع تمام نقاط قوت هر سه استراتژی خواهد بود.
تحویل نهایی
درس 69 این مرحلهی بازنویسی را قبل از بازیابِ درس 65 و بازرتبهبندِ درس 66 قرار میدهد. درس 68 نیز میزان بهبود بازخوانی (Recall) با اضافه شدن بازنویس را ارزیابی خواهد کرد.
تمرینها
- روش RAG-Fusion (نسخهی سال 2024 از چندپرسشی) را پیاده کنید؛ بهطوریکه بازنویسیها عمداً متنوع باشند و مرحلهی بازرتبهبندی (درس 66) فهرست نهایی را انتخاب کند.
- استراتژی چهارمی با عنوان پرامپت گامبهعقب (Step-back prompting) اضافه کنید (از مدل پرسش کلیتری را بخواهید، بر اساس آن بازیابی کنید و سپس دامنه را محدود نمایید). نتایج را روی دادههای نمونه مقایسه کنید.
- با افزودن یک سر (Head) با عنوان «آیا پرسش اتمیک است»، به تجزیهکننده آموزش دهید پرسشهای اتمیک را بشناسد. نرخ خرد کردن بیش از حد را قبل و بعد از این کار بسنجید.
- مدل زبانی ساختگی را با یک مدل واقعی جایگزین کنید و تاخیر هر استراتژی را در پشتهی فنی خود بسنجید.
- به ازای هر بازنویسی یک امتیاز اطمینان در نظر بگیرید. بازنویسیهای پایینتر از آستانه (Threshold) را حذف کرده و تاثیر آن را روی بازخوانی اندازه بگیرید.
اصطلاحات کلیدی
| اصطلاح | در گفتگوها | معنای دقیق فنی |
|---|---|---|
| HyDE | «بازیابی با سند ساختگی» | مدل زبانی پاسخ را مینویسد؛ امبدینگ آن ساخته شده و بهجای پرسش، بر اساس آن بازیابی میشود |
| چندپرسشی (Multi-query) | «گسترش بازنویسیها» | تولید N بازنویسی از پرسش؛ N بار بازیابی و merge کردن با RRF |
| تجزیه (Decomposition) | «شکستن به زیرپرسش» | تقسیم پرسشهای چندموضوعی به زیرپرسشها و بازیابی مجزا برای هر کدام |
| پرسش اتمیک (Atomic query) | «تکموضوعی» | پرسشی که خرد کردن آن بدون ساختن زیرپرسشهای اشتباه ممکن نیست |
| گامبهعقب (Step-back) | «انتزاعی کردن پرسش» | پرسیدن سوالی کلیتر، بازیابی و سپس محدود کردن دامنه |
مطالعهی بیشتر
- Gao, Ma, Lin, Callan, "Precise Zero-Shot Dense Retrieval without Relevance Labels" (HyDE), 2023
- Microsoft Research, "Multi-Query Expansion for Retrieval"
- Stanford DSPy, "Subquery Decomposition for Multi-Hop QA"
- مستندات تبدیلات پرسش در LlamaIndex
- فاز 11 درس 07 - الگوهای پیشرفتهی RAG
- فاز 19 درس 65 - بازیابی که ورودی خود را از این بازنویس میگیرد
- فاز 19 درس 68 - ارزیابی میزان بهبود حاصل از بازنویس
