ساخت یک RAG از صفر

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

آن لحظه بود که دیگر تنها به پرامپت‌ها اعتماد نکردم. سیستم را با یک قانون بازسازی کردم: یا از روی کاتالوگ پاسخ می‌دهد، یا اصلاً پاسخ نمی‌دهد.

در اینجا نحوه ساخت یک سیستم RAG (Retrieval-Augmented Generation) قابل اعتماد با استفاده از Postgres و Python را توضیح می‌دهم.

آماده‌سازی داده‌ها بیشتر آموزش‌ها بخش سخت کار را نادیده می‌گیرند: پاک‌سازی داده‌ها. من فرآیند خود را به دو مرحله تقسیم کردم:

  • مرحله ۱: دانلود فایل‌های HTML روی دیسک. من متادیتا را به عنوان کامنت در بالای هر فایل ذخیره می‌کنم. این کار فرآیند را idempotent می‌کند. اگر فایلی از قبل وجود داشته باشد، از آن عبور می‌کنم.
  • مرحله ۲: تجزیه (Parse) آفلاین آن فایل‌ها. این کار HTML را به یک کاتالوگ JSON تمیز تبدیل می‌کند.

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

بخش هوش مصنوعی من هر محصول را به یک بلوک متنی تبدیل می‌کنم و با استفاده از مدل bge-m3 آن را به یک بردار (vector) تبدیل می‌کنم. این بردارها را با استفاده از افزونه pgvector در Postgres ذخیره می‌کنم.

من از یک رویکرد جستجوی ترکیبی (hybrid search) برای یافتن محصولات استفاده می‌کنم:

  • جستجوی معنایی (Semantic Search): از بردارها برای یافتن محصولاتی که با معنای سوال شما مطابقت دارند استفاده می‌کند.
  • فیلترهای ساختاریافته (Structured Filters): من از یک LLM استفاده می‌کنم تا پرس‌وجویی مانند "Siemens motors under €2000" را به JSON تبدیل کنم. این کار به من اجازه می‌دهد یک پرس‌وجوی SQL با فیلترهای دقیق برای برند و قیمت اجرا کنم.

یک دستور SQL هم جستجوی فازی (fuzzy search) و هم فیلترهای سخت را مدیریت می‌کند. این کار باعث می‌شود همه چیز همگام (in sync) باقی بماند.

حفاظ‌ها (Guardrails) یک RAG خوب باید بداند چه زمانی سکوت کند. من از دو لایه برای جلوگیری از توهم (hallucinations) استفاده می‌کنم:

  • آستانه شباهت (Similarity Threshold): هر تطابق یک امتیاز می‌گیرد. اگر امتیاز کمتر از حد تعیین‌شده باشد، نتایج را حذف می‌کنم. اگر هیچ نتیجه‌ای از حد عبور نکند، سیستم بدون حتی فراخوانی LLM می‌گوید "یافت نشد". اگر مدل هرگز داده‌ها را نبیند، نمی‌تواند دچار توهم شود.
  • پرامپت سیستم سخت‌گیرانه (Strict System Prompt): من به مدل می‌گویم که فقط از محصولات ارائه شده پاسخ دهد. اگر محصولات نامرتبط باشند، مدل باید پاسخ را رد کند.

آستانه، رفتار بد را غیرممکن می‌کند. پرامپت فقط درخواست رفتار خوب می‌کند. از هر دو استفاده کنید.

خلاصه عملکرد

  • با دقت جمع‌آوری کنید.
  • با صداقت پاک‌سازی کنید.
  • به سادگی Embed کنید.
  • بر اساس طراحی، پاسخ را رد کنید.

همین رد کردن است که سیستم را قابل اعتماد می‌کند. اعتماد از معماری می‌آید، نه از درخواست از یک مدل برای مهربان بودن.

منبع: https://dev.to/utku_catal/building-a-rag-from-scratch-collect-clean-embed-refuse-20ob

جامعه یادگیری اختیاری: https://t.me/GyaanSetuAi