Sobre este codelab
1. Visão geral
Em diferentes setores, a pesquisa contextual é uma funcionalidade essencial que forma o centro dos aplicativos. A Geração Aumentada de Recuperação tem sido um fator-chave para essa evolução tecnológica crucial há algum tempo, com mecanismos de recuperação baseados em IA generativa. Os modelos generativos, com janelas de contexto grandes e qualidade de saída impressionante, estão transformando a IA. A RAG oferece uma maneira sistemática de injetar contexto em aplicativos e agentes de IA, fundamentando-os em bancos de dados estruturados ou informações de várias mídias. Esses dados contextuais são cruciais para a clareza da verdade e a precisão da saída, mas qual é a precisão desses resultados? Sua empresa depende principalmente da precisão dessas correspondências contextuais e da relevância? Então este projeto vai te agradar!
Agora imagine se pudéssemos usar o poder dos modelos generativos e criar agentes interativos capazes de tomar decisões autônomas com base em informações críticas ao contexto e fundamentadas na verdade. É isso que vamos criar hoje. Vamos criar um app de agente de IA completo usando o Kit de desenvolvimento de agentes com RAG avançado no AlloyDB para um app de análise de patentes.
O agente de análise de patentes ajuda o usuário a encontrar patentes contextualmente relevantes para o texto de pesquisa e, quando solicitado, fornece uma explicação clara e concisa e detalhes adicionais, se necessário, para uma patente selecionada. Quer saber como fazer isso? Vamos lá.
Objetivo
O objetivo é simples. Permitir que um usuário pesquise patentes com base em uma descrição textual e receba uma explicação detalhada de uma patente específica nos resultados da pesquisa. Tudo isso usando um agente de IA criado com o Java ADK, o AlloyDB, a pesquisa vetorial (com índices avançados), o Gemini e todo o aplicativo implantado sem servidor no Cloud Run.
O que você vai criar
Como parte deste laboratório, você vai:
- Criar uma instância do AlloyDB e carregar dados do conjunto de dados público de patentes
- Implementar a pesquisa vetorial avançada no AlloyDB usando os recursos de avaliação ScaNN e Recall
- Criar um agente usando o Java ADK
- Implementar a lógica do lado do servidor do banco de dados no Cloud Functions sem servidor em Java
- Implantar e testar o agente no Cloud Run
O diagrama a seguir representa o fluxo de dados e as etapas envolvidas na implementação.
High level diagram representing the flow of the Patent Search Agent with AlloyDB & ADK
Requisitos
2. 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. 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. Você pode usar um comando gcloud no terminal do Cloud Shell:
gcloud services enable alloydb.googleapis.com compute.googleapis.com cloudresourcemanager.googleapis.com servicenetworking.googleapis.com run.googleapis.com cloudbuild.googleapis.com cloudfunctions.googleapis.com aiplatform.googleapis.com
A alternativa ao comando gcloud é pelo console, pesquisando cada produto ou usando este link.
Consulte a documentação para ver o uso e os comandos gcloud.
3. Configuração do banco de dados
Neste laboratório, vamos usar o AlloyDB como o banco de dados dos dados de patente. 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 patentes 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
" - PostgreSQL 15 / a versão mais recente recomendada
- 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 (que pode ser encontrado no momento da configuração do cluster / instância) para
vector-instance
. Se não for possível fazer isso, lembre-se de usar o ID da instância em todas as próximas referências.
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.
4. 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 do 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
É possível criar uma tabela usando a instrução DDL abaixo no AlloyDB Studio:
CREATE TABLE patents_data ( id VARCHAR(25), type VARCHAR(25), number VARCHAR(20), country VARCHAR(2), date VARCHAR(20), abstract VARCHAR(300000), title VARCHAR(100000), kind VARCHAR(5), num_claims BIGINT, filename VARCHAR(100), withdrawn BIGINT, abstract_embeddings vector(768)) ;
A coluna abstract_embeddings permite o armazenamento dos valores do vetor do texto.
Conceder permissão
Execute a declaração abaixo para conceder execução na função "embedding":
GRANT EXECUTE ON FUNCTION embedding TO postgres;
Conceder o papel de usuário da Vertex AI à conta de serviço do AlloyDB
No console do IAM do Google Cloud, conceda à conta de serviço do AlloyDB (que tem este formato: service-<<PROJECT_NUMBER>>@gcp-sa-alloydb.iam.gserviceaccount.com) acesso à função "Usuário do Vertex AI". PROJECT_NUMBER terá o número do seu projeto.
Como alternativa, execute o comando abaixo no terminal do Cloud Shell:
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"
Carregar dados de patentes no banco de dados
Os conjuntos de dados públicos das patentes do Google no BigQuery serão usados como nosso conjunto de dados. Vamos usar o AlloyDB Studio para executar nossas consultas. Os dados são fornecidos neste arquivo insert_scripts.sql
e serão executados para carregar os dados da patente.
- No console do Google Cloud, abra a página AlloyDB.
- Selecione o cluster recém-criado e clique na instância.
- No menu de navegação do AlloyDB, clique em AlloyDB Studio. Faça login com suas credenciais.
- Abra uma nova guia clicando no ícone Nova guia à direita.
- Copie a instrução de consulta
insert
do scriptinsert_scripts.sql
mencionado acima para o editor. Você pode copiar de 10 a 50 instruções de inserção para uma demonstração rápida desse caso de uso. - Clique em Executar. Os resultados da consulta aparecem na tabela Resultados.
5. Criar embeddings para dados de patentes
Primeiro, vamos testar a função de incorporação executando o exemplo de consulta a seguir:
SELECT embedding('text-embedding-005', 'AlloyDB is a managed, cloud-hosted SQL database service.');
Isso deve retornar o vetor de embeddings, que se parece com uma matriz de números flutuantes, para o texto de exemplo na consulta. Fica assim:
Atualizar o campo de vetor abstract_embeddings
Execute a DML abaixo para atualizar os resumos das patentes na tabela com as incorporações correspondentes:
UPDATE patents_data set abstract_embeddings = embedding( 'text-embedding-005', abstract);
6. Realizar pesquisa vetorial
Agora que a tabela, os dados e as embeddings estão prontos, vamos realizar a pesquisa de vetor em tempo real para o texto de pesquisa do usuário. Para testar isso, execute a consulta abaixo:
SELECT id || ' - ' || title as title FROM patents_data ORDER BY abstract_embeddings <=> embedding('text-embedding-005', 'Sentiment Analysis')::vector LIMIT 10;
Nesta consulta,
- O texto pesquisado pelo usuário é: "Análise de sentimento".
- Estamos convertendo o texto em embeddings no método embedding() usando o modelo: text-embedding-005.
- "<=>" representa o uso do método de distância de SIMILARIDADE COSINE.
- 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 10 representa que estamos selecionando as 10 correspondências mais próximas do texto de pesquisa.
O AlloyDB leva a RAG de pesquisa vetorial a outro patamar:
Há um bom número de coisas introduzidas. Duas delas são:
- Filtragem inline
- Avaliador de recall
Filtragem inline
Anteriormente, como desenvolvedor, você precisava realizar a consulta de pesquisa de vetor e lidar com a filtragem e a recuperação. O otimizador de consulta do AlloyDB faz escolhas sobre como executar uma consulta com filtros. A filtragem inline é uma nova técnica de otimização de consulta que permite que o otimizador de consulta do AlloyDB avalie as condições de filtragem de metadados e a pesquisa de vetores ao mesmo tempo, aproveitando os índices de vetores e os índices nas colunas de metadados. Isso aumentou a performance de recuperação, permitindo que os desenvolvedores aproveitassem o que o AlloyDB tem a oferecer.
A filtragem inline é a melhor opção para casos com seletividade média. À medida que o AlloyDB pesquisa no índice vetorial, ele só calcula distâncias para vetores que correspondem às condições de filtragem de metadados (seus filtros funcionais em uma consulta geralmente são processados na cláusula WHERE). Isso melhora muito a performance dessas consultas, complementando as vantagens do filtro pós-filtro ou pré-filtro.
- Instalar ou atualizar a extensão pgvector
CREATE EXTENSION IF NOT EXISTS vector WITH VERSION '0.8.0.google-3';
Se a extensão pgvector já estiver instalada, atualize-a para a versão 0.8.0.google-3 ou mais recente para ter os recursos do avaliador de recuperação.
ALTER EXTENSION vector UPDATE TO '0.8.0.google-3';
Esta etapa só precisa ser executada se a extensão de vetor for <0.8.0.google-3.
Observação importante:se a contagem de linhas for inferior a 100, não será necessário criar o índice ScaNN, já que ele não se aplica a menos linhas. Nesse caso, pule as etapas a seguir.
- Para criar índices ScaNN, instale a extensão alloydb_scann.
CREATE EXTENSION IF NOT EXISTS alloydb_scann;
- Primeiro, execute a consulta de pesquisa vetorial sem o índice e sem o filtro inline ativado:
SELECT id || ' - ' || title as title FROM patents_data
WHERE num_claims >= 15
ORDER BY abstract_embeddings <=> embedding('text-embedding-005', 'Sentiment Analysis')::vector LIMIT 10;
O resultado será semelhante a este:
- Execute a análise detalhada: (sem índice nem filtragem inline)
O tempo de execução é de 2,4 ms
- Vamos criar um índice regular no campo num_claims para podermos filtrar por ele:
CREATE INDEX idx_patents_data_num_claims ON patents_data (num_claims);
- Vamos criar o índice ScaNN para nossa pesquisa de patentes. Execute o seguinte no AlloyDB Studio:
CREATE INDEX patent_index ON patents_data
USING scann (abstract_embeddings cosine)
WITH (num_leaves=32);
Observação importante : (num_leaves=32)
se aplica ao conjunto de dados total com mais de 1.000 linhas. Se a contagem de linhas for menor que 100, não será necessário criar um índice, já que ele não se aplica a menos linhas.
- Ative a filtragem inline no índice ScaNN:
SET scann.enable_inline_filtering = on
- Agora, vamos executar a mesma consulta com filtro e pesquisa vetorial:
SELECT id || ' - ' || title as title FROM patents_data
WHERE num_claims >= 15
ORDER BY abstract_embeddings <=> embedding('text-embedding-005', 'Sentiment Analysis')::vector LIMIT 10;
Como você pode ver, o tempo de execução é reduzido significativamente para a mesma pesquisa de vetor. A filtragem inline infundida no índice ScaNN na pesquisa vetorial tornou isso possível!!!
Em seguida, vamos avaliar o recall dessa pesquisa vetorial ativada pelo ScaNN.
Avaliador de recall
A recuperação na pesquisa de similaridade é a porcentagem de instâncias relevantes que foram recuperadas de uma pesquisa, ou seja, o número de verdadeiros positivos. Essa é a métrica mais comum usada para medir a qualidade da pesquisa. Uma fonte de perda de recall vem da diferença entre a pesquisa de vizinho mais próximo aproximado, ou aNN, e a pesquisa de vizinho mais próximo exato, ou kNN. Índices vetoriais, como o ScaNN do AlloyDB, implementam algoritmos de ANN, permitindo acelerar a pesquisa vetorial em grandes conjuntos de dados em troca de uma pequena compensação na recuperação. Agora, o AlloyDB permite medir essa troca diretamente no banco de dados para consultas individuais e garantir que ela seja estável ao longo do tempo. Você pode atualizar os parâmetros de consulta e índice em resposta a essas informações para conseguir resultados e desempenho melhores.
É possível encontrar o recall de uma consulta de vetor em um índice de vetor para uma determinada configuração usando a função evaluate_query_recall. Essa função permite ajustar os parâmetros para conseguir os resultados de recuperação de consulta de vetor que você quer. O recall é a métrica usada para a qualidade da pesquisa e é definido como a porcentagem dos resultados retornados que são objetivamente mais próximos dos vetores de consulta. A função evaluate_query_recall é ativada por padrão.
Observação importante:
Se você encontrar um erro de permissão negada no índice HNSW nas etapas a seguir, pule esta seção de avaliação de recuperação por enquanto. Talvez isso tenha a ver com restrições de acesso, já que o codelab foi documentado recentemente.
- Defina a flag "Enable Index Scan" no índice ScaNN e HNSW:
SET scann.enable_indexscan = on
SET hnsw.enable_index_scan = on
- Execute a seguinte consulta no AlloyDB Studio:
SELECT
*
FROM
evaluate_query_recall($$
SELECT
id || ' - ' || title AS title,
abstract
FROM
patents_data
where num_claims >= 15
ORDER BY
abstract_embeddings <=> embedding('text-embedding-005',
'sentiment analysis')::vector
LIMIT 25 $$,
'{"scann.num_leaves_to_search":1, "scann.pre_reordering_num_neighbors":10}',
ARRAY['scann']);
A função evaluate_query_recall recebe a consulta como parâmetro e retorna a recuperação. Estou usando a mesma consulta que usei para verificar a performance como a consulta de entrada da função. Adicionei o SCaNN como o método de índice. Para mais opções de parâmetro, consulte a documentação.
O recall para esta consulta de pesquisa vetorial que usamos:
Vejo que a RECALL é de 70%. Agora posso usar essas informações para mudar os parâmetros de índice, métodos e consultas e melhorar minha recuperação para essa pesquisa vetorial.
Mudei o número de linhas no conjunto de resultados para 7 (antes eram 10) e notei uma ligeira melhora na RECALL, ou seja, 86%.
Isso significa que, em tempo real, posso variar o número de correspondências que meus usuários veem para melhorar a relevância delas de acordo com o contexto de pesquisa dos usuários.
Tudo bem agora. É hora de implantar a lógica do banco de dados e passar para o agente!!!
7. Leve a lógica do banco de dados para a Web sem servidor
Tudo pronto para levar esse app para a Web? Siga as etapas abaixo:
- 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 "patent-search" e escolha a região como us-central1. 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 o editor inline para o código-fonte.
- Por padrão, ele define o ponto de entrada como gcfv2.HelloHttpFunction. Substitua o código do marcador de posição em HelloHttpFunction.java e pom.xml da sua função do Cloud Run pelo código de "PatentSearch.java" e "pom.xml", respectivamente. Mude o nome do arquivo de classe para PatentSearch.java.
- Lembre-se de mudar o marcador de posição ************* e as credenciais de conexão do AlloyDB pelos 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.
ETAPA IMPORTANTE:
Após a implantação, vamos criar o conector da VPC para permitir que a Função do Cloud acesse a instância do banco de dados do AlloyDB.
Depois de definir a implantação, você poderá conferir as funções no console do Google Cloud Run Functions. Pesquise a função recém-criada (patent-search), clique nela e em EDIT AND DEPLOY NEW REVISIONS (identificado pelo ícone EDIT (caneta) na parte de cima do console do Cloud Run Functions) e mude o seguinte:
- Acesse a guia "Rede":
- Selecione Conectar a uma VPC para tráfego de saída e Usar conectores de acesso VPC sem servidor.
- Em Configurações, clique no menu suspenso "Rede" e selecione a opção Adicionar novo conector VPC (se você ainda não tiver configurado o padrão) 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 CREATE. 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ÓXIMO e em IMPLANTAR.
- Depois que o Cloud Function atualizado for implantado, o endpoint gerado vai aparecer. Copie e substitua no comando a seguir:
PROJECT_ID=$(gcloud config get-value project)
curl -X POST <<YOUR_ENDPOINT>> \
-H 'Content-Type: application/json' \
-d '{"search":"Sentiment Analysis"}'
Pronto! É muito simples realizar uma pesquisa vetorial de similaridade contextual avançada usando o modelo de embeddings nos dados do AlloyDB.
8. Vamos criar o agente com o Java ADK
Primeiro, vamos começar com o projeto Java no editor.
- Acessar o terminal do Cloud Shell
https://shell.cloud.google.com/?fromcloudshell=true&show=ide%2Cterminal
- Autorizar quando solicitado
- Alterne para o editor do Cloud Shell clicando no ícone do editor na parte de cima do console do Cloud Shell.
- No console do editor do Cloud Shell, crie uma nova pasta e nomeie como "adk-agents".
Clique em "Criar nova pasta" no diretório raiz do Cloud Shell, conforme mostrado abaixo:
Nomeie como "adk-agents":
- Crie a estrutura de pastas a seguir e os arquivos vazios com os nomes de arquivo correspondentes na estrutura abaixo:
adk-agents/
└—— pom.xml
└—— src/
└—— main/
└—— java/
└—— agents/
└—— App.java
- Abra o repositório do GitHub em uma guia separada e copie o código-fonte dos arquivos App.java e pom.xml.
- Se você abriu o editor em uma nova guia usando o ícone "Abrir em nova guia" no canto superior direito, o terminal será aberto na parte de baixo da página. Você pode abrir o editor e o terminal em paralelo, permitindo que você opere livremente.
- Depois de clonar, volte ao console do editor do Cloud Shell.
- Como já criamos a função do Cloud Run, não é necessário copiar os arquivos da função do Cloud Run da pasta do repositório.
Introdução ao SDK Java do ADK
É bem simples. Você precisa garantir que as seguintes etapas sejam cobertas na etapa de clonagem:
- Adicionar dependências:
Inclua os artefatos google-adk e google-adk-dev (para a interface da Web) no pom.xml.
<!-- The ADK core dependency -->
<dependency>
<groupId>com.google.adk</groupId>
<artifactId>google-adk</artifactId>
<version>0.1.0</version>
</dependency>
<!-- The ADK dev web UI to debug your agent -->
<dependency>
<groupId>com.google.adk</groupId>
<artifactId>google-adk-dev</artifactId>
<version>0.1.0</version>
</dependency>
Faça referência ao pom.xml do repositório de origem, porque há outras dependências e configurações necessárias para a execução do aplicativo.
- Configurar seu projeto:
Verifique se a versão do Java (17 ou mais recente recomendada) e as configurações do compilador Maven estão configuradas corretamente no pom.xml. É possível configurar o projeto para seguir a estrutura abaixo:
adk-agents/
└—— pom.xml
└—— src/
└—— main/
└—— java/
└—— agents/
└—— App.java
- Definição do agente e das ferramentas dele (App.java):
É aqui que a magia do SDK do Java do ADK brilha. Definimos o agente, os recursos dele (instruções) e as ferramentas que ele pode usar.
Confira uma versão simplificada de alguns snippets de código da classe principal do agente aqui. Para conferir o projeto completo, consulte o repositório aqui.
// App.java (Simplified Snippets)
package agents;
import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.BaseAgent;
import com.google.adk.agents.InvocationContext;
import com.google.adk.tools.Annotations.Schema;
import com.google.adk.tools.FunctionTool;
// ... other imports
public class App {
static FunctionTool searchTool = FunctionTool.create(App.class, "getPatents");
static FunctionTool explainTool = FunctionTool.create(App.class, "explainPatent");
public static BaseAgent ROOT_AGENT = initAgent();
public static BaseAgent initAgent() {
return LlmAgent.builder()
.name("patent-search-agent")
.description("Patent Search agent")
.model("gemini-2.0-flash-001") // Specify your desired Gemini model
.instruction(
"""
You are a helpful patent search assistant capable of 2 things:
// ... complete instructions ...
""")
.tools(searchTool, explainTool)
.outputKey("patents") // Key to store tool output in session state
.build();
}
// --- Tool: Get Patents ---
public static Map<String, String> getPatents(
@Schema(name="searchText",description = "The search text for which the user wants to find matching patents")
String searchText) {
try {
String patentsJson = vectorSearch(searchText); // Calls our Cloud Run Function
return Map.of("status", "success", "report", patentsJson);
} catch (Exception e) {
// Log error
return Map.of("status", "error", "report", "Error fetching patents.");
}
}
// --- Tool: Explain Patent (Leveraging InvocationContext) ---
public static Map<String, String> explainPatent(
@Schema(name="patentId",description = "The patent id for which the user wants to get more explanation for, from the database")
String patentId,
@Schema(name="ctx",description = "The list of patent abstracts from the database from which the user can pick the one to get more explanation for")
InvocationContext ctx) { // Note the InvocationContext
try {
// Retrieve previous patent search results from session state
String previousResults = (String) ctx.session().state().get("patents");
if (previousResults != null && !previousResults.isEmpty()) {
// Logic to find the specific patent abstract from 'previousResults' by 'patentId'
String[] patentEntries = previousResults.split("\n\n\n\n");
for (String entry : patentEntries) {
if (entry.contains(patentId)) { // Simplified check
// The agent will then use its instructions to summarize this 'report'
return Map.of("status", "success", "report", entry);
}
}
}
return Map.of("status", "error", "report", "Patent ID not found in previous search.");
} catch (Exception e) {
// Log error
return Map.of("status", "error", "report", "Error explaining patent.");
}
}
public static void main(String[] args) throws Exception {
InMemoryRunner runner = new InMemoryRunner(ROOT_AGENT);
// ... (Session creation and main input loop - shown in your source)
}
}
Principais componentes do código Java do ADK em destaque:
- LlmAgent.builder(): API Fluent para configurar seu agente.
- .instruction(...): fornece o comando principal e as diretrizes do LLM, incluindo quando usar cada ferramenta.
- FunctionTool.create(App.class, "methodName"): registra facilmente seus métodos Java como ferramentas que o agente pode invocar. A string de nome do método precisa corresponder a um método estático público real.
- @Schema(description = ...): anota parâmetros de ferramentas, ajudando o LLM a entender quais entradas cada ferramenta espera. Essa descrição é crucial para a seleção precisa de ferramentas e o preenchimento de parâmetros.
- InvocationContext ctx:é transmitido automaticamente para métodos de ferramentas, acesso ao estado da sessão (ctx.session().state()), informações do usuário e muito mais.
- .outputKey("patents"): quando uma ferramenta retorna dados, o ADK pode armazená-los automaticamente no estado da sessão com essa chave. É assim que o método explainPatent pode acessar os resultados de getPatents.
- VECTOR_SEARCH_ENDPOINT::é uma variável que contém a lógica funcional principal da pergunta e resposta contextual para o usuário no caso de uso da pesquisa de patentes.
- Item de ação aqui: Depois de implementar a etapa da função Java do Cloud Run da seção anterior, você precisa definir um valor de endpoint implantado atualizado.
- searchTool: interage com o usuário para encontrar correspondências de patentes relevantes do banco de dados de patentes para o texto de pesquisa do usuário.
- explainTool: solicita que o usuário escolha uma patente específica para uma análise detalhada. Em seguida, ele resume o resumo da patente e pode responder a mais perguntas do usuário com base nos detalhes da patente.
Observação importante: substitua a variável VECTOR_SEARCH_ENDPOINT pelo endpoint de CRF implantado.
Como usar o InvocationContext para interações com estado
Um dos recursos essenciais para criar agentes úteis é gerenciar o estado em várias rodadas de uma conversa. O InvocationContext do ADK facilita isso.
No App.java:
- Quando initAgent() é definido, usamos .outputKey("patents"). Isso informa ao ADK que, quando uma ferramenta (como getPatents) retorna dados no campo de relatório, esses dados precisam ser armazenados no estado da sessão com a chave "patents".
- No método de ferramenta explainPatent, injetamos InvocationContext ctx:
public static Map<String, String> explainPatent(
@Schema(description = "...") String patentId, InvocationContext ctx) {
String previousResults = (String) ctx.session().state().get("patents");
// ... use previousResults ...
}
Isso permite que a ferramenta explainPatent acesse a lista de patentes buscada pela ferramenta getPatents em uma rodada anterior, tornando a conversa coerente e com estado.
9. Teste de CLI local
Definir as variáveis de ambiente
Você vai precisar exportar duas variáveis de ambiente:
- Uma chave Gemini que você pode receber do AI Studio:
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:
- Depois de receber a chave, abra o Cloud Shell Terminal e vá para o novo diretório que criamos adk-agents executando o seguinte comando:
cd adk-agents
- Uma variável para especificar que não estamos usando a Vertex AI desta vez.
export GOOGLE_GENAI_USE_VERTEXAI=FALSE
export GOOGLE_API_KEY=AIzaSyDF...
- Executar seu primeiro agente na CLI
Para iniciar esse primeiro agente, use o seguinte comando do Maven no terminal:
mvn compile exec:java -DmainClass="agents.App"
Você vai ver a resposta interativa do agente no terminal.
10. Como implantar no Cloud Run
A implantação do agente Java do ADK no Cloud Run é semelhante à implantação de qualquer outro aplicativo Java:
- Dockerfile: crie um Dockerfile para empacotar seu aplicativo Java.
- Criar e enviar a imagem do Docker: use o Google Cloud Build e o Artifact Registry.
- É possível realizar a etapa acima e implantar no Cloud Run em apenas um comando:
gcloud run deploy --source . --set-env-vars GOOGLE_API_KEY=<<Your_Gemini_Key>>
Da mesma forma, você implantaria a função Java Cloud Run (gcfv2.PatentSearch). Também é possível criar e implantar a função do Cloud Run em Java para a lógica do banco de dados diretamente no console da função do Cloud Run.
11. Como testar com a IU da Web
O ADK vem com uma interface da Web prática para testes locais e depuração do agente. Quando você executa o App.java localmente (por exemplo, mvn exec:java -Dexec.mainClass="agents.App" se estiver configurado ou apenas executando o método principal), o ADK normalmente inicia um servidor da Web local.
Com a IU da Web do ADK, você pode:
- Enviar mensagens para o agente.
- Confira os eventos (mensagem do usuário, chamada de ferramenta, resposta da ferramenta, resposta do LLM).
- Inspecione o estado da sessão.
- Acessar registros e traces.
Isso é muito importante durante o desenvolvimento para entender como o agente processa solicitações e usa as ferramentas. Isso pressupõe que a mainClass no pom.xml esteja definida como com.google.adk.web.AdkWebServer e que seu agente esteja registrado nela ou que você esteja executando um executor de teste local que expõe isso.
Ao executar o App.java com o InMemoryRunner e o Scanner para entrada do console, você está testando a lógica principal do agente. A interface da Web é um componente separado para uma experiência de depuração mais visual, geralmente usada quando o ADK está veiculando o agente por HTTP.
Você pode usar o seguinte comando do Maven no seu diretório raiz para iniciar o servidor local do SpringBoot:
mvn compile exec:java -Dexec.args="--adk.agents.source-dir=src/main/java/ --logging.level.com.google.adk.dev=TRACE --logging.level.com.google.adk.demo.agents=TRACE"
A interface geralmente pode ser acessada no URL que o comando acima gera. Se o aplicativo estiver implantado no Cloud Run, você poderá acessá-lo pelo link implantado do Cloud Run.
O resultado vai aparecer em uma interface interativa.
Confira o vídeo abaixo sobre o Agente de patentes implantado:
12. 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 https://console.cloud.google.com/cloud-resource-manager?utm_campaign=CDR_0x1d2a42f5_default_b419133749&utm_medium=external&utm_source=blog.
- https://console.cloud.google.com/cloud-resource-manager?utm_campaign=CDR_0x1d2a42f5_default_b419133749&utm_medium=external&utm_source=blog.
- 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.
13. Parabéns
Parabéns! Você criou seu agente de análise de patentes em Java combinando os recursos do ADK, https://cloud.google.com/alloydb/docs?utm_campaign=CDR_0x1d2a42f5_default_b419133749&utm_medium=external&utm_source=blog, do Vertex AI e da Pesquisa de vetores. Também demos um grande salto em frente ao criar pesquisas de similaridade contextual tão transformadoras, eficientes e realmente orientadas a significados.
Comece a usar hoje mesmo.
Documentação do ADK: [Link to Official ADK Java Docs]
Código-fonte do agente de análise de patentes: [Link to your (now public) GitHub Repo]
Agentes de amostra Java: [link para o repositório adk-samples]
Participe da comunidade do ADK: https://www.reddit.com/r/agentdevelopmentkit/
Boa criação de agentes!