راهنمای گام به گام ساخت موتور جستجوی معنایی با استفاده از Sentence Transformers، FAISS و all-MiniLM-L6-v2

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

در این آموزش، یک سیستم جستجوی معنایی را با استفاده از Sentence Transformers پیاده‌سازی خواهیم کرد. Sentence Transformers یک کتابخانه قدرتمند است که بر پایه Transformers Hugging Face ساخته شده و مدل‌های از پیش آموزش‌دیده را به طور خاص برای تولید جاسازی‌های جملات (sentence embeddings) بهینه کرده است. این جاسازی‌ها، نمایش‌های عددی از متن هستند که معنای معنایی را در بر می‌گیرند و به ما امکان می‌دهند محتوای مشابه را از طریق شباهت برداری پیدا کنیم. یک برنامه کاربردی عملی ایجاد خواهیم کرد: یک موتور جستجوی معنایی برای مجموعه‌ای از چکیده‌های علمی که می‌تواند به سؤالات تحقیقاتی با مقالات مرتبط پاسخ دهد، حتی اگر اصطلاحات بین سؤال و اسناد مرتبط متفاوت باشد.

ابتدا، کتابخانه‌های مورد نیاز را در نوت‌بوک Colab خود نصب می‌کنیم:

                
!pip install sentence-transformers faiss-cpu numpy pandas matplotlib datasets
                
            

اکنون، کتابخانه‌هایی را که نیاز داریم وارد می‌کنیم:

                
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sentence_transformers import SentenceTransformer
import faiss
from typing import List, Dict, Tuple
import time
import re
import torch
                
            

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

                
abstracts = [
    {
        "id": 1,
        "title": "یادگیری عمیق برای پردازش زبان طبیعی",
        "abstract": "این مقاله به بررسی پیشرفت‌های اخیر در مدل‌های یادگیری عمیق برای وظایف پردازش زبان طبیعی می‌پردازد. ما معماری‌های ترانسفورمر از جمله BERT، GPT و T5 را بررسی می‌کنیم و عملکرد آن‌ها را در معیارهای مختلف از جمله پاسخ به سؤالات، تحلیل احساسات و طبقه‌بندی متن تجزیه و تحلیل می‌کنیم."
    },
    {
        "id": 2,
        "title": "تأثیر تغییرات آب و هوایی بر اکوسیستم‌های دریایی",
        "abstract": "افزایش دمای اقیانوس و اسیدی شدن به شدت بر صخره‌های مرجانی و تنوع زیستی دریایی تأثیر می‌گذارد. این مطالعه داده‌های جمع‌آوری‌شده طی یک دوره 10 ساله را ارائه می‌کند که نشان‌دهنده کاهش سریع در اکوسیستم‌های صخره‌ای و پیشنهاد استراتژی‌های حفاظتی برای کاهش بیشتر آسیب است."
    },
    {
        "id": 3,
        "title": "پیشرفت در فناوری واکسن mRNA",
        "abstract": "توسعه واکسن‌های mRNA نشان‌دهنده یک پیشرفت بزرگ در فناوری ایمن‌سازی است. این بررسی مکانیسم عمل، بهبودهای پایداری و اثربخشی بالینی پلتفرم‌های mRNA را مورد بحث قرار می‌دهد، با توجه ویژه به استقرار سریع آن‌ها در طول همه‌گیری COVID-19."
    },
    {
        "id": 4,
        "title": "الگوریتم‌های محاسبات کوانتومی برای مسائل بهینه‌سازی",
        "abstract": "محاسبات کوانتومی سرعت بالقوه‌ای را برای حل مسائل پیچیده بهینه‌سازی ارائه می‌دهد. این مقاله الگوریتم‌های کوانتومی را برای بهینه‌سازی ترکیبی ارائه می‌کند و عملکرد نظری آن‌ها را با روش‌های کلاسیک در مسائلی از جمله فروشنده دوره‌گرد و برش حداکثر مقایسه می‌کند."
    },
    {
        "id": 5,
        "title": "چارچوب‌های برنامه‌ریزی شهری پایدار",
        "abstract": "این تحقیق چارچوب‌هایی را برای توسعه شهری پایدار پیشنهاد می‌کند که سیستم‌های انرژی تجدیدپذیر، شبکه‌های حمل و نقل عمومی کارآمد و زیرساخت‌های سبز را ادغام می‌کند. مطالعات موردی از پنج شهر، کاهش در انتشار کربن و بهبود در معیارهای کیفیت زندگی را نشان می‌دهد."
    },
    {
        "id": 6,
        "title": "شبکه‌های عصبی برای بینایی کامپیوتر",
        "abstract": "شبکه‌های عصبی کانولوشن در وظایف بینایی کامپیوتر انقلابی ایجاد کرده‌اند. این مقاله نوآوری‌های معماری اخیر از جمله اتصالات باقیمانده، مکانیسم‌های توجه و ترانسفورماتورهای بینایی را بررسی می‌کند و عملکرد آن‌ها را در طبقه‌بندی تصویر، تشخیص اشیا و معیارهای تقسیم‌بندی ارزیابی می‌کند."
    },
    {
        "id": 7,
        "title": "کاربردهای بلاک‌چین در مدیریت زنجیره تأمین",
        "abstract": "فناوری بلاک‌چین ردیابی شفاف و ایمن کالاها را در سراسر زنجیره‌های تأمین امکان‌پذیر می‌کند. این مطالعه پیاده‌سازی‌ها را در صنایع غذایی، دارویی و خرده‌فروشی تجزیه و تحلیل می‌کند و بهبودها را در قابلیت ردیابی، کاهش محصولات تقلبی و افزایش اعتماد مصرف‌کننده کمی می‌کند."
    },
    {
        "id": 8,
        "title": "عوامل ژنتیکی در اختلالات خودایمنی",
        "abstract": "این تحقیق نشانگرهای ژنتیکی کلیدی مرتبط با افزایش حساسیت به شرایط خودایمنی را شناسایی می‌کند. از طریق مطالعات انجمن گسترده ژنومی 15000 بیمار، ما انواع جدیدی را شناسایی کردیم که بر تنظیم سیستم ایمنی تأثیر می‌گذارند و ممکن است به عنوان اهدافی برای رویکردهای درمانی شخصی‌سازی‌شده عمل کنند."
    },
    {
        "id": 9,
        "title": "یادگیری تقویتی برای سیستم‌های کنترل رباتیک",
        "abstract": "یادگیری تقویتی عمیق به ربات‌ها این امکان را می‌دهد تا وظایف پیچیده دستکاری را از طریق آزمون و خطا بیاموزند. این مقاله چارچوبی را ارائه می‌کند که برنامه‌ریزی مبتنی بر مدل را با روش‌های گرادیان سیاست ترکیب می‌کند تا به یادگیری کارآمد نمونه از مهارت‌های دستکاری ماهرانه دست یابد."
    },
    {
        "id": 10,
        "title": "آلودگی میکروپلاستیک در سیستم‌های آب شیرین",
        "abstract": "این مطالعه آلودگی میکروپلاستیک را در 30 دریاچه و رودخانه آب شیرین اندازه‌گیری می‌کند و منابع اصلی و مکانیسم‌های انتقال را شناسایی می‌کند. نتایج نشان‌دهنده همبستگی بین تراکم جمعیت و سطوح آلودگی، با پیامدهایی برای سیاست‌های تصفیه آب و مدیریت زباله‌های پلاستیکی است."
    }
]

papers_df = pd.DataFrame(abstracts)
print(f"مجموعه داده با {len(papers_df)} مقاله علمی بارگذاری شد")
papers_df[["id", "title"]]
                
            

اکنون یک مدل Sentence Transformer از پیش آموزش‌دیده را از Hugging Face بارگیری می‌کنیم. ما از مدل all-MiniLM-L6-v2 استفاده خواهیم کرد که تعادل خوبی بین عملکرد و سرعت ارائه می‌دهد:

                
model_name = 'all-MiniLM-L6-v2'
model = SentenceTransformer(model_name)
print(f"مدل بارگذاری شد: {model_name}")
                
            

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

                
documents = papers_df['abstract'].tolist()
document_embeddings = model.encode(documents, show_progress_bar=True)

print(f"{len(document_embeddings)} جاسازی با ابعاد {document_embeddings.shape[1]} تولید شد")
                
            

FAISS (جستجوی شباهت هوش مصنوعی فیس‌بوک) یک کتابخانه برای جستجوی شباهت کارآمد است. از آن برای فهرست‌بندی جاسازی‌های سند خود استفاده خواهیم کرد:

                
dimension = document_embeddings.shape[1]  

index = faiss.IndexFlatL2(dimension)
index.add(np.array(document_embeddings).astype('float32'))

print(f"شاخص FAISS با {index.ntotal} بردار ایجاد شد")
                
            

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

                
def semantic_search(query: str, top_k: int = 3) -> List[Dict]:
    """
    جستجو برای اسناد مشابه پرس و جو

    Args:
        query: متن برای جستجو
        top_k: تعداد نتایج برای بازگشت

    Returns:
        لیستی از دیکشنری ها که حاوی اطلاعات سند و امتیاز شباهت هستند
    """
    query_embedding = model.encode([query])

    distances, indices = index.search(np.array(query_embedding).astype('float32'), top_k)

    results = []
    for i, idx in enumerate(indices[0]):
        results.append({
            'id': papers_df.iloc[idx]['id'],
            'title': papers_df.iloc[idx]['title'],
            'abstract': papers_df.iloc[idx]['abstract'],
            'similarity_score': 1 - distances[0][i] / 2  
        })

    return results
                
            

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

                
test_queries = [
    "ترانسفورماتورها در پردازش زبان طبیعی چگونه کار می کنند؟",
    "اثرات گرمایش جهانی بر زندگی اقیانوسی چیست؟",
    "در مورد توسعه واکسن کووید به من بگویید",
    "آخرین الگوریتم ها در محاسبات کوانتومی",
    "شهرها چگونه می توانند ردپای کربن خود را کاهش دهند؟"
]

for query in test_queries:
    print("\n" + "="*80)
    print(f"پرس و جو: {query}")
    print("="*80)

    results = semantic_search(query, top_k=3)

    for i, result in enumerate(results):
        print(f"\nنتیجه #{i+1} (امتیاز: {result['similarity_score']:.4f}):")
        print(f"عنوان: {result['title']}")
        print(f"گزیده چکیده: {result['abstract'][:150]}...")
                
            

بیایید جاسازی‌های سند را تجسم کنیم تا ببینیم چگونه بر اساس موضوع خوشه‌بندی می‌شوند:

                
from sklearn.decomposition import PCA

pca = PCA(n_components=2)
reduced_embeddings = pca.fit_transform(document_embeddings)

plt.figure(figsize=(12, 8))
plt.scatter(reduced_embeddings[:, 0], reduced_embeddings[:, 1], s=100, alpha=0.7)

for i, (x, y) in enumerate(reduced_embeddings):
    plt.annotate(papers_df.iloc[i]['title'][:20] + "...",
                 (x, y),
                 fontsize=9,
                 alpha=0.8)

plt.title('تجسم جاسازی های سند (PCA)')
plt.xlabel('مولفه 1')
plt.ylabel('مولفه 2')
plt.grid(True, linestyle='--', alpha=0.7)
plt.tight_layout()
plt.show()
                
            

بیایید یک رابط جستجوی تعاملی‌تر ایجاد کنیم:

                
from IPython.display import display, HTML, clear_output
import ipywidgets as widgets

def run_search(query_text):
    clear_output(wait=True)

    display(HTML(f"<h3>پرس و جو: {query_text}</h3>"))

    start_time = time.time()
    results = semantic_search(query_text, top_k=5)
    search_time = time.time() - start_time

    display(HTML(f"<p>{len(results)} نتیجه در {search_time:.4f} ثانیه یافت شد</p>"))

    for i, result in enumerate(results):
        html = f"""
        <div style="margin-bottom: 20px; padding: 15px; border: 1px solid #ddd; border-radius: 5px;">
            <h4>{i+1}. {result['title']} <span style="color: #007bff;">(امتیاز: {result['similarity_score']:.4f})</span></h4>
            <p>{result['abstract']}</p>
        </div>
        """
        display(HTML(html))

search_box = widgets.Text(
    value='',
    placeholder='پرس و جوی جستجوی خود را اینجا تایپ کنید...',
    description='جستجو:',
    layout=widgets.Layout(width='70%')
)

search_button = widgets.Button(
    description='جستجو',
    button_style='primary',
    tooltip='برای جستجو کلیک کنید'
)

def on_button_clicked(b):
    run_search(search_box.value)

search_button.on_click(on_button_clicked)

display(widgets.HBox([search_box, search_button]))
                
            

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

درباره نویسنده

آصف رزاق مدیر عامل Marktechpost Media Inc است. آصف به عنوان یک کارآفرین و مهندس آینده نگر، متعهد به استفاده از پتانسیل هوش مصنوعی برای خیر اجتماعی است. جدیدترین تلاش او راه اندازی یک پلتفرم رسانه ای هوش مصنوعی، Marktechpost است که به دلیل پوشش عمیق خود از اخبار یادگیری ماشین و یادگیری عمیق که هم از نظر فنی سالم و هم به راحتی برای مخاطبان گسترده قابل درک است، متمایز است. این پلتفرم دارای بیش از 2 میلیون بازدید ماهانه است که نشان دهنده محبوبیت آن در بین مخاطبان است.