1. Pengantar
Dalam codelab ini, Anda akan membuat agen Barista AI interaktif untuk kedai kopi. Dengan menggunakan Agent Development Kit (ADK) open source Google dan model Gemini 3.5 Flash, Anda akan mengimplementasikan Retrieval-Augmented Generation (RAG) untuk mendasarkan rekomendasi agen pada set data menu tiruan. Terakhir, Anda akan membungkus agen dalam antarmuka pengguna Streamlit dan men-deploy-nya ke Cloud Run.
Yang akan Anda lakukan
- Buat sumber data RAG (
menu.json) yang berisi item kopi, tag, dan alergen. - Bangun agen AI menggunakan ADK
LlmAgentdan hubungkan alat Python untuk memuat data menu. - Gabungkan agen dalam aplikasi chat Streamlit yang mengelola histori percakapan.
- Deploy aplikasi Streamlit ke Cloud Run menggunakan deployment berbasis sumber.
- Uji perujukan RAG dan pengetahuan tentang alergen.

Yang Anda butuhkan
- Browser web seperti Chrome.
- Project Google Cloud yang mengaktifkan penagihan.
- Pemahaman dasar tentang Python.
Codelab ini ditujukan bagi developer dari semua level, termasuk pemula.
Perkiraan Biaya: Kurang dari $1,00 USD.
2. Sebelum memulai
Buat Project Google Cloud
- Di Konsol Google Cloud, pilih atau buat project Google Cloud.
- Pastikan penagihan diaktifkan untuk project Cloud Anda.
Mulai Cloud Shell
- Klik Activate Cloud Shell di bagian atas konsol Google Cloud.

- Verifikasi autentikasi:

gcloud auth list
- Pastikan project aktif Anda telah ditetapkan:
gcloud config get project
Jika project ID yang ditampilkan tidak benar atau tidak ada yang ditetapkan, jalankan:
gcloud config set project <YOUR_PROJECT_ID>
Mengaktifkan API
Jalankan perintah ini untuk mengaktifkan semua API yang diperlukan:
gcloud services enable \
run.googleapis.com \
aiplatform.googleapis.com \
cloudbuild.googleapis.com
3. Menyiapkan project
Pada langkah ini, Anda akan melakukan inisialisasi variabel lingkungan project dan membuat direktori kerja untuk project.
- Di sesi Cloud Shell yang aktif, inisialisasi variabel lingkungan project berikut:
export PROJECT_ID=$(gcloud config get-value project)
Catatan: Gunakan region terdekat
Temukan region terdekat Anda dan ganti insert-region-here dengan region tersebut dalam perintah berikut:
export REGION=[insert-region-here]
- Buat dan pindah ke direktori project baru bernama
coffee-barista-agent:
mkdir coffee-barista-agent && cd coffee-barista-agent
4. Membuat sumber data menu tiruan
Untuk melatih AI Barista dan mencegahnya berhalusinasi tentang item yang tidak ada, Anda akan membuat set data menu lokal. Agen akan membaca file ini saat runtime melalui alat kustom.
- Buat dan buka
menu.jsondi Cloud Shell Editor:
cloudshell edit menu.json
- Tempelkan konten JSON berikut ke editor dan simpan file:
[
{
"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"]
}
]
- Verifikasi bahwa file JSON diformat dengan benar:
cat menu.json | python3 -m json.tool > /dev/null && echo "Valid JSON!"
💬 Diskusi: JSON Lokal vs. Database Aktif
Mengapa kita menggunakan file menu.json lokal sederhana, bukan database aktif?
Untuk tutorial atau prototipe cepat, file JSON lokal akan menghilangkan waktu dan kompleksitas penyiapan database awal. Namun, dalam aplikasi produksi perusahaan di dunia nyata, Anda akan menghubungkan agen ke database terkelola seperti Cloud Firestore, AlloyDB, atau Cloud SQL.
Dengan menggunakan database aktif, pengelola kedai kopi dapat menambahkan item musiman, memperbarui harga, atau menyesuaikan tag alergen secara dinamis tanpa membangun ulang image container atau men-deploy ulang kode aplikasi. Kita akan menggunakan database aktif sebagai langkah opsional nanti dalam codelab ini.
5. Membangun agen ADK
Sekarang Anda akan menginstal paket yang diperlukan dan membangun logika agen ADK inti. Anda akan menentukan alat get_menu() dan meneruskannya ke LlmAgent.
- Buat dan buka
requirements.txtdi Cloud Shell Editor:
cloudshell edit requirements.txt
- Tempel dependensi berikut ke dalam editor dan simpan file:
google-adk==2.2.0
streamlit==1.58.0
- Buat dan buka
agent.pydi Cloud Shell Editor:
cloudshell edit agent.py
- Tempelkan kode berikut ke
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
)
- Buat dan buka
app.pydi Cloud Shell Editor:
cloudshell edit app.py
- Tempelkan kode berikut ke
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}")
💬 Diskusi: Penyesuaian Model & Efisiensi Token Pengambilan
Mengapa memanggil alat fungsi untuk mengambil menu, bukan hanya menempelkan seluruh teks menu ke dalam petunjuk sistem agen?
Ekonomi token! Menempatkan 8 item dalam perintah memang murah, tetapi bagaimana jika kedai kopi tersebut memperluas jumlah itemnya menjadi 500, termasuk bahan-bahan kustom? Menempelkan set data besar langsung ke perintah sistem akan meningkatkan jumlah token perintah, sehingga meningkatkan biaya transaksi dan latensi respons API pada setiap kueri.
Dengan menggunakan alat ADK, agen secara dinamis meminta untuk membaca menu HANYA jika diperlukan. LLM hanya menerima data menu yang relevan sebagai konteks, sehingga meminimalkan ukuran token perintah.
💬 Diskusi: Penyimpanan Produksi & Status Memori
Apakah histori chat yang disimpan di dalam st.session_state Streamlit tetap ada saat pengguna menutup tab browser?
Tidak. st.session_state sepenuhnya berada dalam memori dan unik untuk koneksi browser yang aktif. Jika pengguna memuat ulang halaman atau menutup tab, histori percakapan mereka dengan barista akan hilang.
Untuk aplikasi produksi, Anda akan menghubungkan runner ADK ke backend penyimpanan persisten seperti Cloud Firestore atau Redis. ADK menyediakan abstraksi layanan bawaan (seperti SessionService) yang mempermudah penyimpanan dan melanjutkan histori chat di seluruh pemuatan ulang halaman dan perangkat.
6. Men-deploy agen ke Cloud Run
Anda akan men-deploy aplikasi Streamlit langsung dari sumber menggunakan buildpack bawaan Cloud Run. Untuk mengikuti prinsip hak istimewa terendah, Anda akan membuat dan men-deploy menggunakan akun layanan kustom khusus, bukan menggunakan akun layanan Compute Engine default.
- Buat akun layanan khusus:
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"
- Berikan peran pengguna Gemini Enterprise Agent Platform (
roles/aiplatform.user) ke akun layanan baru:
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:barista-agent-sa@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/aiplatform.user"
- Deploy layanan menggunakan
gcloud run deploy, dengan meneruskan email akun layanan baru melalui 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
- Setelah di-deploy, temukan URL layanan di output perintah.
💬 Diskusi: Men-deploy Container vs. Sumber, dan Keamanan IAM
Kita men-deploy ke Cloud Run menggunakan gcloud run deploy –source tanpa membuat Dockerfile atau Procfile. Bagaimana Cloud Run mengetahui cara mengompilasi dan mengeksekusi aplikasi Python kita?
Cloud Run menggunakan Buildpacks di balik layar untuk menganalisis repositori Anda. Setelah mendeteksi keberadaanrequirements.txt dan file sumber Python, mesin akan otomatis mengompilasi dan mengemas container runtime Python.
Menulis Dockerfile kustom memberi Anda kontrol penuh atas paket sistem dan lapisan dasar container. Procfile adalah cara yang lebih sederhana untuk mendeklarasikan perintah startup tanpa mengonfigurasi container sepenuhnya. Namun, untuk deployment cepat, men-deploy dari sumber (--source) sangat efisien.
Mengapa kita melakukan langkah tambahan dengan membuat akun layanan kustom barista-agent-sa, bukan hanya menggunakan akun layanan Compute Engine default?
Utamakan keselamatan! Akun layanan Compute Engine default memiliki izin Editor yang sangat luas secara default. Menjalankan penampung Cloud Run kami dengan akun layanan default berarti jika aplikasi kami memiliki bug keamanan, penyerang berpotensi membaca, menulis, atau menghapus resource lain di project Google Cloud kami.
Dengan membuat akun layanan khusus dan hanya menetapkan peran roles/aiplatform.user, kita mengikuti Prinsip Hak Istimewa Terendah: aplikasi memiliki akses yang tepat yang diperlukan untuk memanggil Gemini, dan tidak lebih.
7. Menguji perilaku RAG
Buka URL layanan Cloud Run di browser web dan ajukan pertanyaan kepada AI Barista untuk menguji batasan perujukan dan keamanannya.
- Permintaan dalam menu: Tanya: "Rekomendasikan sesuatu yang kuat dan hangat."Harapan: Agen merekomendasikan Espresso.
- Perangkap di luar menu: Pertanyaan: "Apakah Anda punya matcha frappuccino?"Diharapkan: Agen menolak dengan sopan dan menjelaskan bahwa minuman tersebut tidak ada di menu.
- Permintaan yang mempertimbangkan alergi: Ajukan: "Saya tidak toleran terhadap laktosa, apa yang bisa saya pesan?"Harapan: Agen hanya merekomendasikan item menu bebas susu (seperti Oat Milk Latte, Espresso, Cold Brew). TIDAK merekomendasikan Cappuccino atau Croissant.

8. Opsional: Menemukan agen Anda di Firestore menggunakan Penelusuran Vektor
Dalam skenario produksi, menyimpan item menu di file menu.json lokal tidak ideal karena setiap perubahan pada menu memerlukan pembangunan ulang image container dan deployment ulang layanan Cloud Run.
Untuk membuat aplikasi yang dinamis dan skalabel, Anda dapat memigrasikan data menu ke Cloud Firestore dan menggunakan Vector Search untuk mengambil hanya item menu yang paling relevan berdasarkan kemiripan semantik.

1. Aktifkan Firestore API dan Inisialisasi Database
Jalankan perintah berikut untuk mengaktifkan Firestore API dan membuat database Firestore bernama coffee-menu dalam mode Native:
gcloud services enable firestore.googleapis.com
gcloud firestore databases create --database="coffee-menu" --location=$REGION
Catatan: Pengaktifan API dapat memerlukan waktu 1–2 menit untuk diterapkan. Jika perintah pembuatan database meminta Anda memasukkan API [firestore.googleapis.com] not enabled on project... Would you like to enable and retry?, ketik Y untuk melanjutkan, atau tunggu sebentar dan jalankan kembali perintah.
2. Menambahkan data ke Firestore dengan Data Menu
Untuk mengisi database Firestore dengan cepat menggunakan item menu dari file menu.json, Anda dapat menjalankan skrip Python secara lokal di Cloud Shell.
- Instal library klien Firestore dan GenAI secara lokal di Cloud Shell untuk menjalankan skrip pengisian data:
pip3 install google-cloud-firestore==2.27.0 google-genai==2.11.0
- Buat skrip pengawalan
seed.py:
cloudshell edit seed.py
- Tempelkan kode berikut ke
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!")
- Jalankan skrip:
python3 seed.py
3. Membuat Indeks Vektor Firestore
Untuk melakukan penelusuran vektor pada item menu, Anda harus membuat indeks vektor komposit pada kolom embedding di database Firestore.
Jalankan perintah berikut di terminal 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": "{}"}'
Catatan: Pembuatan indeks Firestore berjalan di latar belakang dan dapat memerlukan waktu beberapa menit hingga selesai. Anda dapat melanjutkan ke langkah berikutnya dalam codelab ini saat indeks sedang dibuat.
4. Memberi Akun Layanan Akses Firestore
Agar layanan Cloud Run Anda dapat membuat kueri Firestore, Anda harus memberikan peran Pengguna Cloud Datastore (roles/datastore.user) kepada akun layanannya:
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:barista-agent-sa@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/datastore.user"
Catatan: Meskipun kita menggunakan Cloud Firestore dalam mode Native, Google Cloud menggunakan peran IAM Cloud Datastore terpadu (roles/datastore.viewer atau roles/datastore.user) untuk mengelola kontrol akses.
5. Memperbarui Kode
Sekarang, perbarui kode Anda untuk mengambil menu dari Firestore, bukan membaca dari menu.json.
- Buka
requirements.txtdi Cloud Shell Editor:
cloudshell edit requirements.txt
- Tambahkan library klien Firestore dan GenAI ke akhir file, lalu simpan:
google-cloud-firestore==2.27.0
google-genai==2.11.0
- Buka
agent.pydi Cloud Shell Editor:
cloudshell edit agent.py
- Temukan blok
# [START get_menu]diagent.pydan ganti seluruhnya (dari# [START get_menu]hingga# [END get_menu]) dengan implementasi Firestore berikut:
# [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]
- Buka
app.pydi Cloud Shell Editor:
cloudshell edit app.py
- Temukan blok
# [START load_menu]diapp.pydan ganti seluruhnya (dari# [START load_menu]hingga# [END load_menu]) dengan logika pemuatan Firestore berikut:
# [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. Men-deploy ulang ke Cloud Run
Deploy aplikasi yang telah diupdate:
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. Memverifikasi Integrasi Firestore
Untuk menguji koneksi agen ke Firestore, tambahkan item menu baru langsung di Firestore dan pastikan agen merekomendasikannya.
- Jalankan perintah berikut di Cloud Shell untuk menulis dokumen baru ke koleksi
menudi Firestore menggunakan 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!')
"
- Muat ulang aplikasi Streamlit Anda di browser untuk menghapus sesi chat dan memuat status database baru.
- Perhatikan bahwa:
- Matcha Green Tea Latte akan otomatis muncul di menu sidebar.
- Tanyakan kepada chatbot: "Apakah Anda punya minuman matcha?"
- Agen harus berhasil merekomendasikan Matcha Green Tea Latte baru dengan deskripsi dan harga yang baru saja Anda tambahkan. Hal ini mengonfirmasi bahwa agen berbasis kueri langsung di database Firestore aktif Anda.
9. Pembersihan
Untuk menghindari biaya berkelanjutan ke akun penagihan Google Cloud Anda, hapus layanan Cloud Run yang di-deploy dan akun layanan kustom.
Hapus layanan Cloud Run:
gcloud run services delete coffee-barista --region $REGION --quiet
Hapus akun layanan kustom:
gcloud iam service-accounts delete barista-agent-sa@$PROJECT_ID.iam.gserviceaccount.com --quiet
(Opsional) Hapus database Firestore (jika dibuat):
gcloud firestore databases delete --database="coffee-menu" --quiet
Langkah opsional: Hapus seluruh project. ⚠️LAKUKAN ini HANYA jika Anda membuat project khusus untuk lab ini
gcloud projects delete $PROJECT_ID
10. Selamat
Selamat! Anda telah membuat dan men-deploy agen AI Barista Retrieval-Augmented Generation (RAG) menggunakan ADK Google dan Cloud Run.
Yang telah Anda pelajari
- Membuat alat RAG sederhana di Python.
- Memanfaatkan
LlmAgentdanInMemoryRunnerADK. - Membuat pengalaman chat dengan status di Streamlit.
- Men-deploy Streamlit ke Cloud Run menggunakan build berbasis sumber.