অন্তর্নির্মিত সরঞ্জাম এবং ফাংশন কলিং একত্রিত করুন

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

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

পাইথন

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-flash-preview",
    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.ToolGoogleSearch(),  # Built-in tool
          function_declarations=[getWeather]       # Custom tool
        ),
      ],
      include_server_side_tool_invocations=True
    ),
)

for part in response.candidates[0].content.parts:
    if part.tool_call:
        print(f"Tool call: {part.tool_call.tool_type} (ID: {part.tool_call.id})")
    if part.tool_response:
        print(f"Tool response: {part.tool_response.tool_type} (ID: {part.tool_response.id})")
    if part.function_call:
        print(f"Function call: {part.function_call.name} (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=response.candidates[0].content.parts[2].function_call.id # Match the ID from the function_call
            )
        )]
    )
]

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

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

জাভাস্ক্রিপ্ট

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 model = client.getGenerativeModel({
        model: "gemini-3-flash-preview",
    });

    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 result1 = await model.generateContent({
        contents: [{role: "user", parts: [{text: "What is the northernmost city in the United States? What's the weather like there today?"}]}],
        tools: tools,
        toolConfig: toolConfig,
    });

    const response1 = result1.response;

    for (const part of response1.candidates[0].content.parts) {
        if (part.toolCall) {
            console.log(`Tool call: ${part.toolCall.toolType} (ID: ${part.toolCall.id})`);
        }
        if (part.toolResponse) {
            console.log(`Tool response: ${part.toolResponse.toolType} (ID: ${part.toolResponse.id})`);
        }
        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 result2 = await model.generateContent({
        contents: history,
        tools: tools,
        toolConfig: toolConfig,
    });

    for (const part of result2.response.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-flash-preview")
    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
            }
        case genai.ToolCallPart:
            fmt.Printf("Tool call: %s (ID: %s)\n", p.ToolType, p.ID)
        case genai.ToolResponsePart:
            fmt.Printf("Tool response: %s (ID: %s)\n", p.ToolType, 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))
        }
    }
}

বিশ্রাম

# 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-flash-preview: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-flash-preview: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
  }
}'

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

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

টুল সংমিশ্রণ সক্ষম করুন

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

এপিআই অংশ ফেরত দেয়

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

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

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

ফেরত আসা যন্ত্রাংশের গুরুত্বপূর্ণ ক্ষেত্রগুলি

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

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

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

কিছু অন্তর্নির্মিত টুল, টুলের প্রকারভেদের জন্য নির্দিষ্ট, ব্যবহারকারীর কাছে দৃশ্যমান ডেটা আর্গুমেন্ট ফেরত দেয়।

সরঞ্জাম ব্যবহারকারীর কাছে দৃশ্যমান টুল কল আর্গুমেন্ট (যদি থাকে) ব্যবহারকারীর কাছে দৃশ্যমান টুলের প্রতিক্রিয়া (যদি থাকে)
গুগল_সার্চ queries search_suggestions
গুগল_ম্যাপস queries places
google_maps_widget_context_token
URL_CONTEXT urls
ব্রাউজ করার জন্য ইউআরএল
urls_metadata
retrieved_url ইউআরএল : ব্রাউজ করা ইউআরএল
url_retrieval_status : ব্রাউজ স্ট্যাটাস
ফাইল_অনুসন্ধান কোনোটিই না কোনোটিই না

টুল সমন্বয় অনুরোধ কাঠামোর উদাহরণ

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

{
  "model": "models/gemini-3-flash-preview",
  "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
  }
}

টোকেন এবং মূল্য নির্ধারণ

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

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

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

সীমাবদ্ধতা

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

সমর্থিত সরঞ্জাম

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

সরঞ্জাম কার্যনির্বাহী পক্ষ প্রসঙ্গ সঞ্চালন সমর্থন
গুগল অনুসন্ধান সার্ভার-সাইড সমর্থিত
গুগল ম্যাপস সার্ভার-সাইড সমর্থিত
ইউআরএল প্রসঙ্গ সার্ভার-সাইড সমর্থিত
ফাইল অনুসন্ধান সার্ভার-সাইড সমর্থিত
কোড এক্সিকিউশন সার্ভার-সাইড সমর্থিত (অন্তর্নির্মিত, executableCode এবং codeExecutionResult অংশগুলো ব্যবহার করে)
কম্পিউটার ব্যবহার ক্লায়েন্ট-সাইড সমর্থিত (অন্তর্নির্মিত, functionCall এবং functionResponse অংশ ব্যবহার করে)
কাস্টম ফাংশন ক্লায়েন্ট-সাইড সমর্থিত (অন্তর্নির্মিত, functionCall এবং functionResponse অংশ ব্যবহার করে)

এরপর কী?