پرش به مطلب اصلی

وقتی دمو تمام می‌شود؛ داستان معماری یک سرویس RAG قابل اعتماد

· ۲۴ دقیقه مطالعه
مهدی مالوردی
مهندس نرم‌افزار و نویسندهٔ این سایت

بازیابی افزوده یعنی مدل، پیش از پاسخ دادن، در سندهای ما جست و جو می کند و از آن ها برای جواب استفاده می کند. در یک دمو، این کار خیلی ساده به نظر می رسد: پرسش می آید، چند سند پیدا می شوند و مدل پاسخ می دهد. مسئله وقتی شروع می شود که همان دمو باید برای آدم های واقعی، روی داده های واقعی و در ساعت های شلوغ کار کند.

این نوشته از همین جا شروع می کند. نه از این پرسش که کدام مدل بهتر است، بلکه از این پرسش که اگر پاسخ درست بود اما دیر رسید، به سند اشتباه تکیه کرد یا چیزی را افشا کرد، کجای سامانه باید جوابگو باشد؟

چرخه کنترل یک سرویس بازیابی افزوده: اسناد، مجوز، مسیریابی، مدل، اعتبارسنجی و پایش

ساعت ۹:۱۷ صبح

ساعت ۹:۱۷ صبح است. فقط هفده دقیقه از راه‌اندازی دستیار جدید سازمان گذشته و یکی از مهندسان تیم، اولین پیام را می‌بیند:

«پاسخ درست بود، ولی چرا ۲۸ ثانیه طول کشید؟»

هنوز پاسخ نداده که پیام دوم می‌رسد. کاربری در واحد فروش، بخشی از یک سند قدیمی منابع انسانی را در جوابش دیده است؛ سندی که قرار بود هفته قبل از دسترس او خارج شود. چند دقیقه بعد، یکی از تست‌های امنیتی نشان می‌دهد متنی پنهان‌شده داخل یک فایل می‌تواند مدل را به اجرای دستور دیگری ترغیب کند. هم‌زمان provider مدل چند بار timeout می‌شود و retryها هزینه همان درخواست را چند برابر می‌کنند.

مهندس تیم صفحه پایش را باز می‌کند: API پاسخ 200 داده، GPU از پا نیفتاده و هیچ exception واضحی دیده نمی‌شود. از نگاه نمودارهای معمول، سامانه سالم است. از نگاه کاربران، نه.

این صحنه گزارش یک رخداد واقعی در شرکت مشخصی نیست؛ سناریویی ترکیبی و فرضی است که failure modeهای گزارش‌شده در پژوهش‌های RAG را کنار هم می‌گذارد. بااین‌حال پرسش آن کاملا واقعی است: وقتی مدل «جواب می‌دهد» اما نمی‌توان به سرویس اعتماد کرد، باید دنبال ایراد کجا بگردیم؟

این رخداد ساختگی است، اما از مسئله هایی ساخته شده که در پژوهش های RAG بارها گزارش شده اند.

پیش از ادامه، نقشه را ببینیم

اگر فقط یک تصویر از این نوشته به خاطر بماند، همین تصویر باید باشد. یک درخواست از شش ایستگاه می گذرد؛ در هر ایستگاه، سامانه یک پرسش ساده می پرسد و پاسخ آن را نگه می دارد.

شش ایستگاه کنترل یک درخواست: هویت، مسیریابی، بازیابی مجاز، ساخت زمینه، مدل و اعتبارسنجی، رد و ارزیابی

تصویر ۱ — مسیر کنترل شده یک درخواست در شش ایستگاه؛ این شکل برای توضیح معماری پیشنهادی پروژه ساخته شده است.

داستان متن را می توان در سه گام خلاصه کرد:

  1. پیش از پاسخ دادن: بدانیم چه کسی پرسیده و این درخواست چقدر زمان و هزینه می تواند مصرف کند.
  2. هنگام استفاده از سندها: فقط سندهای مجاز و به روز را به مدل بدهیم و متن سند را دستور اجرایی فرض نکنیم.
  3. پیش از انتشار پاسخ: پاسخ را بررسی کنیم و اگر مشکل داشت، به جای حدس زدن یا تکرار بی پایان، مسیر جایگزین یا پاسخ محدود انتخاب کنیم.
اگر این واژه ها ناآشنا هستند
  • مسیر: راهی که سامانه برای جواب دادن انتخاب می کند؛ مثلا پاسخ سریع بدون جست و جو یا پاسخ دقیق تر با جست و جوی بیشتر.
  • بازیابی: پیدا کردن بخش های مرتبط از سندها.
  • مدل: بخشی که با کمک سندهای پیدا شده پاسخ را می نویسد.
  • اعتبارسنجی: بررسی اینکه پاسخ با سندها و قواعد سامانه سازگار است.
  • رد درخواست: اطلاعاتی که نشان می دهد هر پاسخ از چه راهی و با چه داده ای ساخته شده است.
  • راه برگشت: کاری محدود و هدفمند پس از خطا؛ مثلا تلاش دوباره برای خطای شبکه، نه تکرار کورکورانه همه چیز.

مدل بزرگتر چه چیزی را حل نمی کند؟

در جلسه بررسی رخداد، اولین پیشنهاد قابل پیش‌بینی است: «مدل قوی‌تری انتخاب کنیم.» اما هیچ‌کدام از چهار نشانه با این نسخه درمان نمی‌شوند. مدل بزرگ‌تر سند stale را تازه نمی‌کند، ACL را enforce نمی‌کند، جلوی retry storm را نمی‌گیرد و توضیح نمی‌دهد پاسخ بد از retrieval آمده یا generation.

اینجاست که سؤال تیم عوض می‌شود. دیگر نمی‌پرسند «کدام LLM بهتر است؟»؛ می‌پرسند:

یک سرویس RAG چگونه باید ساخته شود تا وقتی retrieval، مدل، داده یا provider اشتباه می‌کنند، خطا را ببیند، واکنش محدودی نشان دهد و مدرک کافی برای توضیح آن نگه دارد؟

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

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

پرونده اول: چرا یک سؤال ساده ۲۸ ثانیه در راه بود؟

ایستگاه درگیر: انتخاب مسیر و بودجه.

مهندس تیم رد اولین شکایت را باز می‌کند. سؤال کاربر ساده بوده، اما orchestrator آن را به همان مسیری فرستاده که برای پرسش‌های چندمرحله‌ای استفاده می‌شود: چند بار retrieval، چند پاسخ میانی و در پایان generation. سامانه جواب درست داده، ولی برای یک سفر کوتاه از طولانی‌ترین جاده رفته است.

پژوهش Adaptive-RAG دقیقا این تفاوت را اندازه گرفته است. سه مسیر بدون retrieval، retrieval تک‌گام و retrieval چندگام در آزمایش آن به‌طور متوسط ۰٫۳۵، ۳٫۰۸ و ۲۷٫۱۸ ثانیه برای هر query زمان برده‌اند [۱]. بنابراین انتخاب route یک جزئیات داخلی نیست؛ تصمیمی مستقیم درباره latency و هزینه است.

مقایسه مسیرهای تک‌گام، چندگام و تطبیقی در Adaptive-RAG

تصویر ۲ — مقایسه مفهومی مسیرهای تک‌گام، چندگام و تطبیقی؛ برگرفته از شکل ۲ مقاله Adaptive-RAG [۱]، با مجوز CC BY 4.0. تنها حاشیه‌های صفحه حذف شده‌اند.

اما درست وقتی به نظر می‌رسد router راه‌حل نهایی است، یک عدد دیگر داستان را پیچیده می‌کند: accuracy کلی classifier انتخاب مسیر در همان مطالعه حدود ۵۴٫۵۲ درصد بود. یعنی router می‌تواند خودش failure mode تازه‌ای به نام routing misclassification بسازد.

پس روی وایت‌برد کنار واژه router سه قید نوشته می‌شود: confidence، budget و fallback. سیستم باید بداند چقدر به انتخابش مطمئن است، هر route تا چه حد اجازه مصرف زمان و token دارد و در ابهام چه می‌کند. خود تصمیم route هم باید در trace بماند؛ وگرنه فردا دوباره همه به مدل مشکوک می‌شوند، درحالی‌که جاده از ابتدا اشتباه انتخاب شده است.

ری و همکاران در پژوهش METIS از زاویه دیگری همین مسئله را دیده اند: بیشترکردن قطعه های سند همیشه کمک نمی کند. در آزمایش آن ها، افزودن بیش از اندازه قطعه ها کیفیت را تا ۲۰ درصد پایین آورد و زمان پاسخ را تا سه برابر بیشتر کرد [۱۴]. پس انتخاب مسیر فقط انتخاب میان «جست و جو» و «بی جست و جو» نیست؛ باید تعیین کند چه مقدار سند واقعا برای این پرسش لازم است.

پرونده دوم: GPU متهم اصلی نبود

ایستگاه درگیر: انتخاب مسیر، فراخوانی مدل و رد درخواست.

شکایت بعدی latency است و نگاه‌ها فورا به GPU برمی‌گردد. اما نمودار utilization عادی است. مهندس تیم زمان درخواست را به stageهای کوچک‌تر می‌شکند و می‌بیند چیزی که زیر عدد end-to-end پنهان شده بود، حالا خودش را نشان می‌دهد: گلوگاه می‌تواند پیش از رسیدن درخواست به مدل باشد.

در مطالعه RAGO، retrieval در یک workload بیش از ۸۰ درصد latency را ساخته، اما در workload دیگری با context بلند سهم آن به کمتر از یک درصد رسیده است [۲]. همان مقاله با بهینه‌سازی کل pipeline، تا دو برابر QPS به‌ازای تراشه و ۵۵ درصد کاهش TTFT گزارش کرد. گلوگاه نه جای ثابتی دارد و نه همیشه گران‌ترین component سامانه است.

تغییر سهم retrieval و inference در workloadهای RAG

تصویر ۳ — سهم زمان retrieval، prefill و decode با تغییر اندازه مدل و تعداد queryها یکسان نمی‌ماند؛ برش از شکل ۶ مقاله RAGO [۲]، با مجوز CC BY 4.0.

نتیجه برای تیم روشن است: autoscaling بر اساس GPU utilization یا model latency به تنهایی مثل زیادکردن آمبولانس‌ها پیش از پیدا کردن محل حادثه است. query encoder، retrieval، reranker، queue، prefill و decode باید زمان جداگانه داشته باشند. عدد کل می‌گوید سامانه کند است؛ stageها می‌گویند کجا باید مداخله کرد.

در همین لحظه پیشنهاد جذاب دیگری مطرح می‌شود: «همه‌چیز را cache کنیم.» شواهد دوباره احتیاط می‌خواهند. RAGCache در محیط آزمایش کاهش ۱٫۲ تا ۴ برابری TTFT و افزایش ۱٫۳ تا ۲٫۱ برابری throughput را گزارش کرده، اما با بزرگ‌شدن top-k و فشار حافظه، سود کم شده است [۳]. Cache-Craft نیز نشان داده reuse تقریبی KV-cache بی‌هزینه نیست؛ در یکی از تنظیم‌ها acceptance از ۸۳٫۷ درصد در محاسبه کامل به ۷۸٫۹ درصد رسیده است [۴].

در نتیجه کنار cache hit rate چهار چراغ دیگر قرار می‌گیرند: freshness، quality delta، memory pressure و index version. cache اگر پاسخ را سریع‌تر اما stale، کم‌کیفیت یا متعلق به tenant دیگری برگرداند، بهینه‌سازی نیست؛ راه سریع‌تری برای رسیدن به خطاست.

شن و همکاران در Hermes به مقیاس خیلی بزرگ نگاه کرده اند. نتیجه آن ها این است که وقتی پیکره به اندازه بسیار بزرگ می رسد، خود جست و جو می تواند گلوگاه اصلی شود و پخش کردن نمایه روی چند بخش، مفید باشد؛ اما برای پیکره کوچک، این پیچیدگی سود چندانی ندارد [۱۵]. درس معماری این نیست که از روز اول جست و جو را توزیع کنیم؛ باید اول از ردهای واقعی بفهمیم گلوگاه کجاست.

پرونده سوم: پاسخ روان بود، اما شاهد چه؟

ایستگاه درگیر: بازیابی مجاز، ساخت زمینه و بررسی پاسخ.

یکی از پاسخ‌های دستیار از نظر نگارش عالی است. مشکل فقط این است که context بازیابی‌شده ارتباط محکمی با سؤال ندارد. dashboard یک score نهایی نشان می‌دهد و آن score هم بد به نظر نمی‌رسد؛ بنابراین تیم نمی‌داند retriever را اصلاح کند، prompt را تغییر دهد یا مدل را.

RAGAS این گره را با شکستن کیفیت به سه پرسش باز می‌کند: آیا پاسخ به context وفادار است؟ آیا واقعا سؤال را جواب می‌دهد؟ و آیا خود context مرتبط است؟ در WikiEval پنجاه‌نمونه‌ای، توافق این معیارها با انسان برای faithfulness، answer relevance و context relevance به‌ترتیب ۰٫۹۵، ۰٫۷۸ و ۰٫۷۰ بوده است [۵]. همین تفاوت نشان می‌دهد حتی LLM judge نیز ground truth قطعی نیست و هر بعد، failure متفاوتی را می‌بیند.

توافق معیارهای RAGAS با ارزیابی انسانی

تصویر ۴ — توافق سه معیار RAGAS با داوری انسانی در WikiEval؛ برگرفته از جدول ۴ مقاله RAGAS [۵]، با مجوز CC BY 4.0.

اما غافلگیری بزرگ‌تر هنوز مانده است. آزمایش‌های BERGEN نشان داده‌اند افزودن retrieval در datasetهایی مانند TruthfulQA، ELI5 و Wizard of Wikipedia کیفیت را کاهش داده و حتی oracle retrieval در بعضی حالت‌ها سودی نداشته است [۶]. یعنی جمله «context بیشتر، پاسخ بهتر» قانون طبیعت نیست.

اثر مثبت و منفی retrieval روی datasetهای مختلف

تصویر ۵ — retrieval در بعضی datasetها سود مثبت و در بعضی دیگر افت عملکرد ایجاد کرده است؛ برش از شکل ۳ مقاله BERGEN [۶]، با مجوز CC BY 4.0.

در معماری جدید، route بدون retrieval از روی نقشه حذف نمی‌شود. metricهای retrieval و generation جدا ذخیره می‌شوند و thresholdها روی داده همان دامنه calibration می‌شوند. گاهی رفتار هوشمندانه این نیست که prompt را با سندهای بیشتری پر کنیم؛ این است که بگوییم «context قابل‌اعتماد کافی ندارم» یا اصلا از retriever نپرسیم.

آیالا و بشار در مسئله ای نزدیک به کارهای سازمانی، نشان داده اند که بازیابی می تواند شمار نام ها و اجزای ساختگی را کم کند، اما آن را صفر نمی کند [۱۶]. برداشت مهم برای این نوشته این است که بازیابی جای بررسی پاسخ را نمی گیرد. سندها فضای پاسخ را محدود می کنند؛ بررسی کننده پاسخ باید مطمئن شود نام، قالب و رابطه های مهم واقعا معتبرند.

مرور ژو و همکاران هم یادآوری می کند که درست بودن پاسخ فقط یکی از جنبه های اعتماد است. ممکن است پاسخ به سند وفادار باشد، اما حریم خصوصی، مقاومت در برابر ورودی مخرب یا امکان توضیح دادن مسیر پاسخ هنوز مسئله داشته باشد [۱۷]. به همین دلیل در نمودار، کیفیت پاسخ و کنترل مجوز را یک جعبه مشترک ندیده ایم.

پرونده چهارم: وقتی یک سند می‌خواهد اپراتور باشد

ایستگاه درگیر: بازیابی مجاز، ساخت زمینه و بررسی پاسخ.

در pipeline اولیه، هر چیزی که retriever برمی‌گرداند «دانش» نامیده می‌شود. همین نام بی‌خطر، یک فرض خطرناک را پنهان می‌کند: انگار متن بازیابی‌شده قابل اعتماد است. اما فایل می‌تواند قدیمی، خارج از مجوز، مسموم یا حاوی دستوری باشد که اصلا نباید اجرا شود.

شواهد privacy اندازه خطر را ملموس می‌کنند. در یک مطالعه، نرخ استخراج اطلاعات در بعضی تنظیم‌ها به نزدیک ۵۰ درصد رسیده است؛ از ۲۵۰ prompt، مدل GPT-3.5 تعداد ۱۰۷ داده شخصی ایمیل و ۸۹ رکورد پزشکی هدف را بازگردانده و reranking تقریبا نقش حفاظتی نداشته است [۷].

مشکل فقط دیدن سند اشتباه نیست. پژوهشی درباره indirect prompt injection نشان داده حمله‌های adaptive هر هشت defense بررسی‌شده را با نرخ موفقیت بالاتر از ۵۰ درصد دور زده‌اند و detection rate بعضی detectorها به نزدیک صفر رسیده است [۸].

نرخ موفقیت حمله‌های تطبیقی علیه دفاع‌های prompt injection

تصویر ۶ — ستون‌های قرمز نشان می‌دهند حمله تطبیقی چگونه نرخ موفقیت را پس از اعمال دفاع‌ها دوباره بالا برده است؛ برگرفته از شکل ۲ مقاله Zhan و همکاران [۸]، با مجوز CC BY 4.0.

پس تیم یک خط قرمز می‌کشد: مدل، مرز امنیتی نیست. delimiter، prompt isolation و detector لایه‌های دفاعی مفیدی‌اند، اما authority ایجاد نمی‌کنند. retrieved text فقط data است. هر tool call باید بیرون مدل و با identity، capability و intent کاربر دوباره authorize شود. مدل می‌تواند action پیشنهاد دهد؛ اجازه اجرا را policy engine صادر می‌کند.

داده بازیابی شده، اختیار ندارد

متن بازیابی شده می تواند شاهد پاسخ باشد، اما نباید مجوز انجام عمل بسازد. اجازه دسترسی به ابزار و داده حساس باید بیرون از مدل و با سیاستی مستقل بررسی شود.

امنیت بعد از جلوگیری از حمله تمام نمی‌شود؛ سامانه باید بتواند اثر آلودگی را پیدا و پاک کند. RAGForensics با حفظ رابطه query، chunk و response برای poisoning هدفمند detection accuracy بین ۹۷٫۴ تا ۹۹٫۶ درصد گزارش کرده است [۹]. ConfusedPilot نیز نشان داده asynchronous indexing ممکن است سند حذف‌شده یا permission تغییریافته را با تأخیر دوباره در پاسخ ظاهر کند [۱۰].

حالا provenance، index version، revocation lag و stale-hit rate دیگر «اطلاعات اضافه برای debug» نیستند. آن‌ها همان ردپاهایی‌اند که به تیم می‌گویند کدام سند وارد کدام پاسخ شده و پس از کشف آلودگی چه چیزهایی باید quarantine یا invalidate شوند.

پرونده پنجم: dashboard سبز بود چون سؤال اشتباهی می‌پرسید

ایستگاه درگیر: رد درخواست و ارزیابی.

نمودار عملیات، average RPS را نشان می‌دهد؛ یک خط آرام و قابل پیش‌بینی. اما کاربران بار را به‌صورت میانگین تولید نمی‌کنند. درخواست‌ها موج می‌زنند، promptها طول یکسانی ندارند و چند burst کوتاه می‌توانند queue و KV-cache را به وضعیتی ببرند که در عدد میانگین دیده نمی‌شود.

BurstGPT با بررسی ۱۰٫۳۱ میلیون trace در ۲۱۳ روز نشان داده workloadهایی با میانگین مشابه، به‌دلیل burstiness متفاوت می‌توانند tail latency، فشار KV-cache و failure rate متفاوتی داشته باشند [۱۱]. پس load testی که فقط نرخ ثابت می‌سازد، ممکن است دقیقا لحظه‌ای را حذف کند که معماری در آن می‌شکند.

مسئله بعدی زمان واکنش است. routing می‌تواند ظرف چند ثانیه بار را جابه‌جا کند، اما آماده‌شدن GPU تازه چند دقیقه زمان می‌خواهد. SageServe یک حلقه سریع برای هدایت بار و حلقه‌ای کندتر برای provisioning در نظر گرفته و در محیط مطالعه تا ۲۵ درصد کاهش GPU-hour و ۸۰ درصد کاهش wastage ناشی از autoscaling گزارش کرده است [۱۲]. این اعداد به workload و مدل هزینه همان پژوهش وابسته‌اند؛ چیزی که قابل انتقال است، جداسازی دو timescale است.

راهبردهای siloed، reactive و predictive برای scaling مدل

تصویر ۷ — مقایسه pool جدا، scaling واکنشی و scaling پیش‌بینانه؛ برگرفته از شکل ۷ مقاله SageServe [۱۲]، با مجوز CC BY 4.0.

آخرین مدرک از مرور EDDOps می‌آید: ۱۲۵ مورد از ۱۳۴ منبع دانشگاهی عمدتا بر ارزیابی پیش از استقرار، ۱۲۴ مورد بر metricهای end-to-end و ۱۳۱ مورد بر evaluation ثابت تمرکز داشته‌اند [۱۳]. بخش بزرگی از ادبیات دقیقا جایی را کمتر می‌بیند که سرویس زنده شروع به تغییر می‌کند: پس از release.

بنابراین evaluation از انتهای pipeline برداشته و وارد control loop می‌شود؛ متصل به trace، dataset نسخه‌دار، canary و rollback. dashboard از این پس فقط نمی‌پرسد «چند درخواست موفق بود؟»؛ می‌پرسد «کدام نسخه، با کدام context، در چه route و با چه هزینه‌ای پاسخ قابل‌اعتماد ساخت؟»

هان در یک نمونه اجرایی نشان می دهد که اگر ورودی، خروجی، نسخه مدل و نتیجه ارزیابی کنار هم ثبت شوند، می توان فهمید افت کیفیت از کدام تغییر آمده است [۱۸]. این کار شاید در آغاز ساده به نظر برسد، اما همان چیزی است که بعدا اجازه می دهد به جای بحث های حدسی، نسخه ها را با هم مقایسه کنیم.

این نتیجه ها از کجا آمده اند؟

برای این پروژه، ۲۶۷ نتیجه ثبت شد. پس از غربال عنوان و چکیده، متن کامل ۳۶ منبع خوانده شد و ۲۵ منبع که برای یک مسئله معماری شاهد مستقیم داشتند وارد تحلیل شدند. از هر منبع، مسئله، روش، یافته، محدودیت و تصمیمی که می شد از آن برداشت کرد جدا شد. فهرست انتهای همین نوشته ۱۸ منبعی را نشان می دهد که در متن به آن ها ارجاع داده شده است؛ بقیه منابع در مستندات پروژه نگه داری شده اند.

این کار مرور کامل همه پژوهش های دنیا نیست. عددهای مقاله ها نیز هدف عملیاتی آماده برای هر سامانه نیستند. آن ها کمک می کنند بفهمیم کجا باید اندازه گیری کنیم و چه بده بستانی را نباید نادیده بگیریم.

ساعت ۱۴:۳۰؛ حالا نقشه را با جزئیات بخوانیم

یکی از مهندسان تیم یک درخواست فرضی را از چپ به راست روی شکل حرکت می‌دهد. هر ایستگاه، پاسخی به یکی از شکست‌های صبح است:

  1. درگاه ورود: در آغاز، هویت کاربر، دامنه داده ای که می تواند ببیند و مهلت پاسخ همراه درخواست ثبت می شود. اگر این اطلاعات گم شوند، هیچ بخش دیگری نمی داند برای چه کسی تصمیم می گیرد.

  2. انتخاب مسیر: همه پرسش ها یک اندازه سخت نیستند. سامانه باید تشخیص دهد پاسخ ساده را سریع بدهد، برای پاسخ سخت تر جست و جوی بیشتری انجام دهد، یا از همان ابتدا بگوید مدرک کافی ندارد. هم زمان، سقف زمان و هزینه را هم تعیین می کند.

  3. بازیابی مجاز و ساخت زمینه: پیش از فرستادن سند به مدل، مجوز دوباره بررسی می شود. بعد فقط بخش های مرتبط و لازم از سندها انتخاب می شوند. متن پیدا شده داده است، نه دستور؛ پس نباید بتواند مدل را به کار نامربوطی وادار کند.

  4. انتخاب و فراخوانی مدل: مدل محلی و مدل بیرونی هر کدام هزینه و محدودیت خودشان را دارند. یک درگاه واحد باید انتخاب مدل، خطای ارتباط و حساب هزینه را کنترل کند تا بقیه سامانه به یک فراهم کننده وابسته نشود.

  5. بررسی پاسخ: پیش از نمایش پاسخ، سامانه چیزهای قابل بررسی را کنترل می کند: آیا قالب پاسخ درست است؟ آیا ادعا به سند برمی گردد؟ آیا داده حساس یا عملی خارج از مجوز در آن نیست؟ اگر پاسخ از این آزمون ها رد نشد، نباید فقط برای اینکه چیزی نمایش داده شود منتشرش کنیم.

  6. رد و ارزیابی: در پایان، سامانه نگه می دارد که پاسخ با کدام سندها، کدام نسخه داده، کدام مدل و چه هزینه ای ساخته شده است. این رد، هم برای پیدا کردن علت خطا لازم است و هم برای سنجیدن اینکه تغییرهای بعدی واقعا بهتر شده اند یا نه.

این ها لزوما شش خدمت جداگانه نیستند. شش مسئولیت اند؛ در یک برنامه ساده هم می توان آن ها را از هم جدا و قابل پیگیری نگه داشت.

ساعت ۱۷:۱۰؛ این‌بار provider واقعا قطع می‌شود

وایت‌برد هنوز پاک نشده که سناریوی آخر مطرح می‌شود: اگر provider همین حالا از دسترس خارج شود چه؟ پاسخ نسخه اولیه ساده بود: retry. اما retry بدون فهم نوع شکست، فقط تکرار سریع‌تر همان اشتباه است.

تیم پیش از انتخاب fallback، شکست را طبقه‌بندی می‌کند:

  • timeout یا خطای موقت شبکه: retry محدود با backoff یا provider جایگزین؛
  • context ضعیف: retriever، top-k یا route جایگزین، یا درخواست clarification؛
  • خروجی ناسازگار با schema: regeneration محدود؛
  • grounding ضعیف: retrieval متفاوت و در نهایت abstain؛
  • نقض policy یا احتمال leakage: توقف پاسخ، ثبت incident و در صورت نیاز quarantine.

همه این شاخه‌ها زیر یک سقف مشترک attempt، deadline، token و cost قرار می‌گیرند. اگر بودجه در هر شاخه از نو صفر شود، fallback به retry storm، هزینه چندبرابری و پاسخ‌های متناقض تبدیل خواهد شد. علت انتخاب شاخه و نتیجه آن نیز در trace می‌ماند.

پاسخ ندادن آگاهانه

پاسخ «اطلاعات کافی برای پاسخ مطمئن ندارم» گاهی شکست سیستم نیست؛ تصمیم درست معماری است که کیفیت و امنیت را فدای دسترس پذیری ظاهری نمی کند.

صبح روز بعد؛ اولین sprint از کجا شروع می‌شود؟

تیم قرار نیست شکل روی وایت‌برد را یک‌شبه به ده‌ها سرویس تبدیل کند. اولین sprint با کم‌کردن ابهام شروع می‌شود، نه زیادکردن componentها:

از کم هزینه ترین کنترل ها آغاز کنید

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

  1. وضعیت امروز را بسنجید. چند پرسش واقعی بردارید و ببینید پاسخ با جست و جو و بدون جست و جو چقدر زمان می برد و چقدر قابل اعتماد است.
  2. برای هر پاسخ رد نگه دارید. کافی است بدانید کاربر چه کسی بوده، چه راهی انتخاب شده، چه سندهایی استفاده شده و نتیجه چه بوده است.
  3. مجوز را درست پیش از بازیابی بررسی کنید. به مجوزی که هنگام ورود سند ثبت شده اکتفا نکنید؛ دسترسی ممکن است تغییر کرده باشد.
  4. چند بررسی ساده پیش از انتشار بگذارید. مثلا قالب پاسخ، وجود سند پشتیبان و مجوز هر عمل مهم را بررسی کنید.
  5. شکست های رایج را تمرین کنید. قطع ارتباط با مدل، پیدا نشدن سند، سند کهنه و تغییر دسترسی را از پیش آزمایش کنید. بعد از این پنج گام، سراغ نهان گاه، مسیرهای بیشتر و تغییرهای پیچیده تر بروید.

این ترتیب یک مزیت مهم دارد: حتی اگر تیم پس از مرحله چهارم متوقف شود، سامانه از نسخه دمو قابل‌مشاهده‌تر و قابل‌کنترل‌تر است. معماری ارزشش را از کامل‌بودن نمودار نمی‌گیرد؛ از کم‌کردن شکست‌های توضیح‌ناپذیر می‌گیرد.

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

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

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

بازگشت به ساعت ۹:۱۷

حالا همان صبح را با معماری جدید دوباره تصور کنیم. سؤال ساده وارد route بدون retrieval می‌شود. سند قدیمی در query-time ACL یا کنترل index version متوقف می‌شود. دستور پنهان داخل فایل نمی‌تواند برای tool مجوز بسازد. timeout provider فقط تا سقف بودجه retry می‌شود. پاسخ کم‌شاهد به‌جای انتشار با اعتمادبه‌نفس، به clarification یا abstain می‌رسد. و اگر باز هم خطایی رخ دهد، trace نشان می‌دهد کدام route، سند، نسخه و fallback در آن نقش داشته‌اند.

هیچ‌کدام از این کنترل‌ها مدل را بی‌خطا نمی‌کنند. کاری که انجام می‌دهند مهم‌تر است: خطا را محدود، قابل مشاهده و قابل بازیابی می‌کنند.

سه اصل، تمام داستان را به هم وصل می‌کنند:

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

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

پس پیش از اینکه دوباره بپرسیم «کدام مدل بهتر است؟»، شاید باید سؤال دشوارتری بپرسیم: وقتی مدل جواب می‌دهد اما نباید جواب بدهد، معماری ما چه می‌کند؟

درباره تصاویر مقاله

شش تصویر پژوهشی بالا از نسخه متن‌کامل مقالات و با مجوز CC BY 4.0 بازنشر شده‌اند. در همه موارد نام منبع و شماره شکل یا جدول در کپشن آمده و تنها حاشیه‌ها و متن پیرامونی صفحه برای خوانایی بهتر برش خورده‌اند؛ داده‌ها، رنگ‌ها و برچسب‌های داخل تصویر دست‌کاری نشده‌اند. تصاویر منابع ACL بر اساس سیاست حق‌نشر ACL Anthology و دو تصویر RAGO و SageServe بر اساس عبارت مجوز درج‌شده در PDF اصلی استفاده شده‌اند.

ویدئوی پروژه

اگر ترجیح می‌دهید جمع‌بندی این پروژه را به صورت ارائه ببینید، ویدئوی زیر همان مسیر را برای مهندسان نرم‌افزار مرور می‌کند.

منابع

۱. Jeong et al.، «Adaptive-RAG: Learning to Adapt Retrieval-Augmented Large Language Models through Question Complexity»، NAACL 2024 — DOI

۲. Jiang et al.، «RAGO: Systematic Performance Optimization for Retrieval-Augmented Generation Serving»، ISCA 2025 — DOI

۳. Jin et al.، «RAGCache: Efficient Knowledge Caching for Retrieval-Augmented Generation»، ACM TOCS — DOI

۴. Agarwal et al.، «Cache-Craft: Managing Chunk-Caches for Efficient Retrieval-Augmented Generation»، ACM — DOI

۵. Es et al.، «RAGAS: Automated Evaluation of Retrieval Augmented Generation»، EACL 2024 — DOI

۶. Rau et al.، «BERGEN: A Benchmarking Library for Retrieval-Augmented Generation»، EMNLP 2024 — DOI

۷. Zeng et al.، «The Good and The Bad: Exploring Privacy Issues in Retrieval-Augmented Generation»، ACL 2024 — DOI

۸. Zhan et al.، «Adaptive Attacks Break Defenses Against Indirect Prompt Injection Attacks on LLM Agents»، NAACL 2025 — DOI

۹. Zhang et al.، «Traceback of Poisoning Attacks to Retrieval-Augmented Generation»، WWW 2025 — DOI

۱۰. RoyChowdhury et al.، «ConfusedPilot: Confused Deputy Risks in RAG-based LLMs» — arXiv

۱۱. Wang et al.، «BurstGPT: A Real-world Workload Dataset to Optimize LLM Serving Systems»، KDD 2025 — DOI

۱۲. Jaiswal et al.، «SageServe: Optimizing LLM Serving on Cloud Data Centers with Forecast-aware Autoscaling»، ACM 2025 — DOI

۱۳. Xia et al.، «Evaluation-Driven Development and Operations of LLM Agents» — arXiv

۱۴. Ray et al.، «METIS: Fast Quality-Aware RAG Systems with Configuration Adaptation» — arXiv

۱۵. Shen et al.، «Hermes: Algorithm-System Co-design for Efficient Retrieval-Augmented Generation At-Scale» — DOI

۱۶. Ayala and Bechard، «Reducing Hallucination in Structured Outputs via Retrieval-Augmented Generation» — DOI

۱۷. Zhou et al.، «Trustworthiness in Retrieval-Augmented Generation Systems: A Survey» — arXiv

۱۸. Han، «MLOps and LLMOps Engineering for Deployment and Evaluation of AI Models» — OpenAlex

«اين مطلب، بخشي از تمرينهاي درس معماري نرم‌افزار در دانشگاه شهيدبهشتي است»