Esegui una ricerca di somiglianze vettoriali con Vertex AI

Ti diamo il benvenuto nella ricerca di similarità vettoriale di Firebase Data Connect, l'implementazione della ricerca semantica di Firebase che si integra con Google Vertex AI.

Al centro di questa funzionalità ci sono i vector embedding, ovvero array di numeri in virgola mobile che rappresentano il significato semantico di testo o contenuti multimediali. Eseguendo una ricerca del vicino più prossimo utilizzando un incorporamento vettoriale di input, puoi trovare tutti i contenuti semanticamente simili. Data Connect utilizza l'estensione pgvector di PostgreSQL per questa funzionalità.

Questa potente ricerca semantica può essere utilizzata in casi d'uso come i motori per suggerimenti e i motori di ricerca. È anche un componente chiave nella generazione basata sul recupero nei flussi di AI generativa. La documentazione di Vertex AI è un ottimo punto di partenza per scoprire di più.

Puoi fare affidamento sul supporto integrato di Data Connect per la generazione automatica di incorporamenti vettoriali utilizzando l'API Embeddings di Vertex AI oppure utilizzare questa API per generarli manualmente.

Prerequisiti

  • Configura Data Connect per il tuo progetto.

  • Abilita le API Vertex AI.

Configurazione

Puoi scegliere tra un flusso di sviluppo locale (se sei uno sviluppatore web, Kotlin Android o iOS) o un flusso IDX (per gli sviluppatori web). Puoi utilizzare un database locale o il tuo progetto Data Connect di produzione e la relativa istanza Cloud SQL per PostgreSQL per lo sviluppo.

Queste istruzioni presuppongono che tu abbia creato il tuo progetto Data Connect seguendo la guida rapida.

Eseguire l'integrazione con PostgreSQL locale

  1. Configura un'istanza PostgreSQL locale.
  2. Concediti il ruolo IAM Utente Vertex AI.
  3. Configura le credenziali predefinite dell'applicazione Google Cloud nel tuo ambiente.
  4. Installa l'estensione pgvector nell'istanza PostgreSQL locale.
  5. Attiva l'estensione utilizzando CREATE EXTENSION vector come indicato nelle istruzioni del repository pgvector.

Integrare con IDX

  1. Configura il tuo spazio di lavoro IDX utilizzando il modello Data Connect.
  2. Concediti il ruolo IAM Utente Vertex AI.
  3. Attiva l'estensione utilizzando CREATE EXTENSION vector come indicato nelle istruzioni del repository pgvector.

Progettare lo schema

Per eseguire la ricerca vettoriale, aggiungi un nuovo campo di tipo Vector allo schema. Ad esempio, se vuoi eseguire una ricerca semantica utilizzando le descrizioni dei film, aggiungi un campo per contenere gli embedding vettoriali associati alla descrizione del film. In questo schema, descriptionEmbedding viene aggiunto per archiviare gli incorporamenti vettoriali per il campo 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)
 // ...
}

Generare e recuperare incorporamenti

Data Connect offre il supporto integrato per gli incorporamenti vettoriali con il valore del server _embed. In questo modo Data Connect genera embedding vettoriali chiamando internamente le API Embedding di Vertex AI. Il valore del server _embed può essere utilizzato sia nelle mutazioni che nelle query.

Mutazioni

Genera e memorizza un incorporamento tramite Data Connect

Nella tua app di ricerca vettoriale, probabilmente vorrai richiedere che gli embedding vengano generati non appena aggiungi record al database. Ecco una mutazione createMovie che aggiunge un record di film alla tabella Movie e passa anche una descrizione del film con un incorporamento model specificato.

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

In alcuni casi, potresti voler aggiornare la descrizione e l'incorporamento del film.

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

Per chiamare l'ultima mutazione da un client:

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

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

// Use the response

Query

Recupera gli embedding vettoriali utilizzando una query come la seguente. Tieni presente che il descriptionEmbedding restituito dalla query è un array di numeri in virgola mobile, che in genere non è leggibile. Pertanto, gli SDK generati da Data Connect non supportano la restituzione diretta.

Puoi utilizzare gli incorporamenti vettoriali restituiti per eseguire la ricerca di similarità, come descritto nella sezione successiva.

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

Eseguire la ricerca di somiglianze

Ora possiamo eseguire la ricerca per similarità.

Per ogni campo Vector, Data Connect genera una funzione GraphQL che implementa la ricerca per similarità. Il nome di questa funzione generata è ${pluralType}_${vectorFieldName}_similarity. Supporta alcuni parametri come mostrato negli esempi seguenti e nell'elenco di riferimento.

Puoi definire una funzione GraphQL che richiama la ricerca di similarità. Come accennato in precedenza, il valore del server _embed indica a Data Connect di generare gli incorporamenti vettoriali utilizzando le API di incorporamento di Vertex AI, in questo caso per creare incorporamenti per la stringa di ricerca utilizzata per il confronto con gli incorporamenti della descrizione del film.

In questo esempio, la ricerca per similarità restituirà fino a 5 film la cui descrizione è semanticamente più vicina alla query di input. Il set di risultati è ordinato in ordine crescente di distanza, dalla più vicina alla più lontana.

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
      }
  }

Ottimizzare la query di similarità

I valori predefiniti per i parametri di ricerca come method e within funzionano bene per la maggior parte dei casi d'uso. Tuttavia, se noti che la query restituisce risultati troppo diversi o mancano risultati che vuoi includere, prova a modificare questi parametri.

Per trovare un valore appropriato per within, possiamo aggiungere _metadata.distance ai campi selezionati per vedere a quale distanza dal vettore della query si trova ogni risultato. In base ai valori distance restituiti, possiamo impostare il parametro within; verranno inclusi solo i risultati con distanza inferiore al valore di 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
        }
      }
  }

Puoi anche sperimentare con diverse funzioni di distanza impostando il parametro 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
        }
      }
  }

Tieni presente che metodi diversi restituiscono valori molto diversi per la distanza: se hai impostato within, dovrai regolare nuovamente questo valore dopo aver modificato method.

Chiama la query di similarità

Per chiamare una ricerca per somiglianza dal codice client:

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

const response = await searchMovieDescriptionUsingL2similarity({ query });

// Use the response

Utilizzare gli incorporamenti personalizzati

Data Connect ti consente anche di lavorare direttamente con gli incorporamenti come Vector anziché utilizzare il valore del server _embed per generarli.

Memorizzare un incorporamento personalizzato

Utilizzando l'API Vertex Embeddings, specifica un modello di corrispondenza e richiedi risultati di embedding della dimensione corretta.

Poi, esegui il cast dell'array di numeri in virgola mobile restituito in un Vector da passare all'operazione di aggiornamento per l'archiviazione.

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

Eseguire la ricerca di similarità utilizzando gli incorporamenti personalizzati

Esegui la stessa operazione per recuperare gli incorporamenti per i termini di ricerca e trasmettere a Vectors.

Quindi, chiama la query _similarity per eseguire ogni ricerca.

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
      }
  }

Distribuzione in produzione

Esegui il deployment dello schema e del connettore

L'ultimo passaggio di un'iterazione tipica di Data Connect consiste nel deployment degli asset in produzione.

Quando esegui il deployment dello schema contenente i tipi Vector in Cloud SQL utilizzando il comando firebase deploy, la CLI Firebase esegue i passaggi necessari per attivare la generazione di incorporamenti basata su Vertex AI nell'istanza Cloud SQL.

firebase deploy --only dataconnect

Se vuoi attivare manualmente il supporto dell'incorporamento nella tua istanza CloudSQL o riscontri un errore della CLI, segui queste istruzioni.

Sintassi della ricerca vettoriale

Estensioni dello schema

Il tipo di dati Vector di Data Connect viene mappato al tipo vector di PostgreSQL come definito dall'estensione pgvector. Il tipo vector di pgvector viene archiviato come array di numeri in virgola mobile a precisione singola in PostgreSQL.

In Data Connect, il tipo Vector è rappresentato come un array di numeri JSON. Gli input vengono forzati in un array di valori float32. Se la forzatura non va a buon fine, viene generato un errore.

Utilizza il parametro size della direttiva @col per impostare le dimensioni del vettore.

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

size è supportato solo per i tipi Vector. Vector, come la ricerca per somiglianza, richiedono che tutti i Vector abbiano lo stesso numero di dimensioni.

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

Valore del server _embed per query e mutazioni

_embed

Questo valore del server indica al servizio Data Connect di generare e archiviare gli incorporamenti utilizzando le API Embedding di Vertex AI. Questo valore del server può essere utilizzato sia per le query che per le mutazioni.

Parametri per la ricerca di somiglianze

method: COSINE|INNER_PRODUCT|L2

La funzione di distanza utilizzata per cercare i vicini nelle vicinanze. Gli algoritmi attualmente supportati sono un sottoinsieme degli algoritmi di ricerca pgvector.

within: float

Un vincolo sulla distanza entro la quale viene eseguita la ricerca del vicino più prossimo.

where: FDC filter condition

Consulta la guida a schemi, query e mutazioni.

limit: int

Il numero di risultati da restituire.