Un milione di vettori, zero cicli: generazione di embedding su larga scala con AlloyDB

1. Panoramica

In questo codelab, creerai un'applicazione di ricerca scalabile per la Knowledge Base. Anziché gestire una pipeline ETL complessa con script e loop Python per generare vector embedding, utilizzerai AlloyDB AI per gestire la generazione di embedding in modo nativo all'interno del database utilizzando un singolo comando SQL.

d4324260c68d4a70.png

Cosa creerai

Un'applicazione di database della knowledge base "ricercabile" ad alte prestazioni.

Obiettivi didattici

Imparerai come:

  • Esegui il provisioning di un cluster AlloyDB e abilita le estensioni AI.
  • Genera dati sintetici (oltre 50.000 righe) utilizzando SQL.
  • Esegui il backfill dei vector embedding per l'intero set di dati utilizzando l'elaborazione batch.
  • Configura i trigger incrementali in tempo reale per incorporare automaticamente i nuovi dati.
  • Esegui una ricerca ibrida (vettoriale + filtri SQL) per "Flexing Context".

Requisiti

  • Un browser, ad esempio Chrome o Firefox.
  • Un progetto Google Cloud con la fatturazione abilitata.
  • Conoscenza di base di SQL.

2. Prima di iniziare

Crea un progetto

  1. Nella console Google Cloud, nella pagina di selezione del progetto, seleziona o crea un progetto Google Cloud.
  2. Verifica che la fatturazione sia attivata per il tuo progetto Cloud. Scopri come verificare se la fatturazione è abilitata per un progetto.
  3. Utilizzerai Cloud Shell, un ambiente a riga di comando in esecuzione in Google Cloud. Fai clic su Attiva Cloud Shell nella parte superiore della console Google Cloud.

Immagine del pulsante Attiva Cloud Shell

  1. Una volta eseguita la connessione a Cloud Shell, verifica che il tuo account sia già autenticato e che il progetto sia impostato sul tuo ID progetto utilizzando il seguente comando:
gcloud auth list
  1. Esegui questo comando in Cloud Shell per verificare che il comando gcloud riconosca il tuo progetto.
gcloud config list project
  1. Se il progetto non è impostato, utilizza il seguente comando per impostarlo:
gcloud config set project <YOUR_PROJECT_ID>
  1. Abilita le API richieste: segui il link e abilita le API.

In alternativa, puoi utilizzare il comando gcloud. Consulta la documentazione per i comandi gcloud e l'utilizzo.

gcloud services enable \
  alloydb.googleapis.com \
  compute.googleapis.com \
  cloudresourcemanager.googleapis.com \
  servicenetworking.googleapis.com \
  aiplatform.googleapis.com

Problemi e risoluzione dei problemi

La sindrome del "progetto fantasma"

Hai eseguito gcloud config set project, ma in realtà stai visualizzando un progetto diverso nell'interfaccia utente della console. Controlla l'ID progetto nel menu a discesa in alto a sinistra.

La barricata della fatturazione

Hai abilitato il progetto, ma hai dimenticato l'account di fatturazione. AlloyDB è un motore ad alte prestazioni; non si avvia se il "serbatoio" (fatturazione) è vuoto.

Ritardo di propagazione dell'API

Hai fatto clic su "Abilita API", ma la riga di comando indica ancora Service Not Enabled. Attendi 60 secondi. Il cloud ha bisogno di un momento per attivare i suoi neuroni.

Quota Quags

Se utilizzi un account di prova nuovo di zecca, potresti raggiungere una quota regionale per le istanze AlloyDB. Se us-central1 non va a buon fine, prova us-east1.

"Hidden" Service Agent

A volte, all'agente di servizio AlloyDB non viene concesso automaticamente il ruolo aiplatform.user. Se le tue query SQL non riescono a comunicare con Gemini in un secondo momento, di solito il problema è questo.

3. Configurazione del database

In questo lab utilizzeremo AlloyDB come database per i dati di test. Utilizza i cluster per contenere tutte le risorse, come database e log. Ogni cluster ha un'istanza principale che fornisce un punto di accesso ai dati. Le tabelle conterranno i dati effettivi.

Creiamo un cluster, un'istanza e una tabella AlloyDB in cui verrà caricato il set di dati di test.

  1. Fai clic sul pulsante o copia il link di seguito nel browser in cui hai eseguito l'accesso come utente della console Google Cloud.

  1. Una volta completato questo passaggio, il repository verrà clonato nell'editor di Cloud Shell locale e potrai eseguire il comando seguente dalla cartella del progetto (è importante assicurarti di trovarti nella directory del progetto):
sh run.sh
  1. Ora utilizza l'interfaccia utente (fai clic sul link nel terminale o sul link "Anteprima sul web" nel terminale).
  2. Per iniziare, inserisci i dettagli relativi all'ID progetto, al cluster e ai nomi delle istanze.
  3. Vai a prendere un caffè mentre i log scorrono e puoi leggere come avviene tutto questo dietro le quinte qui. L'operazione potrebbe richiedere circa 10-15 minuti.

Problemi e risoluzione dei problemi

Il problema della "pazienza"

I cluster di database sono un'infrastruttura pesante. Se aggiorni la pagina o interrompi la sessione di Cloud Shell perché "sembra bloccata", potresti ritrovarti con un'istanza "fantasma" di cui è stato eseguito il provisioning parziale e che è impossibile eliminare senza un intervento manuale.

Mancata corrispondenza della regione

Se hai abilitato le API in us-central1, ma provi a eseguire il provisioning del cluster in asia-south1, potresti riscontrare problemi di quota o ritardi nelle autorizzazioni del service account. Utilizza una sola regione per l'intero lab.

Cluster zombie

Se in precedenza hai utilizzato lo stesso nome per un cluster e non lo hai eliminato, lo script potrebbe indicare che il nome del cluster esiste già. I nomi dei cluster devono essere univoci all'interno di un progetto.

Timeout di Cloud Shell

Se la tua pausa caffè dura 30 minuti, Cloud Shell potrebbe entrare in modalità di sospensione e disconnettere il processo sh run.sh. Mantieni la scheda attiva.

4. Provisioning dello schema

In questo passaggio, tratteremo i seguenti argomenti:

879263c907f3cac6.png

Una volta che il cluster e l'istanza AlloyDB sono in esecuzione, vai all'editor SQL di AlloyDB Studio per abilitare le estensioni AI ed eseguire il provisioning dello schema.

1e3ac974b18a8113.png

Potresti dover attendere il completamento della creazione dell'istanza. Una volta completata, accedi ad AlloyDB utilizzando le credenziali che hai creato durante la creazione del cluster. Utilizza i seguenti dati per l'autenticazione in PostgreSQL:

  • Nome utente : "postgres"
  • Database : "postgres"
  • Password : "alloydb" (o quella che hai impostato al momento della creazione)

Una volta eseguita l'autenticazione in AlloyDB Studio, i comandi SQL vengono inseriti nell'editor. Puoi aggiungere più finestre dell'editor utilizzando il segno Più a destra dell'ultima finestra.

28cb9a8b6aa0789f.png

Inserirai i comandi per AlloyDB nelle finestre dell'editor, utilizzando le opzioni Esegui, Formatta e Cancella, se necessario.

Attiva le estensioni

Per creare questa app, utilizzeremo le estensioni pgvector e google_ml_integration. L'estensione pgvector consente di archiviare e cercare vector embedding. L'estensione google_ml_integration fornisce funzioni che utilizzi per accedere agli endpoint di previsione di Vertex AI per ottenere previsioni in SQL. Abilita queste estensioni eseguendo i seguenti DDL:

CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector;

Creare una tabella

Abbiamo bisogno di un set di dati per dimostrare la scalabilità. Anziché importare un file CSV, genereremo istantaneamente 50.000 righe di "articoli del Centro assistenza" sintetici utilizzando SQL.

Puoi creare una tabella utilizzando la seguente istruzione DDL in AlloyDB Studio:

-- 1. Create the table
CREATE TABLE help_articles (
    id SERIAL PRIMARY KEY,
    title TEXT,
    category TEXT,
    product_version TEXT,
    content_body TEXT,
    embedding vector(768) -- Dimension for text-embedding-005
);

-- 2. Generate 50,000 rows of synthetic data
INSERT INTO help_articles (title, category, product_version, content_body)
SELECT
    'Help Article ' || i,
    CASE 
        WHEN i % 3 = 0 THEN 'Billing' 
        WHEN i % 3 = 1 THEN 'Technical' 
        ELSE 'General' 
    END,
    CASE 
        WHEN i % 2 = 0 THEN '2.0' 
        ELSE '1.0' 
    END,
    'This article covers common issues regarding ' || 
    CASE 
        WHEN i % 3 = 0 THEN 'payment failures, invoice disputes, and credit card updates.'
        WHEN i % 3 = 1 THEN 'connection timeouts, latency issues, and API errors.'
        ELSE 'account profile settings, password resets, and user roles.' 
    END
FROM generate_series(1, 50000) AS i;

La colonna item_vector consentirà di archiviare i valori vettoriali del testo.

Verifica i dati:

SELECT count(*) FROM help_articles;
-- Output: 50000

Abilita i flag di database

Vai alla console di configurazione dell'istanza, fai clic su "Modifica istanza principale", vai a Configurazione avanzata e fai clic su "Aggiungi flag di database".

  1. Verifica che il flag google_ml_integration.enable_model_support sia impostato su on:

In caso contrario, inseriscilo nel menu a discesa dei flag, impostalo su "ON" e aggiorna l'istanza.

  1. Verifica che il flag google_ml_integration.enable_faster_embedding_generation sia impostato su on:

In caso contrario, inseriscilo nel menu a discesa dei flag, impostalo su "ON" e aggiorna l'istanza.

Passaggi per configurare i flag di database:

  1. Nella console Google Cloud, vai alla pagina Cluster.

Vai a Cluster

  1. Fai clic su un cluster nella colonna Nome risorsa.
  2. Nella pagina Panoramica, vai a Istanze nel cluster, seleziona un'istanza e fai clic su Modifica.
  3. Aggiungi, modifica o elimina un flag di database dalla tua istanza:

Aggiungi un flag

  1. Per aggiungere un flag di database all'istanza, fai clic su Aggiungi flag.
  2. Seleziona un flag dall'elenco Nuovo flag di database.
  3. Specifica un valore per il flag.
  4. Fai clic su Fine.
  5. Fai clic su Aggiorna istanza.
  6. Verifica che l'estensione google_ml_integration sia la versione 1.5.2 o successiva:

Per controllare la versione dell'estensione con il seguente comando:

SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration';

Se devi aggiornare l'estensione a una versione successiva, utilizza il comando:

ALTER EXTENSION google_ml_integration UPDATE;

Concedi autorizzazione

  1. Per consentire a un utente di gestire la generazione automatica degli embedding, concedi le autorizzazioni INSERT, UPDATE e DELETE sulle tabelle google_ml.embed_gen_progress e google_ml.embed_gen_settings:
GRANT INSERT, UPDATE, DELETE ON google_ml.embed_gen_progress TO postgres;

"postgres" è lo USER_NAME per cui vengono concesse le autorizzazioni.

  1. Esegui la seguente istruzione per concedere l'esecuzione della funzione "embedding":
GRANT EXECUTE ON FUNCTION embedding TO postgres;

Concedi il ruolo Utente Vertex AI al service account AlloyDB

Dalla console IAM di Google Cloud, concedi al service account AlloyDB (che ha questo aspetto: service-<<PROJECT_NUMBER>>@gcp-sa-alloydb.iam.gserviceaccount.com) l'accesso al ruolo "Vertex AI User". PROJECT_NUMBER conterrà il numero del tuo progetto.

In alternativa, puoi eseguire questo comando dal terminale Cloud Shell:

PROJECT_ID=$(gcloud config get-value project)


gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" \
--role="roles/aiplatform.user"

Problemi e risoluzione dei problemi

Il loop "Amnesia della password"

Se hai utilizzato la configurazione "One Click" e non ricordi la password, vai alla pagina Informazioni di base sull'istanza nella console e fai clic su "Modifica" per reimpostare la password di postgres.

Errore "Estensione non trovata"

Se CREATE EXTENSION non va a buon fine, spesso è perché l'istanza è ancora in stato "Manutenzione" o "In aggiornamento" dal provisioning iniziale. Controlla se il passaggio di creazione dell'istanza è stato completato e attendi qualche secondo, se necessario.

5. Generazione di vettori "one-shot"

Questo è il nucleo del lab. Invece di scrivere un ciclo Python per elaborare queste 50.000 righe, utilizzeremo la funzione ai.initialize_embeddings.

Questo singolo comando esegue due operazioni:

  1. Esegue il backfill di tutte le righe esistenti.
  2. Crea un trigger per incorporare automaticamente le righe future.

Esegui la seguente istruzione SQL dall'editor di query di AlloyDB

CALL ai.initialize_embeddings(
  model_id => 'text-embedding-005',
  table_name => 'help_articles',
  content_column => 'content_body',
  embedding_column => 'embedding',
  incremental_refresh_mode => 'transactional'
);

Verifica gli embedding

Verifica che la colonna embedding sia ora compilata:

SELECT id, left(content_body, 30), substring(embedding::text, 1, 30) as vector_partial 
FROM help_articles;

Dovresti vedere un risultato simile al seguente:

a872b8926a164275.png

Che cosa è successo?

  1. Backfill su larga scala: esegue automaticamente la scansione delle 50.000 righe esistenti e genera embedding tramite Vertex AI.
  2. Automazione: impostando incremental_refresh_mode => 'transactional', AlloyDB configura automaticamente i trigger interni. L'embedding di ogni nuova riga inserita in help_articles verrà generato immediatamente.
  3. Facoltativamente, puoi impostare incremental_refresh_mode => "None" in modo da poter ottenere solo l'istruzione per eseguire aggiornamenti in blocco e chiamare manualmente ai.refresh_embeddings() per aggiornare gli embedding di tutte le righe.

Hai appena sostituito una coda Kafka, un worker Python e uno script di migrazione con 6 righe di SQL. Ecco la documentazione ufficiale dettagliata per tutti gli attributi.

Test dell'attivatore in tempo reale

Verifichiamo che l'automazione "Zero Loop" funzioni per i nuovi dati.

  1. Inserisci una nuova riga:
INSERT INTO help_articles (title, category, product_version, content_body)
VALUES ('New Scaling Guide', 'Technical', '2.0', 'How to scale AlloyDB to millions of transactions.');
  1. Controlla immediatamente:
SELECT embedding FROM help_articles WHERE title = 'New Scaling Guide';

Risultato:

Dovresti vedere il vettore generato istantaneamente senza eseguire alcuno script esterno.

Dimensione del batch di ottimizzazione

Al momento, AlloyDB utilizza per impostazione predefinita una dimensione del batch di 50. Sebbene le impostazioni predefinite funzionino perfettamente, AlloyDB offre comunque agli utenti il controllo per ottimizzare la configurazione perfetta per il modello e il set di dati unici.

CALL ai.initialize_embeddings(
  model_id => 'text-embedding-005',
  table_name => 'help_articles',
  content_column => 'content_body',
  embedding_column => 'embedding',
  incremental_refresh_mode => 'transactional',
  batch_size => 20
);

Tuttavia, gli utenti devono essere consapevoli dei limiti di quota che possono limitare le prestazioni. Per esaminare le quote consigliate per AlloyDB, consulta la sezione "Prima di iniziare" della documentazione.

Problemi e risoluzione dei problemi

Il gap di propagazione di IAM

Hai eseguito il comando IAM gcloud, ma il comando SQL CALL continua a non riuscire con un errore di autorizzazione. La propagazione delle modifiche IAM attraverso il backbone di Google può richiedere un po' di tempo. Rilassati.

Mancata corrispondenza delle dimensioni del vettore

La tabella help_articles è impostata su VECTOR(768) nella colonna content_body. Se in un secondo momento provi a utilizzare un modello diverso (ad esempio un modello a 1536 dimensioni), gli inserimenti non andranno a buon fine. Attieniti a text-embedding-005.

6. Ricerca contestuale flessibile

Ora eseguiamo una ricerca ibrida. Combiniamo la comprensione semantica (vettoriale) con la logica di business (filtri SQL).

Esegui questa query per trovare i problemi di fatturazione specifici per la versione 2.0 del prodotto:

SELECT
  title,
  left(content_body, 100) as content_snippet,
  1 - (embedding <=> embedding('text-embedding-005', 'Invoice did not go through')::vector) as relevance
FROM help_articles
WHERE category = 'Billing'  -- Hard SQL Filter
  AND product_version = '2.0' -- Hard SQL Filter
ORDER BY relevance DESC
LIMIT 5;

Questo è il contesto flessibile. La ricerca si "adatta" per comprendere l'intent dell'utente ("problemi di fatturazione") rispettando al contempo i rigidi vincoli aziendali (versione 2.0).

f0fdb50d6195c462.png

Perché questa soluzione è vincente per startup e migrazioni

  1. Zero debito infrastrutturale: non hai creato un DB vettoriale separato (Pinecone/Milvus). Non hai scritto un job ETL separato. È tutto in Postgres.
  2. Aggiornamenti in tempo reale: utilizzando la modalità "transazionale", l'indice della Ricerca non è mai obsoleto. Nel momento in cui i dati vengono sottoposti a commit, sono pronti per i vettori.
  3. Scalabilità: AlloyDB è basato sull'infrastruttura di Google. Può gestire la generazione collettiva di milioni di vettori più velocemente di quanto potrebbe mai fare il tuo script Python.

Problemi e risoluzione dei problemi

Problema relativo alle prestazioni di produzione

Problema: veloce per 50.000 righe. Molto lento per 1 milione di righe se il filtro per categoria non è abbastanza selettivo.Soluzione:Aggiungi un indice vettoriale: per la scalabilità in produzione, devi creare un indice:CREATE INDEX ON help_articles USING hnsw (embedding vector_cosine_ops);Verifica l'utilizzo dell'indice: esegui EXPLAIN ANALYZE SELECT ... per assicurarti che il database utilizzi l'indice e non esegua una scansione sequenziale.

Il disastro della "mancata corrispondenza dei modelli"

Problema: hai inizializzato la colonna utilizzando text-embedding-005 nella procedura CALL. Se utilizzi accidentalmente un modello diverso (ad esempio text-embedding-004 o un modello OSS) nella funzione di query SELECT embedding('model-name', …), le dimensioni potrebbero corrispondere (768), ma lo spazio vettoriale sarà completamente diverso. La query viene eseguita senza errori, ma i risultati sono completamente irrilevanti (punteggi di pertinenza spazzatura). Risoluzione dei problemi:assicurati che il model_id in ai.initialize_embeddings corrisponda esattamente al model_id nella query SELECT.

Il risultato "Vuoto silenzioso" (filtro eccessivo)

Problema: la ricerca ibrida è un'operazione "AND". Richiede Corrispondenza semantica E Corrispondenza SQL.Se un utente cerca "Guida alla fatturazione", ma la colonna product_version contiene ‘2.0.1' anziché ‘2.0', il risultato è zero righe, anche se la corrispondenza vettoriale è del 99%.Risoluzione dei problemi:

  • Esegui prima la query senza l'ordinamento vettoriale per verificare se i filtri SQL (WHERE category...) restituiscono effettivamente i dati.
  • Controlla la sensibilità alle maiuscole (Billing rispetto a billing).

4. Errori di autorizzazione/quota (errore 500)

Problema:la funzione embedding() nella clausola SELECT effettua una chiamata di rete in tempo reale a Vertex AI.Se il service account del database perde il ruolo Vertex AI User o se raggiungi la quota dell'API Vertex AI (QPM), l'intera query SQL non andrà a buon fine.Risoluzione dei problemi:

  • Controlla Cloud Logging per AlloyDB.
  • Assicurati che il ruolo IAM sia ancora attivo.
  • Racchiudi la funzione in un blocco TRY/CATCH nelle stored procedure se è necessaria un'elevata resilienza.

5. Embedding nulli

Problema:se inserisci i dati prima che il modello sia completamente inizializzato o se il worker in background non va a buon fine, alcune righe potrebbero avere NULL nella colonna embedding. NULL <=> Vector restituisce NULL. Queste righe scompaiono dall'ordinamento.Risoluzione dei problemi:

  • Esegui SELECT count(*) FROM help_articles WHERE embedding IS NULL; per verificare la copertura del 100%.

7. Esegui la pulizia

Al termine di questo lab, non dimenticare di eliminare il cluster e l'istanza AlloyDB.

Dovrebbe eseguire la pulizia del cluster e delle relative istanze.

8. Complimenti

Hai creato un'applicazione di ricerca scalabile nella Knowledge Base. Anziché gestire una pipeline ETL complessa con script e loop Python per generare vector embedding, hai utilizzato AlloyDB AI per gestire la generazione di embedding in modo nativo all'interno del database utilizzando un singolo comando SQL.

Argomenti trattati

  • Abbiamo eliminato il "ciclo for di Python" per il trattamento dati.
  • Abbiamo generato 50.000 vettori con un solo comando SQL.
  • Abbiamo automatizzato la generazione di vettori futuri con i trigger.
  • Abbiamo eseguito la ricerca ibrida.

Passaggi successivi