জেমিনি ফাংশন কলিংয়ের সাথে কীভাবে ক্লাউড রান ব্যবহার করবেন

১. ভূমিকা

সংক্ষিপ্ত বিবরণ

এই কোডল্যাবে, আপনি দেখবেন কীভাবে 'ফাংশন কলিং' নামক একটি নতুন ফিচার ব্যবহার করে জেমিনিকে রিয়েল-টাইম ডেটা অ্যাক্সেস করার সুযোগ দেওয়া যায়। রিয়েল-টাইম ডেটা সিমুলেট করার জন্য, আপনি একটি ওয়েদার সার্ভিস এন্ডপয়েন্ট তৈরি করবেন যা দুটি স্থানের বর্তমান আবহাওয়া জানাবে। এরপর, আপনি জেমিনি দ্বারা চালিত একটি চ্যাট অ্যাপ তৈরি করবেন, যা বর্তমান আবহাওয়া জানার জন্য ফাংশন কলিং ব্যবহার করবে।

ফাংশন কলিং বোঝার জন্য চলুন একটি সহজ উদাহরণ দেখি।

  • একটি নির্দিষ্ট স্থানের বর্তমান আবহাওয়ার অবস্থান জানতে তাৎক্ষণিক অনুরোধ।
  • এই প্রম্পট এবং getWeather() ফাংশনের কন্ট্রাক্টটি জেমিনিতে পাঠানো হয়।
  • জেমিনি অনুরোধ করে যে চ্যাট বট অ্যাপটি তার পক্ষ থেকে "getWeather(Seattle)"-কে কল করুক।
  • অ্যাপটি ফলাফল পাঠিয়েছে (৪০ ডিগ্রি ফারেনহাইট এবং বৃষ্টি হচ্ছে)।
  • জেমিনি কলারকে ফলাফল ফেরত পাঠায়।

সংক্ষেপে বলতে গেলে, জেমিনি ফাংশনটিকে কল করে না। ডেভেলপার হিসেবে আপনাকেই ফাংশনটি কল করতে হবে এবং ফলাফল জেমিনিতে ফেরত পাঠাতে হবে।

ফাংশন কলিং প্রবাহের ডায়াগ্রাম

আপনি যা শিখবেন

  • জেমিনি ফাংশন কলিং কীভাবে কাজ করে
  • জেমিনি-চালিত চ্যাটবট অ্যাপকে ক্লাউড রান পরিষেবা হিসাবে কীভাবে স্থাপন করবেন

২. সেটআপ এবং প্রয়োজনীয়তা

পূর্বশর্ত

ক্লাউড শেল সক্রিয় করুন

  1. ক্লাউড কনসোল থেকে, অ্যাক্টিভেট ক্লাউড শেল-এ ক্লিক করুন। d1264ca30785e435.png .

cb81e7c8e34bc8d.png

আপনি যদি প্রথমবারের মতো ক্লাউড শেল চালু করেন, তাহলে এটি কী তা বর্ণনা করে একটি মধ্যবর্তী স্ক্রিন আপনার সামনে আসবে। যদি একটি মধ্যবর্তী স্ক্রিন আসে, তাহলে 'চালিয়ে যান' (Continue) এ ক্লিক করুন।

d95252b003979716.png

ক্লাউড শেল প্রস্তুত করতে এবং এর সাথে সংযোগ স্থাপন করতে মাত্র কয়েক মুহূর্ত সময় লাগা উচিত।

7833d5e1c5d18f54.png

এই ভার্চুয়াল মেশিনটিতে প্রয়োজনীয় সমস্ত ডেভেলপমেন্ট টুলস লোড করা আছে। এটি একটি স্থায়ী ৫ জিবি হোম ডিরেক্টরি প্রদান করে এবং গুগল ক্লাউডে চলে, যা নেটওয়ার্ক পারফরম্যান্স ও অথেনটিকেশনকে ব্যাপকভাবে উন্নত করে। এই কোডল্যাবে আপনার প্রায় সমস্ত কাজই একটি ব্রাউজার দিয়ে করা সম্ভব।

ক্লাউড শেলে সংযুক্ত হওয়ার পর, আপনি দেখতে পাবেন যে আপনাকে প্রমাণীকৃত করা হয়েছে এবং প্রজেক্টটি আপনার প্রজেক্ট আইডিতে সেট করা আছে।

  1. আপনি প্রমাণীকৃত কিনা তা নিশ্চিত করতে ক্লাউড শেলে নিম্নলিখিত কমান্ডটি চালান:
gcloud auth list

কমান্ড আউটপুট

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. gcloud কমান্ডটি আপনার প্রজেক্ট সম্পর্কে জানে কিনা তা নিশ্চিত করতে ক্লাউড শেলে নিম্নলিখিত কমান্ডটি চালান:
gcloud config list project

কমান্ড আউটপুট

[core]
project = <PROJECT_ID>

যদি তা না থাকে, তবে আপনি এই কমান্ডটি দিয়ে এটি সেট করতে পারেন:

gcloud config set project <PROJECT_ID>

কমান্ড আউটপুট

Updated property [core/project].

৩. এনভায়রনমেন্ট ভেরিয়েবল সেটআপ করুন এবং এপিআই (API) সক্রিয় করুন।

পরিবেশ ভেরিয়েবল সেটআপ করুন

আপনি এনভায়রনমেন্ট ভেরিয়েবল সেট করতে পারেন, যা এই কোডল্যাব জুড়ে ব্যবহৃত হবে।

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) সক্রিয় করতে হবে। এই কোডল্যাবটির জন্য নিম্নলিখিত এপিআইগুলো ব্যবহার করা প্রয়োজন। আপনি নিম্নলিখিত কমান্ডটি চালিয়ে সেই এপিআইগুলো সক্রিয় করতে পারেন:

gcloud services enable run.googleapis.com \
    cloudbuild.googleapis.com \
    aiplatform.googleapis.com

৪. Vertex AI-কে কল করার জন্য একটি সার্ভিস অ্যাকাউন্ট তৈরি করুন।

এই সার্ভিস অ্যাকাউন্টটি ক্লাউড রান কর্তৃক ভার্টেক্স এআই জেমিনি এপিআই কল করার জন্য ব্যবহৃত হবে।

প্রথমে, এই কমান্ডটি চালিয়ে সার্ভিস অ্যাকাউন্টটি তৈরি করুন:

gcloud iam service-accounts create $SERVICE_ACCOUNT \
  --display-name="Cloud Run to access Vertex AI APIs"

দ্বিতীয়ত, সার্ভিস অ্যাকাউন্টটিকে Vertex AI User রোলটি প্রদান করুন।

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
  --role=roles/aiplatform.user

৫. ব্যাকএন্ড ক্লাউড রান পরিষেবা তৈরি করুন

প্রথমে, সোর্স কোডের জন্য একটি ডিরেক্টরি তৈরি করুন এবং সেই ডিরেক্টরিতে প্রবেশ করুন।

mkdir -p gemini-function-calling/weatherservice gemini-function-calling/frontend && cd gemini-function-calling/weatherservice

এরপর, নিম্নলিখিত বিষয়বস্তু সহ একটি package.json ফাইল তৈরি করুন:

{
    "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"
    }
}

এরপর, নিচের বিষয়বস্তু দিয়ে একটি app.js সোর্স ফাইল তৈরি করুন। এই ফাইলে সার্ভিসের এন্ট্রি পয়েন্ট এবং অ্যাপের মূল লজিক থাকবে।

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!");
});

আবহাওয়া পরিষেবা মোতায়েন করুন

আপনি এই কমান্ডটি ব্যবহার করে আবহাওয়া পরিষেবাটি চালু করতে পারেন।

gcloud run deploy $WEATHER_SERVICE \
  --source . \
  --region $REGION \
  --allow-unauthenticated

আবহাওয়া পরিষেবা পরীক্ষা করুন

আপনি 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

সিয়াটলের তাপমাত্রা ৪০ ডিগ্রি ফারেনহাইট এবং সেখানে বৃষ্টি হয়, আর নিউ অরলিন্সের তাপমাত্রা ৯৯ ডিগ্রি ফারেনহাইট এবং তা সবসময়ই আর্দ্র থাকে।

৬. ফ্রন্টএন্ড সার্ভিস তৈরি করুন

প্রথমে, ফ্রন্টএন্ড ডিরেক্টরিতে প্রবেশ করুন।

cd gemini-function-calling/frontend

এরপর, নিম্নলিখিত বিষয়বস্তু সহ একটি package.json ফাইল তৈরি করুন:

{
  "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"
  }
}

এরপর, নিচের বিষয়বস্তু দিয়ে একটি app.js সোর্স ফাইল তৈরি করুন। এই ফাইলে সার্ভিসের এন্ট্রি পয়েন্ট এবং অ্যাপের মূল লজিক থাকবে।

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-এর জন্য একটি input.css ফাইল তৈরি করুন।

@tailwind base;
@tailwind components;
@tailwind utilities;

tailwindCSS-এর জন্য tailwind.config.js ফাইলটি তৈরি করুন।

/** @type {import('tailwindcss').Config} */
module.exports = {
    content: ["./**/*.{html,js}"],
    theme: {
        extend: {}
    },
    plugins: []
};

ডেপ্লয় করা ক্লাউড রান সার্ভিসের প্রজেক্ট আইডি এবং রিজিয়ন পাওয়ার জন্য metadataService.js ফাইলটি তৈরি করুন। এই মানগুলো ভার্টেক্স এআই ক্লায়েন্ট লাইব্রেরির একটি ইনস্ট্যান্স তৈরি করতে ব্যবহৃত হবে।

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 নামে একটি ফাইল তৈরি করুন।

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>`;

একটি নতুন public ডিরেক্টরি তৈরি করুন।

mkdir public
cd public

এখন ফ্রন্ট এন্ডের জন্য index.html ফাইলটি তৈরি করুন, যেটি 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&apos;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>

৭. ফ্রন্টএন্ড সার্ভিসটি স্থানীয়ভাবে চালান

প্রথমে, নিশ্চিত করুন যে আপনি আপনার কোডল্যাবের জন্য frontend ডিরেক্টরিতে আছেন।

cd .. && pwd

এরপর, নিচের কমান্ডটি চালিয়ে ডিপেন্ডেন্সিগুলো ইনস্টল করুন:

npm install

স্থানীয়ভাবে চালানোর সময় ADC ব্যবহার করা

আপনি যদি ক্লাউড শেলে (Cloud Shell) চালান, তাহলে আপনি ইতিমধ্যেই একটি গুগল কম্পিউট ইঞ্জিন (Google Compute Engine) ভার্চুয়াল মেশিনে কাজ করছেন। এই ভার্চুয়াল মেশিনের সাথে যুক্ত আপনার ক্রেডেনশিয়াল (যা gcloud auth list চালালে দেখা যায়) অ্যাপ্লিকেশন ডিফল্ট ক্রেডেনশিয়ালস (Application Default Credentials) দ্বারা স্বয়ংক্রিয়ভাবে ব্যবহৃত হবে, তাই gcloud auth application-default login কমান্ডটি ব্যবহার করার প্রয়োজন নেই। আপনি সরাসরি "অ্যাপটি স্থানীয়ভাবে চালান" (Run the app locally) অংশে চলে যেতে পারেন।

তবে, আপনি যদি আপনার লোকাল টার্মিনালে (অর্থাৎ ক্লাউড শেল-এ নয়) এটি চালান, তাহলে গুগল এপিআই-তে প্রমাণীকরণের জন্য আপনাকে অ্যাপ্লিকেশন ডিফল্ট ক্রেডেনশিয়াল ব্যবহার করতে হবে। আপনি হয় ১) আপনার ক্রেডেনশিয়াল ব্যবহার করে লগইন করতে পারেন (যদি আপনার ভার্টেক্স এআই ইউজার এবং ডেটাস্টোর ইউজার উভয় রোল থাকে) অথবা ২) এই কোডল্যাবে ব্যবহৃত সার্ভিস অ্যাকাউন্টটি ইমপারসোনেট করে লগইন করতে পারেন।

বিকল্প ১) ADC-এর জন্য আপনার পরিচয়পত্র ব্যবহার করা

আপনি যদি আপনার ক্রেডেনশিয়াল ব্যবহার করতে চান, তাহলে প্রথমে gcloud-এ আপনার অথেন্টিকেশন যাচাই করার জন্য gcloud auth list চালাতে পারেন। এরপর, আপনাকে আপনার আইডেন্টিটিকে Vertex AI User রোলটি প্রদান করতে হতে পারে। যদি আপনার আইডেন্টিটির Owner রোল থাকে, তাহলে আপনার কাছে ইতিমধ্যেই এই Vertex AI ইউজার রোলটি আছে। যদি না থাকে, তাহলে আপনার আইডেন্টিটিকে Vertex AI ইউজার রোল এবং Datastore ইউজার রোল প্রদান করার জন্য আপনি এই কমান্ডটি চালাতে পারেন।

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

তারপর নিম্নলিখিত কমান্ডটি চালান।

gcloud auth application-default login

বিকল্প ২) এডিসি-র জন্য একটি সার্ভিস অ্যাকাউন্টের ছদ্মবেশ ধারণ করা

আপনি যদি এই কোডল্যাবে তৈরি করা সার্ভিস অ্যাকাউন্টটি ব্যবহার করতে চান, তাহলে আপনার ইউজার অ্যাকাউন্টে ‘সার্ভিস অ্যাকাউন্ট টোকেন ক্রিয়েটর’ রোলটি থাকতে হবে। নিম্নলিখিত কমান্ডটি চালিয়ে আপনি এই রোলটি পেতে পারেন:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member user:$USER \
  --role=roles/iam.serviceAccountTokenCreator

এরপরে, সার্ভিস অ্যাকাউন্টের সাথে ADC ব্যবহার করার জন্য আপনাকে নিম্নলিখিত কমান্ডটি চালাতে হবে।

gcloud auth application-default login --impersonate-service-account=$SERVICE_ACCOUNT_ADDRESS

অ্যাপটি স্থানীয়ভাবে চালান

সবশেষে, নিচের স্ক্রিপ্টটি রান করে আপনি অ্যাপটি চালু করতে পারেন। এই ডেভ স্ক্রিপ্টটি tailwindCSS থেকে output.css ফাইলটিও তৈরি করবে।

npm run dev

আপনি ওয়েব প্রিভিউ বাটনটি খুলে এবং প্রিভিউ পোর্ট ৮০৮০ নির্বাচন করে ওয়েবসাইটটি প্রিভিউ করতে পারেন।

ওয়েব প্রিভিউ - পোর্ট ৮০৮০-তে প্রিভিউ বাটন

৮. ফ্রন্টএন্ড সার্ভিসটি ডেপ্লয় এবং টেস্ট করুন

প্রথমে, ডেপ্লয়মেন্ট শুরু করতে এই কমান্ডটি চালান এবং ব্যবহৃতব্য সার্ভিস অ্যাকাউন্টটি নির্দিষ্ট করুন। যদি কোনো সার্ভিস অ্যাকাউন্ট নির্দিষ্ট করা না থাকে, তাহলে ডিফল্ট কম্পিউট সার্ভিস অ্যাকাউন্টটি ব্যবহৃত হবে।

gcloud run deploy $FRONTEND \
  --service-account $SERVICE_ACCOUNT_ADDRESS \
  --source . \
  --region $REGION \
  --allow-unauthenticated

আপনার ব্রাউজারে ফ্রন্টএন্ডের সার্ভিস ইউআরএলটি খুলুন। "সিয়াটলের বর্তমান আবহাওয়া কী?" প্রশ্নটি করুন এবং জেমিনি উত্তর দেবে "বর্তমানে তাপমাত্রা ৪০ ডিগ্রি এবং বৃষ্টি হচ্ছে।" যদি আপনি জিজ্ঞাসা করেন "বস্টনের বর্তমান আবহাওয়া কী?", জেমিনি উত্তর দেবে "আমি এই অনুরোধটি পূরণ করতে পারছি না। উপলব্ধ ওয়েদার এপিআই-তে বস্টনের ডেটা নেই।"

৯. অভিনন্দন!

কোডল্যাবটি সম্পন্ন করার জন্য অভিনন্দন!

আমরা ক্লাউড রান , ভার্টেক্স এআই জেমিনি এপিআই এবং ফাংশন কলিং- এর ডকুমেন্টেশন পর্যালোচনা করার পরামর্শ দিই।

আমরা যা আলোচনা করেছি

  • জেমিনি ফাংশন কলিং কীভাবে কাজ করে
  • জেমিনি-চালিত চ্যাটবট অ্যাপকে ক্লাউড রান পরিষেবা হিসাবে কীভাবে স্থাপন করবেন

১০. পরিষ্কার করুন

অনিচ্ছাকৃত চার্জ এড়াতে, (উদাহরণস্বরূপ, যদি এই ক্লাউড রান পরিষেবাটি ফ্রি টিয়ারে আপনার মাসিক ক্লাউড রান ব্যবহারের বরাদ্দের চেয়ে বেশিবার অনিচ্ছাকৃতভাবে চালু হয়ে যায়), আপনি হয় ক্লাউড রান পরিষেবাটি অথবা ধাপ ২-এ তৈরি করা প্রজেক্টটি ডিলিট করে দিতে পারেন।

Cloud Run সার্ভিসগুলো ডিলিট করতে, https://console.cloud.google.com/functions/ -এ অবস্থিত Cloud Run ক্লাউড কনসোলে যান এবং এই কোডল্যাবে আপনার তৈরি করা $WEATHER_SERVICE ও $FRONTEND সার্ভিসগুলো ডিলিট করে দিন।

জেমিনিতে কোনো অনিচ্ছাকৃত কল এড়ানোর জন্য, আপনি vertex-ai-caller সার্ভিস অ্যাকাউন্টটি মুছে ফেলতে অথবা Vertex AI User রোলটি প্রত্যাহার করতে পারেন।

আপনি যদি পুরো প্রজেক্টটি মুছে ফেলতে চান, তাহলে আপনি https://console.cloud.google.com/cloud-resource-manager -এ গিয়ে, ধাপ ২-এ তৈরি করা প্রজেক্টটি নির্বাচন করে 'ডিলিট' (Delete) বিকল্পটি বেছে নিতে পারেন। প্রজেক্টটি মুছে ফেললে, আপনাকে আপনার ক্লাউড এসডিকে (Cloud SDK)-তে প্রজেক্ট পরিবর্তন করতে হবে। আপনি gcloud projects list চালিয়ে সমস্ত উপলব্ধ প্রজেক্টের তালিকা দেখতে পারেন।