1. Introdução
Você gosta de ler livros, mas tem dificuldade em escolher um entre tantas opções? Imagine ter um app com tecnologia de IA que recomenda a leitura perfeita e oferece um resumo conciso com base no gênero escolhido, apresentando um pouco da essência do livro. Neste codelab, vou mostrar como criar um app assim usando o BigQuery e o Cloud Functions com tecnologia do Gemini.
Visão geral do projeto
Nosso caso de uso foca estes quatro componentes principais:
- Banco de dados de livros: o vasto conjunto de dados públicos de livros arquivados da Internet no BigQuery vai servir como nosso catálogo abrangente.
- Mecanismo de resumo de IA: o Cloud Functions do Google Cloud, equipado com o modelo de linguagem Gemini Pro, vai gerar resumos práticos de acordo com os pedidos dos usuários.
- Integração com o BigQuery: uma função remota dentro do BigQuery que chama nossa função do Cloud para entregar resumos e temas de livros sob demanda.
- Interface do usuário: um app da Web hospedado no Cloud Run vai oferecer um aplicativo da Web para que os usuários vejam os resultados.
Vamos dividir a implementação em três codelabs:
Codelab 1: use o Gemini para criar uma função do Cloud em Java para um aplicativo do Gemini.
Codelab 2: use o Gemini para criar aplicativos de IA generativa somente de SQL com o BigQuery.
Codelab 3: use o Gemini para criar um aplicativo da Web em Java do Spring Boot que interage com o BigQuery.
2. Usar o Gemini para criar um aplicativo de IA generativa sem servidor em uma função do Cloud em Java
O que você vai criar
Você vai criar um
- Aplicativo Java do Cloud Functions que implementa o Gemini 1.0 Pro para receber um comando específico como entrada na forma de uma matriz JSON e retornar uma resposta (valor JSON rotulado como "replies").
- Você vai fazer as etapas de build e implantação com a ajuda do Gemini.
3. Requisitos
- Use um navegador, como o Chrome ou o Firefox.
- Tenha um projeto do Google Cloud com o faturamento ativado.
Confira os pré-requisitos abaixo:
Criar seu projeto
- No console do Google Cloud, na página de seletor de projetos, selecione ou crie um projeto do Google Cloud.
- Confira se o faturamento está ativado para seu projeto do Cloud. Saiba como verificar se o faturamento está ativado em um projeto.
Ativar o Cloud Shell
- Você vai usar o Cloud Shell, um ambiente de linha de comando executado no Google Cloud que vem pré-carregado com bq:
No console do Cloud, clique em "Ativar o Cloud Shell" no canto superior direito: 
- Depois de se conectar ao Cloud Shell, você vai ver que sua conta já está autenticada e que o projeto está configurado com seu ID do projeto. Execute o seguinte comando no Cloud Shell para confirmar se a conta está autenticada:
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>
Consulte a documentação para ver o uso e os comandos gcloud.
4. Ativar o Gemini para Google Cloud e as APIs necessárias
Ativar o Gemini
- Acesse Gemini para Google Cloud no Marketplace para ativar a API. Também é possível usar o seguinte comando:
gcloud services enable cloudaicompanion.googleapis.com --project PROJECT_ID
- Acesse a página do Gemini e clique em "Iniciar conversa".
Importante: siga as etapas 1 e 2 deste codelab para começar a usar o Gemini e ativar o Gemini no Cloud Shell IDE, respectivamente.
Ativar outras APIs necessárias
Como podemos fazer isso? Vamos perguntar para o Gemini. Mas, antes disso, não se esqueça:
Os LLMs não são deterministas. Ao testar esses comandos, a resposta gerada pode ser diferente da que aparece na captura de tela.
Para acessar o console de conversa no Gemini, clique no ícone "Abrir Gemini" no canto superior direito, ao lado da barra de pesquisa no console do Google Cloud.

Digite esta pergunta na seção "Insira um comando aqui":
How do I enable the cloud functions api using a gcloud command?
Você receberá uma resposta semelhante a:
gcloud services enable cloudfunctions.googleapis.com
Copie (use o ícone de cópia na parte de cima do trecho de comando) e execute isso no terminal do Cloud Shell para ativar o Cloud Functions. Faça o mesmo para o Cloud Run, já que precisamos dos dois para criar e implantar o Cloud Functions:
gcloud services enable \
cloudfunctions.googleapis.com \
aiplatform.googleapis.com \
run.googleapis.com \
cloudbuild.googleapis.com
5. Como preparar um modelo do Cloud Functions com o Gemini
Neste ponto, presumo que você já tenha o Gemini ativado no Cloud Shell IDE.
Para abrir o editor do Cloud Shell, clique no ícone "Abrir editor" no canto superior direito do terminal do Cloud Shell. Geralmente, prefiro abrir o terminal e o editor em duas guias paralelas para escrever o código em uma e desenvolver em outra.

Depois de abrir o editor, confira se o logotipo do Gemini no canto inferior direito do console do editor está ativo (e não cancelado). Verifique também se o projeto do Google Cloud no canto inferior esquerdo aponta para o projeto ativo em que você quer trabalhar. Se estiverem inativos, clique neles, autorize, selecione o projeto do Google Cloud que você quer apontar e faça a ativação.
Quando ambos estiverem ativos, clique no nome do projeto no canto inferior esquerdo. Na lista pop-up chamada "Cloud Code", role para baixo até "Novo aplicativo".

Em seguida, selecione o aplicativo do Cloud Functions. Na lista exibida, selecione Java:

Na lista resultante, digite o nome do projeto "duetai-gemini-calling" em vez de "helloworld" e clique em OK.

Oba! Você inicializou um aplicativo simples do Cloud Functions em Java com o Gemini e não fez muito mais do que ativar e definir configurações, concorda?
Esta deve ser a estrutura do projeto:

Agora você já pode implantar a função. Mas não foi por isso que começamos. Vamos criar a implementação da API Gemini Pro nesta função do Cloud usando o SDK do Java.
Agora vamos criar a funcionalidade para nosso caso de uso, que é invocar o modelo Gemini Pro nessa função do Cloud. Para isso, você pode adicionar mais comandos e desenvolver seu código incrementalmente com o Gemini ou escrever a lógica por conta própria. Vou combinar as duas opções.
6. Adicione dependências
Na conversa no Gemini (aquela no Editor do Cloud Code, no painel esquerdo), digite o seguinte comando:
what is the maven dependency for com.google.cloud.vertexai library
Estou pedindo especificamente o pacote com.google.cloud.vertexai porque é o que estou usando no meu código-fonte, onde implemento o código de invocação do Gemini.
Recebi este resultado:

<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-vertexai</artifactId>
<version>0.1.0</version>
</dependency>
Copie e cole no arquivo pom.xml, logo antes da tag </dependencies>. Substitua a versão por 0.1.0. É possível remover a tag <version> se você estiver usando a BOM do Spring Cloud GCP para gerenciar os números de versão do spring-cloud-gcp.
A seção de dependências vai ficar assim:

Atualize os números de versão, se necessário, para corresponder ao exemplo acima. Se você notar, também incluí outra dependência:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10</version>
</dependency>
7. Modificar o ponto de entrada da função e o nome da classe
- Acesse o arquivo "launch.json" na pasta ".vscode". Edite o nome da função de "function-hello-world" para "function-gemini-calling".
- Atualize o valor de "entryPoint" de "cloudcode.helloworld.HelloWorld" para "cloudcode.bookshelf.Bookshelf".
- Agora navegue até o arquivo de classe Java "HelloWorld.java". Mude o nome do pacote para package cloudcode.bookshelf. No erro que aparece, clique na lâmpada amarela e na opção "Move HelloWorld.java" para package cloudcode.bookshelf.

- Atualize o nome da classe para Bookshelf e, no erro que aparecer, clique na pequena lâmpada amarela e selecione "Renomear arquivo para Bookshelf.java". Selecione essa opção.
8. Criar o método que chama o Gemini Pro
Vamos implementar essa funcionalidade na classe Bookshelf.java. Substitua o Bookshelf.java pelo código abaixo:
package cloudcode.bookshelf;
import java.io.BufferedWriter;
import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import com.google.cloud.vertexai.VertexAI;
import com.google.cloud.vertexai.api.GenerateContentResponse;
import com.google.cloud.vertexai.api.GenerationConfig;
import com.google.cloud.vertexai.generativeai.preview.GenerativeModel;
import com.google.cloud.vertexai.generativeai.preview.ResponseHandler;
import java.io.IOException;
import java.util.List;
import java.util.Arrays;
import java.util.Map;
import java.util.LinkedHashMap;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonArray;
public class Bookshelf implements HttpFunction {
private static final Gson gson = new Gson();
@Override
public void service(HttpRequest request, HttpResponse response) throws Exception {
BufferedWriter writer = response.getWriter();
// Get the request body as a JSON object.
JsonObject requestJson = new Gson().fromJson(request.getReader(), JsonObject.class);
JsonArray calls_array = requestJson.getAsJsonArray("calls");
JsonArray calls = (JsonArray) calls_array.get(0);
String context = calls.get(0).toString().replace("\"", "");
//Invoke Gemini model
String raw_result = callGemini(context);
raw_result = raw_result.replace("\n","");
String trimmed = raw_result.trim();
List<String> result_list = Arrays.asList(trimmed);
Map<String, List<String>> stringMap = new LinkedHashMap<>();
stringMap.put("replies", result_list);
// Serialization
String return_value = gson.toJson(stringMap);
writer.write(return_value);
}
public String callGemini(String context) throws IOException{
String res = "";
try (VertexAI vertexAi = new VertexAI("REPLACE_WITH_YOUR_PROJECT_ID", "us-central1"); ) {
GenerationConfig generationConfig =
GenerationConfig.newBuilder()
.setMaxOutputTokens(2048)
.setTemperature(0.4F)
.setTopK(32)
.setTopP(1)
.build();
GenerativeModel model = new GenerativeModel("gemini-pro", generationConfig, vertexAi);
GenerateContentResponse response = model.generateContent(context);
res = ResponseHandler.getText(response);
}catch(Exception e){
System.out.println(e);
}
return res;
}
}
Essa classe espera entrada na estrutura JSON, como abaixo:
{ "calls": [["YOUR_PROMPT_HERE"]] }
Ele retorna uma resposta como esta:
(Json) Map<String, List<String>> {"replies": ["response"]}
Teste a opção de conversa no Gemini no painel esquerdo do editor do Cloud Shell para explicar o código. Outra opção é selecionar todo o código, clicar na lâmpada amarela no canto superior esquerdo da seleção e escolher a opção "Explicar isso".

9. Implante a Função do Cloud
Agora que a função do Cloud está pronta, vamos perguntar ao Gemini como implantá-la. Acesse a conversa no Gemini no editor de código do Cloud Code e insira o seguinte:
How to deploy this Cloud Function with a gcloud command?
Recebi a seguinte resposta:

Agora eu queria investigar mais a fundo. Então, pedi para o Gemini me dar o comando completo de implantação das funções do gcloud. A resposta é mostrada abaixo:

Não posso dizer se você vai receber a mesma resposta, mas achei interessante ver que ela complementa com mais alguns detalhes, como mostrado na imagem abaixo:
Formato do corpo da solicitação:

e
Formato da resposta:

Agora, vamos implantar a função executando o comando gcloud que o Gemini nos forneceu. Para isso, abra o terminal do Cloud Shell. Abra em uma nova guia https://console.cloud.google.com e confira se o projeto certo está selecionado. Abra o terminal do Cloud Shell clicando no ícone "Ativar o Cloud Shell" no canto superior direito do console e verifique se você está na pasta do projeto certa usando o comando abaixo:
cd duetai-gemini-calling
Seguido pelo comando abaixo:
gcloud functions deploy bookshelf --runtime java17 --trigger-http --entry-point cloudcode.bookshelf.Bookshelf --allow-unauthenticated
Ele vai perguntar: "Permitir invocações não autenticadas da nova função [bookshelf]?" Diga "y" e pressione Enter. Depois disso, algumas perguntas, se aplicável, e ele vai implantar sua função do Cloud sem servidor com o URL implantado: https://us-central1-*******.cloudfunctions.net/bookshelf.
Agora vamos invocar as funções do Cloud implantadas e testar!
Observação: se você pulou acidentalmente a pergunta "Permitir invocações não autenticadas" ou selecionou "N", não será possível acessar o resultado das funções do Cloud e vai aparecer um "erro de permissões" sem conceder outras configurações do IAM. Preste atenção nisso.
10. Chamar a função do Cloud implantada
Vamos perguntar para o Gemini. Inseri o comando
How to call the deployed cloud function?
Recebi o resultado abaixo: (você pode ou não receber a mesma resposta. Não hesite em testar o comando e ver a diferença nas respostas).

Faça perguntas específicas sobre outras maneiras de invocar a função implantada, chame usando o comando gcloud etc. Enviei o seguinte comando:
how to call the deployed cloud function using gcloud
Recebi a seguinte resposta: 
Você pode usar essa resposta (comando "gcloud functions call") do terminal com ajustes para que ela funcione no nosso cenário. Como alternativa, tente transmitir os parâmetros no próprio comando e veja se é possível receber a chamada detalhada das funções do gcloud em resposta:
gcloud functions call bookshelf --region=us-central1 --gen2 --data '{"calls":[["Hello! This is my test prompt."]]}'
Este é meu resultado:

11. Limpar
Para excluir as funções do Cloud que você criou antes, clique no botão "EXCLUIR" na página de detalhes do Cloud Functions.
12. Parabéns
Você criou, implantou e testou uma função do Cloud em Java para chamar o Gemini 1.0 Pro usando o Gemini. Esse aplicativo usa o comando de entrada relacionado à recomendação de livros com o resumo e o tema dos livros.