1. Pengantar
Ringkasan
Dalam codelab ini, Anda akan melihat cara memberi Gemini akses ke data real-time menggunakan fitur baru yang disebut Panggilan Fungsi. Untuk menyimulasikan data real time, Anda akan membuat endpoint layanan cuaca yang menampilkan cuaca saat ini untuk 2 lokasi. Kemudian, Anda akan membuat aplikasi chat yang didukung oleh Gemini, yang menggunakan panggilan fungsi untuk mengambil data cuaca saat ini.
Mari kita gunakan visual singkat untuk memahami Panggilan Fungsi.
- Perintah meminta lokasi cuaca saat ini di lokasi tertentu
- Perintah ini + kontrak fungsi untuk getWeather() dikirim ke Gemini
- Gemini meminta aplikasi chatbot memanggil "getWeather(Seattle)" atas namanya
- Aplikasi akan mengirimkan kembali hasilnya (40 derajat Fahrenheit dan hujan)
- Gemini mengirimkan kembali hasil ke pemanggil
Singkatnya, Gemini tidak memanggil Fungsi. Anda sebagai developer harus memanggil fungsi dan mengirimkan hasilnya kembali ke Gemini.

Yang akan Anda pelajari
- Cara kerja panggilan fungsi Gemini
- Cara men-deploy aplikasi chatbot yang didukung Gemini sebagai layanan Cloud Run
2. Penyiapan dan Persyaratan
Prasyarat
- Anda login ke Konsol Cloud.
- Anda telah men-deploy fungsi generasi ke-2 sebelumnya. Misalnya, Anda dapat mengikuti panduan memulai Cloud Function generasi ke-2 untuk mulai menggunakannya.
Mengaktifkan Cloud Shell
- Dari Cloud Console, klik Aktifkan Cloud Shell
.

Jika ini adalah pertama kalinya Anda memulai Cloud Shell, Anda akan melihat layar perantara yang menjelaskan apa itu Cloud Shell. Jika Anda melihat layar perantara, klik Continue.

Perlu waktu beberapa saat untuk menyediakan dan terhubung ke Cloud Shell.

Virtual machine ini dilengkapi dengan semua alat pengembangan yang diperlukan. VM ini menawarkan direktori beranda tetap sebesar 5 GB dan beroperasi di Google Cloud, sehingga sangat meningkatkan performa dan autentikasi jaringan. Sebagian besar pekerjaan Anda dalam codelab ini dapat dilakukan dengan browser.
Setelah terhubung ke Cloud Shell, Anda akan melihat bahwa Anda telah diautentikasi dan project telah ditetapkan ke project ID Anda.
- Jalankan perintah berikut di Cloud Shell untuk mengonfirmasi bahwa Anda telah diautentikasi:
gcloud auth list
Output perintah
Credentialed Accounts
ACTIVE ACCOUNT
* <my_account>@<my_domain.com>
To set the active account, run:
$ gcloud config set account `ACCOUNT`
- Jalankan perintah berikut di Cloud Shell untuk mengonfirmasi bahwa perintah gcloud mengetahui project Anda:
gcloud config list project
Output perintah
[core] project = <PROJECT_ID>
Jika tidak, Anda dapat menyetelnya dengan perintah ini:
gcloud config set project <PROJECT_ID>
Output perintah
Updated property [core/project].
3. Menyiapkan variabel lingkungan dan mengaktifkan API
Menyiapkan variabel lingkungan
Anda dapat menetapkan variabel lingkungan yang akan digunakan di seluruh codelab ini.
PROJECT_ID=<YOUR_PROJECT_ID> REGION=<YOUR_REGION, e.g. us-central1> WEATHER_SERVICE=weatherservice FRONTEND=frontend SERVICE_ACCOUNT="vertex-ai-caller" SERVICE_ACCOUNT_ADDRESS=$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
Mengaktifkan API
Sebelum Anda dapat mulai menggunakan codelab ini, ada beberapa API yang perlu diaktifkan. Codelab ini memerlukan penggunaan API berikut. Anda dapat mengaktifkan API tersebut dengan menjalankan perintah berikut:
gcloud services enable run.googleapis.com \
cloudbuild.googleapis.com \
aiplatform.googleapis.com
4. Membuat akun layanan untuk memanggil Vertex AI
Akun layanan ini akan digunakan oleh Cloud Run untuk memanggil Vertex AI Gemini API.
Pertama, buat akun layanan dengan menjalankan perintah ini:
gcloud iam service-accounts create $SERVICE_ACCOUNT \ --display-name="Cloud Run to access Vertex AI APIs"
Kedua, berikan peran Vertex AI User ke akun layanan.
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \ --role=roles/aiplatform.user
5. Buat layanan Cloud Run backend
Pertama, buat direktori untuk kode sumber dan cd ke direktori tersebut.
mkdir -p gemini-function-calling/weatherservice gemini-function-calling/frontend && cd gemini-function-calling/weatherservice
Kemudian, buat file package.json dengan konten berikut:
{
"name": "weatherservice",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.18.3"
}
}
Selanjutnya, buat file sumber app.js dengan konten di bawah. File ini berisi titik entri untuk layanan dan berisi logika utama untuk aplikasi.
const express = require("express");
const app = express();
app.get("/getweather", (req, res) => {
const location = req.query.location;
let temp, conditions;
if (location == "New Orleans") {
temp = 99;
conditions = "hot and humid";
} else if (location == "Seattle") {
temp = 40;
conditions = "rainy and overcast";
} else {
res.status(400).send("there is no data for the requested location");
}
res.json({
weather: temp,
location: location,
conditions: conditions
});
});
const port = parseInt(process.env.PORT) || 8080;
app.listen(port, () => {
console.log(`weather service: listening on port ${port}`);
});
app.get("/", (req, res) => {
res.send("welcome to hard-coded weather!");
});
Men-deploy Layanan Cuaca
Anda dapat menggunakan perintah ini untuk men-deploy layanan cuaca.
gcloud run deploy $WEATHER_SERVICE \ --source . \ --region $REGION \ --allow-unauthenticated
Menguji Layanan Cuaca
Anda dapat memverifikasi cuaca untuk 2 lokasi menggunakan curl:
WEATHER_SERVICE_URL=$(gcloud run services describe $WEATHER_SERVICE \
--platform managed \
--region=$REGION \
--format='value(status.url)')
curl $WEATHER_SERVICE_URL/getweather?location=Seattle
curl $WEATHER_SERVICE_URL/getweather?location\=New%20Orleans
Seattle bersuhu 40 derajat F dan hujan, sedangkan New Orleans bersuhu 99 derajat F dan lembap, selalu.
6. Buat layanan Frontend
Pertama, cd ke direktori frontend.
cd gemini-function-calling/frontend
Kemudian, buat file package.json dengan konten berikut:
{
"name": "demo1",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node app.js",
"nodemon": "nodemon app.js",
"cssdev": "npx tailwindcss -i ./input.css -o ./public/output.css --watch",
"tailwind": "npx tailwindcss -i ./input.css -o ./public/output.css",
"dev": "npm run tailwind && npm run nodemon"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@google-cloud/vertexai": "^0.4.0",
"axios": "^1.6.7",
"express": "^4.18.2",
"express-ws": "^5.0.2",
"htmx.org": "^1.9.10"
},
"devDependencies": {
"nodemon": "^3.1.0",
"tailwindcss": "^3.4.1"
}
}
Selanjutnya, buat file sumber app.js dengan konten di bawah. File ini berisi titik entri untuk layanan dan berisi logika utama untuk aplikasi.
const express = require("express");
const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
const path = require("path");
const fs = require("fs");
const util = require("util");
const { spinnerSvg } = require("./spinnerSvg.js");
const expressWs = require("express-ws")(app);
app.use(express.static("public"));
const {
VertexAI,
FunctionDeclarationSchemaType
} = require("@google-cloud/vertexai");
// get project and location from metadata service
const metadataService = require("./metadataService.js");
// instance of Gemini model
let generativeModel;
// 1: define the function
const functionDeclarations = [
{
function_declarations: [
{
name: "getweather",
description: "get weather for a given location",
parameters: {
type: FunctionDeclarationSchemaType.OBJECT,
properties: {
location: {
type: FunctionDeclarationSchemaType.STRING
},
degrees: {
type: FunctionDeclarationSchemaType.NUMBER,
"description":
"current temperature in fahrenheit"
},
conditions: {
type: FunctionDeclarationSchemaType.STRING,
"description":
"how the weather feels subjectively"
}
},
required: ["location"]
}
}
]
}
];
// on instance startup
const port = parseInt(process.env.PORT) || 8080;
app.listen(port, async () => {
console.log(`demo1: listening on port ${port}`);
const project = await metadataService.getProjectId();
const location = await metadataService.getRegion();
// Vertex client library instance
const vertex_ai = new VertexAI({
project: project,
location: location
});
// Instantiate models
generativeModel = vertex_ai.getGenerativeModel({
model: "gemini-1.0-pro-001"
});
});
const axios = require("axios");
const baseUrl = "https://weatherservice-k6msmyp47q-uc.a.run.app";
app.ws("/sendMessage", async function (ws, req) {
// this chat history will be pinned to the current
// Cloud Run instance. Consider using Firestore &
// Firebase anonymous auth instead.
// start ephemeral chat session with Gemini
const chatWithModel = generativeModel.startChat({
tools: functionDeclarations
});
ws.on("message", async function (message) {
let questionToAsk = JSON.parse(message).message;
console.log("WebSocket message: " + questionToAsk);
ws.send(`<div hx-swap-oob="beforeend:#toupdate"><div
id="questionToAsk"
class="text-black m-2 text-right border p-2 rounded-lg ml-24">
${questionToAsk}
</div></div>`);
// to simulate a natural pause in conversation
await sleep(500);
// get timestamp for div to replace
const now = "fromGemini" + Date.now();
ws.send(`<div hx-swap-oob="beforeend:#toupdate"><div
id=${now}
class=" text-blue-400 m-2 text-left border p-2 rounded-lg mr-24">
${spinnerSvg}
</div></div>`);
const results = await chatWithModel.sendMessage(questionToAsk);
// Function calling demo
let response1 = await results.response;
let data = response1.candidates[0].content.parts[0];
let methodToCall = data.functionCall;
if (methodToCall === undefined) {
console.log("Gemini says: ", data.text);
ws.send(`<div
id=${now}
hx-swap-oob="true"
hx-swap="outerHTML"
class="text-blue-400 m-2 text-left border p-2 rounded-lg mr-24">
${data.text}
</div>`);
// bail out - Gemini doesn't want to return a function
return;
}
// otherwise Gemini wants to call a function
console.log(
"Gemini wants to call: " +
methodToCall.name +
" with args: " +
util.inspect(methodToCall.args, {
showHidden: false,
depth: null,
colors: true
})
);
// make the external call
let jsonReturned;
try {
const responseFunctionCalling = await axios.get(
baseUrl + "/" + methodToCall.name,
{
params: {
location: methodToCall.args.location
}
}
);
jsonReturned = responseFunctionCalling.data;
} catch (ex) {
// in case an invalid location was provided
jsonReturned = ex.response.data;
}
console.log("jsonReturned: ", jsonReturned);
// tell the model what function we just called
const functionResponseParts = [
{
functionResponse: {
name: methodToCall.name,
response: {
name: methodToCall.name,
content: { jsonReturned }
}
}
}
];
// // Send a follow up message with a FunctionResponse
const result2 = await chatWithModel.sendMessage(
functionResponseParts
);
// This should include a text response from the model using the response content
// provided above
const response2 = await result2.response;
let answer = response2.candidates[0].content.parts[0].text;
console.log("answer: ", answer);
ws.send(`<div
id=${now}
hx-swap-oob="true"
hx-swap="outerHTML"
class="text-blue-400 m-2 text-left border p-2 rounded-lg mr-24">
${answer}
</div>`);
});
ws.on("close", () => {
console.log("WebSocket was closed");
});
});
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
Buat file input.css untuk tailwindCSS.
@tailwind base; @tailwind components; @tailwind utilities;
Buat file tailwind.config.js untuk tailwindCSS.
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./**/*.{html,js}"],
theme: {
extend: {}
},
plugins: []
};
Buat file metadataService.js untuk mendapatkan project ID dan region untuk layanan Cloud Run yang di-deploy. Nilai ini akan digunakan untuk membuat instance library klien Vertex AI.
const your_project_id = "YOUR_PROJECT_ID";
const your_region = "YOUR_REGION";
const axios = require("axios");
module.exports = {
getProjectId: async () => {
let project = "";
try {
// Fetch the token to make a GCF to GCF call
const response = await axios.get(
"http://metadata.google.internal/computeMetadata/v1/project/project-id",
{
headers: {
"Metadata-Flavor": "Google"
}
}
);
if (response.data == "") {
// running locally on Cloud Shell
project = your_project_id;
} else {
// use project id from metadata service
project = response.data;
}
} catch (ex) {
// running locally on local terminal
project = your_project_id;
}
return project;
},
getRegion: async () => {
let region = "";
try {
// Fetch the token to make a GCF to GCF call
const response = await axios.get(
"http://metadata.google.internal/computeMetadata/v1/instance/region",
{
headers: {
"Metadata-Flavor": "Google"
}
}
);
if (response.data == "") {
// running locally on Cloud Shell
region = your_region;
} else {
// use region from metadata service
let regionFull = response.data;
const index = regionFull.lastIndexOf("/");
region = regionFull.substring(index + 1);
}
} catch (ex) {
// running locally on local terminal
region = your_region;
}
return region;
}
};
Buat file bernama spinnerSvg.js
module.exports.spinnerSvg = `<svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-blue-500"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
class="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
stroke-width="4"
></circle>
<path
class="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path></svg>`;
Buat direktori public baru.
mkdir public cd public
Sekarang buat file index.html untuk front-end, yang akan menggunakan htmx.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<script
src="https://unpkg.com/htmx.org@1.9.10"
integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC"
crossorigin="anonymous"
></script>
<link href="./output.css" rel="stylesheet" />
<script src="https://unpkg.com/htmx.org/dist/ext/ws.js"></script>
<title>Demo 2</title>
</head>
<body>
<div id="herewego" text-center>
<!-- <div id="replaceme2" hx-swap-oob="true">Hello world</div> -->
<div
class="container mx-auto mt-8 text-center max-w-screen-lg"
>
<div
class="overflow-y-scroll bg-white p-2 border h-[500px] space-y-4 rounded-lg m-auto"
>
<div id="toupdate"></div>
</div>
<form
hx-trigger="submit, keyup[keyCode==13] from:body"
hx-ext="ws"
ws-connect="/sendMessage"
ws-send=""
hx-on="htmx:wsAfterSend: document.getElementById('message').value = ''"
>
<div class="mb-6 mt-6 flex gap-4">
<textarea
rows="2"
type="text"
id="message"
name="message"
class="block grow rounded-lg border p-6 resize-none"
required
>
What's is the current weather in Seattle?</textarea
>
<button
type="submit"
class="bg-blue-500 text-white px-4 py-2 rounded-lg text-center text-sm font-medium"
>
Send
</button>
</div>
</form>
</div>
</div>
</body>
</html>
7. Menjalankan layanan Frontend secara lokal
Pertama, pastikan Anda berada di direktori frontend untuk codelab Anda.
cd .. && pwd
Kemudian, instal dependensi dengan menjalankan perintah berikut:
npm install
Menggunakan ADC saat berjalan secara lokal
Jika Anda menjalankan di Cloud Shell, Anda sudah menjalankan di virtual machine Google Compute Engine. Kredensial Anda yang terkait dengan mesin virtual ini (seperti yang ditunjukkan dengan menjalankan gcloud auth list) akan otomatis digunakan oleh Kredensial Default Aplikasi, sehingga Anda tidak perlu menggunakan perintah gcloud auth application-default login. Anda dapat langsung membuka bagian Menjalankan aplikasi secara lokal
Namun, jika Anda menjalankan di terminal lokal (yaitu, bukan di Cloud Shell), Anda harus menggunakan Kredensial Default Aplikasi untuk melakukan autentikasi ke Google API. Anda dapat 1) login menggunakan kredensial Anda (asalkan Anda memiliki peran Pengguna Vertex AI dan Pengguna Datastore) atau 2) Anda dapat login dengan meniru akun layanan yang digunakan dalam codelab ini.
Opsi 1) Menggunakan kredensial Anda untuk ADC
Jika ingin menggunakan kredensial, Anda dapat menjalankan gcloud auth list terlebih dahulu untuk memverifikasi cara Anda diautentikasi di gcloud. Selanjutnya, Anda mungkin perlu memberikan peran Vertex AI User ke identitas Anda. Jika identitas Anda memiliki peran Pemilik, Anda sudah memiliki peran pengguna Vertex AI ini. Jika tidak, Anda dapat menjalankan perintah ini untuk memberikan peran pengguna Vertex AI dan peran Pengguna Datastore ke identitas Anda.
USER=<YOUR_PRINCIPAL_EMAIL> gcloud projects add-iam-policy-binding $PROJECT_ID \ --member user:$USER \ --role=roles/aiplatform.user gcloud projects add-iam-policy-binding $PROJECT_ID \ --member user:$USER \ --role=roles/datastore.user
Kemudian, jalankan perintah berikut
gcloud auth application-default login
Opsi 2) Meniru Identitas Akun Layanan untuk ADC
Jika Anda ingin menggunakan akun layanan yang dibuat dalam codelab ini, akun pengguna Anda harus memiliki peran Service Account Token Creator. Anda dapat memperoleh peran ini dengan menjalankan perintah berikut:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member user:$USER \ --role=roles/iam.serviceAccountTokenCreator
Selanjutnya, Anda akan menjalankan perintah berikut untuk menggunakan ADC dengan akun layanan
gcloud auth application-default login --impersonate-service-account=$SERVICE_ACCOUNT_ADDRESS
Menjalankan aplikasi secara lokal
Terakhir, Anda dapat memulai aplikasi dengan menjalankan skrip berikut. Skrip dev ini juga akan menghasilkan file output.css dari tailwindCSS.
npm run dev
Anda dapat melihat pratinjau situs dengan membuka tombol Pratinjau Web dan memilih Pratinjau Port 8080

8. Men-deploy dan menguji layanan Frontend
Pertama, jalankan perintah ini untuk memulai deployment dan tentukan akun layanan yang akan digunakan. Jika akun layanan tidak ditentukan, akun layanan komputasi default akan digunakan.
gcloud run deploy $FRONTEND \ --service-account $SERVICE_ACCOUNT_ADDRESS \ --source . \ --region $REGION \ --allow-unauthenticated
Buka URL layanan untuk frontend di browser Anda. Ajukan pertanyaan "What is the current weather in Jakarta?" (Bagaimana cuaca saat ini di Jakarta?) dan Gemini akan menjawab "It is currently 30 degrees and sunny" (Saat ini 30 derajat dan cerah). Jika Anda bertanya "Bagaimana cuaca saat ini di Jakarta?", Gemini akan merespons dengan "Saya tidak dapat memenuhi permintaan ini. Weather API yang tersedia tidak memiliki data untuk Boston."
9. Selamat!
Selamat, Anda telah menyelesaikan codelab.
Sebaiknya tinjau dokumentasi Cloud Run, Vertex AI Gemini API, dan panggilan fungsi.
Yang telah kita bahas
- Cara kerja panggilan fungsi Gemini
- Cara men-deploy aplikasi chatbot yang didukung Gemini sebagai layanan Cloud Run
10. Pembersihan
Untuk menghindari biaya yang tidak disengaja (misalnya, jika layanan Cloud Run ini tidak sengaja dipanggil lebih banyak daripada alokasi pemanggilan Cloud Run bulanan Anda di tingkat gratis), Anda dapat menghapus layanan Cloud Run atau menghapus project yang Anda buat di Langkah 2.
Untuk menghapus layanan Cloud Run, buka Konsol Cloud Run di https://console.cloud.google.com/functions/ dan hapus layanan $WEATHER_SERVICE dan $FRONTEND yang Anda buat dalam codelab ini.
Anda juga dapat menghapus akun layanan vertex-ai-caller atau mencabut peran Vertex AI User, untuk menghindari panggilan yang tidak disengaja ke Gemini.
Jika Anda memilih untuk menghapus seluruh project, Anda dapat membuka https://console.cloud.google.com/cloud-resource-manager, memilih project yang Anda buat di Langkah 2, lalu memilih Hapus. Jika menghapus project, Anda harus mengubah project di Cloud SDK. Anda dapat melihat daftar semua project yang tersedia dengan menjalankan gcloud projects list.