1. مقدمة
جعلت التطورات الحديثة في التعلم المتعمق من الممكن تمثيل النص والبيانات الأخرى بطريقة تعكس المعنى الدلالي. وقد أدى ذلك إلى التوصل إلى طريقة جديدة للبحث، تسمى بحث المتجه، والذي يستخدم تمثيلات المتجهات للنص (المعروفة باسم التضمينات) للعثور على المستندات الأكثر صلة بطلب بحث المستخدم. يُفضّل البحث في المتجهات عن البحث التقليدي عن تطبيقات مثل بحث الملابس، حيث يبحث المستخدمون غالبًا عن عناصر حسب الوصف أو الأسلوب أو السياق بدلاً من استخدام أسماء المنتجات أو العلامات التجارية الدقيقة. يمكننا دمج قاعدة بيانات Cloud Spanner مع بحث Vector لإجراء مطابقة تشابه المتجه. باستخدام Spanner وVector Search معًا، يمكن للعملاء إنشاء عملية تكامل فعّالة تجمع بين مدى توفّر Spanner وموثوقيتها وحجمها، وإمكانات البحث عن التشابه المتقدمة في Vertex AI Vector Search. ويتم إجراء هذا البحث من خلال مقارنة عمليات تضمين العناصر في فهرس بحث المتجه وعرض النتائج الأكثر تشابهًا.
حالة الاستخدام
تخيل أنك عالم بيانات لدى بائع تجزئة للأزياء تحاول مواكبة الاتجاهات السريعة التغير وعمليات البحث عن المنتجات والاقتراحات. يكمن التحدي في أنك تمتلك موارد محدودة ومستودعات بيانات محدودة. تشرح مشاركة المدونة هذه طريقة تنفيذ حالة استخدام لاقتراح الملابس باستخدام نهج البحث عن التشابه على بيانات الملابس.وتم تناول الخطوات التالية:
- البيانات التي تم الحصول عليها من Spanner
- ملفات متجهات تم إنشاؤها لبيانات الملابس باستخدام ML.PREDICT وتم تخزينها في Spanner
- بيانات متّجه Spanner مدمجة مع بحث المتجه باستخدام مهام تدفق البيانات وسير العمل
- تم إجراء بحث المتجه للعثور على تطابق تشابه للإدخال الذي أدخله المستخدم
سننشئ تطبيق ويب تجريبيًا لإجراء بحث عن الملابس بناءً على نص إدخال المستخدم. يتيح التطبيق للمستخدمين البحث عن الملابس من خلال إدخال وصف نصي.
فهرس البحث باستخدام Spanner وVector:
ويتم تخزين بيانات البحث عن الملابس في Spanner. سيتم استدعاء واجهة برمجة تطبيقات Vertex AI Embeddings في بنية ML.PREDICT مباشرةً من بيانات Spanner. بعد ذلك، سنستفيد من مهمتَي Dataflow وWorkflow. تُحمِّل هذه البيانات (المستودع والتضمينات) بشكل مجمَّع إلى Vector Search في Vertex AI وسنعيد تحميل الفهرس.
تنفيذ طلبات بحث المستخدم على الفهرس:
عندما يُدخِل المستخدم وصفًا للملابس، ينشئ التطبيق التضمينات في الوقت الفعلي باستخدام واجهة برمجة التطبيقات Text Embeddings. ويتم بعد ذلك إرسال هذه البيانات كإدخال إلى Vector Search API للعثور على 10 أوصاف منتجات ذات صلة من الفهرس وعرض الصورة المقابلة لها.
نظرة عامة على الهندسة
يتم عرض بنية تطبيق بحث Spanner-Vector في المخطط التالي المكون من جزأين:
فهرس البحث عن المتجهات والدمج:
تنفيذ طلبات بحث المستخدمين في الفهرس من خلال تطبيق العميل:
ما الذي ستنشئه
مؤشر الموزِّع إلى مؤشر المتجه:
- قاعدة بيانات Spanner لتخزين بيانات المصدر والتضمينات المقابلة وإدارتها
- مهمة سير عمل تحمِّل البيانات (المعرّفات والتضمينات) بشكل مجمّع إلى قاعدة بيانات Vertex AI Vector Search.
- يشير ذلك المصطلح إلى واجهة برمجة تطبيقات Vector Search API المستخدَمة للعثور على أوصاف المنتجات ذات الصلة من الفهرس.
تنفيذ طلبات بحث المستخدم على الفهرس:
- يشير ذلك المصطلح إلى تطبيق ويب يتيح للمستخدمين إدخال أوصاف نصية للملابس، ويُجري عملية بحث عن التشابه باستخدام نقطة نهاية الفهرس المنشورة ويعرض أقرب الملابس إلى الإدخال.
آلية العمل
عندما يُدخِل المستخدم وصفًا نصيًا للملابس، يرسل تطبيق الويب الوصف إلى واجهة برمجة تطبيقات Vector Search. بعد ذلك، تستخدم واجهة Vector Search API تضمينات أوصاف الملابس للعثور على أوصاف المنتجات الأكثر صلة من الفهرس. يتم بعد ذلك عرض أوصاف المنتج والصور المقابلة للمستخدم. في ما يلي خطوات سير العمل العامة:
- إنشاء تضمينات للبيانات المخزَّنة في Spanner.
- صدِّر التضمينات وحمِّلها في فهرس "بحث المتجهات".
- يمكنك إجراء طلب بحث في فهرس البحث عن عناصر مشابهة من خلال إجراء بحث عن الجار الأقرب.
2. المتطلبات
قبل البدء
- في Google Cloud Console، ضمن صفحة أداة اختيار المشاريع، اختَر مشروعًا على Google Cloud أو أنشئه.
- تأكَّد من تفعيل الفوترة لمشروعك على السحابة الإلكترونية. التعرُّف على كيفية التحقّق مما إذا كانت الفوترة مفعّلة في مشروع
- تأكَّد من تفعيل جميع واجهات برمجة التطبيقات اللازمة (Cloud Spanner وVertex AI وGoogle Cloud Storage).
- ستستخدم Cloud Shell، وهي بيئة سطر أوامر تعمل في Google Cloud وتكون محمَّلة مسبقًا بـ gcloud. يمكنك الرجوع إلى المستندات حول أوامر gcloud واستخدامها. إذا لم يتم ضبط مشروعك، استخدِم الأمر التالي لضبطه:
gcloud config set project <YOUR_PROJECT_ID>
- للبدء، انتقِل إلى صفحة Cloud Spanner التي تتضمّن مشروعك النشِط على Google Cloud.
3- الخلفية: إنشاء مصدر بيانات Spanner والتضمينات
في حالة الاستخدام هذه، تضم قاعدة بيانات Spanner مخزون الملابس مع الصور والوصف المقابل. احرِص على إنشاء تضمينات لوصف النص وتخزينها في قاعدة بيانات Spanner على هيئة ARRAY<float64>.
- إنشاء بيانات Spanner
إنشاء مثيل باسم "spanner-headex" وقاعدة بيانات باسم "spanner-vertex-embeddings". إنشاء جدول باستخدام DDL:
CREATE TABLE
apparels ( id NUMERIC,
category STRING(100),
sub_category STRING(50),
uri STRING(200),
content STRING(2000),
embedding ARRAY<FLOAT64>
)
PRIMARY KEY
(id);
- إدراج البيانات في الجدول باستخدام INSERT SQL
تتوفّر ميزة إدراج النصوص البرمجية لعيّنة البيانات هنا.
- إنشاء نموذج تضمين النص
هذا مطلوب حتى نتمكن من إنشاء تضمينات للمحتوى في الإدخال. وفي ما يلي DDL الخاصة بك:
CREATE MODEL text_embeddings INPUT(content STRING(MAX))
OUTPUT(
embeddings
STRUCT<
statistics STRUCT<truncated BOOL, token_count FLOAT64>,
values ARRAY<FLOAT64>>
)
REMOTE OPTIONS (
endpoint = '//aiplatform.googleapis.com/projects/abis-345004/locations/us-central1/publishers/google/models/textembedding-gecko');
- إنشاء نصوص مضمَّنة للبيانات المصدر
إنشاء جدول لتخزين التضمينات وإدراج التضمينات التي تم إنشاؤها. في أي تطبيق قاعدة بيانات فعلي، يكون تحميل البيانات إلى Spanner وصولاً إلى الخطوة 2 معاملات. لأغراض الحفاظ على أفضل ممارسات التصميم بدون أي تغيير، أفضّل إبقاء جداول المعاملات مساوية، لذا أنشئ جدولاً منفصلاً للتضمينات.
CREATE TABLE apparels_embeddings (id string(100), embedding ARRAY<FLOAT64>)
PRIMARY KEY (id);
INSERT INTO apparels_embeddings(id, embeddings)
SELECT CAST(id as string), embeddings.values
FROM ML.PREDICT(
MODEL text_embeddings,
(SELECT id, content from apparels)
) ;
الآن وبعد أن أصبح المحتوى المجمّع والتضمينات جاهزة، اسمح لنا بإنشاء فهرس بحث المتجه ونقطة النهاية لتخزين التضمينات التي ستساعد في إجراء بحث المتجه.
4. مهمة سير العمل: تصدير بيانات Spanner إلى Vector Search
- إنشاء حزمة Cloud Storage
يجب تنفيذ هذا الإجراء لتخزين عمليات التضمين من Spanner في حزمة GCS بتنسيق JSON الذي تتوقّعه ميزة "بحث Vector" كإدخال. أنشِئ حزمة في المنطقة نفسها التي تتوفّر فيها بياناتك على Spanner. أنشِئ مجلدًا في الداخل إذا لزم الأمر، وأنشِئ فيه ملفًا كبيرًا يُسمّى فارغًا.json.
- إعداد Cloud Workflow
لإعداد عملية تصدير مجمّعة من Spanner إلى فهرس Vertex AI Vector Search، عليك اتّباع الخطوات التالية:
إنشاء فهرس فارغ:
تأكَّد من أنّ "فهرس بحث المتجهات" في المنطقة نفسها التي تتضمّن البيانات وحزمة Cloud Storage. اتّبِع الخطوات الـ 11 ذات التعليمات الواردة ضمن علامة تبويب "وحدة التحكّم" في القسم إنشاء فهرس للتحديث المجمّع في صفحة "إدارة الفهارس". في المجلّد الذي يتم تمريره إلى contentsDeltaUri، أنشئ ملفًا فارغًا باسم empty.json، لأنّك لن تكون قادرًا على إنشاء فهرس بدون هذا الملف. يؤدي هذا إلى إنشاء فهرس فارغ.
وإذا كان لديك فهرس، يمكنك تخطّي هذه الخطوة. سيؤدي سير العمل إلى استبدال الفهرس.
ملاحظة: لا يمكنك نشر فهرس فارغ إلى نقطة نهاية. لذا، سنؤجل خطوة نشر الأداة إلى نقطة نهاية إلى خطوة لاحقة، بعد تصدير بيانات المتجه إلى Cloud Storage.
استنساخ مستودع git هذا: هناك عدة طُرق لنسخ مستودع git، ويمكنك تنفيذ الأمر التالي باستخدام GitHub CLI. شغِّل الأمرَين أدناه من الوحدة الطرفية في Cloud Shell:
gh repo clone cloudspannerecosystem/spanner-ai
cd spanner-ai/vertex-vector-search/workflows
يحتوي هذا المجلد على ملفين
batch-export.yaml
: هذا هو تعريف سير العمل.sample-batch-input.json
: هذا نموذج من مَعلمات إدخال سير العمل.
إعداد enter.json من نموذج الملف: انسخ أولاً نموذج JSON.
cp sample-batch-input.json enter.json
بعد ذلك، يمكنك تعديل input.json
مع تضمين تفاصيل مشروعك. في هذه الحالة، يجب أن يكون ملف json على النحو التالي:
{
"project_id": "<<YOUR_PROJECT>>",
"location": "<<us-central1>>",
"dataflow": {
"temp_location": "gs://<<YOUR_BUCKET>>/<<FOLDER_IF_ANY>>/workflow_temp"
},
"gcs": {
"output_folder": "gs://<<YOUR_BUCKET>>/<<FOLDER_IF_ANY>>/workflow_output"
},
"spanner": {
"instance_id": "spanner-vertex",
"database_id": "spanner-vertex-embeddings",
"table_name": "apparels_embeddings",
"columns_to_export": "embedding,id"
},
"vertex": {
"vector_search_index_id": "<<YOUR_INDEX_ID>>"
}
}
أذونات الإعداد
بالنسبة إلى بيئات الإنتاج، ننصح بشدة بإنشاء حساب خدمة جديد ومنحه دور واحد أو أكثر من أدوار إدارة الهوية وإمكانية الوصول التي تتضمّن الحدّ الأدنى من الأذونات المطلوبة لإدارة الخدمة. يجب توفّر الأدوار التالية لإعداد سير العمل من أجل تصدير البيانات من Spanner (عمليات التضمين) إلى فهرس Vector Search:
يتم تلقائيًا استخدام حساب الخدمة التلقائي في Compute Engine.
إذا كنت تستخدم حساب خدمة تم إعداده يدويًا، يجب تضمين الأدوار التالية:
لتشغيل مهمة تدفق البيانات: مشرف تدفق البيانات، وعامل تدفق البيانات.
لانتحال هوية حساب خدمة عامل تدفق البيانات: مستخدم حساب الخدمة
لكتابة السجلات: محرِّر السجلات.
لتشغيل Vertex AI Vector Search، عليك اتّباع الخطوات التالية: مستخدم Vertex AI
إذا كنت تستخدم حساب خدمة تم إعداده يدويًا، يجب تضمين الأدوار التالية:
لإدارة تدفق البيانات: مشرف Dataflow وDataflow Worker. لقراءة البيانات من Spanner: قارئ قاعدة بيانات Cloud Spanner. الإذن بتعديل المحتوى من خلال سجلّ حاويات GCS المحدَّد: مالك حزمة التخزين في GCS
- نشر Cloud Workflow
انشر ملف yaml لسير العمل في مشروعك على Google Cloud. يمكنك ضبط المنطقة أو الموقع الجغرافي الذي سيتم فيه تنفيذ سير العمل عند تنفيذه.
gcloud workflows deploy vector-export-workflow --source=batch-export.yaml --location="us-central1" [--service account=<service_account>]
or
gcloud workflows deploy vector-export-workflow --source=batch-export.yaml --location="us-central1"
من المفترض أن يظهر سير العمل الآن في صفحة "سير العمل" في وحدة تحكُّم Google Cloud.
ملاحظة: يمكنك أيضًا إنشاء سير العمل ونشره من وحدة تحكُّم Google Cloud. اتّبِع التعليمات في Cloud Console. بالنسبة إلى تعريف سير العمل، انسخ محتويات package-export.yaml والصقها.
وبعد اكتمال ذلك، يمكنك تنفيذ سير العمل حتى يبدأ تصدير البيانات.
- تنفيذ Cloud Workflow
شغِّل الأمر التالي لتنفيذ سير العمل:
gcloud workflows execute vector-export-workflow --data="$(cat input.json)"
من المفترض أن تظهر عملية التنفيذ في علامة التبويب "عمليات التنفيذ" في "سير العمل". من المفترض أن يؤدي هذا إلى تحميل بياناتك إلى قاعدة بيانات Vector Search وفهرستها.
ملاحظة: يمكنك أيضًا التنفيذ من وحدة التحكّم باستخدام الزر "تنفيذ". اتّبِع التعليمات، وبالنسبة إلى الإدخال، انسخ محتوى ملف enter.json المخصّص والصقه.
5- نشر فهرس البحث المتجه
نشر الفهرس إلى نقطة نهاية
يمكنك اتباع الخطوات أدناه لنشر الفهرس:
- في صفحة فهارس Vector Search، من المفترض أن يظهر لك الزر DEPLOY بجوار الفهرس الذي أنشأته للتو في الخطوة 2 من القسم السابق. يمكنك بدلاً من ذلك الانتقال إلى صفحة معلومات الفهرس والنقر على زر "التوزيع إلى نقطة النهاية".
- قدِّم المعلومات اللازمة وانشر الفهرس في نقطة نهاية.
بدلاً من ذلك، يمكنك الاطّلاع على ورقة الملاحظات هذه لنشرها في نقطة نهاية (تخطّي للوصول إلى جزء النشر من ورقة الملاحظات). بعد النشر، يُرجى تدوين رقم تعريف الفهرس المنشور وعنوان URL لنقطة النهاية.
6- الواجهة الأمامية: بيانات المستخدم إلى البحث المتجه
لننشئ تطبيق Python بسيطًا مع تجربة مستخدم تعمل بـ gراديو لاختبار التنفيذ بسرعة: يمكنك الرجوع إلى عملية التنفيذ هنا لتنفيذ هذا التطبيق التجريبي في دفتر الملاحظات colab الخاص بك.
- سنستخدم aiplatform python sdk لاستدعاء Embeddings API وأيضًا لاستدعاء نقطة نهاية فهرس Vector Search.
# [START aiplatform_sdk_embedding]
!pip install google-cloud-aiplatform==1.35.0 --upgrade --quiet --user
import vertexai
vertexai.init(project=PROJECT_ID, location="us-central1")
from vertexai.language_models import TextEmbeddingModel
import sys
if "google.colab" in sys.modules:
# Define project information
PROJECT_ID = " " # Your project id
LOCATION = " " # Your location
# Authenticate user to Google Cloud
from google.colab import auth
auth.authenticate_user()
- سنستخدم gRadio لعرض تطبيق الذكاء الاصطناعي الذي نعمل على إنشائه بسرعة وسهولة باستخدام واجهة مستخدم. يجب إعادة تشغيل بيئة التشغيل قبل تنفيذ هذه الخطوة.
!pip install gradio
import gradio as gr
- من تطبيق الويب عند إدخال المستخدم واستدعاء واجهة برمجة التطبيقات Embeddings، سنستخدم نموذج تضمين النص: textembedding-gecko@latest
استدعاء الطريقة التالية نموذج تضمين النص وعرض تضمينات المتجه للنص الذي أدخله المستخدم:
def text_embedding(content) -> list:
"""Text embedding with a Large Language Model."""
model = TextEmbeddingModel.from_pretrained("textembedding-gecko@latest")
embeddings = model.get_embeddings(content)
for embedding in embeddings:
vector = embedding.values
#print(f"Length of Embedding Vector: {len(vector)}")
return vector
اختباره
text_embedding("red shorts for girls")
من المفترض أن تظهر لك نتيجة مشابهة لما يلي (يُرجى ملاحظة أنّ ارتفاع الصورة تم اقتصاصه بحيث لا يمكنك رؤية استجابة المتجه بالكامل):
- تعريف معرّف الفهرس المنشور ورقم تعريف نقطة النهاية
from google.cloud import aiplatform
DEPLOYED_INDEX_ID = "spanner_vector1_1702366982123"
#Vector Search Endpoint
index_endpoint = aiplatform.MatchingEngineIndexEndpoint('projects/273845608377/locations/us-central1/indexEndpoints/2021628049526620160')
- حدِّد طريقة البحث المتجه لاستدعاء نقطة نهاية الفهرس وإظهار النتيجة بأقرب 10 نتائج لاستجابة التضمين المقابلة للنص الذي أدخله المستخدم.
في تعريف الطريقة أدناه لبحث المتجه، لاحظ أنه يتم استدعاء طريقة find_neighbors لتحديد أقرب 10 متجهات.
def vector_search(content) -> list:
result = text_embedding(content)
#call_vector_search_api(content)
index_endpoint = aiplatform.MatchingEngineIndexEndpoint('projects/273845608377/locations/us-central1/indexEndpoints/2021628049526620160')
# run query
response = index_endpoint.find_neighbors(
deployed_index_id = DEPLOYED_INDEX_ID,
queries = [result],
num_neighbors = 10
)
out = []
# show the results
for idx, neighbor in enumerate(response[0]):
print(f"{neighbor.distance:.2f} {spanner_read_data(neighbor.id)}")
out.append(f"{spanner_read_data(neighbor.id)}")
return out
ستلاحظ أيضًا استدعاء الطريقة spanner_read_data. لنلقِ نظرة على ذلك في الخطوة التالية.
- حدد تنفيذ طريقة بيانات قراءة Spanner التي تستدعي طريقة تنفيذ_sql لاستخراج الصور المقابلة لمعرفات أقرب متجهات الجار التي تم إرجاعها من الخطوة الأخيرة.
!pip install google-cloud-spanner==3.36.0
from google.cloud import spanner
instance_id = "spanner-vertex"
database_id = "spanner-vertex-embeddings"
projectId = PROJECT_ID
client = spanner.Client()
client.project = projectId
instance = client.instance(instance_id)
database = instance.database(database_id)
def spanner_read_data(id):
query = "SELECT uri FROM apparels where id = " + id
outputs = []
with database.snapshot() as snapshot:
results = snapshot.execute_sql(query)
for row in results:
#print(row)
#output = "ID: {}, CONTENT: {}, URI: {}".format(*row)
output = "{}".format(*row)
outputs.append(output)
return "\n".join(outputs)
يُفترض أن يعرض عناوين URL للصور المقابلة للمتجهات المحددة.
- لنجمع أخيرًا القطع معًا في واجهة مستخدم ونشغّل عملية "بحث Vector"
from PIL import Image
def call_search(query):
response = vector_search(query)
return response
input_text = gr.Textbox(label="Enter your query. Examples: Girls Tops White Casual, Green t-shirt girls, jeans shorts, denim skirt etc.")
output_texts = [gr.Image(label="") for i in range(10)]
demo = gr.Interface(fn=call_search, inputs=input_text, outputs=output_texts, live=True)
resp = demo.launch(share = True)
من المفترض أن تظهر لك النتيجة كما هو موضّح أدناه:
الصورة: رابط
يمكنك الاطّلاع على فيديو النتيجة: هنا.
7. تَنظيم
لتجنُّب تحصيل رسوم من حسابك على Google Cloud مقابل الموارد المُستخدَمة في هذه المشاركة، يُرجى اتّباع الخطوات التالية:
- في وحدة تحكُّم Google Cloud، انتقِل إلى صفحة إدارة الموارد.
- في قائمة المشاريع، اختَر المشروع الذي تريد حذفه، ثم انقر على "حذف".
- في مربع الحوار، اكتب معرّف المشروع، ثم انقر على "إيقاف التشغيل" لحذف المشروع.
- إذا كنت لا تريد حذف المشروع، يمكنك حذف مثيل Spanner من خلال الانتقال إلى المثيل الذي أنشأته للتو لهذا المشروع والنقر على زر "حذف النسخة" في أعلى يسار صفحة النظرة العامة على المثيل.
- يمكنك أيضًا الانتقال إلى فهرس البحث عن المتجهات وإلغاء نشر نقطة النهاية والفهرس وحذف الفهرس.
8. الخاتمة
تهانينا لقد أكملت بنجاح تنفيذ بحث Spanner - Vertex Vector بحلول
- إنشاء مصدر بيانات Spanner وتضمينات للتطبيقات التي يتم الحصول عليها من قاعدة بيانات Spanner.
- إنشاء فهرس قاعدة بيانات بحث المتجه.
- دمج بيانات المتجهات من Spanner إلى Vector Search باستخدام مهام Dataflow وWorkflow.
- نشر فهرس إلى نقطة نهاية.
- أخيرًا، استدعاء Vector Search في عمليات إدخال المستخدم في تنفيذ مستند إلى Python لـ Vertex AI sdk.
لا تتردد في توسيع نطاق التنفيذ ليشمل حالة استخدامك الخاصة أو ارتجال في حالة الاستخدام الحالية بميزات جديدة. يمكنك الاطّلاع على مزيد من المعلومات حول إمكانات تعلُّم الآلة في Spanner هنا.