বিল্ট-ইন টুল ও ফাংশন কলিংয়ের সুবিধা একত্রিত করা


Gemini, বিল্ট-ইন টুল, যেমন google_search এবং ফাংশন কলিং (কাস্টম টুল নামেও পরিচিত) একসাথে ব্যবহার করার অনুমতি দেয়। এটি টুল কলের প্রসঙ্গগত ইতিহাস বজায় রাখে এবং প্রকাশ করে। বিল্ট-ইন ও কাস্টম টুলের কম্বিনেশন জটিল, এজেন্টিক ওয়ার্কফ্লোর সুবিধা দেয়, যেখানে, উদাহরণস্বরূপ, আপনার নির্দিষ্ট বিজনেস লজিক কল করার আগে মডেলটি রিয়েল-টাইম ওয়েব ডেটায় নিজেকে গ্রাউন্ড করতে পারে।

এখানে এমন একটি উদাহরণ দেওয়া হল যা google_search এবং কাস্টম ফাংশন getWeather-এর সাথে বিল্ট-ইন ও কাস্টম টুলের কম্বিনেশন চালু করে:

Python

from google import genai
from google.genai import types

client = genai.Client()

getWeather = {
    "name": "getWeather",
    "description": "Gets the weather for a requested city.",
    "parameters": {
        "type": "object",
        "properties": {
            "city": {
                "type": "string",
                "description": "The city and state, e.g. Utqiaġvik, Alaska",
            },
        },
        "required": ["city"],
    },
}

# Turn 1: Initial request with Google Search (built-in) and getWeather (custom) tools enabled
response = client.models.generate_content(
    model="gemini-3.8-flash",
    contents="What is the northernmost city in the United States? What's the weather like there today?",
    config=types.GenerateContentConfig(
        tools=[
            types.Tool(
                google_search=types.GoogleSearch(),  # Built-in tool
                function_declarations=[getWeather],  # Custom tool
            ),
        ],
        tool_config=types.ToolConfig(
            include_server_side_tool_invocations=True
        )
    ),
)
function_call_id = None
for part in response.candidates[0].content.parts:
    if part.function_call:
        print(f"Function call: {part.function_call.name} (ID: {part.function_call.id})")
        function_call_id = part.function_call.id

# Turn 2: Manually build history to circulate both tool and function context
history = [
    types.Content(
        role="user",
        parts=[types.Part(text="What is the northernmost city in the United States? What's the weather like there today?")]
    ),
    # Response from Turn 1 includes tool_call, tool_response, and thought_signatures
    response.candidates[0].content,
    # Return the function_response
    types.Content(
        role="user",
        parts=[types.Part(
            function_response=types.FunctionResponse(
                name="getWeather",
                response={"response": "Very cold. 22 degrees Fahrenheit."},
                id=function_call_id # Match the ID from the function_call
            )
        )]
    )
]

response_2 = client.models.generate_content(
    model="gemini-3.8-flash",
    contents=history,
    config=types.GenerateContentConfig(
        tools=[
            types.Tool(
                google_search=types.GoogleSearch(),
                function_declarations=[getWeather]
            ),
        ],
        # This flag needs to be enabled for built-in tool context circulation and tool combination
        tool_config=types.ToolConfig(
            include_server_side_tool_invocations=True
        )
    ),
)

for part in response_2.candidates[0].content.parts:
    if part.text:
        print(part.text)

Javascript

import { GoogleGenAI } from '@google/genai';

const client = new GoogleGenAI({});

const getWeather = {
    name: "getWeather",
    description: "Get the weather in a given location",
    parameters: {
        type: "OBJECT",
        properties: {
            location: {
                type: "STRING",
                description: "The city and state, e.g. San Francisco, CA"
            }
        },
        required: ["location"]
    }
};

async function run() {
    const tools = [
      { googleSearch: {} },
      { functionDeclarations: [getWeather] }
    ];
    // This flag needs to be enabled for built-in tool context circulation and tool combination
    const toolConfig = { includeServerSideToolInvocations: true };

    // Turn 1: Initial request with Google Search (built-in) and getWeather (custom) tools enabled
    const response1 = await client.models.generateContent({
        model: "gemini-3.8-flash",
        contents: [{role: "user", parts: [{text: "What is the northernmost city in the United States? What's the weather like there today?"}]}],
        config: {
            tools: tools,
            toolConfig: toolConfig,
        },
    });

    for (const part of response1.candidates[0].content.parts) {
        if (part.functionCall) {
            console.log(`Function call: ${part.functionCall.name} (ID: ${part.functionCall.id})`);
        }
    }

   const functionCallId = response1.candidates[0].content.parts.find(p => p.functionCall)?.functionCall?.id;

    // Turn 2: Manually build history to circulate both tool and function context
    const history = [
        {
            role: "user",
            parts:[{text: "What is the northernmost city in the United States? What's the weather like there today?"}]
        },
        // Response from Turn 1 includes tool_call, tool_response, and thought_signatures
        response1.candidates[0].content,
        // Return the function_response
        {
            role: "user",
            parts: [{
                functionResponse: {
                    name: "getWeather",
                    response: {response: "Very cold. 22 degrees Fahrenheit."},
                    id: functionCallId // Match the ID from the function_call
                }
            }]
        }
    ];

    const response2 = await client.models.generateContent({
        model: "gemini-3.8-flash",
        contents: history,
        config: {
            tools: tools,
            toolConfig: toolConfig,
        },
    });

    for (const part of response2.candidates[0].content.parts) {
        if (part.text) {
            console.log(part.text);
        }
    }
}

run();

খুলুন

package main

import (
    "context"
    "fmt"
    "log"
    "os"

    "github.com/google/generative-ai-go/genai"
    "google.golang.org/api/option"
)

func main() {
    ctx := context.Background()
    client, err := genai.NewClient(ctx, option.WithAPIKey(os.Getenv("GEMINI_API_KEY")))
    if err != nil {
        log.Exit(err)
    }
    defer client.Close()

    getWeather := &genai.FunctionDeclaration{
        Name:        "getWeather",
        Description: "Get the weather in a given location",
        Parameters: &genai.Schema{
            Type: genai.Object,
            Properties: map[string]*genai.Schema{
                "location": {
                    Type:        genai.String,
                    Description: "The city and state, e.g. San Francisco, CA",
                },
            },
            Required: []string{"location"},
        },
    }

    model := client.GenerativeModel("gemini-3.8-flash")
    model.Tools = []*genai.Tool{
        {GoogleSearch: &genai.GoogleSearch{}}, // Built-in tool
        {FunctionDeclarations: []*genai.FunctionDeclaration{getWeather}}, // Custom tool
    }
    ist := true
    model.ToolConfig = &genai.ToolConfig{
        IncludeServerSideToolInvocations: &ist, // This flag needs to be enabled for built-in tool context circulation and tool combination
    }

    chat := model.StartChat()

    // Turn 1: Initial request with Google Search (built-in) and getWeather (custom) tools enabled
    prompt := genai.Text("What is the northernmost city in the United States? What's the weather like there today?")
    resp1, err := chat.SendMessage(ctx, prompt)
    if err != nil {
        log.Exitf("SendMessage failed: %v", err)
    }

    if resp1 == nil || len(resp1.Candidates) == 0 || resp1.Candidates[0].Content == nil {
        log.Exit("empty response from model")
    }

    var functionCallID string
    for _, part := range resp1.Candidates[0].Content.Parts {
        switch p := part.(type) {
        case genai.FunctionCall:
            fmt.Printf("Function call: %s (ID: %s)\n", p.Name, p.ID)
            if p.Name == "getWeather" {
                functionCallID = p.ID
            }
        }
    }

    if functionCallID == "" {
        log.Exit("no getWeather function call in response")
    }

    // Turn 2: Provide function result back to model.
    // Chat history automatically includes tool_call, tool_response, and thought_signatures from Turn 1.
    fr := genai.FunctionResponse{
        Name: "getWeather",
        ID:   functionCallID,
        Response: map[string]any{
            "response": "Very cold. 22 degrees Fahrenheit.",
        },
    }

    resp2, err := chat.SendMessage(ctx, fr)
    if err != nil {
        log.Exitf("SendMessage for turn 2 failed: %v", err)
    }

    if resp2 == nil || len(resp2.Candidates) == 0 || resp2.Candidates[0].Content == nil {
        log.Exit("empty response from model in turn 2")
    }

    for _, part := range resp2.Candidates[0].Content.Parts {
        if txt, ok := part.(genai.Text); ok {
            fmt.Println(string(txt))
        }
    }
}

REST

# Turn 1: Initial request with Google Search (built-in) and getWeather (custom) tools enabled
curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-flash:generateContent" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
  "contents": [{
    "role": "user",
    "parts": [{
      "text": "What is the northernmost city in the United States? What'\''s the weather like there today?"
    }]
  }],
  "tools": [{
    "googleSearch": {}
  }, {
    "functionDeclarations": [{
      "name": "getWeather",
      "description": "Get the weather in a given location",
      "parameters": {
          "type": "OBJECT",
          "properties": {
              "location": {
                  "type": "STRING",
                  "description": "The city and state, e.g. San Francisco, CA"
              }
          },
          "required": ["location"]
      }
    }]
  }],
  "toolConfig": {
    "includeServerSideToolInvocations": true
  }
}'

# Turn 2: Manually build history to circulate both tool and function context
# The following request assumes you have captured candidates[0].content from Turn 1 response,
# and extracted function_call.id for getWeather.
# Replace FUNCTION_CALL_ID and insert candidate content from turn 1.
curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-flash:generateContent" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
  "contents": [
    {
      "role": "user",
      "parts": [{"text": "What is the northernmost city in the United States? What'\''s the weather like there today?"}]
    },
    YOUR_CANDIDATE_CONTENT_FROM_TURN_1_RESPONSE,
    {
      "role": "user",
      "parts": [{
        "functionResponse": {
          "name": "getWeather",
          "id": "FUNCTION_CALL_ID",
          "response": {"response": "Very cold. 22 degrees Fahrenheit."}
        }
      }]
    }
  ],
  "tools": [{
    "googleSearch": {}
  }, {
    "functionDeclarations": [{
      "name": "getWeather",
      "description": "Get the weather in a given location",
      "parameters": {
          "type": "OBJECT",
          "properties": {
              "location": {
                  "type": "STRING",
                  "description": "The city and state, e.g. San Francisco, CA"
              }
          },
          "required": ["location"]
      }
    }]
  }],
  "toolConfig": {
    "includeServerSideToolInvocations": true
  }
}'

এটি কীভাবে কাজ করে

বিল্ট-ইন ও কাস্টম টুলের কম্বিনেশন চালু করতে Gemini 3 মডেল টুল কন্টেক্সট সার্কুলেশন ব্যবহার করে। টুল কনটেক্সট সার্কুলেশন, বিল্ট-ইন টুলের কনটেক্সটকে সেভ ও এক্সপোজ করা এবং একই কলের মধ্যে এক টার্ন থেকে অন্য টার্নে কাস্টম টুলের সাথে শেয়ার করা সম্ভব করে তোলে।

টুল কম্বিনেশন চালু করা

  • টুল কনটেক্সট সার্কুলেশন চালু করতে আপনাকে অবশ্যই include_server_side_tool_invocations ফ্ল্যাগটি true-এ সেট করতে হবে।
  • কম্বিনেশন আচরণ ট্রিগার করতে, আপনি ব্যবহার করতে চান এমন বিল্ট-ইন টুলের সাথে function_declarations অন্তর্ভুক্ত করুন।
    • আপনি function_declarations অন্তর্ভুক্ত না করলে, ফ্ল্যাগ সেট করা থাকলে, টুল কনটেক্সট সার্কুলেশন অন্তর্ভুক্ত বিল্ট-ইন টুলে কাজ করবে।

API রিটার্ন পার্টস

একটিমাত্র উত্তরের মধ্যে, API বিল্ট-ইন টুলের কলের জন্য toolCall এবং toolResponse পার্ট রিটার্ন করে। ফাংশন (কাস্টম টুল) কলের জন্য, API functionCall কল পার্ট রিটার্ন করে, যার উত্তরে ব্যবহারকারী functionResponse পার্ট প্রদান করেন।

  • toolCall ও toolResponse: সার্ভার সাইডে কোন টুল রান করা হয়েছে এবং সেগুলির এক্সিকিউশনের ফলাফল, এই দু'টি বিষয়কে পরবর্তী টার্নের জন্য সংরক্ষণ করতে API এই অংশগুলি রিটার্ন করে।
  • functionCall ও functionResponse: API, ব্যবহারকারীকে পূরণ করার জন্য ফাংশন কল পাঠায় এবং ব্যবহারকারী ফাংশন রেসপন্সে ফলাফল ফেরত পাঠান (এই অংশগুলি Gemini API-তে সমস্ত ফাংশন কলিং-এর জন্য স্ট্যান্ডার্ড, টুল কম্বিনেশন ফিচারের জন্য অনন্য নয়)।
  • (শুধুমাত্র কোড এক্সিকিউশন টুল) executableCode এবং codeExecutionResult: কোড এক্সিকিউশন টুল ব্যবহার করার সময়, functionCall এবং functionResponse-এর পরিবর্তে, API executableCode (মডেলের মাধ্যমে জেনারেট করা কোড যা এক্সিকিউট করা হবে) এবং codeExecutionResult (এক্সিকিউটেবল কোডের ফলাফল) রিটার্ন করে।

প্রতিটি টার্নে আপনাকে অবশ্যই মডেলটিকে সমস্ত অংশ ফেরত দিতে হবে, যার মধ্যে সমস্ত ফিল্ড অন্তর্ভুক্ত যা সেগুলিতে রয়েছে, যাতে প্রসঙ্গ বজায় রাখা যায় এবং টুল কম্বিনেশন চালু করা যায়।

ফেরানো পার্টের গুরুত্বপূর্ণ ফিল্ড

API-এর মাধ্যমে রিটার্ন করা নির্দিষ্ট কিছু অংশে id, tool_type ও thought_signature ফিল্ড অন্তর্ভুক্ত থাকবে। টুলের প্রসঙ্গ বজায় রাখার জন্য (এবং সেই কারণে টুল কম্বিনেশনের জন্য) এইসব ফিল্ড খুবই গুরুত্বপূর্ণ; পরবর্তী অনুরোধে আপনাকে উত্তরে যেভাবে দেওয়া হয়েছে সেইভাবে সব অংশ ফেরত দিতে হবে।

  • id: একটি অনন্য শনাক্তকারী যা কলকে তার উত্তরের সাথে ম্যাপ করে। টুল কন্টেক্সট সার্কুলেশন নির্বিশেষে, id সব ফাংশন কল রেসপন্সে সেট করা আছে। ফাংশন কলের সময় API যে id প্রদান করে, আপনাকে ফাংশন রেসপন্সে সেই একই প্রদান করতেই হবে। বিল্ট-ইন টুল অটোমেটিক টুল কল ও টুল উত্তরের মধ্যে id শেয়ার করে।
    • টুল-সম্পর্কিত সব অংশে পাওয়া গেছে: toolCall, toolResponse, functionCall, functionResponse, executableCode, codeExecutionResult
  • tool_type: ব্যবহার করা হচ্ছে এমন নির্দিষ্ট টুল শনাক্ত করে; আক্ষরিক বিল্ট-ইন টুল বা (যেমন, URL_CONTEXT) বা ফাংশন (যেমন, getWeather) নাম।
    • toolCall এবং toolResponse অংশে পাওয়া গেছে।
  • thought_signature: API-এর মাধ্যমে রিটার্ন করা প্রতিটি পার্টে এম্বেড করা আসল এনক্রিপ্টেড কনটেক্সট। চিন্তার সিগনেচার ছাড়া কন্টেক্সট রিকনস্ট্রাক্ট করা যায় না; প্রতিটি টার্নের সব পার্টের জন্য চিন্তার সিগনেচার না দিলে, মডেলটি এরর মেসেজ দেখাবে।
    • সব পার্টে পাওয়া যায়।

টুল-নির্দিষ্ট ডেটা

কিছু বিল্ট-ইন টুল, টুলের টাইপ অনুযায়ী ব্যবহারকারীর দেখার উপযুক্ত ডেটা আর্গুমেন্ট রিটার্ন করে।

টুল ব্যবহারকারীর কাছে দৃশ্যমান টুল কলের আর্গুমেন্ট (যদি থাকে) ব্যবহারকারীকে দেখানো টুলের উত্তর (যদি থাকে)
GOOGLE_SEARCH queries search_suggestions
GOOGLE_MAPS queries places
google_maps_widget_context_token
URL_CONTEXT urls
ব্রাউজ করার জন্য URL
url_metadata
retrieved_url: ব্রাউজ করা URL
url_retrieval_status: ব্রাউজ করার স্ট্যাটাস
FILE_SEARCH কোনওটিই নয় কোনওটিই নয়

টুল কম্বিনেশন সংক্রান্ত অনুরোধের স্ট্রাকচারের উদাহরণ

নিম্নলিখিত অনুরোধের স্ট্রাকচারটি প্রম্পটের অনুরোধের স্ট্রাকচার দেখায়: "মার্কিন যুক্তরাষ্ট্রের সবচেয়ে উত্তরের শহর কোনটি? আজকে সেখানকার আবহাওয়া কেমন?" এটি তিনটি টুলকে একত্রিত করে: বিল্ট-ইন Gemini টুল google_search এবং code_execution, এবং একটি কাস্টম ফাংশন get_weather।

{
  "model": "models/gemini-3.8-flash",
  "contents": [{
    "parts": [{
      "text": "What is the northernmost city in the United States? What's the weather like there today?"
    }],
    "role": "user"
  }, {
    "parts": [{
      "thoughtSignature": "...",
      "toolCall": {
        "toolType": "GOOGLE_SEARCH_WEB",
        "args": {
          "queries": ["northernmost city in the United States"]
        },
        "id": "a7b3k9p2"
      }
    }, {
      "thoughtSignature": "...",
      "toolResponse": {
        "toolType": "GOOGLE_SEARCH_WEB",
        "response": {
          "search_suggestions": "..."
        },
        "id": "a7b3k9p2"
      }
    }, {
      "functionCall": {
        "name": "getWeather",
        "args": {
          "city": "Utqiaġvik, Alaska"
        },
        "id": "m4q8z1v6"
      },
      "thoughtSignature": "..."
    }],
    "role": "model"
  }, {
    "parts": [{
      "functionResponse": {
        "name": "getWeather",
        "response": {
          "response": "Very cold. 22 degrees Fahrenheit."
        },
        "id": "m4q8z1v6"
      }
    }],
    "role": "user"
  }],
  "tools": [{
    "functionDeclarations": [{
      "name": "getWeather"
    }]
  }, {
    "googleSearch": {
    }
  }, {
    "codeExecution": {
    }
  }],
  "toolConfig": {
    "includeServerSideToolInvocations": true
  }
}

টোকেন ও দাম

মনে রাখবেন, অনুরোধের toolCall ও toolResponse অংশগুলি prompt_token_count-এর মধ্যে গণনা করা হয়। যেহেতু এই মধ্যবর্তী টুল ধাপগুলি এখন দৃশ্যমান এবং আপনাকে ফেরত দেওয়া হয়েছে, তাই সেগুলি কথোপকথনের ইতিহাসের অংশ। এটি শুধুমাত্র অনুরোধের ক্ষেত্রে প্রযোজ্য, উত্তরের ক্ষেত্রে নয়।

Google Search টুল এই নিয়মের ব্যতিক্রম। Google Search আগেই কোয়েরি লেভেলে নিজস্ব প্রাইসিং মডেল প্রয়োগ করে, তাই টোকেনের জন্য ডবল চার্জ করা হয় না (প্রাইসিং পৃষ্ঠা দেখুন)।

আরও তথ্যের জন্য টোকেন পৃষ্ঠাটি পড়ুন।

সীমাবদ্ধতা

  • include_server_side_tool_invocations ফ্ল্যাগ চালু থাকলে VALIDATED মোডে (AUTO মোড কাজ করে না) ডিফল্ট করুন
  • google_search-এর মতো বিল্ট-ইন টুল লোকেশন ও বর্তমান সময় সংক্রান্ত তথ্যের উপর নির্ভর করে, তাই আপনার system_instruction বা function_declaration.description-এ লোকেশন ও সময় সংক্রান্ত তথ্য পরস্পরবিরোধী হলে, টুল কম্বিনেশন ফিচার ভালোভাবে কাজ নাও করতে পারে।

মানানসই টুল

সার্ভার-সাইড (বিল্ট-ইন) টুলের ক্ষেত্রে স্ট্যান্ডার্ড টুল কন্টেক্সট সার্কুলেশন প্রযোজ্য হয়। কোড এক্সিকিউশনও একটি সার্ভার-সাইড টুল, তবে প্রসঙ্গ সার্কুলেশনের জন্য এর নিজস্ব বিল্ট-ইন সমাধান রয়েছে। কম্পিউটার ব্যবহার ও ফাংশন কলিং হল ক্লায়েন্ট-সাইড টুল, এবং এতে প্রসঙ্গ সার্কুলেশনের বিল্ট-ইন সমাধানও আছে।

টুল এক্সিকিউশন সাইড Context Circulation Support
Google Search সার্ভার-সাইড কাজ করে
Google Maps সার্ভার-সাইড কাজ করে
URL কন্টেক্সট সার্ভার-সাইড কাজ করে
ফাইল সার্চ সার্ভার-সাইড কাজ করে
কোড এক্সিকিউশন সার্ভার-সাইড কাজ করে (বিল্ট-ইন, executableCode ও codeExecutionResult পার্ট ব্যবহার করে)
কম্পিউটার ইউজ ক্লায়েন্ট-সাইড কাজ করে (বিল্ট-ইন, functionCall ও functionResponse পার্ট ব্যবহার করে)
কাস্টম ফাংশন ক্লায়েন্ট-সাইড কাজ করে (বিল্ট-ইন, functionCall ও functionResponse পার্ট ব্যবহার করে)

এর পরে কী করতে হবে