جستجوی شباهت با Spanner و Vertex AI

1. مقدمه

پیشرفت‌های اخیر در یادگیری عمیق امکان نمایش متن و سایر داده‌ها را به گونه‌ای فراهم کرده است که معنای معنایی را به تصویر بکشد. این منجر به رویکرد جدیدی برای جستجو به نام جستجوی برداری شده است که از نمایش های برداری متن (معروف به جاسازی ها) برای یافتن اسنادی که بیشترین ارتباط را با درخواست کاربر دارند، استفاده می کند. جستجوی برداری نسبت به جستجوی سنتی برای برنامه‌هایی مانند جستجوی پوشاک ترجیح داده می‌شود، جایی که کاربران اغلب موارد را بر اساس شرح، سبک یا زمینه جستجو می‌کنند نه بر اساس نام دقیق محصول یا برند. ما می توانیم پایگاه داده Cloud Spanner را با جستجوی برداری ادغام کنیم تا تطبیق شباهت برداری را انجام دهیم. با استفاده از Spanner و Vector Search با هم، مشتریان می‌توانند یک ادغام قدرتمند ایجاد کنند که در دسترس بودن، قابلیت اطمینان و مقیاس Spanner و قابلیت‌های جستجوی شباهت پیشرفته Vertex AI Vector Search را ترکیب می‌کند. این جستجو با مقایسه موارد جاسازی شده در فهرست جستجوی برداری و برگرداندن بیشترین موارد مشابه انجام می شود.

استفاده از مورد

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

  1. منبع داده ها از Spanner است
  2. بردارهای تولید شده برای داده های پوشاک با استفاده از ML.PREDICT و ذخیره شده در Spanner
  3. داده‌های برداری آچار با جستجوی برداری با استفاده از گردش داده و کارهای گردش کار یکپارچه شده است
  4. جستجوی برداری برای یافتن مطابقت شباهت برای ورودی وارد شده توسط کاربر انجام شد

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

فهرست جستجوی آچار به برداری:

داده های جستجوی پوشاک در Spanner ذخیره می شود. ما Vertex AI Embeddings API را در ساختار ML.PREDICT مستقیماً از داده‌های Spanner فراخوانی می‌کنیم. سپس از کارهای Dataflow و Workflow استفاده می کنیم که این داده ها (موجودی و جاسازی ها) را به صورت انبوه در جستجوی برداری Vertex AI آپلود کرده و ایندکس را تازه می کند.

اجرای پرس و جوهای کاربر در فهرست:

هنگامی که یک کاربر توضیحات مربوط به پوشاک را وارد می کند، برنامه با استفاده از api Text Embeddings جاسازی ها را در زمان واقعی ایجاد می کند. سپس به عنوان ورودی به API جستجوی Vector ارسال می شود تا 10 توصیف محصول مرتبط را از فهرست پیدا کند و تصویر مربوطه را نمایش دهد.

نمای کلی معماری

معماری اپلیکیشن Spanner- Vector Search در نمودار 2 قسمتی زیر نشان داده شده است:

فهرست جستجوی آچار به برداری: a79932a25bee23a4.png

برنامه مشتری برای اجرای پرس و جوهای کاربر در فهرست:

b2b4d5a5715bd4c4.png چیزی که خواهی ساخت

آچار به نمایه برداری:

  • پایگاه داده آچار برای ذخیره و مدیریت داده های منبع و جاسازی های مربوطه
  • یک کار گردش کار که داده ها (شناسه و جاسازی ها) را به صورت انبوه در پایگاه داده Vertex AI Vector Search آپلود می کند.
  • API جستجوی برداری که برای یافتن توضیحات محصول مرتبط از فهرست استفاده می‌شود.

اجرای پرس و جوهای کاربر در فهرست:

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

چگونه کار می کند

هنگامی که کاربر توضیحات متنی پوشاک را وارد می کند، برنامه وب توضیحات را به API جستجوی Vector ارسال می کند. سپس Vector Search API از تعبیه‌های توضیحات پوشاک برای یافتن مرتبط‌ترین توضیحات محصول از فهرست استفاده می‌کند. سپس توضیحات محصول و تصاویر مربوطه به کاربر نمایش داده می شود. روند کلی کار به شرح زیر است:

  1. جاسازی‌هایی را برای داده‌های ذخیره شده در Spanner ایجاد کنید .
  2. موارد تعبیه شده را در فهرست جستجوی برداری صادر و آپلود کنید.
  3. با انجام جستجوی نزدیکترین همسایه، فهرست جستجوی برداری را برای موارد مشابه جستجو کنید.

2. الزامات

  • مرورگری مانند کروم یا فایرفاکس
  • یک پروژه Google Cloud با فعال کردن صورت‌حساب

قبل از شروع

  1. در Google Cloud Console ، در صفحه انتخاب پروژه، یک پروژه Google Cloud را انتخاب یا ایجاد کنید
  2. مطمئن شوید که صورتحساب برای پروژه Cloud شما فعال است. با نحوه بررسی فعال بودن صورت‌حساب در پروژه آشنا شوید
  3. مطمئن شوید که همه APIهای لازم (Cloud Spanner، Vertex AI، Google Cloud Storage) فعال هستند.
  4. شما از Cloud Shell استفاده خواهید کرد، یک محیط خط فرمان در حال اجرا در Google Cloud که از قبل با gcloud بارگذاری شده است. برای دستورات و استفاده از gcloud به اسناد مراجعه کنید. اگر پروژه شما تنظیم نشده است، از دستور زیر برای تنظیم آن استفاده کنید:
gcloud config set project <YOUR_PROJECT_ID>
  1. برای شروع، با پروژه فعال Google Cloud خود به صفحه Cloud Spanner بروید

3. Backend: منبع داده و جاسازی های Spanner خود را ایجاد کنید

در این مورد، پایگاه داده Spanner موجودی پوشاک را با تصاویر و توضیحات مربوطه در خود جای می دهد. اطمینان حاصل کنید که جاسازی هایی را برای توضیحات متن ایجاد کرده اید و آنها را در پایگاه داده Spanner خود به عنوان ARRAY<float64> ذخیره می کنید.

  1. داده های Spanner را ایجاد کنید

یک نمونه با نام "spanner-vertex" و یک پایگاه داده با نام "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);
  1. داده ها را با استفاده از INSERT SQL در جدول وارد کنید

درج اسکریپت برای داده های نمونه در اینجا موجود است.

  1. ایجاد مدل جاسازی متن

این مورد نیاز است تا بتوانیم جاسازی هایی را برای محتوای ورودی ایجاد کنیم. در زیر 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');
  1. جاسازی های متنی برای داده های منبع ایجاد کنید

یک جدول برای ذخیره جاسازی ها ایجاد کنید و جاسازی های ایجاد شده را وارد کنید. در یک برنامه پایگاه داده دنیای واقعی، بارگذاری داده به 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. کار گردش کار: صادرات داده های آچار به جستجوی برداری

  1. یک سطل ذخیره سازی ابری ایجاد کنید

این برای ذخیره جاسازی‌های Spanner در یک سطل GCS در قالب json که جستجوی برداری به عنوان ورودی انتظار دارد، لازم است. یک سطل در همان منطقه با داده های خود در Spanner ایجاد کنید . در صورت نیاز یک پوشه در داخل آن ایجاد کنید، اما عمدتاً یک فایل خالی به نام vala.json در آن ایجاد کنید.

  1. Cloud Workflow را تنظیم کنید

برای راه‌اندازی یک صادرات دسته‌ای از Spanner به فهرست جستجوی برداری Vertex AI:

یک نمایه خالی ایجاد کنید :

مطمئن شوید که نمایه جستجوی برداری در همان منطقه با سطل ذخیره سازی ابری شما و داده ها قرار دارد. 11 مرحله دستورالعمل را در زبانه کنسول در بخش Create an index for batch update در صفحه مدیریت ایندکس ها دنبال کنید. در پوشه ای که به contentsDeltaUri ارسال می شود، یک فایل خالی به نام vala.json ایجاد کنید زیرا بدون این فایل نمی توانید یک فهرست ایجاد کنید. این یک شاخص خالی ایجاد می کند.

اگر از قبل یک فهرست دارید، می توانید از این مرحله صرف نظر کنید. گردش کار فهرست شما را بازنویسی می کند.

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

کلون کردن این مخزن git : راه های متعددی برای شبیه سازی یک مخزن git وجود دارد، یکی از راه ها اجرای دستور زیر با استفاده از GitHub CLI است. 2 دستور زیر را از ترمینال Cloud Shell اجرا کنید:

gh repo clone cloudspannerecosystem/spanner-ai

cd spanner-ai/vertex-vector-search/workflows

این پوشه شامل دو فایل است

  • batch-export.yaml : این تعریف گردش کار است.
  • sample-batch-input.json : این نمونه ای از پارامترهای ورودی گردش کار است.

راه اندازی input.json از فایل نمونه: ابتدا نمونه json را کپی کنید.

cp sample-batch-input.json input.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>>"
  }
}

مجوزهای راه اندازی

برای محیط‌های تولید، ما قویاً توصیه می‌کنیم یک حساب سرویس جدید ایجاد کنید و یک یا چند نقش IAM را به آن اعطا کنید که حاوی حداقل مجوزهای لازم برای مدیریت سرویس است. نقش‌های زیر برای راه‌اندازی گردش کار برای صادرات داده‌ها از Spanner (جاسازی‌ها) به فهرست جستجوی برداری لازم است:

حساب خدمات گردش کار ابری :

به طور پیش فرض از حساب خدمات پیش فرض Compute Engine استفاده می کند.

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

برای راه اندازی یک کار جریان داده: مدیر جریان داده، کارگر داده جریان.

جعل هویت یک حساب سرویس کارگر جریان داده: کاربر حساب سرویس.

برای نوشتن Logs: Logs Writer.

برای شروع بازسازی Vertex AI Vector Search: Vertex AI User.

حساب خدمات Dataflow Worker :

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

برای مدیریت جریان داده: مدیر Dataflow ، Dataflow Worker. برای خواندن داده ها از Spanner: Cloud Spanner Database Reader. دسترسی نوشتن بر روی رجیستری کانتینر GCS انتخاب شده: مالک سطل ذخیره سازی GCS.

  1. گردش کار ابری را مستقر کنید

فایل 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"

گردش کار اکنون باید در صفحه Workflows در کنسول Google Cloud قابل مشاهده باشد.

توجه : همچنین می‌توانید گردش کار را از کنسول Google Cloud ایجاد و اجرا کنید. دستورات موجود در کنسول Cloud را دنبال کنید. برای تعریف گردش کار، محتویات batch-export.yaml را کپی و جایگذاری کنید.

پس از تکمیل، گردش کار را اجرا کنید تا صادرات داده آغاز شود.

  1. Cloud Workflow را اجرا کنید

دستور زیر را برای اجرای گردش کار اجرا کنید:

gcloud workflows execute vector-export-workflow --data="$(cat input.json)"

اجرا باید در تب Executions در Workflow ها نمایش داده شود. این باید داده های شما را در پایگاه داده Vector Search بارگیری کند و آن را فهرست کند.

توجه : همچنین می توانید با استفاده از دکمه Execute از کنسول اجرا کنید. دستورات را دنبال کنید و برای ورودی، محتویات input.json سفارشی شده خود را کپی و جایگذاری کنید.

5. استقرار نمایه جستجوی برداری

ایندکس را در یک نقطه پایانی مستقر کنید

برای استقرار ایندکس می توانید مراحل زیر را دنبال کنید:

  1. در صفحه نمایه های جستجوی برداری ، باید یک دکمه DEPLOY در کنار نمایه ای که در مرحله 2 از بخش قبل ایجاد کرده اید، مشاهده کنید. یا می توانید به صفحه اطلاعات فهرست بروید و روی دکمه DEPLOY TO ENDPOINT کلیک کنید.
  2. اطلاعات لازم را ارائه دهید و شاخص را در یک نقطه پایانی مستقر کنید.

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

6. Frontend: داده های کاربر برای جستجوی برداری

بیایید یک برنامه ساده پایتون با یک UX با استفاده از گرادیو بسازیم تا به سرعت پیاده‌سازی خود را آزمایش کنیم: برای پیاده‌سازی این برنامه آزمایشی در نوت‌بوک colab خود می‌توانید به پیاده‌سازی در اینجا مراجعه کنید.

  1. ما از aiplatform python sdk برای فراخوانی Embeddings API و همچنین برای فراخوانی نقطه پایانی فهرست جستجوی برداری استفاده خواهیم کرد.
# [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()
  1. ما از gradio برای نمایش برنامه هوش مصنوعی که در حال ساخت سریع و آسان با رابط کاربری هستیم استفاده خواهیم کرد. قبل از اجرای این مرحله، زمان اجرا را مجدداً راه اندازی کنید.
!pip install gradio
import gradio as gr
  1. از برنامه وب پس از ورودی کاربر، Embeddings API را فراخوانی کنید، ما از مدل جاسازی متن استفاده خواهیم کرد: 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")

شما باید خروجی مشابه زیر را ببینید (لطفاً توجه داشته باشید که تصویر از نظر ارتفاع برش داده شده است بنابراین نمی توانید کل پاسخ برداری را ببینید):

5d8355ec04dac1f9.png

  1. شناسه شاخص مستقر شده و شناسه نقطه پایانی را اعلام کنید
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')
  1. روش جستجوی برداری را برای فراخوانی نقطه پایانی شاخص تعریف کنید و نتیجه را با 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 خواهید شد. بیایید در مرحله بعدی به آن نگاه کنیم.

  1. پیاده سازی روش داده خواندن Spanner را تعریف کنید که متد execute_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های تصاویر مربوط به بردارهای انتخابی را برگرداند.

  1. در نهایت اجازه دهید قطعات را در یک رابط کاربری کنار هم قرار دهیم و فرآیند جستجوی برداری را آغاز کنیم
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)

شما باید نتیجه را مطابق شکل زیر ببینید:

8093b39fbab1a9cc.png

تصویر: پیوند

ویدیوی نتیجه را مشاهده کنید: اینجا .

7. پاکسازی کنید

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

  1. در کنسول Google Cloud، به صفحه مدیریت منابع بروید.
  2. در لیست پروژه، پروژه ای را که می خواهید حذف کنید انتخاب کنید و سپس روی Delete کلیک کنید.
  3. در محاوره، شناسه پروژه را تایپ کنید و سپس روی Shut down کلیک کنید تا پروژه حذف شود.
  4. اگر نمی‌خواهید پروژه را حذف کنید، با رفتن به نمونه‌ای که به تازگی برای این پروژه ایجاد کرده‌اید، نمونه Spanner را حذف کنید و روی دکمه DELETE INSTANCE در گوشه سمت راست بالای صفحه نمای کلی نمونه کلیک کنید.
  5. همچنین می‌توانید به فهرست جستجوی برداری بروید، نقطه پایانی و فهرست را از حالت عادی خارج کنید، و فهرست را حذف کنید.

8. نتیجه گیری

تبریک می گویم! شما با موفقیت اجرای Spanner - Vertex Vector Search توسط

  1. ایجاد منبع داده و جاسازی های Spanner برای برنامه هایی که از پایگاه داده Spanner منبع می شوند.
  2. ایجاد نمایه پایگاه داده جستجوی برداری
  3. ادغام داده های برداری از Spanner به Vector Search با استفاده از Dataflow و Workflow.
  4. استقرار شاخص به نقطه پایانی
  5. در نهایت جستجوی برداری را در ورودی کاربر در پیاده‌سازی Vertex AI sdk با پایتون فراخوانی می‌کنیم.

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