1. Giriş
Genel Bakış
Bu codelab'de, işlev çağrısı adlı yeni bir özelliği kullanarak Gemini'a gerçek zamanlı verilere erişim izni verme adımları gösterilmektedir. Anlık verileri simüle etmek için 2 konumun mevcut hava durumunu döndüren bir hava durumu hizmeti uç noktası oluşturacaksınız. Ardından, mevcut hava durumunu almak için işlev çağrısı kullanan, Gemini destekli bir sohbet uygulaması oluşturacaksınız.
İşlev çağrısını anlamak için hızlı bir görsel kullanalım.
- İstem, belirli bir konumdaki mevcut hava durumu konumlarını istiyor
- Bu istem ve getWeather() işlev sözleşmesi Gemini'a gönderilir.
- Gemini, sohbet botu uygulamasının kendi adına "getWeather(Seattle)" işlevini çağırmasını istiyor.
- Uygulama sonuçları geri gönderir (4,4 °C ve yağmurlu).
- Gemini, sonuçları arayana geri gönderir.
Özetlemek gerekirse Gemini, işlevi çağırmaz. Geliştirici olarak işlevi çağırmalı ve sonuçları Gemini'a geri göndermelisiniz.

Neler öğreneceksiniz?
- Gemini işlev çağrısının işleyiş şekli
- Gemini destekli bir chatbot uygulamasını Cloud Run hizmeti olarak dağıtma
2. Kurulum ve Gereksinimler
Ön koşullar
- Cloud Console'a giriş yapmış olmanız gerekir.
- Daha önce 2. nesil bir işlev dağıtmış olmanız gerekir. Örneğin, başlamak için 2. nesil Cloud Functions işlevini dağıtma hızlı başlangıç kılavuzunu inceleyebilirsiniz.
Cloud Shell'i etkinleştirme
- Cloud Console'da Cloud Shell'i etkinleştir 'i
tıklayın.

Cloud Shell'i ilk kez başlatıyorsanız ne olduğunu açıklayan bir ara ekran gösterilir. Ara ekran gösterildiyse Devam'ı tıklayın.

Cloud Shell'in temel hazırlığı ve bağlanması yalnızca birkaç dakikanızı alır.

Bu sanal makineye, ihtiyaç duyacağınız tüm geliştirme araçları yüklenmiştir. 5 GB boyutunda kalıcı bir ana dizin bulunur ve Google Cloud'da çalışır. Bu sayede ağ performansı ve kimlik doğrulama önemli ölçüde güçlenir. Bu codelab'deki çalışmalarınızın neredeyse tamamını tarayıcıyla yapabilirsiniz.
Cloud Shell'e bağlandıktan sonra kimliğinizin doğrulandığını ve projenin, proje kimliğinize ayarlandığını görürsünüz.
- Kimliğinizin doğrulandığını onaylamak için Cloud Shell'de şu komutu çalıştırın:
gcloud auth list
Komut çıkışı
Credentialed Accounts
ACTIVE ACCOUNT
* <my_account>@<my_domain.com>
To set the active account, run:
$ gcloud config set account `ACCOUNT`
- gcloud komutunun projeniz hakkında bilgi sahibi olduğunu onaylamak için Cloud Shell'de aşağıdaki komutu çalıştırın:
gcloud config list project
Komut çıkışı
[core] project = <PROJECT_ID>
Değilse şu komutla ayarlayabilirsiniz:
gcloud config set project <PROJECT_ID>
Komut çıkışı
Updated property [core/project].
3. Ortam değişkenlerini ayarlama ve API'leri etkinleştirme
Ortam değişkenlerini ayarlama
Bu codelab boyunca kullanılacak ortam değişkenlerini ayarlayabilirsiniz.
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
API'leri etkinleştir
Bu codelab'i kullanmaya başlamadan önce etkinleştirmeniz gereken birkaç API vardır. Bu codelab'de aşağıdaki API'lerin kullanılması gerekir. Bu API'leri aşağıdaki komutu çalıştırarak etkinleştirebilirsiniz:
gcloud services enable run.googleapis.com \
cloudbuild.googleapis.com \
aiplatform.googleapis.com
4. Vertex AI'ı çağırmak için hizmet hesabı oluşturma
Bu hizmet hesabı, Vertex AI Gemini API'yi çağırmak için Cloud Run tarafından kullanılır.
Öncelikle şu komutu çalıştırarak hizmet hesabını oluşturun:
gcloud iam service-accounts create $SERVICE_ACCOUNT \ --display-name="Cloud Run to access Vertex AI APIs"
İkinci olarak, hizmet hesabına Vertex AI Kullanıcısı rolünü verin.
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \ --role=roles/aiplatform.user
5. Arka uç Cloud Run hizmetini oluşturma
Öncelikle kaynak kodu için bir dizin oluşturun ve bu dizine gidin.
mkdir -p gemini-function-calling/weatherservice gemini-function-calling/frontend && cd gemini-function-calling/weatherservice
Ardından, aşağıdaki içeriğe sahip bir package.json dosyası oluşturun:
{
"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"
}
}
Ardından, aşağıdaki içeriğe sahip bir app.js kaynak dosyası oluşturun. Bu dosya, hizmetin giriş noktasını ve uygulamanın ana mantığını içerir.
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!");
});
Hava durumu hizmetini dağıtma
Hava durumu hizmetini dağıtmak için bu komutu kullanabilirsiniz.
gcloud run deploy $WEATHER_SERVICE \ --source . \ --region $REGION \ --allow-unauthenticated
Hava durumu hizmetini test etme
2 konumun hava durumunu curl kullanarak doğrulayabilirsiniz:
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'da sıcaklık 40 derece ve hava yağmurlu, New Orleans'ta ise sıcaklık 99 derece ve hava her zaman nemli.
6. Ön uç hizmetini oluşturun
Öncelikle, cd komutunu kullanarak ön uç dizinine gidin.
cd gemini-function-calling/frontend
Ardından, aşağıdaki içeriğe sahip bir package.json dosyası oluşturun:
{
"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"
}
}
Ardından, aşağıdaki içeriğe sahip bir app.js kaynak dosyası oluşturun. Bu dosya, hizmetin giriş noktasını ve uygulamanın ana mantığını içerir.
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);
});
}
TailwindCSS için bir input.css dosyası oluşturun.
@tailwind base; @tailwind components; @tailwind utilities;
tailwindCSS için tailwind.config.js dosyasını oluşturun.
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./**/*.{html,js}"],
theme: {
extend: {}
},
plugins: []
};
Dağıtılan Cloud Run hizmetinin proje kimliğini ve bölgesini almak için metadataService.js dosyasını oluşturun. Bu değerler, Vertex AI istemci kitaplıklarının bir örneğini oluşturmak için kullanılır.
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;
}
};
spinnerSvg.js adlı bir dosya oluşturun.
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>`;
Yeni bir public dizini oluşturun.
mkdir public cd public
Şimdi htmx kullanacak olan index.html dosyasını kullanıcı arabirimi için oluşturun.
<!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. Ön uç hizmetini yerel olarak çalıştırma
Öncelikle, codelab'iniz için frontend dizininde olduğunuzdan emin olun.
cd .. && pwd
Ardından, aşağıdaki komutu çalıştırarak bağımlılıkları yükleyin:
npm install
Yerel olarak çalıştırırken ADC'yi kullanma
Cloud Shell'de çalışıyorsanız zaten bir Google Compute Engine sanal makinesinde çalışıyorsunuzdur. Bu sanal makineyle ilişkili kimlik bilgileriniz (gcloud auth list çalıştırılarak gösterildiği gibi) Uygulama Varsayılan Kimlik Bilgileri tarafından otomatik olarak kullanılacağından gcloud auth application-default login komutunu kullanmanız gerekmez. Uygulamayı yerel olarak çalıştırma bölümüne atlayabilirsiniz.
Ancak yerel terminalinizde (ör. Cloud Shell'de değil) çalışıyorsanız Google API'lerinde kimlik doğrulaması yapmak için Uygulama Varsayılan Kimlik Bilgileri'ni kullanmanız gerekir. 1) Kimlik bilgilerinizi kullanarak giriş yapabilir (hem Vertex AI Kullanıcısı hem de Veri Deposu Kullanıcısı rollerine sahip olmanız gerekir) veya 2) bu codelab'de kullanılan hizmet hesabının kimliğine bürünerek giriş yapabilirsiniz.
1. seçenek: ADC için kimlik bilgilerinizi kullanma
Kimlik bilgilerinizi kullanmak istiyorsanız öncelikle gcloud auth list komutunu çalıştırarak gcloud'da nasıl kimlik doğrulandığınızı doğrulayabilirsiniz. Ardından, kimliğinize Vertex AI Kullanıcısı rolünü vermeniz gerekebilir. Kimliğinizde Sahip rolü varsa bu Vertex AI kullanıcı rolüne zaten sahipsinizdir. Aksi takdirde, kimliğinize Vertex AI kullanıcı rolü ve veri deposu kullanıcı rolü vermek için bu komutu çalıştırabilirsiniz.
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
Ardından aşağıdaki komutu çalıştırın.
gcloud auth application-default login
2. seçenek: ADC için bir hizmet hesabının kimliğine bürünme
Bu codelab'de oluşturulan hizmet hesabını kullanmak istiyorsanız kullanıcı hesabınızın Hizmet Hesabı Jetonu Oluşturucu rolüne sahip olması gerekir. Bu rolü aşağıdaki komutu çalıştırarak edinebilirsiniz:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member user:$USER \ --role=roles/iam.serviceAccountTokenCreator
Ardından, hizmet hesabıyla ADC'yi kullanmak için aşağıdaki komutu çalıştıracaksınız.
gcloud auth application-default login --impersonate-service-account=$SERVICE_ACCOUNT_ADDRESS
Uygulamayı yerel olarak çalıştırma
Son olarak, aşağıdaki komut dosyasını çalıştırarak uygulamayı başlatabilirsiniz. Bu geliştirme komut dosyası, tailwindCSS'den output.css dosyasını da oluşturur.
npm run dev
Web Önizlemesi düğmesini açıp Önizleme Bağlantı Noktası 8080'i seçerek web sitesini önizleyebilirsiniz.

8. Ön uç hizmetini dağıtma ve test etme
Öncelikle, dağıtımı başlatmak ve kullanılacak hizmet hesabını belirtmek için bu komutu çalıştırın. Hizmet hesabı belirtilmezse varsayılan Compute hizmet hesabı kullanılır.
gcloud run deploy $FRONTEND \ --service-account $SERVICE_ACCOUNT_ADDRESS \ --source . \ --region $REGION \ --allow-unauthenticated
Tarayıcınızda ön uç için hizmet URL'sini açın. "Seattle'da şu anda hava nasıl?" diye sorun. Gemini, "Şu anda hava 40 derece ve yağmurlu." şeklinde yanıt vermelidir. "Boston'da şu an hava nasıl?" diye sorarsanız Gemini, "Bu isteği yerine getiremiyorum. Kullanılabilir hava durumu API'sinde Boston'a ait veri yok."
9. Tebrikler!
Tebrikler, codelab'i tamamladınız.
Cloud Run, Vertex AI Gemini API'leri ve işlev çağrısı belgelerini incelemenizi öneririz.
İşlediğimiz konular
- Gemini işlev çağrısının işleyiş şekli
- Gemini destekli bir chatbot uygulamasını Cloud Run hizmeti olarak dağıtma
10. Temizleme
Yanlışlıkla ücretlendirilmemek için (örneğin, bu Cloud Run hizmeti ücretsiz katmandaki aylık Cloud Run çağırma tahsisinizden daha fazla sayıda yanlışlıkla çağrılırsa) Cloud Run hizmetini veya 2. adımda oluşturduğunuz projeyi silebilirsiniz.
Cloud Run hizmetlerini silmek için https://console.cloud.google.com/functions/ adresinden Cloud Run Cloud Console'a gidin ve bu codelab'de oluşturduğunuz $WEATHER_SERVICE ve $FRONTEND hizmetlerini silin.
Gemini'a yanlışlıkla yapılan çağrıları önlemek için vertex-ai-caller hizmet hesabını silebilir veya Vertex AI Kullanıcısı rolünü iptal edebilirsiniz.
Projenin tamamını silmeyi tercih ederseniz https://console.cloud.google.com/cloud-resource-manager adresine gidebilir, 2. adımda oluşturduğunuz projeyi seçip Sil'i tıklayabilirsiniz. Projeyi silerseniz Cloud SDK'nızda projeleri değiştirmeniz gerekir. gcloud projects list komutunu çalıştırarak kullanılabilir tüm projelerin listesini görüntüleyebilirsiniz.