البحث باستخدام تضمينات المتجهات

توضّح لك الصفحة كيفية استخدام Cloud Firestore لإجراء عمليات بحث عن متجه الجار الأقرب (KNN) باستخدام الأساليب التالية:

  • تخزين قيم الخط المتجه
  • إنشاء وإدارة فهارس متجه KNN
  • قم بعمل استعلام خوارزمية الجار الأقرب (KNN) باستخدام إحدى دوال المسافة المتجهة المدعومة

تخزين تضمينات المتجه

يمكنك إنشاء قيم متجهات مثل تضمينات النص من بيانات Cloud Firestore وتخزينها في مستندات Cloud Firestore.

كتابة العملية باستخدام تضمين متّجه

يوضح المثال التالي كيفية تخزين تضمين متجه في مستند Cloud Firestore:

Python
from google.cloud import firestore
from google.cloud.firestore_v1.vector import Vector

firestore_client = firestore.Client()
collection = firestore_client.collection("coffee-beans")
doc = {
  "name": "Kahawa coffee beans",
  "description": "Information about the Kahawa coffee beans.",
  "embedding_field": Vector([1.0 , 2.0, 3.0])
}

collection.add(doc)
    
Node.js
import {
  Firestore,
  FieldValue,
} from "@google-cloud/firestore";

const db = new Firestore();
const coll = db.collection('coffee-beans');
await coll.add({
  name: "Kahawa coffee beans",
  description: "Information about the Kahawa coffee beans.",
  embedding_field: FieldValue.vector([1.0 , 2.0, 3.0])
});
    

حساب عمليات تضمين المتجهات باستخدام دالة السحابة

لحساب عمليات تضمين المتجهات وتخزينها عند تعديل مستند أو إنشائه، يمكنك إعداد دالة Cloud:

Python
@functions_framework.cloud_event
def store_embedding(cloud_event) -> None:
  """Triggers by a change to a Firestore document.
  """
  firestore_payload = firestore.DocumentEventData()
  payload = firestore_payload._pb.ParseFromString(cloud_event.data)

  collection_id, doc_id = from_payload(payload)
  # Call a function to calculate the embedding
  embedding = calculate_embedding(payload)
  # Update the document
  doc = firestore_client.collection(collection_id).document(doc_id)
  doc.set({"embedding_field": embedding}, merge=True)
    
Node.js
/**
 * A vector embedding will be computed from the
 * value of the `content` field. The vector value
 * will be stored in the `embedding` field. The
 * field names `content` and `embedding` are arbitrary
 * field names chosen for this example.
 */
async function storeEmbedding(event: FirestoreEvent<any>): Promise<void> {
  // Get the previous value of the document's `content` field.
  const previousDocumentSnapshot = event.data.before as QueryDocumentSnapshot;
  const previousContent = previousDocumentSnapshot.get("content");

  // Get the current value of the document's `content` field.
  const currentDocumentSnapshot = event.data.after as QueryDocumentSnapshot;
  const currentContent = currentDocumentSnapshot.get("content");

  // Don't update the embedding if the content field did not change
  if (previousContent === currentContent) {
    return;
  }

  // Call a function to calculate the embedding for the value
  // of the `content` field.
  const embeddingVector = calculateEmbedding(currentContent);

  // Update the `embedding` field on the document.
  await currentDocumentSnapshot.ref.update({
    embedding: embeddingVector,
  });
}
    

إنشاء فهارس المتجهات وإدارتها

قبل أن تتمكن من إجراء بحث الجار الأقرب باستخدام تضمينات المتجه، يجب عليك إنشاء فهرس مقابل. توضح الأمثلة التالية كيفية إنشاء فهارس المتجهات وإدارتها.

إنشاء فهرس متجه أحادي الحقل

لإنشاء فهرس متّجه أحادي الحقل، استخدِم السمة gcloud alpha firestore indexes composite create:

gcloud
gcloud alpha firestore indexes composite create \
--collection-group=collection-group \
--query-scope=COLLECTION \
--field-config field-path=vector-field,vector-config='vector-configuration' \
--database=database-id
    

حيث:

  • collection-group هو رقم تعريف مجموعة المجموعات.
  • vector-field هو اسم الحقل الذي يحتوي على تضمين المتجه.
  • database-id هو معرف قاعدة البيانات.
  • تتضمن vector-configuration الخط المتجه dimension ونوع الفهرس. dimension هو عدد صحيح يصل إلى 2048. يجب أن يكون نوع الفهرس flat. يمكنك تنسيق إعدادات الفهرس كما يلي: {"dimension":"DIMENSION", "flat": "{}"}.

إنشاء فهرس متجه مركب

ينشئ المثال التالي فهرسًا متّجهًا مركبًا للحقل color وحقل تضمين متجه.

gcloud
gcloud alpha firestore indexes composite create \
--collection-group=collection-group \
--query-scope=COLLECTION \
--field-config=order=ASCENDING,field-path="color" \
--field-config field-path=field,vector-config='{"dimension":"1024", "flat": "{}"}' \
--database=database-id
    

سرد كل الفهارس المتجهة

gcloud
gcloud alpha firestore indexes composite list --database=database-id

استبدِل database-id بمعرّف قاعدة البيانات.

حذف فهرس متجه

gcloud
gcloud alpha firestore indexes composite delete index-id --database=database-id
    

حيث:

  • index-id هو الرقم التعريفي للفهرس المراد حذفه. استخدِم indexes composite list لاسترداد رقم تعريف الفهرس.
  • database-id هو معرف قاعدة البيانات.

وصف مؤشر المتّجه

gcloud
gcloud alpha firestore indexes composite describe index-id --database=database-id
    

حيث:

  • index-id هو الرقم التعريفي للفهرس المطلوب وصفه. استخدِم أو indexes composite list لاسترداد رقم تعريف الفهرس.
  • database-id هو معرف قاعدة البيانات.

إجراء طلب بحث من الجار الأقرب

يمكنك إجراء بحث تشابه للعثور على أقرب الجيران لتضمين المتجه. تتطلب عمليات البحث عن التشابه فهارس متجهات. في حال عدم توفّر فهرس، يقترح Cloud Firestore فهرسًا لإنشائه باستخدام gCloud CLI.

Python
from google.cloud.firestore_v1.base_vector_query import DistanceMeasure

collection = collection("coffee-beans")

# Requires vector index
collection.find_nearest(
   vector_field="embedding_field",
   query_vector=Vector([3.0, 1.0, 2.0]),
   distance_measure=DistanceMeasure.EUCLIDEAN,
   limit=5)
    
Node.js
import {
  Firestore,
  FieldValue,
  VectorQuery,
  VectorQuerySnapshot,
} from "@google-cloud/firestore";

// Requires single-field vector index
const vectorQuery: VectorQuery = coll.findNearest('embedding_field', FieldValue.vector([3.0, 1.0, 2.0]), {
  limit: 5,
  distanceMeasure: 'EUCLIDEAN'
});

const vectorQuerySnapshot: VectorQuerySnapshot = await vectorQuery.get();
    

المسافات المتجهة

تتيح طلبات البحث ذات الجار الأقرب الخيارات التالية لمسافة المتجه:

  • EUCLIDEAN: يقيس مسافة EUCLIDEAN بين المتجهات. لمزيد من المعلومات، يمكنك الاطّلاع على القسم الإقليدية.
  • COSINE: مقارنة المتجهات بناءً على الزاوية بينها، ما يتيح لك قياس التشابه الذي لا يعتمد على حجم المتجهات. ننصح باستخدام DOT_PRODUCT مع الوحدة المتجهة التي تمت تسويتها بدلاً من المسافة COSINE، والتي تكون مكافئة رياضيًا من خلال أداء أفضل. لمزيد من المعلومات، يمكنك الاطّلاع على تشابه جيب التمام لمعرفة المزيد.
  • DOT_PRODUCT: تشبه COSINE ولكنها تتأثر بحجم المتجهات. لمزيد من المعلومات، راجِع المنتَج النقطي.

بيانات التصفية المسبقة

لفلترة البيانات مسبقًا قبل العثور على أقرب الجيران، يمكنك الجمع بين بحث التشابه وفلاتر أخرى باستثناء فلاتر عدم المساواة. يمكن استخدام الفلتر المركّب and وor. بالنسبة إلى فلاتر الحقول، تتوفّر الفلاتر التالية:

  • == يساوي
  • in
  • array_contains
  • array_contains_any
Python
# Similarity search with pre-filter
# Requires composite vector index
collection.where("color", "==", "red").find_nearest(
   vector_field="embedding_field",
   query_vector=Vector([3.0, 1.0, 2.0]),
   distance_measure=DistanceMeasure.EUCLIDEAN,
   limit=5)
    
Node.js
// Similarity search with pre-filter
// Requires composite vector index
const preFilteredVectorQuery: VectorQuery = coll
  .where("color", "==", "red")
  .findNearest("embedding_field", FieldValue.vector([3.0, 1.0, 2.0]), {
    limit: 5,
    distanceMeasure: "EUCLIDEAN",
  });

vectorQueryResults = await preFilteredVectorQuery.get();
    

القيود

أثناء عملك مع تضمينات المتجهات، لاحظ القيود التالية:

  • الحد الأقصى لبُعد التضمين المسموح به هو 2048. لتخزين فهارس أكبر، استخدِم ميزة تقليل الأبعاد.
  • الحد الأقصى لعدد المستندات التي يتم عرضها من طلب بحث الجار الأقرب هو 1000.
  • لا يوفّر بحث المتجه أدوات معالجة اللقطات في الوقت الفعلي.
  • ولا يمكنك استخدام فلاتر عدم المساواة لفلترة البيانات مسبقًا.
  • تدعم مكتبات العملاء Python وNode.js فقط البحث المتجه.

الخطوات التالية