1. Introdução
Neste codelab, você vai aprender a usar o AlloyDB AI combinando a pesquisa vetorial com os embeddings da Vertex AI.
Pré-requisitos
- Conhecimentos básicos sobre o console do Google Cloud
- Habilidades básicas na interface de linha de comando e no Google Shell
O que você vai aprender
- Como implantar o cluster e a instância principal do AlloyDB
- Como se conectar ao AlloyDB usando uma VM do Google Compute Engine
- Como criar um banco de dados e ativar o AlloyDB AI
- Como carregar dados no banco de dados
- Como usar o modelo de incorporação da Vertex AI no AlloyDB
- Como enriquecer o resultado usando o modelo generativo da Vertex AI
- Como melhorar a performance usando o índice vetorial
O que é necessário
- Uma conta e um projeto do Google Cloud
- Um navegador da Web, como o Chrome
2. Configuração e requisitos
Configuração de ambiente autoguiada
- Faça login no Console do Google Cloud e crie um novo projeto ou reutilize um existente. Crie uma conta do Gmail ou do Google Workspace, se ainda não tiver uma.
- O Nome do projeto é o nome de exibição para os participantes do projeto. É uma string de caracteres não usada pelas APIs do Google e pode ser atualizada quando você quiser.
- O ID do projeto precisa ser exclusivo em todos os projetos do Google Cloud e não pode ser mudado após a definição. O console do Cloud gera automaticamente uma string exclusiva. Em geral, não importa o que seja. Na maioria dos codelabs, é necessário fazer referência ao ID do projeto, normalmente identificado como
PROJECT_ID
. Se você não gostar do ID gerado, crie outro aleatório. Se preferir, teste o seu e confira se ele está disponível. Ele não pode ser mudado após essa etapa e permanece durante o projeto. - Para sua informação, há um terceiro valor, um Número do projeto, que algumas APIs usam. Saiba mais sobre esses três valores na documentação.
- Em seguida, ative o faturamento no console do Cloud para usar os recursos/APIs do Cloud. A execução deste codelab não vai ser muito cara, se tiver algum custo. Para encerrar os recursos e evitar cobranças além deste tutorial, exclua os recursos criados ou exclua o projeto. Novos usuários do Google Cloud estão qualificados para o programa de US$ 300 de avaliação sem custos.
Inicie o Cloud Shell
Embora o Google Cloud e o Spanner possam ser operados remotamente do seu laptop, neste codelab usaremos o Google Cloud Shell, um ambiente de linha de comando executado no Cloud.
No Console do Google Cloud, clique no ícone do Cloud Shell na barra de ferramentas superior à direita:
O provisionamento e a conexão com o ambiente levarão apenas alguns instantes para serem concluídos: Quando o processamento for concluído, você verá algo como:
Essa máquina virtual contém todas as ferramentas de desenvolvimento necessárias. Ela oferece um diretório principal persistente de 5 GB, além de ser executada no Google Cloud. Isso aprimora o desempenho e a autenticação da rede. Neste codelab, todo o trabalho pode ser feito com um navegador. Você não precisa instalar nada.
3. Antes de começar
Ativar API
Saída:
No Cloud Shell, verifique se o ID do projeto está configurado:
gcloud config set project [YOUR-PROJECT-ID]
Defina a variável de ambiente PROJECT_ID:
PROJECT_ID=$(gcloud config get-value project)
Ative todos os serviços necessários:
gcloud services enable alloydb.googleapis.com \
compute.googleapis.com \
cloudresourcemanager.googleapis.com \
servicenetworking.googleapis.com \
aiplatform.googleapis.com
Resultado esperado
student@cloudshell:~ (test-project-001-402417)$ gcloud config set project test-project-001-402417 Updated property [core/project]. student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=$(gcloud config get-value project) Your active configuration is: [cloudshell-14650] student@cloudshell:~ (test-project-001-402417)$ student@cloudshell:~ (test-project-001-402417)$ gcloud services enable alloydb.googleapis.com \ compute.googleapis.com \ cloudresourcemanager.googleapis.com \ servicenetworking.googleapis.com \ aiplatform.googleapis.com Operation "operations/acat.p2-4470404856-1f44ebd8-894e-4356-bea7-b84165a57442" finished successfully.
Configure a região padrão para usar os modelos de embedding da Vertex AI. Saiba mais sobre os locais disponíveis para a Vertex AI. Neste exemplo, usamos a região us-central1.
gcloud config set compute/region us-central1
4. Implantar o AlloyDB
Antes de criar um cluster do AlloyDB, é necessário ter um intervalo de IP privado disponível na VPC para ser usado pela instância futura do AlloyDB. Se não tivermos, precisamos criar e atribuir o cluster para que ele seja usado pelos serviços internos do Google. Depois disso, poderemos criar o cluster e a instância.
Criar um intervalo de IP privado
É preciso configurar o Acesso a serviços particulares na VPC para o AlloyDB. Vamos supor que o projeto tem uma rede VPC "padrão" a ser usada para todas as ações.
Crie o intervalo de IP privado:
gcloud compute addresses create psa-range \
--global \
--purpose=VPC_PEERING \
--prefix-length=24 \
--description="VPC private service access" \
--network=default
Crie uma conexão privada com o intervalo de IP alocado:
gcloud services vpc-peerings connect \
--service=servicenetworking.googleapis.com \
--ranges=psa-range \
--network=default
Saída esperada do console:
student@cloudshell:~ (test-project-402417)$ gcloud compute addresses create psa-range \ --global \ --purpose=VPC_PEERING \ --prefix-length=24 \ --description="VPC private service access" \ --network=default Created [https://www.googleapis.com/compute/v1/projects/test-project-402417/global/addresses/psa-range]. student@cloudshell:~ (test-project-402417)$ gcloud services vpc-peerings connect \ --service=servicenetworking.googleapis.com \ --ranges=psa-range \ --network=default Operation "operations/pssn.p24-4470404856-595e209f-19b7-4669-8a71-cbd45de8ba66" finished successfully. student@cloudshell:~ (test-project-402417)$
Criar cluster do AlloyDB
Crie um cluster do AlloyDB na região us-central1.
Defina a senha para o usuário postgres. Defina sua própria senha ou use uma função aleatória para gerar uma
export PGPASSWORD=`openssl rand -hex 12`
Saída esperada do console:
student@cloudshell:~ (test-project-402417)$ export PGPASSWORD=`openssl rand -hex 12`
Anote a senha do PostgreSQL para uso futuro:
echo $PGPASSWORD
Saída esperada do console:
student@cloudshell:~ (test-project-402417)$ echo $PGPASSWORD bbefbfde7601985b0dee5723
Defina a região e o nome do cluster do AlloyDB. Usaremos a região us-central1 e alloydb-aip-01 como o nome do cluster:
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
Execute o comando para criar o cluster:
gcloud alloydb clusters create $ADBCLUSTER \
--password=$PGPASSWORD \
--network=default \
--region=$REGION
Saída esperada do console:
export REGION=us-central1 export ADBCLUSTER=alloydb-aip-01 gcloud alloydb clusters create $ADBCLUSTER \ --password=$PGPASSWORD \ --network=default \ --region=$REGION Operation ID: operation-1697655441138-6080235852277-9e7f04f5-2012fce4 Creating cluster...done.
Criar instância principal do AlloyDB
Crie uma instância principal do AlloyDB para o cluster na mesma sessão do Cloud Shell. Se você se desconectar, vai precisar definir as variáveis de ambiente de nome de região e cluster novamente.
gcloud alloydb instances create $ADBCLUSTER-pr \
--instance-type=PRIMARY \
--cpu-count=2 \
--region=$REGION \
--cluster=$ADBCLUSTER
Saída esperada do console:
student@cloudshell:~ (test-project-402417)$ gcloud alloydb instances create $ADBCLUSTER-pr \ --instance-type=PRIMARY \ --cpu-count=2 \ --region=$REGION \ --availability-type ZONAL \ --cluster=$ADBCLUSTER Operation ID: operation-1697659203545-6080315c6e8ee-391805db-25852721 Creating instance...done.
5. Conectar-se ao AlloyDB
O AlloyDB é implantado usando uma conexão somente particular. Portanto, precisamos de uma VM com o cliente PostgreSQL instalado para trabalhar com o banco de dados.
Implantar a VM do GCE
Crie uma VM do GCE na mesma região e VPC que o cluster do AlloyDB.
No Cloud Shell, execute:
export ZONE=us-central1-a
gcloud compute instances create instance-1 \
--zone=$ZONE \
--create-disk=auto-delete=yes,boot=yes,image=projects/debian-cloud/global/images/$(gcloud compute images list --filter="family=debian-12 AND family!=debian-12-arm64" --format="value(name)") \
--scopes=https://www.googleapis.com/auth/cloud-platform
Saída esperada do console:
student@cloudshell:~ (test-project-402417)$ export ZONE=us-central1-a student@cloudshell:~ (test-project-402417)$ export ZONE=us-central1-a gcloud compute instances create instance-1 \ --zone=$ZONE \ --create-disk=auto-delete=yes,boot=yes,image=projects/debian-cloud/global/images/$(gcloud compute images list --filter="family=debian-12 AND family!=debian-12-arm64" --format="value(name)") \ --scopes=https://www.googleapis.com/auth/cloud-platform Created [https://www.googleapis.com/compute/v1/projects/test-project-402417/zones/us-central1-a/instances/instance-1]. NAME: instance-1 ZONE: us-central1-a MACHINE_TYPE: n1-standard-1 PREEMPTIBLE: INTERNAL_IP: 10.128.0.2 EXTERNAL_IP: 34.71.192.233 STATUS: RUNNING
Instale o cliente Postgres
Instale o software do cliente PostgreSQL na VM implantada.
Conecte-se à VM:
gcloud compute ssh instance-1 --zone=us-central1-a
Saída esperada do console:
student@cloudshell:~ (test-project-402417)$ gcloud compute ssh instance-1 --zone=us-central1-a Updating project ssh metadata...working..Updated [https://www.googleapis.com/compute/v1/projects/test-project-402417]. Updating project ssh metadata...done. Waiting for SSH key to propagate. Warning: Permanently added 'compute.5110295539541121102' (ECDSA) to the list of known hosts. Linux instance-1.us-central1-a.c.gleb-test-short-001-418811.internal 6.1.0-18-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.76-1 (2024-02-01) x86_64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. student@instance-1:~$
Instale o comando em execução do software na VM:
sudo apt-get update
sudo apt-get install --yes postgresql-client
Saída esperada do console:
student@instance-1:~$ sudo apt-get update sudo apt-get install --yes postgresql-client Get:1 https://packages.cloud.google.com/apt google-compute-engine-bullseye-stable InRelease [5146 B] Get:2 https://packages.cloud.google.com/apt cloud-sdk-bullseye InRelease [6406 B] Hit:3 https://deb.debian.org/debian bullseye InRelease Get:4 https://deb.debian.org/debian-security bullseye-security InRelease [48.4 kB] Get:5 https://packages.cloud.google.com/apt google-compute-engine-bullseye-stable/main amd64 Packages [1930 B] Get:6 https://deb.debian.org/debian bullseye-updates InRelease [44.1 kB] Get:7 https://deb.debian.org/debian bullseye-backports InRelease [49.0 kB] ...redacted... update-alternatives: using /usr/share/postgresql/13/man/man1/psql.1.gz to provide /usr/share/man/man1/psql.1.gz (psql.1.gz) in auto mode Setting up postgresql-client (13+225) ... Processing triggers for man-db (2.9.4-2) ... Processing triggers for libc-bin (2.31-13+deb11u7) ...
Conectar-se à instância
Conecte-se à instância principal pela VM com psql.
Na mesma guia do Cloud Shell com a sessão SSH aberta para a VM instance-1.
Use o valor da senha do AlloyDB (PGPASSWORD) e o ID do cluster do AlloyDB para se conectar ao AlloyDB pela VM do GCE:
export PGPASSWORD=<Noted password>
export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
export INSTANCE_IP=$(gcloud alloydb instances describe $ADBCLUSTER-pr --cluster=$ADBCLUSTER --region=$REGION --format="value(ipAddress)")
psql "host=$INSTANCE_IP user=postgres sslmode=require"
Saída esperada do console:
student@instance-1:~$ export PGPASSWORD=CQhOi5OygD4ps6ty student@instance-1:~$ ADBCLUSTER=alloydb-aip-01 student@instance-1:~$ REGION=us-central1 student@instance-1:~$ INSTANCE_IP=$(gcloud alloydb instances describe $ADBCLUSTER-pr --cluster=$ADBCLUSTER --region=$REGION --format="value(ipAddress)") gleb@instance-1:~$ psql "host=$INSTANCE_IP user=postgres sslmode=require" psql (15.6 (Debian 15.6-0+deb12u1), server 15.5) SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off) Type "help" for help. postgres=>
Feche a sessão psql:
exit
6. Preparar banco de dados
Precisamos criar um banco de dados, ativar a integração da Vertex AI, criar objetos de banco de dados e importar os dados.
Conceder as permissões necessárias ao AlloyDB
Adicione as permissões da Vertex AI ao agente de serviço do AlloyDB.
Abra outra guia do Cloud Shell pelo sinal "+" na parte superior.
Na nova guia do Cloud Shell, execute:
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"
Saída esperada do console:
student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=$(gcloud config get-value project) Your active configuration is: [cloudshell-11039] student@cloudshell:~ (test-project-001-402417)$ 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" Updated IAM policy for project [test-project-001-402417]. bindings: - members: - serviceAccount:service-4470404856@gcp-sa-alloydb.iam.gserviceaccount.com role: roles/aiplatform.user - members: ... etag: BwYIEbe_Z3U= version: 1
Feche a guia pelo comando de execução "sair" na guia:
exit
Criar banco de dados
Guia de início rápido do banco de dados.
Na sessão da VM do GCE, execute:
Criar banco de dados:
psql "host=$INSTANCE_IP user=postgres" -c "CREATE DATABASE quickstart_db"
Saída esperada do console:
student@instance-1:~$ psql "host=$INSTANCE_IP user=postgres" -c "CREATE DATABASE quickstart_db" CREATE DATABASE student@instance-1:~$
Ativar a integração com a Vertex AI
Ativar a integração da Vertex AI e as extensões pgvector no banco de dados.
Na VM do GCE, execute:
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE"
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS vector"
Saída esperada do console:
student@instance-1:~$ psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE" psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS vector" CREATE EXTENSION CREATE EXTENSION student@instance-1:~$
Importar dados
Faça o download dos dados preparados e importe-os para o novo banco de dados.
Na VM do GCE, execute:
gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"
gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_products from stdin csv header"
gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_inventory from stdin csv header"
gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_stores from stdin csv header"
Saída esperada do console:
student@instance-1:~$ gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" SET SET SET SET SET set_config ------------ (1 row) SET SET SET SET SET SET CREATE TABLE ALTER TABLE CREATE TABLE ALTER TABLE CREATE TABLE ALTER TABLE CREATE TABLE ALTER TABLE CREATE SEQUENCE ALTER TABLE ALTER SEQUENCE ALTER TABLE ALTER TABLE ALTER TABLE student@instance-1:~$ gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_products from stdin csv header" COPY 941 student@instance-1:~$ gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_inventory from stdin csv header" COPY 263861 student@instance-1:~$ gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_stores from stdin csv header" COPY 4654 student@instance-1:~$
7. Calcular embeddings
Depois de importar os dados, recebemos os dados de produtos na tabela "cymbal_products", o inventário mostrando o número de produtos disponíveis em cada loja na tabela "cymbal_inventory" e a lista de lojas na tabela "cymbal_stores". Precisamos calcular os dados vetoriais com base nas descrições dos nossos produtos e vamos usar a função embedding para isso. Usando a função, vamos usar a integração da Vertex AI para calcular dados vetoriais com base nas descrições dos produtos e adicionar à tabela. Leia mais sobre a tecnologia usada na documentação.
Criar coluna de embedding
Conecte-se ao banco de dados usando o psql e crie uma coluna virtual com os dados vetoriais usando a função de embedding na tabela cymbal_products. A função de embedding retorna dados vetoriais da Vertex AI com base nos dados fornecidos na coluna "product_description".
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"
Na sessão psql após a conexão com o banco de dados, execute:
ALTER TABLE cymbal_products ADD COLUMN embedding vector(768) GENERATED ALWAYS AS (embedding('text-embedding-004',product_description)) STORED;
O comando cria a coluna virtual e a preenche com dados vetoriais.
Saída esperada do console:
student@instance-1:~$ psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" psql (13.11 (Debian 13.11-0+deb11u1), server 14.7) WARNING: psql major version 13, server major version 14. Some psql features might not work. SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off) Type "help" for help. quickstart_db=> ALTER TABLE cymbal_products ADD COLUMN embedding vector(768) GENERATED ALWAYS AS (embedding('text-embedding-004',product_description)) STORED; ALTER TABLE quickstart_db=>
8. Executar pesquisa por similaridade
Agora podemos executar a pesquisa usando a pesquisa por similaridade com base nos valores vetoriais calculados para as descrições e no valor do vetor que obtemos para a solicitação.
A consulta SQL pode ser executada na mesma interface de linha de comando psql ou, como alternativa, no AlloyDB Studio. Qualquer saída complexa e com várias linhas pode ficar melhor no AlloyDB Studio.
Conectar ao AlloyDB Studio
Nos capítulos a seguir, todos os comandos SQL que exigem conexão com o banco de dados podem ser executados no AlloyDB Studio. Para executar o comando, você precisa abrir a interface do console da Web do seu cluster do AlloyDB clicando na instância primária.
Em seguida, clique em AlloyDB Studio à esquerda:
Escolha o banco de dados quickstart_db, o usuário postgres e informe a senha anotada quando criamos o cluster. Em seguida, clique no botão "Autenticar" .
A interface do AlloyDB Studio vai ser aberta. Para executar os comandos no banco de dados, clique no "Editor 1" à direita.
Ele abre uma interface na qual é possível executar comandos SQL
Se preferir usar o psql na linha de comando, siga a rota alternativa e conecte-se ao banco de dados pela sessão SSH da VM, como foi descrito nos capítulos anteriores.
Executar a pesquisa de similaridade no psql
Se a sessão do banco de dados foi desconectada, conecte-se novamente ao banco de dados usando o psql ou o AlloyDB Studio.
Conecte-se ao banco de dados:
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"
Execute uma consulta para conseguir uma lista dos produtos disponíveis que melhor se relacionam com a solicitação do cliente. A solicitação que vamos transmitir à Vertex AI para gerar o valor do vetor soa como "Que tipo de árvores frutíferas crescem bem aqui?".
Aqui está a consulta que você pode executar para escolher os 10 primeiros itens mais adequados para nossa solicitação:
SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
(cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) as distance
FROM
cymbal_products cp
JOIN cymbal_inventory ci on
ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
cs.store_id=ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
distance ASC
LIMIT 10;
Esta é a saída esperada:
quickstart_db=> SELECT cp.product_name, left(cp.product_description,80) as description, cp.sale_price, cs.zip_code, (cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) as distance FROM cymbal_products cp JOIN cymbal_inventory ci on ci.uniq_id=cp.uniq_id JOIN cymbal_stores cs on cs.store_id=ci.store_id AND ci.inventory>0 AND cs.store_id = 1583 ORDER BY distance ASC LIMIT 10; product_name | description | sale_price | zip_code | distance -------------------------+----------------------------------------------------------------------------------+------------+----------+--------------------- Cherry Tree | This is a beautiful cherry tree that will produce delicious cherries. It is an d | 75.00 | 93230 | 0.43922018972266397 Meyer Lemon Tree | Meyer Lemon trees are California's favorite lemon tree! Grow your own lemons by | 34 | 93230 | 0.4685112926118228 Toyon | This is a beautiful toyon tree that can grow to be over 20 feet tall. It is an e | 10.00 | 93230 | 0.4835677149651668 California Lilac | This is a beautiful lilac tree that can grow to be over 10 feet tall. It is an d | 5.00 | 93230 | 0.4947204525907498 California Peppertree | This is a beautiful peppertree that can grow to be over 30 feet tall. It is an e | 25.00 | 93230 | 0.5054166905547247 California Black Walnut | This is a beautiful walnut tree that can grow to be over 80 feet tall. It is a d | 100.00 | 93230 | 0.5084219510932597 California Sycamore | This is a beautiful sycamore tree that can grow to be over 100 feet tall. It is | 300.00 | 93230 | 0.5140519790508755 Coast Live Oak | This is a beautiful oak tree that can grow to be over 100 feet tall. It is an ev | 500.00 | 93230 | 0.5143126438081371 Fremont Cottonwood | This is a beautiful cottonwood tree that can grow to be over 100 feet tall. It i | 200.00 | 93230 | 0.5174774727252058 Madrone | This is a beautiful madrona tree that can grow to be over 80 feet tall. It is an | 50.00 | 93230 | 0.5227400803389093
9. Melhorar resposta
É possível melhorar a resposta a um aplicativo cliente usando o resultado da consulta e preparar uma saída significativa usando os resultados da consulta fornecidos como parte do comando para o modelo de linguagem de base generativa da Vertex AI.
Para isso, planejamos gerar um JSON com os resultados da pesquisa de vetor e, em seguida, usar esse JSON gerado como complemento de um comando para um modelo de LLM de texto na Vertex AI para criar uma saída significativa. Na primeira etapa, geramos o JSON, testamos no Vertex AI Studio e, na última etapa, o incorporamos em uma instrução SQL que pode ser usada em um aplicativo.
Gerar saída no formato JSON
Modifique a consulta para gerar a saída no formato JSON e retornar apenas uma linha a ser transmitida para a Vertex AI
Confira um exemplo da consulta:
WITH trees as (
SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
cp.uniq_id as product_id
FROM
cymbal_products cp
JOIN cymbal_inventory ci on
ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
cs.store_id=ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
(cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;
E este é o JSON esperado na saída:
[{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}]
Executar o comando no Vertex AI Studio
Podemos usar o JSON gerado para fornecê-lo como parte do comando para o modelo de texto de IA generativa no Vertex AI Studio.
Abra o Vertex AI Studio no console do Cloud.
Talvez seja necessário ativar outras APIs, mas você pode ignorar a solicitação. Não precisamos de outras APIs para concluir o laboratório.
Esta é a instrução que vamos usar:
Você é um consultor amigável que ajuda a encontrar um produto com base nas necessidades do cliente.
Com base na solicitação do cliente, carregamos uma lista de produtos estreitamente relacionados à pesquisa.
A lista no formato JSON com uma lista de valores como {"product_name":"name","description":"some description","sale_price":10,"zip_code": 10234, "produt_id": "02056727942aeb714dc9a2313654e1b0"}
Esta é a lista de produtos:
[place for our JSON]
O cliente perguntou "Qual árvore cultiva melhor aqui?".
Você deve fornecer informações sobre o produto, o preço e algumas informações complementares como instrução
E este é o resultado quando executamos o comando com nossos valores JSON e usamos o modelo gemini-1.5-flash:
Confira a resposta que recebemos do modelo neste exemplo. Sua resposta pode ser diferente devido às mudanças no modelo e nos parâmetros ao longo do tempo:
"Vejo que você está procurando uma árvore que cresce na sua área. Com base no seu CEP, 93230, a cerejeira parece uma ótima opção!
Ela é descrita como uma bela árvore que produz deliciosas cerejas. Está à venda por US $75,00.
Embora eu não tenha detalhes específicos sobre a taxa de crescimento na sua área, posso informar que as cerejeiras geralmente preferem solo bem drenado e sol total.
Para garantir os melhores resultados, recomendo consultar um especialista em horticultura ou jardinagem local que possa dar conselhos mais adequados para sua localização e condições do solo. Eles também podem ajudar você a escolher a melhor variedade para suas necessidades e dar dicas sobre plantio e cuidados."
Executar o comando no PSQL
Podemos usar a integração da IA do AlloyDB com a Vertex AI para receber a mesma resposta de um modelo generativo usando SQL diretamente no banco de dados. Mas, para usar o modelo gemini-1.5-flash, precisamos registrá-lo primeiro.
Faça upgrade da extensão para a versão 1.4.1 (se a versão atual for anterior). Conecte-se ao banco de dados quickstart_db usando psql, como mostrado anteriormente (ou use o AlloyDB Studio) e execute:
SELECT extversion from pg_extension where extname='google_ml_integration';
Se o valor retornado for menor que 1.4.1, execute o seguinte:
ALTER EXTENSION google_ml_integration UPDATE TO '1.4.1';
Em seguida, precisamos definir a flag do banco de dados google_ml_integration.enable_model_support como "on". Para isso, use a interface do console da Web do AlloyDB ou execute o comando gcloud abaixo.
PROJECT_ID=$(gcloud config get-value project)
REGION=us-central1
ADBCLUSTER=alloydb-aip-01
gcloud beta alloydb instances update $ADBCLUSTER-pr \
--database-flags google_ml_integration.enable_model_support=on \
--region=$REGION \
--cluster=$ADBCLUSTER \
--project=$PROJECT_ID \
--update-mode=FORCE_APPLY
O comando leva de 3 a 5 minutos para ser executado em segundo plano. Depois, é possível verificar a nova flag na sessão do psql ou usar o AlloyDB Studio para se conectar ao banco de dados quickstart_db.
show google_ml_integration.enable_model_support;
A saída esperada da sessão do psql é "ativada":
postgres=> show google_ml_integration.enable_model_support; google_ml_integration.enable_model_support -------------------------------------------- on (1 row)
Em seguida, precisamos registrar dois modelos. O primeiro é o modelo text-embedding-004 já usado. Ele precisa ser registrado, já que ativamos os recursos de registro de modelo.
Para registrar o modelo, execute no psql ou no AlloyDB Studio o seguinte código:
CALL
google_ml.create_model(
model_id => 'text-embedding-004',
model_provider => 'google',
model_qualified_name => 'text-embedding-004',
model_type => 'text_embedding',
model_auth_type => 'alloydb_service_agent_iam',
model_in_transform_fn => 'google_ml.vertexai_text_embedding_input_transform',
model_out_transform_fn => 'google_ml.vertexai_text_embedding_output_transform');
O próximo modelo que precisamos registrar é gemini-1.5-flash-002, que será usado para gerar a saída fácil de usar.
CALL
google_ml.create_model(
model_id => 'gemini-1.5-flash-002',
model_request_url => 'https://$REGION-aiplatform.googleapis.com/v1/projects/$PROJECT_ID/locations/$REGION/publishers/google/models/gemini-1.5-flash-002:streamGenerateContent',
model_provider => 'google',
model_auth_type => 'alloydb_service_agent_iam');
Você pode verificar a lista de modelos registrados selecionando informações em google_ml.model_info_view.
select model_id,model_type from google_ml.model_info_view;
Confira um exemplo de saída
quickstart_db=> select model_id,model_type from google_ml.model_info_view; model_id | model_type -------------------------+---------------- textembedding-gecko | text_embedding textembedding-gecko@001 | text_embedding text-embedding-004 | text_embedding gemini-1.5-flash-001 | generic (4 rows)
Agora podemos usar o JSON gerado em uma subconsulta para fornecê-lo como parte do comando ao modelo de texto de IA generativa usando SQL.
Na sessão do psql ou do AlloyDB Studio para o banco de dados, execute a consulta.
WITH trees AS (
SELECT
cp.product_name,
cp.product_description AS description,
cp.sale_price,
cs.zip_code,
cp.uniq_id AS product_id
FROM
cymbal_products cp
JOIN cymbal_inventory ci ON
ci.uniq_id = cp.uniq_id
JOIN cymbal_stores cs ON
cs.store_id = ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
(cp.embedding <=> embedding('text-embedding-004',
'What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1),
prompt AS (
SELECT
'You are a friendly advisor helping to find a product based on the customer''s needs.
Based on the client request we have loaded a list of products closely related to search.
The list in JSON format with list of values like {"product_name":"name","product_description":"some description","sale_price":10}
Here is the list of products:' || json_agg(trees) || 'The customer asked "What kind of fruit trees grow well here?"
You should give information about the product, price and some supplemental information' AS prompt_text
FROM
trees),
response AS (
SELECT
json_array_elements(google_ml.predict_row( model_id =>'gemini-1.5-flash-002',
request_body => json_build_object('contents',
json_build_object('role',
'user',
'parts',
json_build_object('text',
prompt_text)))))->'candidates'->0->'content'->'parts'->0->'text' AS resp
FROM
prompt)
SELECT
string_agg(resp::text,
' ')
FROM
response;
E esta é a saída esperada. A saída pode ser diferente dependendo da versão do modelo e dos parâmetros:
"That" "'s a great question! Based on your location (assuming you're" " in zip code 93230), I have a suggestion for a" " fruit tree that should thrive.\n\nWe have the **Cherry Tree** available.\n\n**Product Name:** Cherry Tree\n\n**Description:** This is a beautiful cherry" " tree that will produce delicious cherries. It's a deciduous tree (meaning it loses its leaves in the fall) growing to about 15 feet tall." " The leaves are dark green in summer, turning a beautiful red in the fall. Cherry trees are known for their beauty, shade, and privacy.\n\n**Sale Price:** $75.00\n\n**Important Considerations for Growing" " Cherry Trees:**\n\n* **Climate:** Cherry trees prefer a cool, moist climate, and 93230 falls within a suitable range (USDA zones 4-9). However, it's always a good idea to" " check the specific microclimate of your property (sun exposure, drainage etc.).\n* **Soil:** They do best in sandy soil. If your soil is different, you may need to amend it to improve drainage.\n* **Pollination:** Many cherry varieties require a second, compatible cherry tree for proper pollination" ". Check the specific pollination needs of this variety before purchase if you want a significant cherry yield.\n\nThis cherry tree is a beautiful addition to any yard and will provide you with delicious cherries if you can meet its needs. Would you like to know more about its pollination requirements, or perhaps see if we have any other" " fruit trees suitable for your area?\n" ""
10. Criar índice de vetor
Nosso conjunto de dados é bem pequeno, e o tempo de resposta depende principalmente da interação com os modelos de IA. Mas, quando há milhões de vetores, a parte da pesquisa vetorial pode ocupar uma parte significativa do tempo de resposta e sobrecarregar o sistema. Para melhorar isso, podemos criar um índice sobre nossos vetores.
Criar índice ScaNN
Para criar o índice SCANN, precisamos ativar mais uma extensão. A extensão alloydb_scann fornece uma interface para trabalhar com o índice de vetor do tipo ANN usando o algoritmo ScaNN do Google.
CREATE EXTENSION IF NOT EXISTS alloydb_scann;
Saída esperada:
quickstart_db=> CREATE EXTENSION IF NOT EXISTS alloydb_scann; CREATE EXTENSION Time: 27.468 ms quickstart_db=>
Agora podemos criar o índice. No exemplo a seguir, deixei a maioria dos parâmetros como padrão e forneço apenas algumas partições (num_leaves) para o índice:
CREATE INDEX cymbal_products_embeddings_scann ON cymbal_products
USING scann (embedding cosine)
WITH (num_leaves=31, max_num_levels = 2);
Leia sobre o ajuste de parâmetros de índice na documentação.
Saída esperada:
quickstart_db=> CREATE INDEX cymbal_products_embeddings_scann ON cymbal_products USING scann (embedding cosine) WITH (num_leaves=31, max_num_levels = 2); CREATE INDEX quickstart_db=>
Comparar resposta
Agora podemos executar a consulta de pesquisa vetorial no modo EXPLAIN e verificar se o índice foi usado.
EXPLAIN (analyze)
WITH trees as (
SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
cp.uniq_id as product_id
FROM
cymbal_products cp
JOIN cymbal_inventory ci on
ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
cs.store_id=ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
(cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;
Saída esperada:
Aggregate (cost=16.59..16.60 rows=1 width=32) (actual time=2.875..2.877 rows=1 loops=1) -> Subquery Scan on trees (cost=8.42..16.59 rows=1 width=142) (actual time=2.860..2.862 rows=1 loops=1) -> Limit (cost=8.42..16.58 rows=1 width=158) (actual time=2.855..2.856 rows=1 loops=1) -> Nested Loop (cost=8.42..6489.19 rows=794 width=158) (actual time=2.854..2.855 rows=1 loops=1) -> Nested Loop (cost=8.13..6466.99 rows=794 width=938) (actual time=2.742..2.743 rows=1 loops=1) -> Index Scan using cymbal_products_embeddings_scann on cymbal_products cp (cost=7.71..111.99 rows=876 width=934) (actual time=2.724..2.724 rows=1 loops=1) Order By: (embedding <=> '[0.008864171,0.03693164,-0.024245683,-0.00355923,0.0055611245,0.015985578,...<redacted>...5685,-0.03914233,-0.018452475,0.00826032,-0.07372604]'::vector) -> Index Scan using walmart_inventory_pkey on cymbal_inventory ci (cost=0.42..7.26 rows=1 width=37) (actual time=0.015..0.015 rows=1 loops=1) Index Cond: ((store_id = 1583) AND (uniq_id = (cp.uniq_id)::text))
Na saída, é possível ver claramente que a consulta estava usando "Index Scan using cymbal_products_embeddings_scann on cymbal_products".
E se executarmos a consulta sem explicar:
WITH trees as (
SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
cp.uniq_id as product_id
FROM
cymbal_products cp
JOIN cymbal_inventory ci on
ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
cs.store_id=ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
(cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;
Saída esperada:
[{"product_name":"Meyer Lemon Tree","description":"Meyer Lemon trees are California's favorite lemon tree! Grow your own lemons by ","sale_price":34,"zip_code":93230,"product_id":"02056727942aeb714dc9a2313654e1b0"}]
Podemos ver que o resultado é um pouco diferente e não retornamos a cerejeira que estava no topo da pesquisa sem índice, mas a segunda escolha, o limão Meyer. O índice está mostrando performance, mas ainda é preciso o suficiente para gerar bons resultados.
É possível testar diferentes índices disponíveis para os vetores e outros laboratórios e exemplos com a integração de langchain disponíveis na página de documentação.
11. Limpar o ambiente
Destrua as instâncias e o cluster do AlloyDB quando terminar o laboratório.
Excluir o cluster do AlloyDB e todas as instâncias
O cluster é destruído com a opção "force" que também exclui todas as instâncias pertencentes.
No Cloud Shell, defina o projeto e as variáveis de ambiente se tiver ocorrido uma desconexão e todas as configurações anteriores forem perdidas:
gcloud config set project <your project id>
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
export PROJECT_ID=$(gcloud config get-value project)
Exclua o cluster:
gcloud alloydb clusters delete $ADBCLUSTER --region=$REGION --force
Saída esperada do console:
student@cloudshell:~ (test-project-001-402417)$ gcloud alloydb clusters delete $ADBCLUSTER --region=$REGION --force All of the cluster data will be lost when the cluster is deleted. Do you want to continue (Y/n)? Y Operation ID: operation-1697820178429-6082890a0b570-4a72f7e4-4c5df36f Deleting cluster...done.
Excluir backups do AlloyDB
Exclua todos os backups do AlloyDB do cluster:
for i in $(gcloud alloydb backups list --filter="CLUSTER_NAME: projects/$PROJECT_ID/locations/$REGION/clusters/$ADBCLUSTER" --format="value(name)" --sort-by=~createTime) ; do gcloud alloydb backups delete $(basename $i) --region $REGION --quiet; done
Saída esperada do console:
student@cloudshell:~ (test-project-001-402417)$ for i in $(gcloud alloydb backups list --filter="CLUSTER_NAME: projects/$PROJECT_ID/locations/$REGION/clusters/$ADBCLUSTER" --format="value(name)" --sort-by=~createTime) ; do gcloud alloydb backups delete $(basename $i) --region $REGION --quiet; done Operation ID: operation-1697826266108-60829fb7b5258-7f99dc0b-99f3c35f Deleting backup...done.
Agora você pode destruir a VM.
Excluir a VM do GCE
No Cloud Shell, execute:
export GCEVM=instance-1
export ZONE=us-central1-a
gcloud compute instances delete $GCEVM \
--zone=$ZONE \
--quiet
Saída esperada do console:
student@cloudshell:~ (test-project-001-402417)$ export GCEVM=instance-1 export ZONE=us-central1-a gcloud compute instances delete $GCEVM \ --zone=$ZONE \ --quiet Deleted
12. Parabéns
Parabéns por concluir o codelab.
O que vimos
- Como implantar o cluster e a instância principal do AlloyDB
- Como se conectar ao AlloyDB usando uma VM do Google Compute Engine
- Como criar um banco de dados e ativar o AlloyDB AI
- Como carregar dados no banco de dados
- Como usar o modelo de incorporação da Vertex AI no AlloyDB
- Como enriquecer o resultado usando o modelo generativo da Vertex AI
- Como melhorar o desempenho usando o índice de vetor
13. Pesquisa
Saída: