Tìm kiếm bằng tính năng nhúng vectơ

Trang này cho bạn biết cách sử dụng Cloud Firestore để thực hiện việc tìm kiếm vectơ K-gần nhất lân cận (KNN) bằng cách sử dụng các kỹ thuật sau:

  • Lưu trữ giá trị vectơ
  • Tạo và quản lý chỉ mục vectơ KNN
  • Thực hiện truy vấn K-gần nhất-neighbor (KNN) bằng cách sử dụng một trong các hàm khoảng cách vectơ được hỗ trợ

Lưu trữ các vectơ nhúng

Bạn có thể tạo các giá trị vectơ, chẳng hạn như mục nhúng văn bản từ dữ liệu Cloud Firestore rồi lưu trữ những giá trị đó trong các tài liệu trên Cloud Firestore.

Viết toán tử có nhúng vectơ

Ví dụ sau đây cho thấy cách lưu trữ tệp vectơ nhúng trong tài liệu trên 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])
});
    

Tính toán các mục nhúng vectơ bằng Hàm đám mây

Để tính toán và lưu trữ các mục nhúng vectơ bất cứ khi nào tài liệu được cập nhật hoặc tạo, bạn có thể thiết lập Hàm đám mây:

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,
  });
}
    

Tạo và quản lý chỉ mục vectơ

Trước khi có thể thực hiện một lượt tìm kiếm lân cận gần nhất bằng các mục nhúng vectơ, bạn phải tạo một chỉ mục tương ứng. Các ví dụ sau minh hoạ cách tạo và quản lý chỉ mục vectơ.

Tạo chỉ mục vectơ một trường

Để tạo chỉ mục vectơ một trường, hãy sử dụng gcloud alpha firestore indexes composite create:

Google Cloud
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
    

trong đó:

  • collection-group là mã nhận dạng của nhóm thu thập.
  • vector-field là tên của trường chứa nhúng vectơ.
  • database-id là mã nhận dạng của cơ sở dữ liệu.
  • vector-configuration bao gồm vectơ dimension và loại chỉ mục. dimension là một số nguyên có giá trị tối đa đến 2048. Loại chỉ mục phải là flat. Định dạng cấu hình chỉ mục như sau: {"dimension":"DIMENSION", "flat": "{}"}.

Tạo chỉ mục vectơ tổng hợp

Ví dụ sau đây sẽ tạo một chỉ mục vectơ tổng hợp cho trường color và một trường nhúng vectơ.

Google Cloud
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
    

Liệt kê tất cả chỉ mục vectơ

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

Thay thế database-id bằng mã nhận dạng của cơ sở dữ liệu.

Xoá chỉ mục vectơ

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

trong đó:

  • index-id là mã nhận dạng của chỉ mục cần xoá. Sử dụng indexes composite list để truy xuất mã chỉ mục.
  • database-id là mã nhận dạng của cơ sở dữ liệu.

Mô tả một chỉ mục vectơ

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

trong đó:

  • index-id là mã nhận dạng của chỉ mục cần mô tả. Sử dụng hoặc indexes composite list để truy xuất mã chỉ mục.
  • database-id là mã nhận dạng của cơ sở dữ liệu.

Thực hiện truy vấn lân cận gần nhất

Bạn có thể thực hiện phép tìm kiếm tương tự để tìm các lân cận gần nhất của vectơ nhúng. Tìm kiếm tương tự yêu cầu chỉ mục vectơ. Nếu không có chỉ mục, Cloud Firestore sẽ đề xuất một chỉ mục để tạo bằng 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();
    

Khoảng cách vectơ

Các truy vấn lân cận gần nhất hỗ trợ các tuỳ chọn sau cho khoảng cách vectơ:

  • EUCLIDEAN: Đo khoảng cách EUCLIDEAN giữa các vectơ. Để tìm hiểu thêm, hãy xem phần Euclide.
  • COSINE: So sánh các vectơ dựa trên góc giữa các vectơ đó, cho phép bạn đo lường sự tương đồng không dựa trên độ lớn của vectơ. Bạn nên sử dụng DOT_PRODUCT với vectơ chuẩn hoá theo đơn vị thay vì khoảng cách cosINE (tương đương về mặt toán học với hiệu suất cao hơn). Để tìm hiểu thêm, hãy xem bài viết Sự tương đồng về Cosine để tìm hiểu thêm.
  • DOT_PRODUCT: Tương tự như COSINE nhưng bị ảnh hưởng bởi cường độ của vectơ. Để tìm hiểu thêm, hãy xem bài viết Sản phẩm Dot.

Dữ liệu lọc sơ bộ

Để lọc trước dữ liệu trước khi tìm dữ liệu lân cận gần nhất, bạn có thể kết hợp phép tìm kiếm tương tự với các bộ lọc khác, ngoại trừ bộ lọc bất đẳng thức. Bộ lọc tổng hợp andor được hỗ trợ. Đối với bộ lọc trường, các bộ lọc sau được hỗ trợ:

  • == bằng
  • 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();
    

Hạn chế

Khi bạn làm việc với các mục nhúng vectơ, hãy lưu ý các hạn chế sau:

  • Phương diện nhúng được hỗ trợ tối đa là 2048. Để lưu trữ các chỉ mục lớn hơn, hãy sử dụng tính năng giảm kích thước.
  • Số tài liệu tối đa cần trả về từ truy vấn lân cận gần nhất là 1000.
  • Tính năng tìm kiếm vectơ không hỗ trợ trình nghe ảnh chụp nhanh theo thời gian thực.
  • Bạn không thể sử dụng bộ lọc bất đẳng thức để lọc trước dữ liệu.
  • Chỉ các thư viện ứng dụng Python và Node.js mới hỗ trợ tính năng tìm kiếm vectơ.

Bước tiếp theo