1. Visão geral
Imagine entrar em uma loja de brinquedos virtual ou presencial, onde encontrar o presente perfeito é fácil. Você pode descrever o que está procurando, fazer upload de uma imagem de um brinquedo ou até mesmo criar sua própria criação. A loja entende instantaneamente suas necessidades e oferece uma experiência personalizada. Isso não é uma fantasia futurista, é uma realidade impulsionada pela IA, pela tecnologia de nuvem e por uma visão de e-commerce personalizado.
O desafio:encontrar o produto perfeito que corresponda à sua imaginação pode ser difícil. Termos de pesquisa genéricos, palavras-chave e pesquisas imprecisas muitas vezes não são suficientes. Navegar por páginas infinitas pode ser tedioso, e a desconexão entre o que você imagina e o que está disponível pode causar frustração.
A solução:o aplicativo de demonstração enfrenta esse desafio de frente, aproveitando o poder da IA para oferecer uma experiência realmente personalizada e integrada com a pesquisa contextual e a geração personalizada do produto que corresponde ao contexto da pesquisa.
O que você vai criar
Como parte deste laboratório, você vai:
- Criar uma instância do AlloyDB e carregar o conjunto de dados de brinquedos
- Ativar as extensões de modelo de IA generativa e pgvector no AlloyDB
- Gerar embeddings com base na descrição do produto e realizar a pesquisa de similaridade de cosseno em tempo real para o texto de pesquisa do usuário
- Invocar o Gemini 2.0 Flash para descrever a imagem enviada pelo usuário para a pesquisa contextual de brinquedos
- Invocar a Imagen 3 para criar um brinquedo personalizado com base no interesse do usuário
- Invocar uma ferramenta de previsão de preço criada usando a Caixa de ferramentas de IA generativa para bancos de dados para detalhes de preço do brinquedo criado
- Implantar a solução em funções sem servidor do Cloud Run
Requisitos
2. Arquitetura
Fluxo de dados: vamos analisar como os dados são processados no sistema:
- Pesquisa contextual com RAG (geração aumentada de recuperação) com tecnologia de IA
Pense assim: em vez de procurar apenas "carro vermelho", o sistema entende o seguinte:
"veículo pequeno adequado para um menino de 3 anos".
AlloyDB como base:usamos o AlloyDB, o banco de dados totalmente gerenciado e compatível com PostgreSQL do Google Cloud, para armazenar dados de brinquedos, incluindo descrições, URLs de imagens e outros atributos relevantes.
pgvector para pesquisa semântica:o pgvector, uma extensão do PostgreSQL, permite armazenar embeddings de vetores de descrições de brinquedos e consultas de pesquisa do usuário. Isso permite a pesquisa semântica, ou seja, o sistema entende o significado das palavras, não apenas as palavras-chave exatas.
Similaridade de cossenos para relevância:usamos a similaridade de cossenos para medir a similaridade semântica entre o vetor de pesquisa do usuário e os vetores de descrição do brinquedo, mostrando os resultados mais relevantes.
Índice ScaNN para velocidade e precisão:para garantir resultados rápidos e precisos, especialmente à medida que o inventário de brinquedos cresce, integramos o índice ScaNN (Scalable Nearest Neighbors). Isso melhora significativamente a eficiência e o recall da pesquisa de vetor.
- Pesquisa e compreensão baseada em imagens com o Gemini 2.0 Flash
Em vez de digitar o contexto como texto, digamos que o usuário queira fazer o upload de uma foto de um brinquedo conhecido para pesquisar. Os usuários podem fazer upload de uma imagem de um brinquedo que eles gostam e receber recursos relevantes com isso. Usamos o modelo Flash Gemini 2.0 do Google, invocado usando o LangChain4j, para analisar a imagem e extrair o contexto relevante, como a cor, o material, o tipo e o grupo etário pretendido do brinquedo.
- Como criar o brinquedo dos seus sonhos com IA generativa: Imagen 3
A magia acontece quando os usuários decidem criar o próprio brinquedo. Com o Imagen 3, permitimos que eles descrevam o brinquedo dos sonhos usando comandos de texto simples. Imagine poder dizer: "Quero um dragão de pelúcia com asas roxas e um rosto amigável" e ver esse dragão ganhar vida na tela. A imagem 3 gera uma imagem do brinquedo personalizado, mostrando ao usuário uma visualização clara da criação.
- Previsão de preços com agentes e Gen AI Toolbox para bancos de dados
Implementamos um recurso de previsão de preço que estima o custo de produção do brinquedo personalizado. Isso é feito por um agente que inclui uma ferramenta sofisticada de cálculo de preços.
Gen AI Toolbox para bancos de dados:esse agente é integrado perfeitamente ao nosso banco de dados usando a nova ferramenta de código aberto do Google, a Gen AI Toolbox para bancos de dados. Isso permite que o agente acesse dados em tempo real sobre custos de materiais, processos de fabricação e outros fatores relevantes para fornecer uma estimativa de preço precisa. Saiba mais neste link.
- Java Spring Boot, Gemini Code Assist e Cloud Run para desenvolvimento simplificado e implantação sem servidor
O aplicativo inteiro é criado usando o Java Spring Boot, um framework robusto e escalonável. Usamos o Gemini Code Assist durante todo o processo de desenvolvimento, principalmente no front-end, acelerando significativamente o ciclo de desenvolvimento e melhorando a qualidade do código. Usamos o Cloud Run para implantar todo o aplicativo e o Cloud Run Functions para implantar o banco de dados e as funcionalidades de agente como endpoints independentes.
3. Antes de começar
Criar um projeto
- No console do Google Cloud, na página de seletor de projetos, selecione ou crie um projeto do Google Cloud.
- Verifique se o faturamento está ativado para seu projeto do Cloud. Saiba como verificar se o faturamento está ativado em um projeto .
- Você vai usar o Cloud Shell, um ambiente de linha de comando executado no Google Cloud que vem pré-carregado com bq. Clique em "Ativar o Cloud Shell" na parte de cima do console do Google Cloud.
- Depois de se conectar ao Cloud Shell, verifique se você já está autenticado e se o projeto está definido como seu ID usando o seguinte comando:
gcloud auth list
- Execute o comando a seguir no Cloud Shell para confirmar se o comando gcloud sabe sobre seu projeto.
gcloud config list project
- Se o projeto não estiver definido, use este comando:
gcloud config set project <YOUR_PROJECT_ID>
- Ative as APIs necessárias executando os comandos a seguir um por um no terminal do Cloud Shell:
Há também um único comando para executar o procedimento abaixo, mas se você for um usuário de conta de teste, poderá encontrar problemas de cota ao tentar ativar em massa. É por isso que os comandos são separados um por linha.
gcloud services enable alloydb.googleapis.com
gcloud services enable compute.googleapis.com
gcloud services enable cloudresourcemanager.googleapis.com
gcloud services enable servicenetworking.googleapis.com
gcloud services enable run.googleapis.com
gcloud services enable cloudbuild.googleapis.com
gcloud services enable cloudfunctions.googleapis.com
gcloud services enable aiplatform.googleapis.com
A alternativa ao comando gcloud é pelo console, pesquisando cada produto ou usando este link.
Se alguma API for perdida, você poderá ativá-la durante a implementação.
Consulte a documentação para ver o uso e os comandos gcloud.
4. Configuração do banco de dados
Neste laboratório, vamos usar o AlloyDB como o banco de dados para armazenar os dados da loja de brinquedos. Ele usa clusters para armazenar todos os recursos, como bancos de dados e registros. Cada cluster tem uma instância principal que fornece um ponto de acesso aos dados. As tabelas vão conter os dados reais.
Vamos criar um cluster, uma instância e uma tabela do AlloyDB em que o conjunto de dados de e-commerce será carregado.
Criar um cluster e uma instância
- Navegue pela página do AlloyDB no Console do Cloud. Uma maneira fácil de encontrar a maioria das páginas no console do Cloud é pesquisar usando a barra de pesquisa do console.
- Selecione CREATE CLUSTER nessa página:
- Uma tela como esta vai aparecer. Crie um cluster e uma instância com os seguintes valores. Confira se os valores correspondem ao clonar o código do aplicativo do repositório:
- ID do cluster: "
vector-cluster
" - senha: "
alloydb
" - Compatível com PostgreSQL 15
- Região: "
us-central1
" - Redes: "
default
"
- Ao selecionar a rede padrão, uma tela como a mostrada abaixo será exibida.
Selecione CONFIGURAR CONEXÃO.
- Em seguida, selecione Usar um intervalo de IP alocado automaticamente e clique em "Continuar". Depois de analisar as informações, selecione "CRIAR CONEXÃO".
- Depois que a rede estiver configurada, você poderá continuar a criar o cluster. Clique em CRIAR CLUSTER para concluir a configuração do cluster, conforme mostrado abaixo:
Altere o ID da instância para "
vector-instance"
.
A criação do cluster leva cerca de 10 minutos. Depois que a criação for concluída, uma tela vai mostrar uma visão geral do cluster que você acabou de criar.
5. Ingestão de dados
Agora é hora de adicionar uma tabela com os dados da loja. Acesse o AlloyDB, selecione o cluster principal e o AlloyDB Studio:
Talvez seja necessário aguardar a conclusão da criação da instância. Depois disso, faça login no AlloyDB usando as credenciais que você criou ao criar o cluster. Use os seguintes dados para autenticação no PostgreSQL:
- Nome de usuário : "
postgres
" - Banco de dados : "
postgres
" - Senha : "
alloydb
"
Depois que você fizer a autenticação no AlloyDB Studio, os comandos SQL serão inseridos no editor. É possível adicionar várias janelas do Editor usando o sinal de adição à direita da última janela.
Você vai inserir comandos para o AlloyDB nas janelas do editor usando as opções Executar, Formatar e Limpar conforme necessário.
Ativar extensões
Para criar este app, vamos usar as extensões pgvector
e google_ml_integration
. A extensão pgvector permite armazenar e pesquisar embeddings de vetor. A extensão google_ml_integration fornece funções que você usa para acessar os endpoints de previsão da Vertex AI e receber previsões no SQL. Ative essas extensões executando os seguintes DDLs:
CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector;
Se você quiser verificar as extensões que foram ativadas no seu banco de dados, execute este comando SQL:
select extname, extversion from pg_extension;
Criar uma tabela
Crie uma tabela usando a instrução DDL abaixo:
CREATE TABLE toys ( id VARCHAR(25), name VARCHAR(25), description VARCHAR(20000), quantity INT, price FLOAT, image_url VARCHAR(200), text_embeddings vector(768)) ;
Se o comando acima for executado com sucesso, você poderá acessar a tabela no banco de dados.
Ingerir dados
Para este laboratório, temos dados de teste de cerca de 72 registros neste arquivo SQL. Ele contém os campos id, name, description, quantity, price, image_url
. Os outros campos serão preenchidos mais tarde no laboratório.
Copie as linhas/instruções de inserção e cole em uma guia de editor em branco e selecione EXECUTAR.
Para conferir o conteúdo da tabela, expanda a seção "Explorador" até encontrar a tabela "apparels". Selecione o triponto (⋮) para ver a opção de consultar a tabela. Uma instrução SELECT será aberta em uma nova guia do editor.
Conceder permissão
Execute a instrução abaixo para conceder direitos de execução na função embedding
ao usuário postgres
:
GRANT EXECUTE ON FUNCTION embedding TO postgres;
Conceder o papel de usuário da Vertex AI à conta de serviço do AlloyDB
Acesse o terminal do Cloud Shell e digite o seguinte comando:
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"
6. Criar embeddings para o contexto
É muito mais fácil para os computadores processar números do que processar texto. Um sistema de incorporação converte texto em uma série de números de ponto flutuante que representam o texto, independentemente da forma como ele é escrito, do idioma usado etc.
Considere descrever um local à beira-mar. Pode ser "em frente ao mar", "em frente à praia", "a pé do mar", "sur la mer", "на берегу океана" etc. Todos esses termos parecem diferentes, mas o significado semântico ou a terminologia de aprendizado de máquina deles devem ser muito próximos.
Agora que os dados e o contexto estão prontos, vamos executar o SQL para adicionar as incorporações da descrição do produto à tabela no campo embedding
. Há vários modelos de embedding que podem ser usados. Estamos usando text-embedding-005
da Vertex AI. Use o mesmo modelo de incorporação em todo o projeto.
Observação: se você estiver usando um projeto do Google Cloud criado há algum tempo, talvez seja necessário continuar usando versões mais antigas do modelo de incorporação de texto, como textembedding-gecko.
Volte para a guia do AlloyDB Studio e digite o seguinte DML:
UPDATE toys set text_embeddings = embedding( 'text-embedding-005', description);
Confira a tabela toys
novamente para ver alguns embeddings. Execute novamente a instrução SELECT para conferir as mudanças.
SELECT id, name, description, price, quantity, image_url, text_embeddings FROM toys;
Isso vai retornar o vetor de incorporação, que se parece com uma matriz de flutuações, para a descrição do brinquedo, conforme mostrado abaixo:
Observação:os projetos do Google Cloud recém-criados no nível sem custo financeiro podem ter problemas de cota em relação ao número de solicitações de incorporação permitidas por segundo para os modelos de incorporação. Sugerimos que você use uma consulta de filtro para o ID e escolha seletivamente de 1 a 5 registros e assim por diante ao gerar a incorporação.
7. Realizar a pesquisa de vetor
Agora que a tabela, os dados e os embeddings estão prontos, vamos realizar a pesquisa de vetor em tempo real para o texto de pesquisa do usuário.
Suponha que o usuário pergunte:
"I want a white plush teddy bear toy with a floral pattern
".
Para encontrar correspondências para isso, execute a consulta abaixo:
select * from toys
ORDER BY text_embeddings <=> CAST(embedding('text-embedding-005', 'I want a white plush teddy bear toy with a floral pattern') as vector(768))
LIMIT 5;
Vamos analisar essa consulta em detalhes:
Nesta consulta,
- O texto de pesquisa do usuário é: "
I want a white plush teddy bear toy with a floral pattern.
" - Estamos convertendo em embeddings no método
embedding()
usando o modelo:text-embedding-005
. Esta etapa é semelhante à anterior, em que aplicamos a função de incorporação a todos os itens da tabela. - "
<=>
" representa o uso do método de distância COSINE SIMILARITY. Todas as medidas de similaridade disponíveis estão disponíveis na documentação do pgvector. - Estamos convertendo o resultado do método de embedding em um tipo de vetor para que ele seja compatível com os vetores armazenados no banco de dados.
- LIMIT 5 representa que queremos extrair 5 vizinhos mais próximos para o texto de pesquisa.
O resultado é parecido com este:
Como você pode observar nos resultados, as correspondências são muito próximas do texto da pesquisa. Tente mudar o texto para conferir como os resultados mudam.
Observação importante:
Agora, digamos que queremos aumentar a performance (tempo de consulta), a eficiência e o recall desse resultado de pesquisa vetorial usando o índice ScaNN. Leia as etapas neste blog para comparar a diferença no resultado com e sem o índice.
Etapa opcional: melhorar a eficiência e a recuperação com o índice ScaNN
Para facilitar, listamos aqui as etapas de criação de índice:
- Como já temos o cluster, a instância, o contexto e as embeddings criadas, basta instalar a extensão ScaNN usando a seguinte instrução:
CREATE EXTENSION IF NOT EXISTS alloydb_scann;
- Em seguida, vamos criar o índice (ScaNN):
CREATE INDEX toysearch_index ON toys
USING scann (text_embeddings cosine)
WITH (num_leaves=9);
Na DDL acima, apparel_index é o nome do índice.
"toys" é minha tabela
"scann" é o método de índice
"Incorporação" é a coluna na tabela que eu quero indexar.
"Cosseno" é o método de distância que quero usar com o índice
"8" é o número de partições a serem aplicadas a esse índice. Defina qualquer valor entre 1 e 1048576. Para mais informações sobre como decidir esse valor, consulte Ajustar um índice ScaNN.
Usei uma RAIZ QUADRADA do número de pontos de dados, conforme recomendado no repositório ScaNN. (Ao particionar, o num_leaves precisa ser aproximadamente a raiz quadrada do número de pontos de dados).
- Verifique se o índice foi criado usando a consulta:
SELECT * FROM pg_stat_ann_indexes;
- Realize a pesquisa vetorial usando a mesma consulta que usamos sem o índice:
select * from toys
ORDER BY text_embeddings <=> CAST(embedding('text-embedding-005', 'I want a white plush teddy bear toy with a floral pattern') as vector(768))
LIMIT 5;
A consulta acima é a mesma que usamos no laboratório na etapa 8. No entanto, agora temos o campo indexado.
- Teste com uma consulta de pesquisa simples com e sem o índice (removendo o índice):
Esse caso de uso tem apenas 72 registros, portanto, o índice não entra em vigor. Para um teste realizado em outro caso de uso, os resultados são os seguintes:
A mesma consulta de pesquisa vetorial nos dados de embeddings INDEXADOS resulta em resultados de pesquisa de qualidade e eficiência. A eficiência é muito melhor (em termos de tempo de execução: 10,37 ms sem ScaNN e 0,87 ms com ScaNN) com o índice. Para mais informações sobre esse assunto, consulte este blog.
8. Validação de correspondência com o LLM
Antes de continuar e criar um serviço para retornar as melhores correspondências a um aplicativo, vamos usar um modelo de IA generativa para validar se essas possíveis respostas são realmente relevantes e seguras para compartilhar com o usuário.
Verificar se a instância está configurada para o Gemini
Primeiro, verifique se a integração do Google ML já está ativada para o cluster e a instância. No AlloyDB Studio, execute o seguinte comando:
show google_ml_integration.enable_model_support;
Se o valor for mostrado como "on", pule as próximas duas etapas e vá direto para a configuração da integração do AlloyDB e do modelo da Vertex AI.
- Acesse a instância principal do cluster do AlloyDB e clique em EDIT PRIMARY INSTANCE.
- Navegue até a seção "Flags" nas opções de configuração avançadas. e verifique se o
google_ml_integration.enable_model_support flag
está definido como "on
", conforme mostrado abaixo:
Se não estiver ativado, ative e clique no botão UPDATE INSTANCE. Essa etapa vai levar alguns minutos.
Integração do AlloyDB e do modelo da Vertex AI
Agora você pode se conectar ao AlloyDB Studio e executar a instrução DML a seguir para configurar o acesso ao modelo Gemini no AlloyDB, usando o ID do projeto indicado. Talvez você receba um aviso de erro de sintaxe antes de executar o comando, mas ele deve funcionar bem.
Primeiro, criamos a conexão do modelo Gemini 1.5, conforme mostrado abaixo. Substitua $PROJECT_ID
no comando abaixo pelo ID do projeto do Google Cloud.
CALL
google_ml.create_model( model_id => 'gemini-1.5',
model_request_url => 'https://us-central1-aiplatform.googleapis.com/v1/projects/$PROJECT_ID/locations/us-central1/publishers/google/models/gemini-1.5-pro:streamGenerateContent',
model_provider => 'google',
model_auth_type => 'alloydb_service_agent_iam');
É possível verificar os modelos configurados para acesso usando o seguinte comando no AlloyDB Studio:
select model_id,model_type from google_ml.model_info_view;
Por fim, precisamos conceder permissão aos usuários do banco de dados para executar a função ml_predict_row e fazer previsões usando os modelos da Google Vertex AI. Execute este comando:
GRANT EXECUTE ON FUNCTION ml_predict_row to postgres;
Observação: se você estiver usando um projeto do Google Cloud e um cluster/instância do AlloyDB criados há algum tempo, talvez seja necessário excluir as referências antigas ao modelo gemini-1.5 e criar novamente com a instrução CALL acima e executar o grant execute na função ml_predict_row novamente caso você tenha problemas nas próximas invocações do gemini-1.5.
Como avaliar as respostas
Embora vamos usar uma consulta grande na próxima seção para garantir que as respostas sejam razoáveis, ela pode ser difícil de entender. Vamos analisar as peças agora e ver como elas se juntam em alguns minutos.
- Primeiro, vamos enviar uma solicitação ao banco de dados para receber as 10 correspondências mais próximas de uma consulta do usuário.
- Para determinar a validade das respostas, vamos usar uma consulta externa em que explicamos como avaliar as respostas. Ele usa o campo
recommended_text
, que é o texto de pesquisa, econtent
(que é o campo de descrição do brinquedo) da tabela interna como parte da consulta. - Usando isso, vamos analisar a "qualidade" das respostas retornadas.
- O
predict_row
retorna o resultado no formato JSON. O código "-> 'candidates' -> 0 -> 'content' -> 'parts' -> 0 -> 'text'"
é usado para extrair o texto real desse JSON. Para conferir o JSON real que é retornado, remova esse código. - Por fim, para extrair a resposta do LLM, usamos
REGEXP_REPLACE(gemini_validation,
'[^a-zA-Z,: ]',
'',
'g')
.
SELECT id,
name,
content,
quantity,
price,
image_url,
recommended_text,
REGEXP_REPLACE(gemini_validation, '[^a-zA-Z,: ]', '', 'g') AS gemini_validation
FROM (SELECT id,
name,
content,
quantity,
price,
image_url,
recommended_text,
CAST(ARRAY_AGG(LLM_RESPONSE) AS TEXT) AS gemini_validation
FROM (SELECT id,
name,
content,
quantity,
price,
image_url,
recommended_text,
json_array_elements(google_ml.predict_row(model_id => 'gemini-1.5',
request_body => CONCAT('{ "contents": [ { "role": "user", "parts": [ { "text": "User wants to buy a toy and this is the description of the toy they wish to buy: ', recommended_text, '. Check if the following product items from the inventory are close enough to really, contextually match the user description. Here are the items: ', content, '. Return a ONE-LINE response with 3 values: 1) MATCH: if the 2 contexts are reasonably matching in terms of any of the color or color family specified in the list, approximate style match with any of the styles mentioned in the user search text: This should be a simple YES or NO. Choose NO only if it is completely irrelevant to users search criteria. 2) PERCENTAGE: percentage of match, make sure that this percentage is accurate 3) DIFFERENCE: A clear one-line easy description of the difference between the 2 products. Remember if the user search text says that some attribute should not be there, and the record has it, it should be a NO match. " } ] } ] }')::JSON)) -> 'candidates' -> 0 -> 'content' -> 'parts' -> 0 -> 'text' :: TEXT AS LLM_RESPONSE
FROM (SELECT id,
name,
description AS content,
quantity,
price,
image_url,
'Pink panther standing' AS recommended_text
FROM toys
ORDER BY text_embeddings <=> embedding('text-embedding-005',
'Pink panther standing')::VECTOR
LIMIT 10) AS xyz) AS X
GROUP BY id,
name,
content,
quantity,
price,
image_url,
recommended_text) AS final_matches
WHERE REGEXP_REPLACE(gemini_validation, '[^a-zA-Z,: ]', '', 'g') LIKE '%MATCH%:%YES%';
Embora isso possa parecer assustador, esperamos que você consiga entender melhor. Os resultados informam se há ou não uma correspondência, qual é a porcentagem dela e uma explicação da classificação.
O modelo do Gemini tem streaming ativado por padrão, então a resposta real é distribuída em várias linhas:
9. Fazer a pesquisa de brinquedos sem servidor no Cloud
Tudo pronto para levar esse app para a Web? Siga as etapas abaixo para criar este mecanismo de conhecimento sem servidor com as funções do Cloud Run:
- Acesse as Funções do Cloud Run no console do Google Cloud para CRIAr uma nova função do Cloud Run ou use o link: https://console.cloud.google.com/functions/add.
- Selecione o ambiente como Função do Cloud Run. Informe o nome da função "get-toys-alloydb" e escolha "us-central1" como região. Defina a autenticação como "Permitir invocações não autenticadas" e clique em PRÓXIMO. Escolha Java 17 como ambiente de execução e Editor in-line para o código-fonte.
- Por padrão, o ponto de entrada é definido como "
gcfv2.HelloHttpFunction
". Substitua o código de marcador de posição emHelloHttpFunction.java
epom.xml
da função do Cloud Run pelo código de HelloHttpFunction.java e pom.xml, respectivamente. - Lembre-se de mudar o marcador de posição <<YOUR_PROJECT>> e as credenciais de conexão do AlloyDB com seus valores no arquivo Java. As credenciais do AlloyDB são as que usamos no início deste codelab. Se você usou valores diferentes, modifique-os no arquivo Java.
- Clique em Implantar.
Após a implantação, vamos criar o conector da VPC para permitir que a função do Cloud acesse nossa instância de banco de dados do AlloyDB.
ETAPA IMPORTANTE:
Depois de definir a implantação, você poderá ver as funções no console do Cloud Run Functions do Google. Pesquise a função recém-criada (get-toys-alloydb
), clique nela e em EDITAR e mude o seguinte:
- Acessar as Configurações de ambiente de execução, build, conexões e segurança
- Aumente o tempo limite para 180 segundos
- Acesse a guia CONEXÕES:
- Em "Configurações de entrada", verifique se a opção "Permitir todo o tráfego" está selecionada.
- Em "Configurações de saída", clique no menu suspenso "Rede", selecione a opção "Adicionar novo conector VPC" e siga as instruções na caixa de diálogo que aparece:
- Dê um nome ao conector da VPC e verifique se a região é a mesma da sua instância. Deixe o valor da rede como padrão e defina a sub-rede como intervalo de IP personalizado com o intervalo de IP 10.8.0.0 ou algo semelhante que esteja disponível.
- Expanda SHOW SCALING SETTINGS e verifique se a configuração está definida exatamente assim:
- Clique em "Criar". O conector vai ser listado nas configurações de saída.
- Selecione o conector recém-criado
- Escolha que todo o tráfego seja roteado por esse conector da VPC.
- Clique em PRÓXIMA e em IMPLANTAR.
10. Testar a função do Cloud Run
Depois que a função do Cloud atualizada for implantada, o endpoint vai aparecer neste formato:
https://us-central1-YOUR_PROJECT_ID.cloudfunctions.net/get-toys-alloydb
Se preferir, teste a função do Cloud Run da seguinte maneira:
PROJECT_ID=$(gcloud config get-value project)
curl -X POST https://us-central1-$PROJECT_ID.cloudfunctions.net/get-toys-alloydb \
-H 'Content-Type: application/json' \
-d '{"search":"I want a standing pink panther toy"}' \
| jq .
Resultado:
Pronto! É muito simples realizar a pesquisa de vetor de similaridade usando o modelo de embeddings nos dados do AlloyDB.
11. Como criar o cliente do aplicativo da Web
Nesta parte, vamos criar um aplicativo da Web para que o usuário interaja e encontre brinquedos correspondentes com base em texto, imagem e até mesmo crie um novo brinquedo com base nas necessidades dele. Como o aplicativo já foi criado, siga as etapas abaixo para copiá-lo para o ambiente de desenvolvimento integrado e fazer o app funcionar.
- Como usamos o Gemini 2.0 Flash para descrever a imagem que o usuário pode enviar para encontrar brinquedos correspondentes, precisamos da CHAVE DE API para esse aplicativo. Para fazer isso, acesse https://aistudio.google.com/apikey e obtenha a chave de API para o projeto ativo do Google Cloud em que você está implementando o aplicativo e salve a chave em algum lugar:
- Acesse o terminal do Cloud Shell.
- Clone o repositório com o seguinte comando:
git clone https://github.com/AbiramiSukumaran/toysearch
cd toysearch
- Depois que o repositório for clonado, você poderá acessar o projeto no editor do Cloud Shell.
- É necessário excluir as pastas "get-toys-alloydb" e "toolbox-toys" do projeto clonado, porque elas são códigos do Cloud Run Functions que podem ser referenciados no repositório quando necessário.
- Verifique se todas as variáveis de ambiente necessárias estão definidas antes de criar e implantar o app. Acesse o Cloud Shell Terminal e execute o seguinte:
PROJECT_ID=$(gcloud config get-value project)
export PROJECT_ID $PROJECT_ID
export GOOGLE_API_KEY <YOUR API KEY that you saved>
- Crie e execute o app localmente:
Para verificar se você está no diretório do projeto, execute os seguintes comandos:
mvn package
mvn spring-boot:run
- Implantar no Cloud Run
gcloud run deploy --source .
12. Entender os detalhes da IA generativa
Nenhuma ação é necessária. Para sua informação:
Agora que você tem o aplicativo para implantar, entenda como realizamos a pesquisa (texto e imagem) e a geração.
- Pesquisa vetorial baseada no texto do usuário:
Isso já foi abordado nas funções do Cloud Run que implantamos na seção "Testar o aplicativo da Web da Pesquisa de vetor".
- Pesquisa de vetor baseada no upload de imagens:
Em vez de digitar o contexto como texto, digamos que o usuário queira fazer o upload de uma foto de um brinquedo conhecido para pesquisar. Os usuários podem fazer upload de uma imagem de um brinquedo que eles gostam e receber recursos relevantes com isso.
Usamos o modelo Flash Gemini 2.0 do Google, invocado usando o LangChain4j, para analisar a imagem e extrair o contexto relevante, como a cor, o material, o tipo e o grupo etário pretendido do brinquedo.
Em apenas cinco etapas, usamos um framework de código aberto para levar a entrada de dados multimodais do usuário a resultados correspondentes com invocação de modelo de linguagem grande. Saiba como:
package cloudcode.helloworld.web;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.googleai.GoogleAiGeminiChatModel;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.model.output.Response;
import dev.langchain4j.data.message.ImageContent;
import dev.langchain4j.data.message.TextContent;
import java.util.Base64;
import java.util.Optional;
public class GeminiCall {
public String imageToBase64String(byte[] imageBytes) {
String base64Img = Base64.getEncoder().encodeToString(imageBytes);
return base64Img;
}
public String callGemini(String base64ImgWithPrefix) throws Exception {
String searchText = "";
// 1. Remove the prefix
String base64Img = base64ImgWithPrefix.replace("data:image/jpeg;base64,", "");
// 2. Decode base64 to bytes
byte[] imageBytes = Base64.getDecoder().decode(base64Img);
String image = imageToBase64String(imageBytes);
// 3. Get API key from environment variable
String apiKey = Optional.ofNullable(System.getenv("GOOGLE_API_KEY"))
.orElseThrow(() -> new IllegalArgumentException("GOOGLE_API_KEY environment variable not set"));
// 4. Invoke Gemini 2.0
ChatLanguageModel gemini = GoogleAiGeminiChatModel.builder()
.apiKey(apiKey)
.modelName("gemini-2.0-flash-001")
.build();
Response<AiMessage> response = gemini.generate(
UserMessage.from(
ImageContent.from(image, "image/jpeg"),
TextContent.from(
"The picture has a toy in it. Describe the toy in the image in one line. Do not add any prefix or title to your description. Just describe that toy that you see in the image in one line, do not describe the surroundings and other objects around the toy in the image. If you do not see any toy in the image, send response stating that no toy is found in the input image.")));
// 5. Get the text from the response and send it back to the controller
searchText = response.content().text().trim();
System.out.println("searchText inside Geminicall: " + searchText);
return searchText;
}
}
- Entenda como usamos a Imagen 3 para criar um brinquedo personalizado com base na solicitação do usuário usando a IA generativa.
A imagem 3 gera uma imagem do brinquedo personalizado, mostrando ao usuário uma visualização clara da criação. Veja como fizemos isso em apenas cinco etapas:
// Generate an image using a text prompt using an Imagen model
public String generateImage(String projectId, String location, String prompt)
throws ApiException, IOException {
final String endpoint = String.format("%s-aiplatform.googleapis.com:443", location);
PredictionServiceSettings predictionServiceSettings =
PredictionServiceSettings.newBuilder().setEndpoint(endpoint).build();
// 1. Set up the context and prompt
String context = "Generate a photo-realistic image of a toy described in the following input text from the user. Make sure you adhere to all the little details and requirements mentioned in the prompt. Ensure that the user is only describing a toy. If it is anything unrelated to a toy, politely decline the request stating that the request is inappropriate for the current context. ";
prompt = context + prompt;
// 2. Initialize a client that will be used to send requests. This client only needs to be created
// once, and can be reused for multiple requests.
try (PredictionServiceClient predictionServiceClient =
PredictionServiceClient.create(predictionServiceSettings)) {
// 3. Invoke Imagen 3
final EndpointName endpointName =
EndpointName.ofProjectLocationPublisherModelName(
projectId, location, "google", "imagen-3.0-generate-001"); //"imagegeneration@006"; imagen-3.0-generate-001
Map<String, Object> instancesMap = new HashMap<>();
instancesMap.put("prompt", prompt);
Value instances = mapToValue(instancesMap);
Map<String, Object> paramsMap = new HashMap<>();
paramsMap.put("sampleCount", 1);
paramsMap.put("aspectRatio", "1:1");
paramsMap.put("safetyFilterLevel", "block_few");
paramsMap.put("personGeneration", "allow_adult");
paramsMap.put("guidanceScale", 21);
paramsMap.put("imagenControlScale", 0.95); //Setting imagenControlScale
Value parameters = mapToValue(paramsMap);
// 4. Get prediction response image
PredictResponse predictResponse =
predictionServiceClient.predict(
endpointName, Collections.singletonList(instances), parameters);
// 5. Return the Base64 Encoded String to the controller
for (Value prediction : predictResponse.getPredictionsList()) {
Map<String, Value> fieldsMap = prediction.getStructValue().getFieldsMap();
if (fieldsMap.containsKey("bytesBase64Encoded")) {
bytesBase64EncodedOuput = fieldsMap.get("bytesBase64Encoded").getStringValue();
}
}
return bytesBase64EncodedOuput.toString();
}
}
Previsão de preços
Na seção anterior, discutimos como o Imagen está gerando a imagem de um brinquedo que o usuário quer projetar por conta própria. Para que eles possam comprar, o aplicativo precisa definir um preço. Usamos uma lógica intuitiva para definir um preço para o brinquedo personalizado. A lógica é usar o preço médio dos cinco brinquedos mais próximos (em termos de descrição) do brinquedo que o usuário projeta.
A previsão de preço do brinquedo gerado é uma parte importante deste aplicativo, e usamos uma abordagem ativa para gerar isso. Conheça a Gen AI Toolbox para bancos de dados.
13. Gen AI Toolbox para bancos de dados
O Gen AI Toolbox for Databases é um servidor de código aberto do Google que facilita a criação de ferramentas de IA generativa para interagir com bancos de dados. Ele permite que você desenvolva ferramentas de maneira mais fácil, rápida e segura, lidando com complexidades como agrupamento de conexões, autenticação e muito mais. Ele ajuda a criar ferramentas de IA generativa que permitem que seus agentes acessem dados no seu banco de dados.
Estas são as etapas que você precisa seguir para configurar a ferramenta e tornar nosso aplicativo mais eficiente: Link para o codelab da caixa de ferramentas
Agora, seu aplicativo pode usar esse endpoint implantado da função do Cloud Run para preencher o preço e o resultado da imagem gerada para a imagem de brinquedo personalizada.
14. Testar seu aplicativo da Web
Agora que todos os componentes do aplicativo foram criados e implantados, ele está pronto para ser veiculado na nuvem. Teste o aplicativo em todos os cenários. Confira um link de vídeo com o que você pode esperar:
https://www.youtube.com/shorts/ZMqUAWsghYQ
A página de destino vai ficar assim:
15. Limpar
Para evitar cobranças na sua conta do Google Cloud pelos recursos usados nesta postagem, siga estas etapas:
- No console do Google Cloud, acesse a página Gerenciar recursos.
- Na lista de projetos, selecione o projeto que você quer excluir e clique em Excluir.
- Na caixa de diálogo, digite o ID do projeto e clique em Encerrar para excluí-lo.
16. Parabéns
Parabéns! Você realizou uma pesquisa e geração contextual da Toystore usando o AlloyDB, o pgvector, o Imagen e o Gemini 2.0, aproveitando bibliotecas de código aberto para criar integrações robustas. Ao combinar os recursos do AlloyDB, da Vertex AI e da pesquisa vetorial, demos um grande salto em direção a pesquisas contextuais e vetoriais acessíveis, eficientes e realmente orientadas a significados.