تصور کن یک چتبات داخلی برای تیم پشتیبانی یا یک دستیار فنی داری که به مستندات شرکت وصل است. کاربر یک سؤال مشخص میپرسد، جواب میگیرد، و بعد مثل خیلی از مکالمههای واقعی سؤال بعدی را نصفهنیمه میپرسد:
«اینش چطور بود؟»
«همون مورد قبلی رو میگم…»
«برای این سناریو هم جواب میده؟»
اینجا دقیقاً همان جایی است که خیلی از سیستمهای RAG ساده به مشکل میخورند؛ نه بهخاطر اینکه «اطلاعات ندارند»، بلکه چون نمیفهمند ضمیرها و ارجاعها به چه چیزی اشاره میکنند.
یک سناریوی واقعی (خیلی شبیه محیط کار)
فرض کن کاربر قبلاً دربارهی سیاست بازگشت وجه (Refund Policy) سؤال پرسیده و حالا ادامه میدهد:
گفتوگو:
- کاربر: «شرایط بازگشت وجه برای خرید سالانه چیه؟»
- بات: «برای خرید سالانه تا ۷ روز امکان بازگشت هست، با شرایط X و Y…»
- کاربر: «خب اینش برای خرید سازمانی هم صدق میکنه؟»
این «اینش» برای انسان واضح است: منظورش همان شرایط بازگشت وجه است.
اما اگر سیستم فقط پیام آخر را ببیند، ممکن است دنبال «خرید سازمانی» بگردد و سندهای کاملاً دیگری را بالا بیاورد.
شکست رایج یک RAG ساده
در بسیاری از پیادهسازیهای RAG، مرحلهی جستجو (retrieval) بر اساس آخرین پیام انجام میشود. نتیجه؟
- سیستم در بهترین حالت: جوابهای کلی و نصفه میدهد.
- سیستم در بدترین حالت: سند نامربوط میآورد و جواب با اعتمادبهنفس میسازد.
و این یعنی تجربهای که کاربر حس میکند:
«انگار طرف حرفم رو نفهمید.»
RAG سنتی کجاش میلنگه؟
RAG کلاسیک معمولاً اینطور کار میکند:
آخرین سؤال کاربر👈🏻 جستجو در اسناد 👈🏻 چند تکه متن 👈🏻 تولید پاسخ
این جریان برای سؤالهای مستقل (single-shot) خوب است، اما در مکالمههای واقعی سه جای اصلی گیر میکند:
1) وابستگی شدید به آخرین پیام (Dependence on last query)
کاربر اغلب سؤال دوم/سوم را کامل نمیپرسد. RAG سنتی هم چون فقط آخرین پیام را query میکند، مسیر را اشتباه میرود.
2) سؤالهای دنبالهدار مبهم (Ambiguous follow-ups)
کلماتی مثل «این»، «اون»، «همون»، «مثل قبلی»، «برای این مورد» بدون تاریخچه، معنای دقیقی ندارند.
3) از دست رفتن کانتکست مکالمه (Loss of conversational context)
اطلاعات مهم مکالمه معمولاً در پیامهای قبلی گفته میشود:
- موضوع دقیق (محصول/ماژول/سیاست)
- محدودیتها (کشور، پلن، نسخه)
- هدف کاربر (عیبیابی، تصمیمگیری، مقایسه)
اگر اینها وارد retrieval نشوند، حتی مدل زبانی قوی هم با context غلط، خروجی غلط میدهد.
یک جدول ساده برای دیدن مشکل (مثل دنیای واقعی)
| User Message | What system sees (در RAG ساده) | Problem |
|---|---|---|
| «اینش چطور بود؟» | اینش چطور بود؟ |
«این» به چی اشاره میکنه؟ سیستم نمیفهمه. |
| «برای همون مورد قبلی هم جواب میده؟» | مورد قبلی + جواب میده |
بدون دانستن «مورد قبلی»، retrieval شانسی میشود. |
| «پس تو نسخه جدید چی تغییر کرده؟» | نسخه جدید + تغییر |
کدوم محصول/کدوم نسخه؟ کانتکست قبلی حذف شده. |
| «همون policy رو برای سازمانی هم داریم؟» | policy + سازمانی |
سیستم ممکنه policyهای HR یا چیز دیگری را بیاورد. |
| «اگه همون خطا رو دیدم چی؟» | همون خطا |
بدون لاگ/اسم خطا، جستجو بیهدف میشود. |
RAG سنتی از نظر «دانش» مشکل ندارد؛ مشکلش این است که در مکالمه، سؤالِ درست برای جستجو را نمیسازد. و همین دقیقاً مقدمهای است برای اینکه بفهمیم چرا به Conversation-aware Retrieval نیاز داریم.
Conversation-aware Retrieval چطور کار میکند؟
تا اینجا دیدیم Conversation-aware Retrieval چرا لازم است، اما سؤال مهمتر این است:
این سیستم دقیقاً چه کاری انجام میدهد که RAG معمولی انجام نمیدهد؟
پاسخ کوتاه این است که Conversation-aware Retrieval قبل از جستجو، کمی «فکر» میکند.
نه به این معنی که جواب میسازد، بلکه سعی میکند بفهمد اگر این مکالمه را یک انسان میخواند، دنبال چه چیزی میگشت.
برای درک بهتر، بیایید مسیر را قدمبهقدم جلو برویم.
درک مکالمه (Conversation Understanding)
اولین کاری که سیستم انجام میدهد، نگاه کردن به کل مکالمه است، نه فقط آخرین پیام. در مکالمههای واقعی، اطلاعات مهم معمولاً پراکندهاند: کاربر یک چیز را در جملهی اول میگوید، محدودیت را در جملهی دوم اضافه میکند و سؤال اصلی را در جملهی سوم میپرسد.
مثلاً این گفتوگو را در نظر بگیر:
«ما روی پلن Enterprise هستیم»
«برای API محدودیت داریم»
«این برای همه endpointها اعمال میشه؟»
اگر این مکالمه را یک انسان بخواند، خیلی راحت متوجه میشود که سؤال اصلی دربارهی دامنهی محدودیت API در پلن Enterprise است. اما برای سیستم، این فهم باید بهصورت صریح ساخته شود.
در این مرحله، Conversation-aware Retrieval سعی میکند یک تصویر ذهنی بسازد:
- موضوع کلی چیست؟
- سؤال دقیق دربارهی چه چیزی است؟
- کاربر دنبال توضیح، تأیید یا مقایسه است؟
این مرحله شبیه کاری است که خود ما ناخودآگاه انجام میدهیم: «آها، منظورش اینه.»
بازنویسی سؤال برای جستجو (Query Rewriting)
بعد از اینکه سیستم «منظور» مکالمه را فهمید، هنوز آمادهی جستجو نیست. چرا؟
چون سؤالی که کاربر پرسیده، معمولاً برای جستجو مناسب نیست.
جملههایی مثل «اینش چطور بود؟» یا «برای همون مورد قبلی چی؟» برای انسان واضحاند، اما برای موتور جستجو کاملاً بیمعنیاند. اینجاست که مرحلهی بازنویسی وارد میشود.
در این مرحله، سیستم سؤالی میسازد که:
- مستقل باشد (بدون ارجاع به مکالمه)
- دقیق باشد
- شامل کلمات کلیدی درست باشد
مثلاً بهجای:
«این برای همه endpointها اعمال میشه؟»
سیستم این را میسازد:
«API rate limits in Enterprise plan and whether they apply to all endpoints»
نکتهی مهم اینجاست که این سؤال را کاربر نگفته، اما دقیقاً همان چیزی است که منظورش بوده.
جستجو با سؤال درست (Retrieval)
وقتی سؤال درست ساخته شد، تازه وارد مرحلهای میشویم که RAG سنتی از همانجا شروع میکند: جستجو در اسناد.
اما تفاوت بزرگ اینجاست که حالا موتور جستجو با یک query شفاف و دقیق طرف است.
در نتیجه:
- بهجای سندهای عمومی API
- به مستندات مخصوص پلن Enterprise
- و دقیقاً بخش مربوط به rate limitها
دسترسی پیدا میکند.
به بیان ساده، Conversation-aware Retrieval کاری میکند که retrieval با حدس و گمان جلو نرود، بلکه با نیت مشخص انجام شود.
تصویر کلی فرآیند (برای جمع شدن توی ذهن)
اگر بخواهیم کل این مسیر را در یک نگاه ببینیم، میشود اینطور تصورش کرد:
Chat History
↓
(فهم مکالمه و نیت کاربر)
↓
تبدیل به یک سؤال دقیق و مستقل
↓
جستجو در اسناد مرتبط
این «فهم مکالمه» و «تبدیل سؤال» همان چیزی است که در RAG ساده وجود ندارد و دقیقاً همان جایی است که Conversation-aware Retrieval ارزش خودش را نشان میدهد.
Conversation-aware Retrieval تلاش نمیکند جواب بهتری بسازد؛
تلاش میکند سؤال بهتری برای جستجو بسازد.
و وقتی سؤال درست باشد،
بقیهی سیستم (Retriever و LLM) معمولاً کارشان را درست انجام میدهند.
روشهای پیادهسازی Conversation-aware Retrieval
Conversation-aware Retrieval یک ایدهی واحد نیست که فقط یک راه پیادهسازی داشته باشد. در عمل، تیمها بسته به پیچیدگی محصول، حجم داده و حساسیت پاسخها، از روشهای مختلفی استفاده میکنند. بیایید سه رویکرد رایج را از ساده تا حرفهای بررسی کنیم.
1) رویکرد ساده (Naive Approach)
در سادهترین حالت، بعضی سیستمها تلاش میکنند با چسباندن چند پیام آخر مکالمه به هم، مشکل کانتکست را حل کنند. یعنی بهجای اینکه فقط آخرین پیام کاربر را برای جستجو بفرستند، مثلاً ۳ یا ۵ پیام آخر را کنار هم میگذارند و همان را query میکنند.
در نگاه اول، این کار منطقی به نظر میرسد؛ بالاخره اطلاعات بیشتری وارد جستجو شده. اما در عمل، این روش خیلی زود به مشکل میخورد. مکالمهها پر از جملههای محاورهای، تکراری و حتی بیربط هستند و موتور جستجو نمیداند کدام بخش مهمتر است.
مزیت اصلی این روش سادگی آن است. پیادهسازی سریع است و نیاز به مدل اضافه یا طراحی پیچیده ندارد.
اما محدودیت بزرگش نویز بالاست؛ هم context window مدل هدر میرود، هم retrieval نتایج شلختهتری برمیگرداند.
این روش معمولاً فقط برای نمونههای اولیه (PoC) یا پروژههای خیلی کوچک جواب میدهد.
2) بازنویسی Query با LLM (LLM-based Query Rewriting)
این روش، رایجترین و عملیترین انتخاب در سیستمهای production است. ایده ساده است:
قبل از اینکه جستجو انجام شود، یک LLM کل مکالمه را میخواند و آن را به یک سؤال مستقل، شفاف و قابل جستجو تبدیل میکند.
در این رویکرد، سیستم بهجای اینکه مکالمهی خام را وارد retrieval کند، از LLM میخواهد «منظور کاربر را در قالب یک query رسمی و دقیق» بنویسد. نتیجه معمولاً چیزی است که اگر یک انسان میخواست در مستندات جستجو کند، دقیقاً همان را مینوشت.
مزیت اصلی این روش این است که نویز را بهشدت کاهش میدهد و retrieval را هدفمند میکند. همچنین با مکالمههای طولانی هم خوب کنار میآید، چون خروجی نهایی فقط یک query تمیز است.
محدودیتش این است که به کیفیت prompt و مدل وابسته است و یک لایهی پردازش اضافی به سیستم اضافه میکند.
با این حال، در بیشتر محصولات واقعی، این روش بهترین توازن بین کیفیت و پیچیدگی را دارد.
3) خلاصهسازی مکالمه (Conversation Summarization)
در سیستمهای پیچیدهتر، بهخصوص جاهایی که مکالمه طولانی است یا تصمیمها در چند مرحله گرفته میشوند، از خلاصهسازی مکالمه استفاده میشود. در این روش، سیستم یک خلاصهی ساختیافته از مکالمه میسازد و آن را بهروز نگه میدارد.
بهجای اینکه هر بار کل تاریخچه بررسی شود، یک خلاصهی زنده وجود دارد که شامل موضوع، محدودیتها و هدف کاربر است. این خلاصه بعداً برای بازنویسی query یا حتی برای تولید پاسخ استفاده میشود.
مزیت این روش مقیاسپذیری و نظم بالای آن است. برای agentهای چندمرحلهای یا copilotهای پیشرفته، این رویکرد بسیار مؤثر است.
محدودیتش پیچیدگی پیادهسازی و نیاز به طراحی دقیق است؛ اگر خلاصه بد ساخته شود، کل سیستم گمراه میشود.
تفاوت Conversation-aware Retrieval با Memory
یکی از رایجترین سوءتفاهمها این است که Conversation-aware Retrieval با Memory یکی گرفته میشود. در حالی که این دو، نقشهای کاملاً متفاوتی دارند.
Conversation-aware Retrieval تمرکزش روی درست جستجو کردن است، در حالی که Memory تمرکزش روی یادآوری اطلاعات در طول زمان است.
برای شفاف شدن تفاوت، جدول زیر خیلی کمک میکند:
| Concept | Scope | Purpose |
|---|---|---|
| Conversation-aware Retrieval | همان مکالمهی فعلی | ساخت query درست برای جستجو |
| Short-term Memory | طول یک session | حفظ فرضها و تنظیمات مکالمه |
| Long-term Memory | چندین session | نگهداشت ترجیحات و اطلاعات پایدار کاربر |
به زبان ساده:
Conversation-aware Retrieval میپرسد «الان دقیقاً چی رو باید سرچ کنم؟»
Memory میپرسد «این کاربر یا این سیستم قبلاً چی گفته یا چی ترجیح میده؟»
چه زمانی Conversation-aware Retrieval لازم است؟ چه زمانی نه؟
دانستن اینکه کجا نباید از این تکنیک استفاده کرد، به اندازهی دانستن کاربردش مهم است.
Conversation-aware Retrieval معمولاً لازم است وقتی:
- سیستم شما چتمحور است و کاربر سؤالهای دنبالهدار میپرسد.
- Copilot یا دستیار فنی میسازید که روی context قبلی جلو میرود.
- سیستم پشتیبانی دارید که یک مشکل در چند پیام توضیح داده میشود.
در مقابل، معمولاً لازم نیست وقتی:
- کاربر فقط یک سؤال مستقل میپرسد و میرود.
- با FAQهای ثابت و از پیشتعریفشده سروکار دارید.
- جستجو کاملاً single-shot و بدون مکالمه است.
استفادهی بیدلیل از Conversation-aware Retrieval فقط سیستم را پیچیدهتر میکند، بدون اینکه ارزش واقعی اضافه کند.
اشتباهات رایج در پیادهسازی
تجربهی عملی نشان میدهد بعضی اشتباهها بارها و بارها تکرار میشوند.
یکی از رایجترین اشتباهها این است که کل تاریخچهی مکالمه بدون فیلتر وارد retrieval میشود. این کار معمولاً باعث افزایش نویز و کاهش دقت میشود، نه برعکس.
اشتباه رایج بعدی، نادیده گرفتن query rewriting است. بعضی تیمها فکر میکنند vector search بهتنهایی کافی است، در حالی که بدون سؤال درست، بهترین embedding هم خروجی ضعیفی میدهد.
و در نهایت، استفادهی بیشازحد از Memory. Memory قرار نیست جای retrieval یا query rewriting را بگیرد. وقتی همهچیز را به memory بسپارید، سیستم بهجای «دقیق شدن»، «سنگین و غیرقابلپیشبینی» میشود.
جمعبندی نهایی
در نهایت، اگر بخواهیم کل بحث را در چند خط جمع کنیم:
- Problem: RAG سنتی در مکالمهها سؤال درست برای جستجو را نمیفهمد.
- Solution: Conversation-aware Retrieval با فهم مکالمه، query مناسب میسازد.
- Benefit: سند دقیقتر، پاسخ قابل اعتمادتر و تجربهی کاربری حرفهایتر.
Conversation-aware Retrieval قرار نیست جادو کند؛
قرار است کاری را انجام دهد که انسانها همیشه انجام میدهند:
اول بفهمند، بعد بگردند.

