ค้นหาด้วยการฝังเวกเตอร์

หน้านี้แสดงวิธีใช้ Cloud Firestore เพื่อค้นหาเวกเตอร์เพื่อนบ้าน (KNN) ที่ใกล้เคียงที่สุดโดยใช้เทคนิคต่อไปนี้

  • เก็บค่าเวกเตอร์
  • สร้างและจัดการดัชนีเวกเตอร์ KNN
  • สร้างการค้นหา K-Nabest-Neighbor (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 Function

คุณสามารถตั้งค่า Cloud Function เพื่อคำนวณและจัดเก็บการฝังเวกเตอร์เมื่อมีการอัปเดตหรือสร้างเอกสาร

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 แต่ได้รับผลกระทบจากขนาดของเวกเตอร์ ดูข้อมูลเพิ่มเติมได้ที่ Dot product

ข้อมูลที่กรองไว้ล่วงหน้า

ในการกรองข้อมูลล่วงหน้าก่อนที่จะพบเพื่อนบ้านที่อยู่ใกล้ที่สุด คุณสามารถใช้การค้นหาที่คล้ายกันร่วมกับตัวกรองอื่นๆ ยกเว้นตัวกรองอสมการ ระบบรองรับตัวกรองแบบผสม 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 หากต้องการจัดเก็บดัชนีที่ใหญ่กว่า ให้ใช้การลดมิติข้อมูล
  • จำนวนเอกสารสูงสุดที่จะแสดงจากคำค้นหาใกล้เคียงที่สุดคือ 1,000 รายการ
  • การค้นหาเวกเตอร์ไม่รองรับ Listener ของสแนปชอตแบบเรียลไทม์
  • คุณจะใช้ตัวกรองอสมการเพื่อกรองข้อมูลล่วงหน้าไม่ได้
  • เฉพาะไลบรารีของไคลเอ็นต์ Python และ Node.js เท่านั้นที่รองรับการค้นหาเวกเตอร์

ขั้นตอนถัดไป