Wyszukiwanie podobieństw wektorowych za pomocą Vertex AI

Witamy w wyszukiwaniu wektorowym opartym na podobieństwie w Firebase Data Connect – implementacji wyszukiwania semantycznego w Firebase, która integruje się z Google Vertex AI.

Podstawą tej funkcji są wektory dystrybucyjne, czyli tablice liczb zmiennoprzecinkowych, które reprezentują znaczenie semantyczne tekstu lub multimediów. Wykonując wyszukiwanie najbliższych sąsiadów za pomocą wektora dystrybucyjnego wejściowego, możesz znaleźć wszystkie treści podobne semantycznie. Data Connect używa do tego celu rozszerzenia pgvector w PostgreSQL.

Ta zaawansowana wyszukiwarka semantyczna może być wykorzystywana w przypadkach takich jak systemy rekomendacji i wyszukiwarki. Jest to też kluczowy element generowania wspomaganego przez wyszukiwanie w ramach procesów generatywnej AI. Więcej informacji znajdziesz w dokumentacji Vertex AI.

Możesz polegać na wbudowanym w Data Connect mechanizmie automatycznego generowania wektorów dystrybucyjnych za pomocą interfejsu Embeddings API Vertex AI lub użyć tego interfejsu do ich ręcznego generowania.

Wymagania wstępne

  • Skonfiguruj Data Connect w przypadku swojego projektu.

  • Włącz interfejsy Vertex AI API.

Konfiguracja

Możesz wybrać lokalny proces tworzenia aplikacji (jeśli jesteś deweloperem witryn internetowych, Kotlina, Androida lub iOS) albo proces IDX (dla deweloperów witryn internetowych). Do celów programistycznych możesz użyć lokalnej bazy danych lub produkcyjnego projektu Data Connect i jego instancji Cloud SQL for PostgreSQL.

W tych instrukcjach przyjęto założenie, że masz utworzony projekt Data Connectzgodnie z instrukcjami z krótkiego przewodnika.

Integracja z lokalną bazą danych PostgreSQL

  1. skonfigurować lokalną instancję PostgreSQL;
  2. Przypisz sobie rolę uprawnień użytkownika Vertex AI.
  3. Skonfiguruj domyślne uwierzytelnianie aplikacji Google Cloud w swoim środowisku.
  4. Zainstaluj rozszerzenie pgvector w lokalnej instancji PostgreSQL.
  5. Włącz rozszerzenie za pomocą CREATE EXTENSION vector zgodnie z instrukcjami w repozytorium pgvector.

Integracja z IDX

  1. Skonfiguruj obszar roboczy IDX za pomocą szablonu Data Connect.
  2. Przypisz sobie rolę uprawnień użytkownika Vertex AI.
  3. Włącz rozszerzenie za pomocą CREATE EXTENSION vector zgodnie z instrukcjami w repozytorium pgvector.

Projektowanie schematu

Aby przeprowadzić wyszukiwanie wektorów, dodaj w schemacie nowe pole typu Vector. Jeśli na przykład chcesz przeprowadzić wyszukiwanie semantyczne za pomocą opisów filmów, dodaj pole do przechowywania wektorów dystrybucyjnych powiązanych z opisem filmu. W tym schemacie pole descriptionEmbedding służy do przechowywania wektorów dystrybucyjnych w polu description.

type Movie @table {
 id: ID! @col(name: "movie_id") @default(id: ID! @col(name: "movie_id") @default(expr: "uuidV4()")
 title: String!
 description: String
 descriptionEmbedding: Vector! @col(size:768)
 // ...
}

Generowanie i pobieranie wektorów

Data Connect zapewnia zintegrowane wsparcie dla wektorów embeddingu z wartością serwera _embed. W ten sposób usługa Data Connect generuje wektory dystrybucyjne, wywołując wewnętrznie interfejsy Embedding API Vertex AI. Wartość serwera _embed może być używana zarówno w mutacjach, jak i w zapytaniach.

Mutacje

Generowanie i przechowywanie dystrybucji za pomocą Data Connect

W aplikacji do wyszukiwania wektorów prawdopodobnie będziesz chciał(-a) generować kody zastępcze zaraz po dodaniu rekordów do bazy danych. Oto przykład createMovie mutacji, która dodaje rekord filmu do tabeli Movie, a także przekazuje opis filmu z określonym elementem osadzania model.

mutation createMovie($movieData: Movie_Data! @pick(fields: ["title", "genre", "description"])) {
  movie_insert(data: {
    ...movieData,
    descriptionEmbedding_embed: {model: "textembedding-gecko@003", text: $movieData.description}
  })
}

W niektórych przypadkach warto zaktualizować opis filmu i opcję osadzenia.

mutation updateDescription($id: String!, $description: String!) {
  movie_update(id: $id, data: {
    description: $description,
    descriptionEmbedding_embed: {model: "textembedding-gecko@003", text: $description}
  })
}

Aby wywołać tę mutację z klienta:

import { updateMovieDescriptionWithEmbed } from 'lib/dataconnect-sdk/';

await updateMovieDescriptionWithEmbed({ id: movieId, description: description});

// Use the response

Zapytania

Aby pobrać wektory rozkładu, użyj zapytania podobnego do tego: Pamiętaj, że zmienna descriptionEmbedding zwracana przez zapytanie to tablica typu float, która zazwyczaj nie jest czytelna dla człowieka. Dlatego pakiety SDK utworzone przez Data Connect nie obsługują bezpośredniego zwracania.

Zwrócone wektory dystrybucyjne możesz wykorzystać do wyszukiwania podobieństw, jak opisano w następnej sekcji.

query getMovieDescription($id: String!) @auth(is: PUBLIC) {
 movie(id: $id)
   id
   description
   descriptionEmbedding
}

Przeprowadź wyszukiwanie podobieństw

Teraz możemy przeprowadzić wyszukiwanie podobieństw.

W przypadku każdego pola Vector funkcja Data Connect generuje funkcję GraphQL, która implementuje wyszukiwanie podobieństw. Nazwa tej wygenerowanej funkcji to ${pluralType}_${vectorFieldName}_similarity. Obsługuje on kilka parametrów, jak pokazano w następujących przykładach i w liście referencyjnej.

Możesz zdefiniować funkcję GraphQL, która wywołuje wyszukiwanie podobieństw. Jak wspomnieliśmy powyżej, wartość serwera _embed kieruje Data Connect do generowania wektorów dystrybucyjnych za pomocą interfejsów API Vertex AI, w tym przypadku do tworzenia wektorów dystrybucyjnych dla ciągu wyszukiwania używanego do porównania z wektorami dystrybucyjnymi opisu filmu.

W tym przykładzie wyszukiwanie podobieństw zwróci do 5 filmów, których opis jest semantycznie najbardziej zbliżony do zapytania wejściowego. Zestaw wyników jest sortowany w rosnącej kolejności według odległości – od najbliższej do najdalszej.

query searchMovieDescriptionUsingL2Similarity ($query: String!) @auth(level: PUBLIC) {
    movies_descriptionEmbedding_similarity(
      compare_embed: {model: "textembedding-gecko@003", text: $query},
      where: {content: {ne: "No info available for this movie."}}, limit: 5)
      {
        id
        title
        description
      }
  }

Dostosowywanie zapytania o podobność

Wartości domyślne parametrów wyszukiwania, takich jak methodwithin, sprawdzają się w większości przypadków. Jeśli jednak zauważysz, że zapytanie zwraca wyniki, które są zbyt różne lub że brakuje wyników, które chcesz uwzględnić, spróbuj dostosować te parametry.

Aby znaleźć odpowiednią wartość parametru within, możemy dodać parametr _metadata.distance do wybranych pól, aby sprawdzić, jak daleko od wektora zapytania znajduje się każdy wynik. Na podstawie zwróconych wartości parametru distance możemy ustawić parametr within. Zostaną uwzględnione tylko wyniki, których odległość od wartości parametru within jest mniejsza niż wartość parametru within:

query searchMovieDescriptionUsingL2Similarity ($query: String!) @auth(level: PUBLIC) {
    movies_descriptionEmbedding_similarity(
      compare_embed: {model: "textembedding-gecko@003", text: $query},
      within: 2,
      where: {content: {ne: "No info available for this movie."}}, limit: 5)
      {
        id
        title
        description
        _metadata {
          distance
        }
      }
  }

Możesz też eksperymentować z różnymi funkcjami odległości, ustawiając parametr method.

query searchMovieDescriptionUsingL2Similarity ($query: String!) @auth(level: PUBLIC) {
    movies_descriptionEmbedding_similarity(
      compare_embed: {model: "textembedding-gecko@003", text: $query},
      within: .5,
      method: COSINE,
      where: {content: {ne: "No info available for this movie."}}, limit: 5)
      {
        id
        title
        description
        _metadata {
          distance
        }
      }
  }

Pamiętaj, że różne metody zwracają bardzo różne wartości odległości: jeśli ustawisz wartość within, po zmianie wartości method będziesz musiał ją ponownie dostosować.

Wywoływanie zapytania o podobność

Aby wywołać wyszukiwanie podobieństw w kodzie klienta:

import { searchMovieDescriptionUsingL2similarity} from 'lib/dataconnect-sdk';

const response = await searchMovieDescriptionUsingL2similarity({ query });

// Use the response

Korzystanie z wektorów dystrybucyjnych niestandardowych

Data Connect umożliwia też bezpośrednią pracę z wbudowanymi elementami jako Vectorzamiast generowania ich za pomocą wartości serwera _embed.

Przechowywanie niestandardowego osadzenia

Za pomocą interfejsu Vertex Embeddings API określ odpowiedni model i poproś o wyniki wektorów dystrybucyjnych w odpowiednim wymiarze.

Następnie zmień zwrócony tablicowy tablicowy typ danych na Vector, aby przekazać go operacji aktualizacji w celu zapisania.

mutation updateDescription($id: String!, $description: String!, $descriptionEmbedding: Vector!) {
  movie_update(id: $id, data: {
    // title, genre...
    description: $description,
    descriptionEmbedding: $descriptionEmbedding
  })
}

Wykonywanie wyszukiwania podobieństwa za pomocą niestandardowych wektorów dystrybucyjnych

Wykonaj tę samą operację, aby pobrać wektory dystrybucyjne dla wyszukiwanych haseł, i przypisz je do Vectors.

Następnie wywołaj zapytanie _similarity, aby wykonać każde wyszukiwanie.

query searchMovieDescriptionUsingL2Similarity($compare: Vector!, $within: Float, $excludesContent: String, $limit: Int) @auth(level: PUBLIC) {
    movies_descriptionEmbedding_similarity(
      compare: $compare,
      method: L2,
      within: $within,
      where: {content: {ne: $excludesContent}}, limit: $limit)
      {
        id
        title
        description
      }
  }

Wdrażanie w gałęzi produkcyjnej

Wdrażanie schematu i sprzęgającego

Ostatnim krokiem w typowym cyklu Data Connect jest wdrożenie zasobów do wersji produkcyjnej.

Podczas wdrażania schematu zawierającego typy Vector do CloudSQL za pomocą polecenia firebase deploy interfejs wiersza poleceń Firebase wykonuje niezbędne czynności, aby włączyć w instancji CloudSQL generowanie wektorów dystrybucyjnych na podstawie Vertex AI.

firebase deploy --only dataconnect

Jeśli chcesz ręcznie włączyć obsługę umieszczania w instancji CloudSQL lub napotkasz błąd w interfejsie wiersza poleceń, wykonaj te instrukcje.

Składnia wyszukiwania wektorowego

Rozszerzenia schematu

Typ danych Data Connect Vector jest mapowany na typ vector w PostgreSQL zgodnie z definicją w rozszerzeniu pgvector. Typ vector w pgvector jest przechowywany jako tablica liczb zmiennoprzecinkowych o pojedynczej precyzji w PostgreSQL.

W elementach Data Connect typ Vector jest reprezentowany jako tablica liczb JSON. Dane wejściowe są przekształcane w tablicę wartości float32. Jeśli nie uda się przekształcić wartości, zostanie zgłoszony błąd.

Aby ustawić wymiary wektora, użyj parametru size dyrektywy @col.

type Question @table {
    text: String!
    category: String!
    textEmbedding: Vector! @col(size: 768)
}

Typ size jest obsługiwany tylko w przypadku typów Vector. Operacje Vector, takie jak wyszukiwanie podobnych elementów, wymagają, aby wszystkie Vector miały tę samą liczbę wymiarów.

directive @col(
  # … existing args
  """
  Defines a fixed column size for certain scalar types.

  - For Vector, size is required.
  - For all other types, size is currently unsupported and hence supplying it will result in a schema error.
  """
  size: Int
) on FIELD_DEFINITION

Wartość serwera _embed dla zapytań i mutacji

_embed

Ta wartość serwera kieruje usługę Data Connect do generowania i przechowywania wektorów za pomocą interfejsów Vertex AI Embedding API. Tej wartości serwera można używać zarówno w przypadku zapytań, jak i mutacji.

Parametry wyszukiwania podobieństw

method: COSINE|INNER_PRODUCT|L2

Funkcja odległości używana do wyszukiwania najbliższych sąsiadów. Obecnie obsługiwane algorytmy to podzbiór algorytmów wyszukiwania pgvector.

within: float

Ograniczenie odległości, w której wykonywane jest wyszukiwanie najbliższych sąsiadów.

where: FDC filter condition

Zapoznaj się z przewodnikiem po schematach, zapytaniach i mutacjach.

limit: int

Liczba wyników do zwrócenia.