1. Introdução
Neste codelab, você vai criar um agente de barista de IA interativo para uma cafeteria. Usando o Kit de Desenvolvimento de Agente (ADK) de código aberto do Google e o modelo Gemini 3.5 Flash, você vai implementar a geração aumentada por recuperação (RAG) para embasar as recomendações do agente em um conjunto de dados de menu simulado. Por fim, você vai encapsular o agente em uma interface do usuário do Streamlit e implantá-lo no Cloud Run.
Atividades deste laboratório
- Crie uma fonte de dados de RAG (
menu.json) com itens de café, tags e alérgenos. - Crie um agente de IA usando o ADK
LlmAgente conecte uma ferramenta Python para carregar os dados do menu. - Inclua o agente em um aplicativo de chat do Streamlit que gerencia o histórico de conversas.
- Implante o app Streamlit no Cloud Run usando a implantação baseada em origem.
- Teste o embasamento da RAG e a conscientização sobre alérgenos.

O que é necessário
- Um navegador da Web, como o Chrome.
- Ter um projeto do Google Cloud com o faturamento ativado.
- Conhecimento básico do Python
Este codelab é destinado a desenvolvedores de todos os níveis, inclusive iniciantes.
Custo estimado:menos de US $1.
2. Antes de começar
Criar um projeto do Google Cloud
- No Console do Google Cloud, selecione ou crie um projeto na nuvem do Google Cloud.
- Verifique se o faturamento está ativado para seu projeto do Cloud.
Iniciar o Cloud Shell
- Clique em Ativar o Cloud Shell na parte de cima do console do Google Cloud.

- Verifique a autenticação:

gcloud auth list
- Confirme se o projeto ativo está definido:
gcloud config get project
Se o ID do projeto mostrado não estiver correto ou se nenhum estiver definido, execute:
gcloud config set project <YOUR_PROJECT_ID>
Ativar APIs
Execute este comando para ativar todas as APIs necessárias:
gcloud services enable \
run.googleapis.com \
aiplatform.googleapis.com \
cloudbuild.googleapis.com
3. Criar o projeto
Nesta etapa, você vai inicializar as variáveis de ambiente do projeto e criar um diretório de trabalho para ele.
- Na sessão ativa do Cloud Shell, inicialize as seguintes variáveis de ambiente do projeto:
export PROJECT_ID=$(gcloud config get-value project)
Observação: use a região mais próxima
Encontre a região mais próxima e substitua insert-region-here por ela no seguinte comando:
export REGION=[insert-region-here]
- Crie e acesse um novo diretório de projeto chamado
coffee-barista-agent:
mkdir coffee-barista-agent && cd coffee-barista-agent
4. Criar a fonte de dados de menu simulada
Para fundamentar o AI Barista e evitar que ele alucine itens inexistentes, você vai criar um conjunto de dados de cardápio local. O agente vai ler esse arquivo no ambiente de execução usando uma ferramenta personalizada.
- Crie e abra
menu.jsonno editor do Cloud Shell:
cloudshell edit menu.json
- Cole o seguinte conteúdo JSON no editor e salve o arquivo:
[
{
"name": "Espresso Solo",
"description": "A single shot of rich, bold espresso.",
"price": 2.50,
"tags": ["strong", "hot", "dairy-free", "sugar-free"],
"allergens": []
},
{
"name": "Oat Milk Honey Latte",
"description": "Creamy steamed oat milk with espresso and a touch of honey.",
"price": 5.00,
"tags": ["sweet", "hot", "dairy-free"],
"allergens": []
},
{
"name": "Cold Brew Coffee",
"description": "Smooth, slow-steeped cold brew served over ice.",
"price": 4.00,
"tags": ["strong", "cold", "dairy-free", "sugar-free"],
"allergens": []
},
{
"name": "Seasonal Pumpkin Latte",
"description": "Spiced pumpkin sauce, espresso, and steamed milk, topped with whipped cream.",
"price": 5.50,
"tags": ["sweet", "hot", "seasonal"],
"allergens": ["dairy"]
},
{
"name": "Classic Croissant",
"description": "Flaky, buttery traditional French pastry.",
"price": 3.50,
"tags": ["bakery", "savory"],
"allergens": ["wheat", "dairy"]
},
{
"name": "Vegan Blueberry Muffin",
"description": "Soft, sweet muffin packed with real blueberries, entirely plant-based.",
"price": 3.75,
"tags": ["bakery", "sweet", "dairy-free", "vegan"],
"allergens": ["wheat"]
},
{
"name": "Nitro Cold Brew",
"description": "Cold brew infused with nitrogen for a super smooth, creamy head.",
"price": 4.50,
"tags": ["strong", "cold", "dairy-free", "sugar-free"],
"allergens": []
},
{
"name": "Iced Caramel Macchiato",
"description": "Chilled milk and vanilla syrup marked with espresso and caramel drizzle.",
"price": 5.25,
"tags": ["sweet", "cold"],
"allergens": ["dairy"]
}
]
- Verifique se o arquivo JSON está formatado corretamente:
cat menu.json | python3 -m json.tool > /dev/null && echo "Valid JSON!"
💬 Discussão: JSON local x bancos de dados ativos
Por que estamos usando um arquivo simples menu.json local em vez de um banco de dados ativo?
Para um tutorial ou protótipo rápido, um arquivo JSON local elimina o tempo e a complexidade da configuração inicial do banco de dados. No entanto, em um aplicativo de produção empresarial real, você conectaria o agente a um banco de dados gerenciado, como o Cloud Firestore, o AlloyDB ou o Cloud SQL.
Usar um banco de dados ativo permite que os gerentes de cafeterias adicionem itens sazonais, atualizem preços ou ajustem tags de alérgenos de forma dinâmica sem recriar a imagem do contêiner ou reimplantar o código do aplicativo. Vamos usar um banco de dados ativo como uma etapa opcional mais adiante no codelab.
5. criar o agente do ADK
Agora você vai instalar os pacotes necessários e criar a lógica principal do agente do ADK. Você vai definir uma ferramenta get_menu() e transmiti-la para um LlmAgent.
- Crie e abra
requirements.txtno editor do Cloud Shell:
cloudshell edit requirements.txt
- Cole as seguintes dependências no editor e salve o arquivo:
google-adk==2.2.0
streamlit==1.58.0
- Crie e abra
agent.pyno editor do Cloud Shell:
cloudshell edit agent.py
- Cole o seguinte código em
agent.py:
# agent.py
import json
from google.adk.agents import LlmAgent
# [START get_menu]
def get_menu() -> str:
"""Retrieves the coffee shop menu from menu.json.
Returns:
str: A JSON string representing the list of menu items.
"""
try:
with open("menu.json", "r") as f:
menu_data = json.load(f)
return json.dumps(menu_data)
except Exception as e:
return json.dumps({"error": f"Could not retrieve menu: {str(e)}"})
# [END get_menu]
# Create the barista agent
barista_agent = LlmAgent(
name="barista_agent",
model="gemini-3.5-flash",
instruction="""You are a friendly barista at ☕ Coffee Shop.
Your job is to recommend drinks and pastries to customers based on their preferences.
Rules you MUST follow:
1. You must recommend items ONLY from the menu returned by get_menu().
2. Do NOT recommend or suggest any item that is not present in the menu.
3. If a user's preference is vague or unclear, ask exactly ONE friendly clarifying question to narrow down what they want (e.g., cold or hot, sweet or strong, coffee or pastry).
4. Be warm and welcoming, but remain professional.
5. Ground your recommendations in the actual tags, descriptions, and allergens listed in the menu (e.g., if a user is dairy-free, recommend ONLY items tagged 'dairy-free' or with no dairy allergens).
""",
tools=[get_menu]
)
from google.adk.apps import App
# Define the App object
app = App(
name="coffee_barista_app",
root_agent=barista_agent
)
- Crie e abra
app.pyno editor do Cloud Shell:
cloudshell edit app.py
- Cole o seguinte código em
app.py:
# app.py
import streamlit as st
import json
# Set page config for a premium look
st.set_page_config(
page_title="☕ Coffee Shop - Barista Bot",
page_icon="☕",
layout="wide",
initial_sidebar_state="expanded"
)
# Custom CSS to make the header sticky (adapts to light/dark themes)
st.markdown("""
<style>
div[data-testid="element-container"]:has(.header-container),
div.element-container:has(.header-container) {
position: sticky;
top: 2.875rem;
z-index: 999;
background-color: transparent;
padding-bottom: 10px;
}
</style>
""", unsafe_allow_html=True)
# App Header (using inline styles for the permanent coffee theme look)
st.markdown("""
<div class="header-container" style="text-align: center; padding: 20px; background: linear-gradient(135deg, #8B5E3C, #6F4E37); color: white; border-radius: 12px; box-shadow: 0 4px 15px rgba(0,0,0,0.1);">
<h1 style="margin: 0; font-size: 2.5rem; font-weight: 700; color: white;">☕ ☕ Coffee Shop</h1>
<p style="margin: 5px 0 0 0; font-size: 1.1rem; opacity: 0.9; color: white;">Your friendly AI Barista is ready to help you find the perfect drink or pastry!</p>
</div>
""", unsafe_allow_html=True)
# Load Menu for the sidebar
# [START load_menu]
try:
with open("menu.json", "r") as f:
menu_items = json.load(f)
except Exception as e:
st.error(f"Error loading menu: {e}")
menu_items = []
# [END load_menu]
# Sidebar Menu & Configuration
with st.sidebar:
st.markdown("## ☕ Coffee Shop Menu")
st.markdown("Explore our offerings and ask the barista for recommendations.")
st.markdown("---")
for item in menu_items:
with st.container(border=True):
st.markdown(f"**{item['name']}** • **${item['price']:.2f}**")
st.caption(item['description'])
# Tags & Allergens as native badges
tags = " ".join([f"`{t}`" for t in item.get("tags", [])])
if tags:
st.markdown(tags)
allergens = ", ".join(item.get("allergens", []))
if allergens:
st.markdown(f"⚠️ *Allergens: {allergens}*")
# Chat Interface
if "session_id" not in st.session_state:
import uuid
st.session_state.session_id = str(uuid.uuid4())
if "runner" not in st.session_state:
from google.adk.runners import InMemoryRunner
from agent import app
st.session_state.runner = InMemoryRunner(app=app)
if "messages" not in st.session_state:
st.session_state.messages = [
{"role": "assistant", "content": "Welcome to ☕ Coffee Shop! What can I get started for you today?"}
]
# Display existing messages
for msg in st.session_state.messages:
with st.chat_message(msg["role"]):
st.markdown(msg["content"])
# User Input
if prompt := st.chat_input("Ask for recommendations (e.g., 'What dairy-free pastries do you have?')"):
# Display user message
with st.chat_message("user"):
st.markdown(prompt)
st.session_state.messages.append({"role": "user", "content": prompt})
# Generate response
with st.chat_message("assistant"):
try:
import asyncio
# Run the ADK runner asynchronously using asyncio.run
async def fetch_response():
return await st.session_state.runner.run_debug(
prompt,
session_id=st.session_state.session_id
)
res_events = asyncio.run(fetch_response())
response_text = "".join([
part.text
for event in res_events
if event.content and event.content.parts
for part in event.content.parts
if part.text
])
st.markdown(response_text)
st.session_state.messages.append({"role": "assistant", "content": response_text})
except Exception as e:
st.error(f"Apologies, I ran into an error: {e}")
💬 Discussão: compensações do modelo e eficiência do token de recuperação
Por que chamar uma ferramenta de função para recuperar o menu em vez de apenas colar todo o texto do menu nas instruções do sistema do agente?
Economia de tokens! Colocar oito itens no comando é barato, mas e se a cafeteria expandir para 500 itens, incluindo ingredientes personalizados? Colar grandes conjuntos de dados diretamente no comando do sistema aumenta a contagem de tokens do comando, elevando os custos de transação e a latência de resposta da API em todas as consultas.
Ao usar uma ferramenta do ADK, o agente pede dinamicamente para ler o menu SOMENTE quando necessário. O LLM só recebe os dados relevantes do menu como contexto, minimizando o tamanho do token do comando.
💬 Discussão: estado da memória e lojas de produção
O histórico de chat armazenado no st.session_state do Streamlit é mantido quando um usuário fecha a guia do navegador?
Não, não envia. O st.session_state é totalmente na memória e exclusivo da conexão ativa do navegador. Se um usuário atualizar a página ou fechar a guia, o histórico de conversa com o barista será perdido.
Para um aplicativo de produção, conecte o executor do ADK a um back-end de armazenamento permanente, como o Cloud Firestore ou o Redis. O ADK oferece abstrações de serviço integradas (como SessionService) que facilitam o salvamento e a retomada do histórico de chat em recarregamentos de página e dispositivos.
6. Implantar o agente no Cloud Run
Você vai implantar o aplicativo Streamlit diretamente da origem usando os buildpacks integrados do Cloud Run. Para seguir o princípio de privilégio mínimo, crie e implante usando uma conta de serviço personalizada dedicada em vez da conta de serviço padrão do Compute Engine.
- Crie uma conta de serviço dedicada:
gcloud iam service-accounts create barista-agent-sa \
--description="Service account for Coffee Barista ADK agent on Cloud Run" \
--display-name="Barista Agent Service Account"
- Conceda à nova conta de serviço a função de usuário da plataforma do agente do Gemini Enterprise (
roles/aiplatform.user):
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:barista-agent-sa@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/aiplatform.user"
- Implante o serviço usando
gcloud run deploy, transmitindo o novo e-mail da conta de serviço pela flag--service-account:
gcloud run deploy coffee-barista \
--source . \
--region $REGION \
--allow-unauthenticated \
--labels dev-tutorial=codelab-streamlit-rag-adk \
--command "/cnb/lifecycle/launcher" \
--args "sh,-c,python3 -m streamlit run app.py --server.port=\$PORT --server.address=0.0.0.0 --server.enableCORS=false --server.enableXsrfProtection=false" \
--service-account "barista-agent-sa@$PROJECT_ID.iam.gserviceaccount.com" \
--set-env-vars GOOGLE_GENAI_USE_VERTEXAI=TRUE,GOOGLE_CLOUD_PROJECT=$PROJECT_ID,GOOGLE_CLOUD_LOCATION=global
- Depois da implantação, localize o URL do serviço na resposta ao comando.
💬 Discussão: implantação de contêineres x origem e segurança do IAM
Implantamos no Cloud Run usando gcloud run deploy --source sem criar um Dockerfile ou um Procfile. Como o Cloud Run descobriu como compilar e executar nosso app Python?
O Cloud Run usa buildpacks para analisar seu repositório. Ao detectar a presença de requirements.txt e arquivos de origem Python, o mecanismo compila e empacota automaticamente um contêiner de ambiente de execução Python.
Ao escrever um Dockerfile personalizado, você tem controle total sobre os pacotes do sistema e as camadas de base do contêiner. Um Procfile é uma maneira mais simples de declarar o comando de inicialização sem configurar totalmente um contêiner. Mas para implantações rápidas, a implantação da origem (--source) é altamente eficiente.
Por que passamos pela etapa extra de criar uma conta de serviço personalizada barista-agent-sa em vez de usar apenas a conta de serviço padrão do Compute Engine?
Segurança em primeiro lugar! A conta de serviço padrão do Compute Engine tem permissões de editor extremamente amplas por padrão. Executar nosso contêiner do Cloud Run na conta de serviço padrão significa que, se o app tiver um bug de segurança, um invasor poderá ler, gravar ou excluir outros recursos no projeto do Google Cloud.
Ao criar uma conta de serviço dedicada e atribuir apenas a função roles/aiplatform.user, seguimos o princípio de privilégio mínimo: o app tem exatamente o acesso necessário para chamar o Gemini e nada mais.
7. Testar o comportamento da RAG
Abra o URL do serviço do Cloud Run em um navegador da Web e faça perguntas ao AI Barista para testar as restrições de embasamento e segurança.
- Solicitação no menu:pergunte: "Recomende algo forte e quente". Esperado:o agente recomenda um expresso.
- Armadilha fora do menu:pergunte: "Vocês têm um matcha frappuccino?" Esperado:o agente recusa educadamente e explica que não está no menu.
- Pedido com restrição a alérgenos: pergunte "Sou intolerante à lactose. O que posso pedir?" Esperado: o agente só recomenda itens do cardápio sem laticínios (como café com leite de aveia, expresso, café gelado). Ela NÃO recomenda Cappuccino ou Croissant.

8. Opcional: embasar seu agente no Firestore usando a pesquisa de vetores
Em um cenário de produção, armazenar os itens de menu em um arquivo menu.json local não é o ideal, porque qualquer mudança no menu exige a recriação da imagem do contêiner e a reimplantação do serviço do Cloud Run.
Para tornar o aplicativo dinâmico e escalonável, migre os dados do menu para o Cloud Firestore e use a Pesquisa vetorial para recuperar apenas os itens mais relevantes com base na similaridade semântica.

1. Ativar a API Firestore e inicializar o banco de dados
Execute os comandos a seguir para ativar a API Firestore e criar um banco de dados do Firestore chamado coffee-menu no modo nativo:
gcloud services enable firestore.googleapis.com
gcloud firestore databases create --database="coffee-menu" --location=$REGION
Observação:a ativação da API pode levar de 1 a 2 minutos para ser propagada. Se o comando de criação do banco de dados solicitar API [firestore.googleapis.com] not enabled on project... Would you like to enable and retry?, digite Y para continuar ou aguarde um minuto e execute o comando novamente.
2. Propagar o Firestore com os dados do menu
Para inserir rapidamente no banco de dados do Firestore os itens de menu do arquivo menu.json, execute um script Python localmente no Cloud Shell.
- Instale as bibliotecas de cliente do Firestore e da GenAI localmente no Cloud Shell para executar o script de inicialização:
pip3 install google-cloud-firestore==2.27.0 google-genai==2.11.0
- Crie um script de inicialização
seed.py:
cloudshell edit seed.py
- Cole o seguinte código em
seed.py:
# seed.py
import json
import os
from google import genai
from google.cloud import firestore
from google.cloud.firestore_v1.vector import Vector
db = firestore.Client(database="coffee-menu")
client = genai.Client(
vertexai=True,
project=os.environ.get("PROJECT_ID"),
location=os.environ.get("REGION", "us-central1")
)
with open("menu.json", "r") as f:
menu_items = json.load(f)
for item in menu_items:
# Use the name as the document ID
doc_id = item["name"].lower().replace(" ", "-")
# Generate text embedding using Vertex AI text-embedding-004 model
text_to_embed = f"{item['name']}: {item['description']}"
response = client.models.embed_content(
model="text-embedding-004",
contents=text_to_embed,
)
embedding = response.embeddings[0].values
# Add embedding vector to the menu item data
item["embedding"] = Vector(embedding)
db.collection("menu").document(doc_id).set(item)
print("Firestore menu collection seeded with vector embeddings successfully!")
- Execute o script:
python3 seed.py
3. Criar índice vetorial do Firestore
Para realizar pesquisas vetoriais nos itens do menu, crie um índice de vetor composto no campo embedding do banco de dados do Firestore.
Execute o seguinte comando no terminal do Cloud Shell:
gcloud firestore indexes composite create \
--collection-group=menu \
--query-scope=COLLECTION \
--database="coffee-menu" \
--field-config=field-path=embedding,vector-config='{"dimension":"768", "flat": "{}"}'
Observação:a criação de índices do Firestore é executada em segundo plano e pode levar alguns minutos para ser concluída. Você pode seguir as próximas etapas do codelab enquanto o índice é criado.
4. Conceder acesso do Firestore à conta de serviço
Para que seu serviço do Cloud Run consulte o Firestore, conceda à conta de serviço dele o papel de Usuário do Cloud Datastore (roles/datastore.user):
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:barista-agent-sa@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/datastore.user"
Observação:embora estejamos usando o Cloud Firestore no modo nativo, o Google Cloud utiliza os papéis unificados do IAM do Cloud Datastore (roles/datastore.viewer ou roles/datastore.user) para gerenciar o controle de acesso.
5. Atualizar o código
Agora, atualize seu código para recuperar o menu do Firestore em vez de ler de menu.json.
- Abra
requirements.txtno editor do Cloud Shell:
cloudshell edit requirements.txt
- Adicione as bibliotecas de cliente do Firestore e da GenAI ao final do arquivo e salve:
google-cloud-firestore==2.27.0
google-genai==2.11.0
- Abra
agent.pyno editor do Cloud Shell:
cloudshell edit agent.py
- Localize o bloco
# [START get_menu]emagent.pye substitua-o completamente (de# [START get_menu]a# [END get_menu]) pela seguinte implementação do Firestore:
# [START get_menu]
from google import genai
from google.cloud import firestore
from google.cloud.firestore_v1.base_vector_query import DistanceMeasure
from google.cloud.firestore_v1.vector import Vector
def get_menu(query: str) -> str:
"""Retrieves coffee shop menu items matching the user's query.
Args:
query: The search query or preference to find matching menu items.
Returns:
str: A JSON string representing the list of top matching menu items.
"""
try:
# Initialize clients
db = firestore.Client(database="coffee-menu")
client = genai.Client()
# Generate embedding for the search query
response = client.models.embed_content(
model="text-embedding-004",
contents=query,
)
query_vector = response.embeddings[0].values
# Search the Firestore database using Vector Search
results = db.collection("menu").find_nearest(
vector_field="embedding",
query_vector=Vector(query_vector),
distance_measure=DistanceMeasure.COSINE,
limit=3,
).stream()
menu_data = []
for doc in results:
item = doc.to_dict()
# Remove embedding field to save tokens
item.pop("embedding", None)
menu_data.append(item)
return json.dumps(menu_data)
except Exception as e:
return json.dumps({"error": f"Could not retrieve menu: {str(e)}"})
# [END get_menu]
- Abra
app.pyno editor do Cloud Shell:
cloudshell edit app.py
- Localize o bloco
# [START load_menu]emapp.pye substitua-o completamente (de# [START load_menu]a# [END load_menu]) pela seguinte lógica de carregamento do Firestore:
# [START load_menu]
from google.cloud import firestore
try:
db = firestore.Client(database="coffee-menu")
docs = db.collection("menu").stream()
menu_items = []
for doc in docs:
item = doc.to_dict()
item.pop("embedding", None)
menu_items.append(item)
except Exception as e:
st.error(f"Error loading menu from Firestore: {e}")
menu_items = []
# [END load_menu]
6. Reimplantar no Cloud Run
Implante o aplicativo atualizado:
gcloud run deploy coffee-barista \
--source . \
--region $REGION \
--allow-unauthenticated \
--command "/cnb/lifecycle/launcher" \
--args "sh,-c,python3 -m streamlit run app.py --server.port=\$PORT --server.address=0.0.0.0 --server.enableCORS=false --server.enableXsrfProtection=false" \
--service-account "barista-agent-sa@$PROJECT_ID.iam.gserviceaccount.com" \
--set-env-vars GOOGLE_GENAI_USE_VERTEXAI=TRUE,GOOGLE_CLOUD_PROJECT=$PROJECT_ID,GOOGLE_CLOUD_LOCATION=global
7. Verificar a integração do Firestore
Para testar a conexão do agente com o Firestore, adicione um novo item de menu diretamente no Firestore e verifique se o agente o recomenda.
- Execute o comando a seguir no Cloud Shell para gravar um novo documento na coleção
menudo Firestore usando Python:
python3 -c "
import os
from google import genai
from google.cloud import firestore
from google.cloud.firestore_v1.vector import Vector
db = firestore.Client(database='coffee-menu')
client = genai.Client(
vertexai=True,
project=os.environ.get('PROJECT_ID'),
location=os.environ.get('REGION', 'us-central1')
)
name = 'Matcha Green Tea Latte'
desc = 'Creamy steamed milk infused with premium Japanese matcha powder.'
res = client.models.embed_content(
model='text-embedding-004',
contents=f'{name}: {desc}'
)
embedding = res.embeddings[0].values
db.collection('menu').document('matcha-latte').set({
'name': name,
'description': desc,
'price': 5.50,
'tags': ['sweet', 'hot', 'dairy-free'],
'allergens': [],
'embedding': Vector(embedding)
})
print('Successfully added Matcha Latte with vector embeddings!')
"
- Atualize o app Streamlit no navegador para limpar a sessão de chat e carregar o novo estado do banco de dados.
- Observação:
- Matcha Green Tea Latte aparece automaticamente no menu da barra lateral.
- Pergunte ao chatbot: "Você tem alguma bebida de matcha?"
- O agente precisa recomendar o novo Matcha Green Tea Latte com a descrição e o preço que você acabou de adicionar. Isso confirma que o agente está fundamentado em consultas diretamente no seu banco de dados ativo do Firestore.
9. Limpar
Para evitar cobranças contínuas na sua conta de faturamento do Google Cloud, exclua o serviço implantado do Cloud Run e a conta de serviço personalizada.
Exclua o serviço do Cloud Run:
gcloud run services delete coffee-barista --region $REGION --quiet
Exclua a conta de serviço personalizada:
gcloud iam service-accounts delete barista-agent-sa@$PROJECT_ID.iam.gserviceaccount.com --quiet
(Opcional) Exclua o banco de dados do Firestore (se ele foi criado):
gcloud firestore databases delete --database="coffee-menu" --quiet
Etapa opcional: exclua todo o projeto. ⚠️Faça isso APENAS se você tiver criado um projeto dedicado para este laboratório
gcloud projects delete $PROJECT_ID
10. Parabéns
Parabéns! Você criou e implantou um agente de IA Barista de geração aumentada por recuperação (RAG) usando o ADK do Google e o Cloud Run.
O que você aprendeu
- Construção de ferramentas RAG simples em Python.
- Usando o
LlmAgente oInMemoryRunnerdo ADK. - Como criar experiências de chat com estado no Streamlit.
- Como implantar o Streamlit no Cloud Run usando builds baseados em origem.