1. Visão geral
Imagine entrar em uma loja de brinquedos virtualmente ou presencialmente, onde encontrar o presente perfeito é fácil. Você pode descrever o que está procurando, fazer upload de uma foto 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, mas sim 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 geralmente não são suficientes. Navegar por páginas sem fim pode ser cansativo, 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 verdadeiramente personalizada e perfeita com pesquisa contextual e geração personalizada do produto que corresponde ao contexto da pesquisa.
O que você vai criar
Neste laboratório, você vai:
- Criar uma instância do AlloyDB e carregar o conjunto de dados de brinquedos
- Ativar as extensões pgvector e de modelo de IA generativa no AlloyDB
- Gerar embeddings com base na descrição do produto e realizar uma 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 uma pesquisa contextual de brinquedos
- Invocar o Imagen 3 para criar um brinquedo personalizado com base no interesse do usuário
- Invocar uma ferramenta de previsão de preços criada com a caixa de ferramentas de IA generativa para bancos de dados para ver detalhes de preços do brinquedo personalizado
- Implantar a solução no Cloud Run Functions sem servidor
Requisitos
2. Arquitetura
Fluxo de dados: vamos analisar mais de perto como os dados se movem pelo nosso sistema:
- Pesquisa contextual com RAG (geração aumentada de recuperação) com tecnologia de IA
Pense assim: em vez de apenas procurar "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 nossos 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 por trás das palavras, não apenas as palavras-chave exatas.
Similaridade de cossenos para relevância:usamos a similaridade de cossenos para medir a semelhança 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, principalmente à medida que nosso inventário de brinquedos cresce, integramos o índice ScaNN (vizinhos mais próximos escalonáveis). Isso melhora significativamente a eficiência e o recall da nossa pesquisa de vetor.
- Pesquisa e compreensão baseadas em imagens com o Gemini 2.0 Flash
Em vez de digitar o contexto como texto, digamos que o usuário queira fazer upload de uma foto de um brinquedo conhecido para pesquisar. Os usuários podem fazer upload de uma imagem de um brinquedo que gostam e receber recursos relevantes. Usamos o modelo Gemini 2.0 Flash do Google, invocado com o LangChain4j, para analisar a imagem e extrair o contexto relevante, como cor, material, tipo e faixa etária recomendada do brinquedo.
- Como criar o brinquedo dos seus sonhos com a IA generativa: Imagen 3
A mágica acontece quando os usuários decidem criar o próprio brinquedo. Com o Imagen 3, eles podem descrever 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! Em seguida, o Imagen 3 gera uma imagem do brinquedo personalizado, proporcionando ao usuário uma visualização clara de sua criação.
- Previsão de preços com tecnologia de agentes e caixa de ferramentas de IA generativa para bancos de dados
Implementamos um recurso de previsão de preços 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.
Caixa de ferramentas de IA generativa para bancos de dados:esse agente é integrado ao nosso banco de dados usando a nova ferramenta de código aberto do Google, a caixa de ferramentas de IA generativa 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
Todo o aplicativo é criado usando o Java Spring Boot, um framework robusto e escalonável. Usamos o Gemini Code Assist em todo o processo de desenvolvimento, principalmente para o desenvolvimento de 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 sua conta já está autenticada e se o projeto está configurado com o ID do seu projeto 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>
- Execute os comandos a seguir um por um no terminal do Cloud Shell para ativar as APIs necessárias:
Há também um único comando para executar o que está abaixo, mas se você for um usuário de conta de teste, poderá ter problemas de cota ao tentar ativar esses recursos 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 é usar o console. Para isso, pesquise cada produto ou use este link.
Se alguma API for esquecida, você sempre 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 até a 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 CRIAR CLUSTER nessa página:

- Você vai ver uma tela como a abaixo. Crie um cluster e uma instância com os seguintes valores. Verifique se os valores correspondem caso você esteja clonando o código do aplicativo do repositório:
- ID do cluster: "
vector-cluster" - password: "
alloydb" - Compatível com PostgreSQL 15
- Região: "
us-central1" - Rede: "
default"

- Ao selecionar a rede padrão, uma tela como a abaixo vai aparecer.
Selecione CONFIGURAR CONEXÃO.
- Em seguida, selecione Usar um intervalo de IP alocado automaticamente e clique em "Continuar". Depois de revisar as informações, selecione CRIAR CONEXÃO.

- Depois que a rede for configurada, você poderá continuar criando o cluster. Clique em CRIAR CLUSTER para concluir a configuração do cluster, conforme mostrado abaixo:

Mude o ID da instância para
vector-instance
Se não for possível mudar, altere o ID da instância em todas as referências futuras.
A criação do cluster leva cerca de 10 minutos. Se tudo der certo, uma tela vai mostrar a 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 criadas ao criar o cluster. Use os seguintes dados para autenticar no PostgreSQL:
- Nome de usuário : "
postgres" - Banco de dados : "
postgres" - Senha : "
alloydb"
Depois de se autenticar no AlloyDB Studio, os comandos SQL são inseridos no editor. É possível adicionar várias janelas do Editor usando o sinal de mais à 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 esse app, vamos usar as extensões pgvector e google_ml_integration. A extensão pgvector permite armazenar e pesquisar embeddings de vetores. A extensão google_ml_integration oferece funções que você usa para acessar endpoints de previsão da Vertex AI e receber previsões em SQL. Ative essas extensões executando os seguintes DDLs:
CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector;
Para verificar as extensões 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á ver 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 apenas as cinco primeiras linhas/instruções de inserção e cole em uma guia em branco do editor. Depois, selecione EXECUTAR. Se você NÃO estiver em uma conta de faturamento de teste, provavelmente poderá copiar todas as instruções de inserção e executar.
Para ver o conteúdo da tabela, expanda a seção "Explorer" até encontrar a tabela chamada "apparels". Selecione o tricôlon (⋮) 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 execute o comando a seguir:
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 processarem números do que texto. Um sistema de embedding converte texto em uma série de números de ponto flutuante que representam o texto, não importa como ele seja formulado, qual idioma ele use etc.
Considere descrever um local à beira-mar. Pode ser chamado de "na água", "de frente para a praia", "caminhe do seu quarto até o oceano", "sur la mer", "на берегу океана" etc. Esses termos parecem diferentes, mas o significado semântico ou, na terminologia de aprendizado de máquina, as incorporações devem ser muito semelhantes.
Agora que os dados e o contexto estão prontos, vamos executar o SQL para adicionar os embeddings 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 o textembedding-gecko.
Volte para a guia do AlloyDB Studio e digite o seguinte DML:
UPDATE toys set text_embeddings = embedding( 'text-embedding-005', description);
Consulte a tabela toys novamente para ver alguns encodings. Execute a instrução SELECT novamente para conferir as mudanças.
SELECT id, name, description, price, quantity, image_url, text_embeddings FROM toys;
Isso vai retornar o vetor de incorporações, que parece uma matriz de números de ponto flutuante, para a descrição do brinquedo, conforme mostrado abaixo:

Observação:projetos do Google Cloud recém-criados no nível sem custo financeiro podem enfrentar 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, enquanto gera o embedding.
7. Fazer uma pesquisa vetorial
Agora que a tabela, os dados e os embeddings estão prontos, vamos realizar a pesquisa vetorial 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, 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 2;
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 deve parecer familiar depois da última, em que aplicamos a função de incorporação a todos os itens da tabela. - "
<=>" representa o uso do método de distância SIMILARIDADE DE COSSENO. Confira todas as medidas de similaridade disponíveis na documentação do pgvector. - Estamos convertendo o resultado do método de embedding para o tipo de vetor para torná-lo compatível com os vetores armazenados no banco de dados.
- "LIMIT 5" representa que queremos extrair os cinco vizinhos mais próximos do texto de pesquisa.
O resultado será assim:

Como você pode observar nos resultados, as correspondências são bem próximas ao texto da pesquisa. Tente mudar o texto para ver como os resultados mudam.
Observação importante:
Agora, digamos que queremos aumentar o desempenho (tempo de consulta), a eficiência e o recall desse resultado da 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 o recall com o índice ScaNN
Ignore esta etapa se a contagem de registros for menor que 100.
Listamos as etapas de criação do índice aqui para facilitar:
- Como já temos o cluster, a instância, o contexto e os embeddings criados, 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 indexação
"embedding" é a coluna na tabela que quero indexar
"cosine" é 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. Definido como qualquer valor entre 1 e 1.048.576. Para mais informações sobre como decidir esse valor, consulte Ajustar um índice do ScaNN.
Usei uma RAIZ QUADRADA do número de pontos de dados, conforme recomendado no repositório do ScaNN. Ao particionar, 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;
- Faça uma 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, então 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 da Vector Search nos dados de embeddings INDEXADOS resulta em qualidade e eficiência. A eficiência é muito maior (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 respostas em potencial 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 seu cluster e instância. No AlloyDB Studio, execute o seguinte comando:
show google_ml_integration.enable_model_support;
Se o valor for "ativado", pule as próximas duas etapas e vá direto para a configuração da integração do modelo do AlloyDB e da Vertex AI.
- Acesse a instância principal do cluster do AlloyDB e clique em EDITAR INSTÂNCIA PRINCIPAL.

- Navegue até a seção "Flags" em "Opções de configuração avançadas". e verifique se o
google_ml_integration.enable_model_support flagestá definido como "on", conforme mostrado abaixo:

Se não estiver, defina como "on" e clique no botão ATUALIZAR INSTÂNCIA. Essa etapa leva alguns minutos.
Integração do AlloyDB e da Vertex AI Model
Agora você pode se conectar ao AlloyDB Studio e executar a seguinte instrução DML para configurar o acesso ao modelo do Gemini no AlloyDB, usando o ID do projeto onde indicado. Talvez você receba um aviso de erro de sintaxe antes de executar o comando, mas ele deve funcionar normalmente.
Primeiro, criamos a conexão do modelo do Gemini 1.5, como 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');
Para verificar os modelos configurados para acesso, use 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 executar previsões usando os modelos da Vertex AI do Google. 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 descartar as referências antigas ao modelo gemini-1.5 e criar novamente com a instrução CALL acima. Além disso, execute "grant execute on function ml_predict_row" novamente caso tenha problemas nas próximas invocações do gemini-1.5.
Como avaliar as respostas
Embora usemos 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 partes 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 que explica como avaliá-las. 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. - Com isso, vamos analisar a "qualidade" das respostas retornadas.
- O
predict_rowretorna o resultado no formato JSON. O código "-> 'candidates' -> 0 -> 'content' -> 'parts' -> 0 -> 'text'"" é usado para extrair o texto real desse JSON. Para ver o JSON real retornado, remova esse código. - Por fim, para receber a resposta do LLM, extraímos ela usando
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 1) 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 ainda possa parecer complicado, esperamos que agora faça um pouco mais de sentido. Os resultados informam se há 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. Levar a pesquisa de brinquedos para o Cloud sem servidor
Tudo pronto para levar esse app para a Web? Siga as etapas abaixo para tornar o Knowledge Engine 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 a região "us-central1". Defina a autenticação como "Permitir invocações não autenticadas" e clique em PRÓXIMA. Escolha Java 17 como ambiente de execução e Editor in-line para o código-fonte.
- Por padrão, ele define o ponto de entrada como "
gcfv2.HelloHttpFunction". Substitua o código de marcador de posição emHelloHttpFunction.javaepom.xmlda sua função do Cloud Run pelo código de HelloHttpFunction.java e pom.xml, respectivamente. - Não se esqueça 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 mesmas que usamos no início deste codelab. Se você usou valores diferentes, modifique-os no arquivo Java.
- Clique em Implantar.
Depois da implantação, para permitir que a função do Cloud acesse a instância de banco de dados do AlloyDB, vamos criar o conector de VPC.
ETAPA IMPORTANTE:
Depois de configurar 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. Depois, mude o seguinte:
- Acesse "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:

- Forneça um nome para o 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 MOSTRAR CONFIGURAÇÕES DE ESCALONAMENTO e verifique se a configuração está exatamente assim:

- Clique em "CRIAR". O conector vai aparecer nas configurações de saída.
- Selecione o conector recém-criado.
- Opte por todo o tráfego ser roteado por esse conector de 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 gerado vai aparecer. Copie e substitua no comando a seguir:
Se preferir, teste a função do Cloud Run da seguinte maneira:
PROJECT_ID=$(gcloud config get-value project)
curl -X POST <<YOUR_ENDPOINT>> \
-H 'Content-Type: application/json' \
-d '{"search":"I want a standing pink panther toy"}' \
| jq .
Resultado:

Pronto! É muito simples realizar uma pesquisa vetorial 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 o usuário interagir e encontrar brinquedos correspondentes com base em texto, imagem e até mesmo criar um novo brinquedo com base nas necessidades dele. Como o aplicativo já está criado, siga as etapas abaixo para copiá-lo para sua IDE e colocar o app em funcionamento.
- Como usamos o Gemini 2.0 Flash para descrever a imagem que o usuário pode enviar para encontrar brinquedos correspondentes, precisamos receber a chave de API para esse aplicativo. Para isso, acesse https://aistudio.google.com/apikey e receba a chave de API do seu projeto ativo do Google Cloud em que você está implementando esse aplicativo. 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.
- Exclua as pastas "get-toys-alloydb" e "toolbox-toys" do projeto clonado, porque elas contêm o código das funções do Cloud Run, que pode ser referenciado no repositório quando necessário.
- Acesse GenerateToy.java na pasta "web", encontre a linha a seguir e remova porque a permissão para conteúdo adulto pode exigir uma autorização especial que não está disponível para algumas contas de faturamento de teste:
paramsMap.put("personGeneration", "allow_adult");
- Verifique se todas as variáveis de ambiente necessárias estão definidas antes de criar e implantar o app. Navegue até o terminal do Cloud Shell 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:
Verifique se você está no diretório do projeto e 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 compreensão:
Agora que você tem o aplicativo para implantação, reserve um momento para entender como realizamos a pesquisa (texto e imagem) e a geração.
- Pesquisa vetorial baseada em texto do usuário:
Isso já foi abordado nas funções do Cloud Run que implantamos na seção "Levar o app de pesquisa de vetor para a Web".
- Pesquisa vetorial baseada em upload de imagens:
Em vez de digitar o contexto como texto, digamos que o usuário queira fazer upload de uma foto de um brinquedo conhecido para pesquisar. Os usuários podem fazer upload de uma imagem de um brinquedo que gostam e receber recursos relevantes.
Usamos o modelo Gemini 2.0 Flash do Google, invocado com o LangChain4j, para analisar a imagem e extrair o contexto relevante, como cor, material, tipo e faixa etária recomendada do brinquedo.
Em apenas cinco etapas, transformamos a entrada de dados multimodais do usuário em resultados correspondentes com a invocação de um modelo de linguagem grande usando um framework de código aberto. 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 o Imagen 3 para criar um brinquedo personalizado com base na solicitação do usuário com a IA generativa.
Em seguida, o Imagen 3 gera uma imagem do brinquedo personalizado, proporcionando ao usuário uma visualização clara de sua 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 gera a imagem de um brinquedo que o usuário quer criar por conta própria. Para que eles possam comprar, o aplicativo precisa definir um preço, e usamos uma lógica intuitiva para definir um preço para o brinquedo personalizado feito sob encomenda. A lógica é usar o preço médio dos cinco brinquedos mais parecidos (em termos de descrição) com o que o usuário cria.
A previsão de preço do brinquedo gerado é uma parte importante desse aplicativo, e usamos uma abordagem de agente para gerá-la. Apresentamos a Toolbox de IA generativa para bancos de dados.
13. Toolbox de IA generativa para bancos de dados
A caixa de ferramentas de IA generativa para bancos de dados é 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 desenvolver ferramentas com mais facilidade, rapidez e segurança, lidando com complexidades como pool de conexões, autenticação e muito mais. Ele ajuda você a criar ferramentas de IA generativa que permitem que seus agentes acessem dados no seu banco de dados.
Siga estas etapas para preparar a ferramenta e tornar nosso aplicativo independente: Link para o codelab da caixa de ferramentas
Agora, seu aplicativo pode usar esse endpoint da função do Cloud Run implantada para preencher o preço junto com o resultado gerado da Imagen para a imagem personalizada do brinquedo feito sob encomenda.
14. Testar o aplicativo da Web
Agora que todos os componentes do aplicativo foram criados e implantados, ele está pronto para ser veiculado na nuvem. Teste seu aplicativo em todos os cenários. Confira um link de vídeo sobre o que esperar:
https://www.youtube.com/shorts/ZMqUAWsghYQ
Esta é a aparência da página de destino:

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 de vetor, demos um grande passo para tornar as pesquisas contextuais e de vetor acessíveis, eficientes e realmente orientadas por significado.