Esegui una ricerca di somiglianze vettoriali con Vertex AI

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, che sono array di numeri con rappresentazione in virgola mobile che rappresentano il significato semantico di testo o contenuti multimediali. Eseguendo una ricerca del vicino più prossimo utilizzando un vector embedding 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 motori di ricerca e motori di suggerimenti. È anche un componente chiave della generazione aumentata dal recupero nei flussi di AI generativa. La documentazione di Vertex AI è un ottimo punto di partenza per saperne di più.

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

Prerequisiti

  • Configura Data Connect per il tuo progetto.

  • Attiva 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). Per lo sviluppo, puoi utilizzare un database locale o il progetto Data Connect di produzione e la relativa istanza Cloud SQL per PostgreSQL.

Queste istruzioni presuppongono che tu abbia creato il tuo Data Connect progetto 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 in base alle istruzioni del repository pgvector.

Eseguire l'integrazione con IDX

  1. Configura l'area di lavoro IDX utilizzando il modello Data Connect.
  2. Concediti il ruolo IAM utente Vertex AI.
  3. Attiva l'estensione utilizzando CREATE EXTENSION vector in base alle istruzioni del repository pgvector.

Progettare lo schema

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

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

Mutazioni

Generare e archiviare un embedding tramite Data Connect

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

mutation createMovie($title: String!, $description: String!) {
  movie_insert(data: {
    title: $title,
    description: $description,
    descriptionEmbedding_embed: {model: "textembedding-gecko@003", text: $description}
  })
}

In alcuni casi, potresti voler aggiornare la descrizione e l'embedding 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 { updateMovieDescription } from 'lib/dataconnect-sdk/';

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

// Use the response

Query

Recupera i vector embedding utilizzando una query come la seguente. Tieni presente che descriptionEmbedding restituito dalla query è un array di valori float, che in genere non è leggibile. Pertanto, gli SDK generati da Data Connect non supportano la restituzione diretta.

Puoi utilizzare i vector embedding restituiti per eseguire la ricerca di similarità, come descritto nella sezione successiva.

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

Eseguire la ricerca di similarità

Ora possiamo eseguire la ricerca di similarità.

Per ogni campo Vector, Data Connect genera una funzione GraphQL che implementa la ricerca di 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 i vector embedding utilizzando le API Embedding di Vertex AI, in questo caso per creare embedding per la stringa di ricerca utilizzata per il confronto con gli embedding della descrizione del film.

In questo esempio, la ricerca di 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, dal più vicino al più lontano.

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 i risultati che vuoi includere, prova a ottimizzare questi parametri.

Per trovare un valore appropriato per within, possiamo aggiungere _metadata.distance ai campi selezionati per vedere la distanza di ogni risultato dal vettore della query. 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 provare 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 di distanza molto diversi: se hai impostato within, dovrai ottimizzare di nuovo questo valore dopo aver modificato method.

Chiamare la query di similarità

Per chiamare una ricerca di similarità dal codice client:

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

const response = await searchMovieDescriptionUsingL2similarity({ query });

// Use the response

Utilizzare gli embedding personalizzati

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

Archiviare un embedding personalizzato

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

Quindi, esegui il cast dell'array di valori float 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 embedding personalizzati

Esegui la stessa operazione per recuperare gli embedding per i termini di ricerca ed eseguirne il cast in 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

Eseguire il deployment dello schema e del connettore

L'ultimo passaggio di un'iterazione tipica Data Connect è il deployment dei asset in produzione.

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

firebase deploy --only dataconnect

Se vuoi attivare manualmente il supporto degli embedding nell'istanza CloudSQL o se si verifica un errore CLI, segui queste istruzioni.

Sintassi di ricerca vettoriale

Estensioni dello schema

Il tipo di dati Vector di Data Connect esegue il mapping al tipo vector di PostgreSQL come definito dall'estensione pgvector. Il tipo vector di pgvector viene archiviato come array di numeri con rappresentazione 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 riesce, 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. Le operazioni Vector, come la ricerca di similarità, 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 embedding utilizzando le API Embedding di Vertex AI. Questo valore del server può essere utilizzato sia nelle query sia nelle mutazioni.

Parametri per la ricerca di similarità

method: COSINE|INNER_PRODUCT|L2

La funzione di distanza utilizzata per cercare i vicini più prossimi. 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.