1. Visão geral
Em diferentes setores, a pesquisa contextual é uma funcionalidade essencial que forma o coração e o centro dos aplicativos. A Geração Aumentada de Recuperação tem sido um fator importante dessa evolução tecnológica crucial há algum tempo com seus mecanismos de recuperação baseados em IA generativa. Os modelos generativos, com suas grandes janelas de contexto 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, embasando-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 acurácia desses resultados? Sua empresa depende muito da precisão e da relevância dessas correspondências contextuais? Então este projeto vai te agradar!
Agora imagine se pudéssemos aproveitar o poder dos modelos generativos e criar agentes interativos capazes de tomar decisões autônomas com base em informações críticas para o contexto e fundamentadas na verdade. É isso que vamos criar hoje. Vamos criar um app de agente de IA completo usando o Agent Development Kit com tecnologia de RAG avançado no AlloyDB para um aplicativo 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 mais detalhes, se necessário, para uma patente selecionada. Quer saber como isso é feito? 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 Java ADK, AlloyDB, pesquisa vetorial (com índices avançados), Gemini e todo o aplicativo implantado sem servidor no Cloud Run.
O que você vai criar
Neste laboratório, você vai:
- Criar uma instância do AlloyDB e carregar dados do conjunto de dados públicos de patentes
- Implementar a pesquisa vetorial avançada no AlloyDB usando os recursos de avaliação de recall e ScaNN
- Criar um agente usando o ADK Java
- Implementar a lógica do lado do servidor do banco de dados em funções sem servidor do Cloud Functions 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 sua conta já está autenticada e se o projeto está configurado com seu ID do 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>
- Ative as APIs necessárias. Use 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 é pesquisar cada produto no console ou usar 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 banco de dados para os dados de patentes. 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 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
" - PostgreSQL 15 / mais recente recomendado
- 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 (que pode ser encontrado no momento da configuração do cluster / instância) para
vector-instance
. Se não for possível mudar, use 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.
4. Ingestão de dados
Agora é hora de adicionar uma tabela com os dados da loja. Navegue até 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 vetor. 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
É 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 armazenar os valores de vetor do texto.
Conceder permissão
Execute a instrução abaixo para conceder a 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 Google Cloud IAM, conceda à conta de serviço do AlloyDB (que tem esta aparência: service-<<PROJECT_NUMBER>>@gcp-sa-alloydb.iam.gserviceaccount.com) acesso à função "Usuário da Vertex AI". PROJECT_NUMBER vai 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 do Google Patentes no BigQuery serão usados como nosso conjunto de dados. Vamos usar o AlloyDB Studio para executar nossas consultas. Os dados são extraídos para o arquivo insert scripts sql
neste repo, e vamos executar isso para carregar os dados de patentes.
- 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 e execute as instruções de consulta
insert
dos arquivosinsert_scripts1.sql
,
*insert_script2.sql
*,
*insert_scripts3.sql
*,
*insert_scripts4.sql
* um por um. Execute as instruções de inserção de cópia de 10 a 50 para uma demonstração rápida desse caso de uso.
Para executar, 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 a seguinte consulta de exemplo:
SELECT embedding('text-embedding-005', 'AlloyDB is a managed, cloud-hosted SQL database service.');
Isso vai retornar o vetor de embeddings, que parece uma matriz de números de ponto flutuante, para o texto de exemplo na consulta. Ela tem esta aparência:
Atualizar o campo de vetor abstract_embeddings
A DML abaixo deve ser usada para atualizar os resumos de patentes na tabela com as incorporações correspondentes caso seja necessário gerá-las para os resumos. No entanto, no nosso caso, as instruções de inserção já contêm esses encodings para cada resumo. Portanto, não é necessário chamar o método embeddings().
UPDATE patents_data set abstract_embeddings = embedding( 'text-embedding-005', abstract);
6. Fazer 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. 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 sentimentos".
- Estamos convertendo em embeddings no método embedding() usando o modelo: text-embedding-005.
- "<=>" representa o uso do método de distância de similaridade de cosseno.
- 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 10" representa que estamos selecionando as 10 correspondências mais próximas do texto de pesquisa.
O AlloyDB leva a RAG da pesquisa vetorial a outro nível:
Há várias coisas novas. Dois deles são:
- Filtragem inline
- Avaliador de recall
Filtragem inline
Antes, como desenvolvedor, você precisava realizar a consulta de pesquisa de vetor e lidar com a filtragem e o recall. O otimizador de consultas do AlloyDB escolhe como executar uma consulta com filtros. A filtragem inline é uma nova técnica de otimização de consultas que permite que o otimizador de consultas do AlloyDB avalie as condições de filtragem de metadados e a pesquisa vetorial simultaneamente, aproveitando os índices vetoriais e os índices nas colunas de metadados. Isso aumentou o desempenho de recall, permitindo que os desenvolvedores aproveitem o que o AlloyDB tem a oferecer sem precisar fazer nada.
A filtragem inline é ideal para casos com seletividade média. À medida que o AlloyDB pesquisa no índice de vetores, ele só calcula distâncias para vetores que correspondem às condições de filtragem de metadados (seus filtros funcionais em uma consulta geralmente processada na cláusula WHERE). Isso melhora muito o desempenho dessas consultas, complementando as vantagens do 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, faça upgrade para a versão 0.8.0.google-3 ou mais recente para ter recursos de avaliador de recall.
ALTER EXTENSION vector UPDATE TO '0.8.0.google-3';
Essa 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 menor que 100, não será necessário criar o índice do ScaNN, já que ele não se aplica a menos linhas. Nesse caso, pule as etapas a seguir.
- Para criar índices do ScaNN, instale a extensão alloydb_scann.
CREATE EXTENSION IF NOT EXISTS alloydb_scann;
- Primeiro, execute a consulta do Vector Search 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 o recurso Explicar análise nele (sem índice nem filtragem inline):
O tempo de execução é de 2,4 ms
- Vamos criar um índice regular no campo "num_claims" para poder filtrar por ele:
CREATE INDEX idx_patents_data_num_claims ON patents_data (num_claims);
- Vamos criar o índice do ScaNN para nosso aplicativo de 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 nosso 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.
- Defina a filtragem inline ativada no índice ScaNN:
SET scann.enable_inline_filtering = on
- Agora, vamos executar a mesma consulta com filtro e Vector Search:
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. O índice do ScaNN com filtragem inline na Pesquisa Vetorial tornou isso possível.
Em seguida, vamos avaliar o recall para essa Pesquisa Vetorial ativada pelo ScaNN.
Avaliador de recall
O recall 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 (aNN) e a pesquisa de vizinho k (exato) mais próximo (kNN). Os índices de vetores, como o ScaNN do AlloyDB, implementam algoritmos aNN, permitindo acelerar a pesquisa de vetores em grandes conjuntos de dados em troca de uma pequena compensação no recall. 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. É possível atualizar os parâmetros de consulta e índice em resposta a essas informações para alcançar melhores resultados e desempenho.
É possível encontrar o recall de uma consulta de vetor em um índice vetorial para uma determinada configuração usando a função evaluate_query_recall. Com essa função, é possível ajustar os parâmetros para alcançar os resultados de recall da consulta de vetor desejados. O recall é a métrica usada para a qualidade da pesquisa e é definida como a porcentagem dos resultados retornados que estão objetivamente mais próximos dos vetores de consulta. A função evaluate_query_recall fica ativada por padrão.
Observação importante:
Se você estiver enfrentando um erro de permissão negada no índice HNSW nas etapas a seguir, pule toda esta seção de avaliação de recall por enquanto. Isso pode estar relacionado a restrições de acesso, já que ele foi lançado recentemente quando este codelab foi documentado.
- 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" usa a consulta como um parâmetro e retorna a acurácia dela. Estou usando a mesma consulta que usei para verificar a performance como consulta de entrada da função. Adicionei o SCaNN como método de indexação. Para mais opções de parâmetros, consulte a documentação.
O recall para esta consulta de pesquisa vetorial que estamos usando:
Vejo que o RECALL é de 70%. Agora posso usar essas informações para mudar os parâmetros, métodos e parâmetros de consulta do índice e melhorar a capacidade de recall para essa pesquisa vetorial.
Modifiquei o número de linhas no conjunto de resultados para 7 (antes eram 10) e notei uma melhoria leve no 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 de acordo com o contexto de pesquisa deles.
Tudo bem! Agora é hora de implantar a lógica do banco de dados e passar para o agente.
7. Levar a lógica do banco de dados para o servidor da 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 função do Cloud Run clicando em "Escrever uma função" ou use o link: https://console.cloud.google.com/run/create?deploymentType=function.
- Escolha a opção "Usar um editor in-line para criar uma função" e comece a configuração. Forneça o nome do serviço "patent-search", escolha a região "us-central1" e o tempo de execução "Java 17". Defina a autenticação como Permitir invocações não autenticadas.
- Na seção "Contêineres, volumes, rede, segurança", siga as etapas abaixo sem perder nenhum detalhe:
Acesse a guia "Rede":
Selecione Conectar a uma VPC para tráfego de saída e Usar conectores de acesso VPC sem servidor.
No menu suspenso "Rede", clique nele 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:
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.
- Por padrão, ele define o ponto de entrada como "gcfv2.HelloHttpFunction". Substitua o código de 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.
- Não se esqueça de mudar o marcador ************* e as credenciais de conexão do AlloyDB pelos 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 que a função do Cloud atualizada for implantada, 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! É simples assim realizar uma pesquisa vetorial avançada de similaridade contextual usando o modelo de embeddings em dados do AlloyDB.
8. Vamos criar o agente com o ADK Java
Primeiro, vamos começar com o projeto Java no editor.
- Acesse o terminal do Cloud Shell.
https://shell.cloud.google.com/?fromcloudshell=true&show=ide%2Cterminal
- Autorizar quando solicitado
- Clique no ícone do editor na parte de cima do console do Cloud Shell para alternar para o editor do Cloud Shell.
- No console do editor do Cloud Shell, crie uma pasta chamada "adk-agents".
Clique em "Criar nova pasta" no diretório raiz do Cloud Shell, conforme mostrado abaixo:
Nomeie como "adk-agents":
- Crie a seguinte estrutura de pastas e os arquivos vazios com os nomes 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ê tiver aberto o editor em uma nova guia usando o ícone "Abrir em nova guia" no canto superior direito, o terminal vai aparecer na parte de baixo da página. Você pode abrir o editor e o terminal em paralelo para operar livremente.
- Depois de clonado, volte para o 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.
Como começar a usar o SDK do ADK para Java
É bem simples. Principalmente, 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, já que 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 recomendado) e as configurações do compilador Maven estão configuradas corretamente no pom.xml. Você pode configurar seu projeto para seguir a estrutura abaixo:
adk-agents/
└—— pom.xml
└—— src/
└—— main/
└—— java/
└—— agents/
└—— App.java
- Definir o agente e as ferramentas dele (App.java):
É aqui que a mágica do SDK do ADK para Java brilha. Definimos nosso agente, as capacidades dele (instruções) e as ferramentas que ele pode usar.
Confira aqui uma versão simplificada de alguns snippets de código da classe principal do agente. Para 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 de código Java do ADK em destaque:
- LlmAgent.builder():: API fluente para configurar seu agente.
- .instruction(...): fornece o comando principal e as diretrizes para o 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 do nome do método precisa corresponder a um método estático público real.
- @Schema(description = ...): anota os parâmetros da ferramenta, ajudando o LLM a entender quais entradas cada ferramenta espera. Essa descrição é essencial 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 explainPatent pode acessar os resultados do getPatents.
- VECTOR_SEARCH_ENDPOINT::é uma variável que contém a lógica funcional principal para as perguntas e respostas contextuais do usuário no caso de uso de pesquisa de patentes.
- Item de ação: defina um valor de endpoint implantado atualizado depois de implementar a etapa da função do Cloud Run em Java da seção anterior.
- searchTool: interage com o usuário para encontrar correspondências de patentes contextualmente relevantes no banco de dados de patentes para o texto de pesquisa do usuário.
- explainTool: pede ao usuário uma patente específica para analisar em detalhes. Em seguida, ele resume o resumo da patente e pode responder a mais perguntas do usuário com base nos detalhes da patente que tem.
Observação importante: substitua a variável VECTOR_SEARCH_ENDPOINT pelo endpoint de CRF implantado.
Como aproveitar 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 nosso 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, eles precisam ser armazenados no estado da sessão com a chave "patents".
- No método 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 com estado e coerente.
9. Teste local da CLI
Definir as variáveis de ambiente
Você precisa exportar duas variáveis de ambiente:
- Uma chave do Gemini que você pode acessar no AI Studio:
Para fazer 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:
- Depois de conseguir a chave, abra o terminal do Cloud Shell e acesse o novo diretório que acabamos de criar, 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 o primeiro agente, use o seguinte comando do Maven no terminal:
mvn compile exec:java -DmainClass="agents.App"
Você 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 imagem do Docker: use o Google Cloud Build e o Artifact Registry.
- Você pode executar a etapa acima e implantar no Cloud Run com apenas um comando:
gcloud run deploy --source . --set-env-vars GOOGLE_API_KEY=<<Your_Gemini_Key>>
Da mesma forma, você implantaria sua função do Cloud Run em Java (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 de funções do Cloud Run.
11. Como testar com a interface da Web
O ADK vem com uma interface da Web prática para testes e depuração locais do seu agente. Quando você executa o App.java localmente (por exemplo, mvn exec:java -Dexec.mainClass="agents.App" se configurado ou apenas executando o método principal), o ADK normalmente inicia um servidor da Web local.
Com a interface da Web do ADK, você pode:
- Envie mensagens para seu agente.
- Confira os eventos (mensagem do usuário, chamada de ferramenta, resposta da ferramenta, resposta do LLM).
- Inspecione o estado da sessão.
- Veja registros e traces.
Isso é muito útil durante o desenvolvimento para entender como o agente processa solicitações e usa as ferramentas. Isso pressupõe que sua mainClass em 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 testes local que exponha 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 veicula seu agente por HTTP.
Use o seguinte comando do Maven no 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 gerado pelo comando acima. Se for Implantado no Cloud Run, você poderá acessar o link implantado do Cloud Run.
Você poderá conferir o resultado em uma interface interativa.
Confira o vídeo abaixo para conhecer nosso 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 com sucesso 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, Vertex AI e pesquisa vetorial. Além disso, avançamos muito para tornar as pesquisas de similaridade contextual transformadoras, eficientes e realmente orientadas a significado.
Comece hoje mesmo!
Documentação do ADK: [Link para a documentação oficial do ADK em Java]
Código-fonte do agente de análise de patentes: [link para seu repositório do GitHub (agora público)]
Agentes de amostra em Java: [link para o repositório adk-samples]
Participe da comunidade do ADK: https://www.reddit.com/r/agentdevelopmentkit/
Boa criação de agentes!