جستوجوی معنایی با Embedding در API هوش مصنوعی: آموزش گامبهگام
جستوجوی معنایی با Embedding در API هوش مصنوعی یعنی بهجای تطبیق دقیق کلمات، معنای متنها را با هم مقایسه کنید. اگر کاربری در فروشگاه یا مستندات شما «بازگشت وجه» بنویسد و متن شما «استرداد مبلغ» باشد، جستوجوی معمولی شاید چیزی پیدا نکند، اما جستوجوی معنایی آن را پیدا میکند. در این راهنما، بر پایه مستندات رسمی OpenAI، مفهوم Embedding و ساخت یک جستوجوی ساده را مرور میکنیم.
Embedding چیست؟
Embedding یک بردار عددی (فهرستی از اعداد اعشاری) است که مدل برای یک متن تولید میکند. متنهایی که از نظر معنا به هم نزدیکاند، بردارهایی نزدیک به هم دارند. به همین دلیل میتوانید با محاسبه فاصله بین بردارها، شباهت معنایی متنها را بسنجید. کاربردهای رایج آن عبارتاند از:
- جستوجوی معنایی در مقالات، محصولات یا پرسشهای متداول
- پیشنهاد محتوای مشابه
- دستهبندی و خوشهبندی متنها
- بازیابی اسناد در سیستمهای RAG (راهنمای چتبات RAG را در همین وبلاگ ببینید)
مدلها و اندازه بردار
طبق مستندات OpenAI، طول بردار بهطور پیشفرض برای مدل text-embedding-3-small برابر ۱۵۳۶ و برای text-embedding-3-large برابر ۳۰۷۲ است. با پارامتر dimensions میتوانید بردار را کوتاهتر کنید؛ مثلاً اگر پایگاه برداری شما فقط تا ۱۰۲۴ بُعد را پشتیبانی میکند. هر ورودی حداکثر ۸۱۹۲ توکن میتواند باشد و در یک درخواست میتوان آرایهای از چند متن (حداکثر ۲۰۴۸ مورد) فرستاد.
| مدل | طول پیشفرض بردار | نکته |
|---|---|---|
| text-embedding-3-small | ۱۵۳۶ | انتخاب مناسب برای شروع و حجم بالا |
| text-embedding-3-large | ۳۰۷۲ | برای زمانی که کیفیت بازیابی اهمیت بیشتری دارد |
مرحله اول: گرفتن Embedding
با کتابخانه رسمی پایتون، یک درخواست ساده بهشکل زیر است:
from openai import OpenAI
client = OpenAI()
def embed(texts):
res = client.embeddings.create(
model="text-embedding-3-small",
input=texts,
)
return [item.embedding for item in res.data]
docs = [
"نحوه استرداد مبلغ سفارش",
"آموزش اتصال به API با پایتون",
"روشهای پرداخت ریالی",
]
doc_vectors = embed(docs)
مرحله دوم: محاسبه شباهت کسینوسی
برای یافتن نزدیکترین متن، از شباهت کسینوسی (cosine similarity) استفاده میشود. مستندات OpenAI توضیح میدهد که بردارهای خروجی بهطور پیشفرض نرمالسازی شدهاند، بنابراین شباهت کسینوسی با ضرب داخلی (dot product) همارز است و رتبهبندی آن با فاصله اقلیدسی یکسان میشود.
import numpy as np
def search(query, docs, doc_vectors, top_k=2):
q = np.array(embed([query])[0])
scores = [float(np.dot(q, np.array(v))) for v in doc_vectors]
ranked = sorted(zip(scores, docs), reverse=True)
return ranked[:top_k]
for score, text in search("بازگشت وجه", docs, doc_vectors):
print(round(score, 3), text)
نکته مهم: برای پرسش و اسناد باید از یک مدل یکسان استفاده کنید؛ بردار مدلهای مختلف قابل مقایسه با هم نیست.
الگوی کلی جستوجوی معنایی در پروژه واقعی
طبق راهنمای OpenAI، روند ساده جستوجو به این صورت است:
- پیشمحاسبه: متنها را به تکههای کوچکتر از سقف توکن تقسیم کنید و برای هر تکه Embedding بگیرید.
- ذخیرهسازی: بردارها را در پایگاه داده خودتان یا یک پایگاه برداری مانند Pinecone، Weaviate یا Qdrant نگه دارید.
- زمان جستوجو: از پرسش کاربر Embedding بگیرید، نزدیکترین بردارها را پیدا کنید و نتایج برتر را برگردانید.
برای چند صد یا چند هزار متن، همین آرایه در حافظه و NumPy کافی است. با رشد داده، پایگاه برداری مناسبتر میشود.
نکات عملی برای متن فارسی
- کیفیت را خودتان بسنجید: چند ده پرسش واقعی تهیه کنید و ببینید نتیجه درست در میان نتایج برتر هست یا نه، سپس مدل و طول بردار را انتخاب کنید.
- تکهبندی منطقی: متن را بر اساس بخشها یا پاراگرافها تقسیم کنید، نه بریدن تصادفی وسط جمله.
- یکسانسازی متن: نیمفاصله، ی و ک عربی و فارسی و ارقام را قبل از Embedding یکدست کنید.
- ذخیره بردارها: Embedding هر متن را فقط یک بار بگیرید و ذخیره کنید تا هزینه توکن تکراری ندهید.
- هزینه: مصرف Embedding هم بر حسب توکن محاسبه میشود؛ مفهوم توکن را در مقاله «توکن و هزینه API» مرور کنید.
خطاهای رایج در جستوجوی معنایی
چند اشتباه پرتکرار وجود دارد که کیفیت نتیجه را پایین میآورد. اول، مخلوط کردن بردارهای مدلهای مختلف در یک پایگاه: اگر مدل را عوض کردید، باید همه اسناد را دوباره Embedding کنید. دوم، تکههای بسیار بزرگ: وقتی یک بردار برای چندین موضوع ساخته میشود، معنای آن مبهم میشود و بازیابی دقیق سختتر است. سوم، تکیه بر یک عدد آستانه برای شباهت: مقدار شباهت قابل قبول به داده و مدل بستگی دارد، پس آن را با نمونههای واقعی خودتان تعیین کنید و فرض نکنید عددی ثابت برای همه پروژهها درست است.
چهارم، فراموش کردن بهروزرسانی: وقتی یک سند ویرایش میشود، بردار آن هم باید دوباره ساخته شود. برای این کار میتوانید هر سند را همراه با یک شناسه و تاریخ ویرایش ذخیره کنید و فقط اسنادی را که تغییر کردهاند دوباره پردازش کنید. این روش هم دقت را حفظ میکند و هم از مصرف اضافه توکن جلوگیری میکند.
در نهایت، جستوجوی معنایی لزوماً جایگزین جستوجوی کلیدواژهای نیست. در بسیاری از سیستمها ترکیب هر دو بهتر عمل میکند؛ مثلاً برای کدهای محصول یا شماره سفارش، تطبیق دقیق مناسبتر است و برای پرسشهای زبان طبیعی، Embedding.
جمعبندی
Embedding سادهترین راه برای افزودن درک معنایی به جستوجو و بازیابی اسناد است: متن را به بردار تبدیل کنید، ذخیره کنید و با شباهت کسینوسی نزدیکترینها را پیدا کنید. برای تهیه کلید API و شروع آزمایش، میتوانید از فروشگاه الینلند با پرداخت ریالی و تحویل فوری استفاده کنید.