1. Introduzione
Spanner è un servizio di database completamente gestito, scalabile orizzontalmente e distribuito a livello globale, ottimo per carichi di lavoro operativi relazionali e non relazionali.
Spanner supporta la ricerca vettoriale integrato, che ti consente di eseguire ricerche di somiglianze o semantiche e implementare RAG (Retrieval Augmented Generation) nelle applicazioni di IA generativa su larga scala, sfruttando le funzionalità KNN (esattamente vicino) (KNN) o ANN (approximate Nearest neighbor).
Le query di ricerca vettoriale di Spanner restituiscono dati in tempo reale aggiornati non appena vengono eseguite le transazioni, proprio come qualsiasi altra query sui dati operativi.
In questo lab imparerai a configurare le funzionalità di base necessarie per sfruttare Spanner per eseguire ricerche vettoriali e accedere all'incorporamento e ai modelli LLM dal giardino dei modelli di Vertex AI utilizzando SQL.
L'architettura sarebbe la seguente:
Sulla base di queste premesse, imparerai a creare un indice vettoriale supportato dall'algoritmo di ScaNN e a utilizzare le funzioni di distanza APPROX quando è necessario scalare i carichi di lavoro semantici.
Cosa creerai
Nell'ambito di questo lab imparerai a:
- Creazione di un'istanza di Spanner
- Configura lo schema del database di Spanner per l'integrazione con i modelli di incorporamento e LLM in Vertex AI
- Carica un set di dati retail
- Genera query di ricerca di somiglianza con il set di dati
- Fornisci il contesto al modello LLM per generare suggerimenti specifici per il prodotto.
- Modifica lo schema e crea un indice vettoriale.
- Modifica le query per sfruttare l'indice vettoriale appena creato.
Obiettivi didattici
- Configurare un'istanza Spanner
- Come eseguire l'integrazione con Vertex AI
- Come utilizzare Spanner per eseguire una ricerca vettoriale e trovare elementi simili in un set di dati retail
- Prepara il tuo database per scalare i carichi di lavoro di ricerca vettoriale utilizzando la ricerca ANN.
Che cosa ti serve
2. Configurazione e requisiti
Creare un progetto
Se non disponi già di un account Google (Gmail o Google Apps), devi crearne uno. Accedi alla console della piattaforma Google Cloud ( console.cloud.google.com) e crea un nuovo progetto.
Se hai già un progetto, fai clic sul menu a discesa per la selezione del progetto in alto a sinistra nella console:
e fai clic su "NUOVO PROGETTO" nella finestra di dialogo risultante per creare un nuovo progetto:
Se non hai ancora un progetto, dovresti visualizzare una finestra di dialogo come questa per crearne uno:
La finestra di dialogo di creazione del progetto successiva ti consente di inserire i dettagli del nuovo progetto:
Ricorda l'ID progetto, che è un nome univoco tra tutti i progetti Google Cloud (il nome precedente è già in uso e non funzionerà per te). Verrà indicato più avanti in questo codelab come PROJECT_ID.
Successivamente, se non l'hai ancora fatto, dovrai abilitare la fatturazione in Developers Console per utilizzare le risorse Google Cloud e abilitare l'API Spanner.
L'esecuzione di questo codelab non dovrebbe costare più di qualche euro, ma potrebbe essere più costoso se decidi di utilizzare più risorse o se le lasci in esecuzione (consulta la sezione relativa alla pulizia alla fine di questo documento). I prezzi di Google Cloud Spanner sono documentati qui.
I nuovi utenti della piattaforma Google Cloud hanno diritto a una prova senza costi di 300$, che dovrebbe rendere questo codelab completamente senza costi.
Configurazione di Google Cloud Shell
Mentre Google Cloud e Spanner possono essere gestiti da remoto dal tuo laptop, in questo codelab utilizzeremo Google Cloud Shell, un ambiente a riga di comando in esecuzione nel cloud.
Questa macchina virtuale basata su Debian viene caricata con tutti gli strumenti di sviluppo necessari. Offre una home directory permanente da 5 GB e viene eseguita in Google Cloud, migliorando notevolmente le prestazioni di rete e l'autenticazione. Ciò significa che per questo codelab è sufficiente un browser (sì, funziona su Chromebook).
- Per attivare Cloud Shell dalla console Cloud, fai clic su Attiva Cloud Shell (il provisioning e la connessione all'ambiente dovrebbero richiedere solo pochi minuti).
Una volta stabilita la connessione a Cloud Shell, dovresti vedere che hai già eseguito l'autenticazione e che il progetto è già impostato sul tuo PROJECT_ID.
gcloud auth list
Output comando
Credentialed accounts:
- <myaccount>@<mydomain>.com (active)
gcloud config list project
Output comando
[core]
project = <PROJECT_ID>
Se, per qualche motivo, il progetto non è impostato, invia semplicemente il seguente comando:
gcloud config set project <PROJECT_ID>
Stai cercando il tuo PROJECT_ID
? Controlla l'ID utilizzato nei passaggi di configurazione o cercalo nella dashboard della console Cloud:
Cloud Shell imposta anche alcune variabili di ambiente per impostazione predefinita, cosa che può essere utile quando eseguirai comandi futuri.
echo $GOOGLE_CLOUD_PROJECT
Output comando
<PROJECT_ID>
Abilita l'API Spanner
gcloud services enable spanner.googleapis.com
Riepilogo
In questo passaggio hai configurato il progetto, se non ne avevi già uno, attivato Cloud Shell e abilitato le API richieste.
Successivo
Quindi, configurerai l'istanza e il database Spanner.
3. Creare un'istanza e un database Spanner
crea l'istanza Spanner
In questo passaggio configuriamo la nostra istanza Spanner per il codelab. Per farlo, apri Cloud Shell ed esegui questo comando:
export SPANNER_INSTANCE_ID=retail-demo
gcloud spanner instances create $SPANNER_INSTANCE_ID \
--config=regional-us-central1 \
--description="spanner AI retail demo" \
--nodes=1
Output comando:
$ gcloud spanner instances create $SPANNER_INSTANCE_ID \
--config=regional-us-central1 \
--description="spanner AI retail demo" \
--nodes=1
Creating instance...done.
crea il database
Quando l'istanza è in esecuzione, puoi creare il database. Spanner consente di avere più database su una singola istanza.
Il database è il luogo in cui definisci lo schema. Puoi anche controllare chi ha accesso al database, impostare la crittografia personalizzata, configurare l'ottimizzatore e impostare il periodo di conservazione.
Per creare il database, utilizza nuovamente lo strumento a riga di comando gcloud:
export SPANNER_DATABASE=cymbal-bikes
gcloud spanner databases create $SPANNER_DATABASE \
--instance=$SPANNER_INSTANCE_ID
Output comando:
$ gcloud spanner databases create $SPANNER_DATABASE \
--instance=$SPANNER_INSTANCE_ID
Creating database...done.
Riepilogo
In questo passaggio hai creato l'istanza e il database Spanner.
Successivo
Il passaggio successivo consiste nel configurare lo schema e i dati di Spanner.
4. Carica schema e dati di Cymbal
Crea lo schema Cymbal
Per configurare lo schema, vai a Spanner Studio:
Lo schema è composto da due parti. Innanzitutto, vuoi aggiungere la tabella products
. Copia e incolla questa istruzione nella scheda vuota.
Per lo schema, copia e incolla questo DDL nella casella:
CREATE TABLE products (
categoryId INT64 NOT NULL,
productId INT64 NOT NULL,
productName STRING(MAX) NOT NULL,
productDescription STRING(MAX) NOT NULL,
productDescriptionEmbedding ARRAY<FLOAT32>,
createTime TIMESTAMP NOT NULL OPTIONS (
allow_commit_timestamp = true
),
inventoryCount INT64 NOT NULL,
priceInCents INT64,
) PRIMARY KEY(categoryId, productId);
Poi fai clic sul pulsante run
e attendi qualche secondo per la creazione dello schema.
Quindi, creerai i due modelli e li configurerai per gli endpoint del modello VertexAI.
Il primo è un modello di incorporamento utilizzato per generare incorporamenti dal testo e il secondo è un modello LLM utilizzato per generare risposte basate sui dati in Spanner.
Incolla il seguente schema in una nuova scheda di Spanner Studio:
CREATE MODEL EmbeddingsModel INPUT(
content STRING(MAX),
) OUTPUT(
embeddings STRUCT<statistics STRUCT<truncated BOOL, token_count FLOAT32>, values ARRAY<FLOAT32>>,
) REMOTE OPTIONS (
endpoint = '//aiplatform.googleapis.com/projects/<PROJECT_ID>/locations/us-central1/publishers/google/models/text-embedding-004'
);
CREATE MODEL LLMModel INPUT(
prompt STRING(MAX),
) OUTPUT(
content STRING(MAX),
) REMOTE OPTIONS (
endpoint = '//aiplatform.googleapis.com/projects/<PROJECT_ID>/locations/us-central1/publishers/google/models/gemini-pro',
default_batch_size = 1
);
Quindi, fai clic sul pulsante run
e attendi qualche secondo per la creazione dei modelli.
Nel riquadro sinistro di Spanner Studio dovresti vedere le tabelle e i modelli seguenti:
Carica i dati
Ora vorrai inserire alcuni prodotti nel tuo database. Apri una nuova scheda in Spanner Studio, quindi copia e incolla le seguenti istruzioni di inserimento:
INSERT INTO products (categoryId, productId, productName, productDescription, createTime, inventoryCount, priceInCents)
VALUES (1, 1, "Cymbal Helios Helmet", "Safety meets style with the Cymbal children's bike helmet. Its lightweight design, superior ventilation, and adjustable fit ensure comfort and protection on every ride. Stay bright and keep your child safe under the sun with Cymbal Helios!", PENDING_COMMIT_TIMESTAMP(), 100, 10999),
(1, 2, "Cymbal Sprout", "Let their cycling journey begin with the Cymbal Sprout, the ideal balance bike for beginning riders ages 2-4 years. Its lightweight frame, low seat height, and puncture-proof tires promote stability and confidence as little ones learn to balance and steer. Watch them sprout into cycling enthusiasts with Cymbal Sprout!", PENDING_COMMIT_TIMESTAMP(), 10, 13999),
(1, 3, "Cymbal Spark Jr.", "Light, vibrant, and ready for adventure, the Spark Jr. is the perfect first bike for young riders (ages 5-8). Its sturdy frame, easy-to-use brakes, and puncture-resistant tires inspire confidence and endless playtime. Let the spark of cycling ignite with Cymbal!", PENDING_COMMIT_TIMESTAMP(), 34, 13900),
(1, 4, "Cymbal Summit", "Conquering trails is a breeze with the Summit mountain bike. Its lightweight aluminum frame, responsive suspension, and powerful disc brakes provide exceptional control and comfort for experienced bikers navigating rocky climbs or shredding downhill. Reach new heights with Cymbal Summit!", PENDING_COMMIT_TIMESTAMP(), 0, 79999),
(1, 5, "Cymbal Breeze", "Cruise in style and embrace effortless pedaling with the Breeze electric bike. Its whisper-quiet motor and long-lasting battery let you conquer hills and distances with ease. Enjoy scenic rides, commutes, or errands with a boost of confidence from Cymbal Breeze!", PENDING_COMMIT_TIMESTAMP(), 72, 129999),
(1, 6, "Cymbal Trailblazer Backpack", "Carry all your essentials in style with the Trailblazer backpack. Its water-resistant material, multiple compartments, and comfortable straps keep your gear organized and accessible, allowing you to focus on the adventure. Blaze new trails with Cymbal Trailblazer!", PENDING_COMMIT_TIMESTAMP(), 24, 7999),
(1, 7, "Cymbal Phoenix Lights", "See and be seen with the Phoenix bike lights. Powerful LEDs and multiple light modes ensure superior visibility, enhancing your safety and enjoyment during day or night rides. Light up your journey with Cymbal Phoenix!", PENDING_COMMIT_TIMESTAMP(), 87, 3999),
(1, 8, "Cymbal Windstar Pump", "Flat tires are no match for the Windstar pump. Its compact design, lightweight construction, and high-pressure capacity make inflating tires quick and effortless. Get back on the road in no time with Cymbal Windstar!", PENDING_COMMIT_TIMESTAMP(), 36, 24999),
(1, 9,"Cymbal Odyssey Multi-Tool","Be prepared for anything with the Odyssey multi-tool. This handy gadget features essential tools like screwdrivers, hex wrenches, and tire levers, keeping you ready for minor repairs and adjustments on the go. Conquer your journey with Cymbal Odyssey!", PENDING_COMMIT_TIMESTAMP(), 52, 999),
(1, 10,"Cymbal Nomad Water Bottle","Stay hydrated on every ride with the Nomad water bottle. Its sleek design, BPA-free construction, and secure lock lid make it the perfect companion for staying refreshed and motivated throughout your adventures. Hydrate and explore with Cymbal Nomad!", PENDING_COMMIT_TIMESTAMP(), 42, 1299);
Fai clic sul pulsante run
per inserire i dati.
Riepilogo
In questo passaggio hai creato lo schema e caricato alcuni dati di base nel database cymbal-bikes
.
Successivo
Successivamente, eseguirai l'integrazione con il modello Embedding per generare incorporamenti per le descrizioni dei prodotti e convertire una richiesta di ricerca testuale in un incorporamento per cercare prodotti pertinenti.
5. Utilizzare gli incorporamenti
Generare incorporamenti vettoriali per le descrizioni dei prodotti
Affinché la ricerca di similitudine funzioni per i prodotti, devi generare incorporamenti per le descrizioni dei prodotti.
Con EmbeddingsModel
creato nello schema, questa è una semplice istruzione DML UPDATE
.
UPDATE products p1
SET productDescriptionEmbedding =
(SELECT embeddings.values from ML.PREDICT(MODEL EmbeddingsModel,
(SELECT productDescription as content FROM products p2 where p2.productId=p1.productId)))
WHERE categoryId=1;
Fai clic sul pulsante run
per aggiornare le descrizioni dei prodotti.
Utilizzo della ricerca vettoriale
In questo esempio, fornirai una richiesta di ricerca in linguaggio naturale tramite una query SQL. Questa query trasformerà la richiesta di ricerca in un incorporamento, quindi cercherà risultati simili in base agli incorporamenti memorizzati delle descrizioni dei prodotti generate nel passaggio precedente.
-- Use Spanner's vector search, and integration with embedding and LLM models to
-- return items that are semantically relevant and available in inventory based on
-- real-time data.
SELECT productName, productDescription, inventoryCount, COSINE_DISTANCE(
productDescriptionEmbedding,
( SELECT embeddings.values
FROM ML.PREDICT(
MODEL EmbeddingsModel,
(SELECT "I'd like to buy a starter bike for my 3 year old child" as content)
)
)
) as distance
FROM products
WHERE inventoryCount > 0
ORDER BY distance
LIMIT 5;
Fai clic sul pulsante run
per trovare prodotti simili. I risultati dovrebbero essere simili ai seguenti:
Tieni presente che nella query vengono utilizzati filtri aggiuntivi, ad esempio interessa solo i prodotti disponibili (inventoryCount > 0
).
Riepilogo
In questo passaggio hai creato gli incorporamenti della descrizione del prodotto e una richiesta di ricerca mediante SQL, sfruttando l'integrazione di Spanner con i modelli in Vertex AI. Hai anche eseguito una ricerca vettoriale per trovare prodotti simili che corrispondono alla richiesta di ricerca.
Passaggi successivi
Ora utilizziamo i risultati di ricerca per alimentare un LLM al fine di generare una risposta personalizzata per ciascun prodotto.
6. Lavora con un LLM
Spanner semplifica l'integrazione con i modelli LLM forniti da Vertex AI. Ciò consente agli sviluppatori di utilizzare SQL per interfacciarsi direttamente con gli LLM, anziché richiedere all'applicazione di eseguire la logica.
Ad esempio, abbiamo i risultati della query SQL precedente dell'utente "I'd like to buy a starter bike for my 3 year old child".
Lo sviluppatore vorrebbe fornire una risposta per ogni risultato che indica se il prodotto è adatto all'utente, usando il seguente comando:
"Answer with ‘Yes' or ‘No' and explain why: Is this a good fit for me? I'd like to buy a starter bike for my 3 year old child"
Ecco la query che puoi utilizzare:
-- Use an LLM to analyze this list and provide a recommendation on whether each
-- product is a good fit for the user. We use the vector search and real time
-- inventory data to first filter the products to reduce the size of the prompt to
-- the LLM.
SELECT productName, productDescription, inventoryCount, content AS LLMResponse
FROM ML.PREDICT(
MODEL LLMModel,
( SELECT
inventoryCount,
productName,
productDescription,
CONCAT(
"Answer with ‘Yes' or ‘No' and explain why: Is this a good fit for me?",
"I'd like to buy a starter bike for my 3 year old child \n",
"Product Name: ", productName, "\n",
"Product Description:", productDescription) AS prompt,
FROM products
WHERE inventoryCount > 0
ORDER by COSINE_DISTANCE(
productDescriptionEmbedding,
( SELECT embeddings.values
FROM ML.PREDICT(
MODEL EmbeddingsModel,
( SELECT "I'd like to buy a starter bike for my 3 year old child" as content)
)
)
) LIMIT 5
),
STRUCT(256 AS maxOutputTokens)
);
Fai clic sul pulsante run
per eseguire la query. I risultati dovrebbero essere simili ai seguenti:
Il primo prodotto è adatto per un bambino di 3 anni a causa della fascia d'età nella descrizione del prodotto (bambini tra i 2 e i 4 anni). Gli altri prodotti non sono adatti.
Riepilogo
In questo passaggio hai lavorato con un LLM per generare risposte di base ai prompt di un utente.
Passaggi successivi
Ora impariamo a utilizzare la ANN per scalare la ricerca vettoriale.
7. Ricerca vettoriale scalabile
I precedenti esempi di ricerca vettoriale utilizzavano la ricerca vettoriale esatta con KNN. Questo è un ottimo modo quando puoi eseguire query su sottoinsiemi molto specifici di dati Spanner. Questi tipi di query sono considerati altamente partizionabili.
Se non hai carichi di lavoro altamente partizionabili e disponi di una grande quantità di dati, ti consigliamo di utilizzare la ricerca vettoriale ANN sfruttando l'algoritmo ScaNN per aumentare le prestazioni della ricerca.
Per farlo in Spanner, dovrai fare due cose:
- Crea un indice vettoriale
- Modifica la query per utilizzare le funzioni di distanza APPROX.
Creare l'indice vettoriale
Per creare un indice vettoriale su questo set di dati, dobbiamo prima modificare la colonna productDescriptionEmbeddings
per definire la lunghezza di ogni vettore. Per aggiungere la lunghezza del vettore a una colonna, devi rilasciare la colonna originale e ricrearla.
ALTER TABLE `products` DROP COLUMN `productDescriptionEmbedding`;
ALTER TABLE
`products` ADD COLUMN `productDescriptionEmbedding` ARRAY<FLOAT32>(vector_length=>768);
A questo punto, crea di nuovo gli incorporamenti dal passaggio Generate Vector embedding
che hai eseguito in precedenza.
UPDATE products p1
SET productDescriptionEmbedding =
(SELECT embeddings.values from ML.PREDICT(MODEL EmbeddingsModel,
(SELECT productDescription as content FROM products p2 where p2.productId=p1.productId)))
WHERE categoryId=1;
Dopo aver creato la colonna, crea l'indice:
CREATE VECTOR INDEX ProductDescriptionEmbeddingIndex
ON products(productDescriptionEmbedding)
WHERE productDescriptionEmbedding IS NOT NULL
OPTIONS (
distance_type = 'COSINE'
);
Utilizza il nuovo indice
Per utilizzare il nuovo indice vettoriale, dovrai modificare leggermente la query di incorporamento precedente.
Ecco la query originale:
SELECT productName, productDescription, inventoryCount, COSINE_DISTANCE(
productDescriptionEmbedding,
( SELECT embeddings.values
FROM ML.PREDICT(
MODEL EmbeddingsModel,
(SELECT "I'd like to buy a starter bike for my 3 year old child" as content)
)
)
) as distance
FROM products
WHERE inventoryCount > 0
ORDER BY distance
LIMIT 5;
Dovrai apportare le seguenti modifiche:
- Utilizza un suggerimento indice per il nuovo indice vettoriale:
@{force_index=ProductDescriptionEmbeddingIndex}
- Modifica la chiamata di funzione
COSINE_DISTANCE
inAPPROX_COSINE_DISTANCE
. Tieni presente che sono necessarie anche le opzioni JSON nella query finale riportata di seguito. - Generare separatamente gli incorporamenti dalla funzione ML.PREDICT.
- Copia i risultati degli incorporamenti nella query finale.
Genera gli incorporamenti
-- Generate the prompt embeddings
SELECT embeddings.values
FROM ML.PREDICT(
MODEL EmbeddingsModel,
(SELECT "I'd like to buy a starter bike for my 3 year old child" as content)
)
)
Evidenzia i risultati della query e copiali.
Poi sostituisci <VECTOR>
nella seguente query incollando gli incorporamenti che hai copiato.
-- Embedding query now using the vector index
SELECT productName, productDescription, inventoryCount,
APPROX_COSINE_DISTANCE(productDescriptionEmbedding, array<float32>[@VECTOR], options => JSON '{\"num_leaves_to_search\": 10}')
FROM products @{force_index=ProductDescriptionEmbeddingIndex}
WHERE productDescriptionEmbedding IS NOT NULL AND inventoryCount > 0
ORDER BY distance
LIMIT 5;
Il sito dovrebbe avere il seguente aspetto:
Riepilogo
In questo passaggio hai convertito lo schema per creare un indice vettoriale. Quindi hai riscritto la query di incorporamento per eseguire la ricerca ANN utilizzando l'indice vettoriale. Si tratta di un passaggio importante man mano che i dati aumentano per scalare i carichi di lavoro di ricerca vettoriale.
Passaggi successivi
Ora è il momento di pulire.
8. Eseguire la pulizia (facoltativo)
Per eseguire la pulizia, vai alla sezione Cloud Spanner della console Cloud ed elimina l'istanza 'retail-demo
' che abbiamo creato nel codelab.
9. Complimenti!
Congratulazioni, hai eseguito correttamente una ricerca di somiglianze utilizzando la ricerca vettoriale integrata di Spanner. Inoltre, hai visto quanto sia facile lavorare con i modelli LLM e di incorporamento per fornire funzionalità di IA generativa direttamente utilizzando SQL.
Infine, hai imparato il processo per eseguire la ricerca ANN supportata dall'algoritmo ScaNN per scalare i carichi di lavoro di ricerca vettoriale.
Passaggi successivi
Scopri di più sulla funzionalità del vicino esatto più vicino di Spanner (ricerca vettoriale KNN) qui: https://cloud.google.com/spanner/docs/find-k-nearest-neighbors
Scopri di più sulla funzionalità del vicino più prossimo approssimativo (ricerca vettoriale ANN) di Spanner qui: https://cloud.google.com/spanner/docs/find-approximate-nearest-neighbors
Puoi anche leggere di più su come eseguire previsioni online con SQL utilizzando l'integrazione Vertex AI di Spanner qui: https://cloud.google.com/spanner/docs/ml