استدعاء الدوالّ باستخدام Gemini API

تتيح لك ميزة "استدعاء الدوال" ربط النماذج بالأدوات وواجهات برمجة التطبيقات الخارجية. بدلاً من إنشاء ردود نصية، يحدّد النموذج الوقت المناسب لاستدعاء دوال معيّنة ويقدّم المَعلمات اللازمة لتنفيذ إجراءات واقعية. ويسمح ذلك للنموذج بأن يكون بمثابة جسر بين اللغة الطبيعية والإجراءات والبيانات الواقعية. تتضمّن ميزة "استدعاء الدوال" 3 حالات استخدام أساسية:

  • تعزيز المعرفة: الوصول إلى المعلومات من مصادر خارجية، مثل قواعد البيانات وواجهات برمجة التطبيقات وقواعد المعارف
  • توسيع الإمكانات: يمكنك استخدام أدوات خارجية لإجراء العمليات الحسابية وتوسيع نطاق إمكانات النموذج، مثل استخدام آلة حاسبة أو إنشاء رسومات بيانية.
  • اتّخاذ إجراءات: التفاعل مع الأنظمة الخارجية باستخدام واجهات برمجة التطبيقات، مثل جدولة المواعيد أو إنشاء الفواتير أو إرسال الرسائل الإلكترونية أو التحكّم في الأجهزة المنزلية الذكية

Python

from google import genai
from google.genai import types

# Define the function declaration for the model
weather_function = {
    "name": "get_current_temperature",
    "description": "Gets the current temperature for a given location.",
    "parameters": {
        "type": "object",
        "properties": {
            "location": {
                "type": "string",
                "description": "The city name, e.g. San Francisco",
            },
        },
        "required": ["location"],
    },
}

# Configure the client and tools
client = genai.Client()
tools = types.Tool(function_declarations=[weather_function])
config = types.GenerateContentConfig(tools=[tools])

# Send request with function declarations
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents="What's the temperature in London?",
    config=config,
)

# Check for a function call
if response.candidates[0].content.parts[0].function_call:
    function_call = response.candidates[0].content.parts[0].function_call
    print(f"Function to call: {function_call.name}")
    print(f"Arguments: {function_call.args}")
    #  In a real app, you would call your function here:
    #  result = get_current_temperature(**function_call.args)
else:
    print("No function call found in the response.")
    print(response.text)

JavaScript

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

// Configure the client
const ai = new GoogleGenAI({});

// Define the function declaration for the model
const weatherFunctionDeclaration = {
  name: 'get_current_temperature',
  description: 'Gets the current temperature for a given location.',
  parameters: {
    type: Type.OBJECT,
    properties: {
      location: {
        type: Type.STRING,
        description: 'The city name, e.g. San Francisco',
      },
    },
    required: ['location'],
  },
};

// Send request with function declarations
const response = await ai.models.generateContent({
  model: 'gemini-2.5-flash',
  contents: "What's the temperature in London?",
  config: {
    tools: [{
      functionDeclarations: [weatherFunctionDeclaration]
    }],
  },
});

// Check for function calls in the response
if (response.functionCalls && response.functionCalls.length > 0) {
  const functionCall = response.functionCalls[0]; // Assuming one function call
  console.log(`Function to call: ${functionCall.name}`);
  console.log(`Arguments: ${JSON.stringify(functionCall.args)}`);
  // In a real app, you would call your actual function here:
  // const result = await getCurrentTemperature(functionCall.args);
} else {
  console.log("No function call found in the response.");
  console.log(response.text);
}

REST

curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent" \
  -H "x-goog-api-key: $GEMINI_API_KEY" \
  -H 'Content-Type: application/json' \
  -X POST \
  -d '{
    "contents": [
      {
        "role": "user",
        "parts": [
          {
            "text": "What'\''s the temperature in London?"
          }
        ]
      }
    ],
    "tools": [
      {
        "functionDeclarations": [
          {
            "name": "get_current_temperature",
            "description": "Gets the current temperature for a given location.",
            "parameters": {
              "type": "object",
              "properties": {
                "location": {
                  "type": "string",
                  "description": "The city name, e.g. San Francisco"
                }
              },
              "required": ["location"]
            }
          }
        ]
      }
    ]
  }'

طريقة عمل ميزة "استدعاء الدوال"

نظرة عامة على ميزة "استدعاء الدوال"

تتضمّن ميزة "استدعاء الدوال" تفاعلاً منظَّمًا بين تطبيقك والنموذج والدوال الخارجية. في ما يلي تفاصيل العملية:

  1. تحديد تعريف الدالة: حدِّد تعريف الدالة في رمز تطبيقك. تصف تعريفات الدوال اسم الدالة ومعلماتها والغرض منها للنموذج.
  2. استدعاء النموذج اللغوي الكبير باستخدام تعريفات الدوال: أرسِل طلب المستخدم مع تعريفات الدوال إلى النموذج. ويحلّل الطلب ويحدّد ما إذا كان استدعاء دالة سيكون مفيدًا. وفي حال توفّرها، سيردّ عليك بنتيجة منظَّمة على شكل عنصر JSON.
  3. تنفيذ رمز الدالة (مسؤوليتك): لا ينفّذ النموذج الدالة بنفسه. يقع على عاتق تطبيقك مسؤولية معالجة الرد والتحقّق من Function Call، إذا كان
    • نعم: استخرِج اسم الدالة ووسيطاتها ونفِّذ الدالة المقابلة في تطبيقك.
    • لا: قدّم النموذج ردًا نصيًا مباشرًا على الطلب (لا يتم التركيز على هذا المسار في المثال، لكنّه نتيجة محتملة).
  4. إنشاء ردّ سهل الاستخدام: إذا تم تنفيذ دالة، سجِّل النتيجة وأرسِلها مرة أخرى إلى النموذج في دورة لاحقة من المحادثة. سيستخدم النتيجة لإنشاء ردّ نهائي سهل الاستخدام يتضمّن المعلومات من استدعاء الدالة.

يمكن تكرار هذه العملية عدة مرات، ما يتيح إجراء تفاعلات وعمليات سير عمل معقّدة. يتيح النموذج أيضًا استدعاء دوال متعددة في دورة واحدة (استدعاء الدوال المتوازية) وبشكل متسلسل (استدعاء الدوال التركيبية).

الخطوة 1: تحديد تعريف دالة

حدِّد دالة وبيانها ضمن رمز تطبيقك يسمح للمستخدمين بضبط قيم الإضاءة وإجراء طلب إلى واجهة برمجة التطبيقات. يمكن أن تستدعي هذه الدالة خدمات أو واجهات برمجة تطبيقات خارجية.

Python

# Define a function that the model can call to control smart lights
set_light_values_declaration = {
    "name": "set_light_values",
    "description": "Sets the brightness and color temperature of a light.",
    "parameters": {
        "type": "object",
        "properties": {
            "brightness": {
                "type": "integer",
                "description": "Light level from 0 to 100. Zero is off and 100 is full brightness",
            },
            "color_temp": {
                "type": "string",
                "enum": ["daylight", "cool", "warm"],
                "description": "Color temperature of the light fixture, which can be `daylight`, `cool` or `warm`.",
            },
        },
        "required": ["brightness", "color_temp"],
    },
}

# This is the actual function that would be called based on the model's suggestion
def set_light_values(brightness: int, color_temp: str) -> dict[str, int | str]:
    """Set the brightness and color temperature of a room light. (mock API).

    Args:
        brightness: Light level from 0 to 100. Zero is off and 100 is full brightness
        color_temp: Color temperature of the light fixture, which can be `daylight`, `cool` or `warm`.

    Returns:
        A dictionary containing the set brightness and color temperature.
    """
    return {"brightness": brightness, "colorTemperature": color_temp}

JavaScript

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

// Define a function that the model can call to control smart lights
const setLightValuesFunctionDeclaration = {
  name: 'set_light_values',
  description: 'Sets the brightness and color temperature of a light.',
  parameters: {
    type: Type.OBJECT,
    properties: {
      brightness: {
        type: Type.NUMBER,
        description: 'Light level from 0 to 100. Zero is off and 100 is full brightness',
      },
      color_temp: {
        type: Type.STRING,
        enum: ['daylight', 'cool', 'warm'],
        description: 'Color temperature of the light fixture, which can be `daylight`, `cool` or `warm`.',
      },
    },
    required: ['brightness', 'color_temp'],
  },
};

/**

*   Set the brightness and color temperature of a room light. (mock API)
*   @param {number} brightness - Light level from 0 to 100. Zero is off and 100 is full brightness
*   @param {string} color_temp - Color temperature of the light fixture, which can be `daylight`, `cool` or `warm`.
*   @return {Object} A dictionary containing the set brightness and color temperature.
*/
function setLightValues(brightness, color_temp) {
  return {
    brightness: brightness,
    colorTemperature: color_temp
  };
}

الخطوة 2: استدعاء النموذج باستخدام تعريفات الدوال

بعد تحديد تعريفات الدوال، يمكنك أن تطلب من النموذج استخدامها. ويحلّل الطلب وتعريفات الدوال ويقرّر ما إذا كان سيردّ مباشرةً أو سيستدعي دالة. إذا تم استدعاء دالة، سيحتوي عنصر الاستجابة على اقتراح باستدعاء دالة.

Python

from google.genai import types

# Configure the client and tools
client = genai.Client()
tools = types.Tool(function_declarations=[set_light_values_declaration])
config = types.GenerateContentConfig(tools=[tools])

# Define user prompt
contents = [
    types.Content(
        role="user", parts=[types.Part(text="Turn the lights down to a romantic level")]
    )
]

# Send request with function declarations
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=contents
    config=config,
)

print(response.candidates[0].content.parts[0].function_call)

JavaScript

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

// Generation config with function declaration
const config = {
  tools: [{
    functionDeclarations: [setLightValuesFunctionDeclaration]
  }]
};

// Configure the client
const ai = new GoogleGenAI({});

// Define user prompt
const contents = [
  {
    role: 'user',
    parts: [{ text: 'Turn the lights down to a romantic level' }]
  }
];

// Send request with function declarations
const response = await ai.models.generateContent({
  model: 'gemini-2.5-flash',
  contents: contents,
  config: config
});

console.log(response.functionCalls[0]);

بعد ذلك، يعرض النموذج كائن functionCall في مخطط متوافق مع OpenAPI يحدّد كيفية طلب إحدى الدوال المحدّدة أو أكثر من أجل الرد على سؤال المستخدم.

Python

id=None args={'color_temp': 'warm', 'brightness': 25} name='set_light_values'

JavaScript

{
  name: 'set_light_values',
  args: { brightness: 25, color_temp: 'warm' }
}

الخطوة 3: تنفيذ رمز الدالة set_light_values

استخرِج تفاصيل طلب استدعاء الدالة من ردّ النموذج، وحلِّل الوسيطات، ونفِّذ الدالة set_light_values.

Python

# Extract tool call details, it may not be in the first part.
tool_call = response.candidates[0].content.parts[0].function_call

if tool_call.name == "set_light_values":
    result = set_light_values(**tool_call.args)
    print(f"Function execution result: {result}")

JavaScript

// Extract tool call details
const tool_call = response.functionCalls[0]

let result;
if (tool_call.name === 'set_light_values') {
  result = setLightValues(tool_call.args.brightness, tool_call.args.color_temp);
  console.log(`Function execution result: ${JSON.stringify(result)}`);
}

الخطوة 4: إنشاء ردّ سهل الاستخدام يتضمّن نتيجة الدالة واستدعاء النموذج مرة أخرى

أخيرًا، أرسِل نتيجة تنفيذ الدالة إلى النموذج لكي يتمكّن من دمج هذه المعلومات في الردّ النهائي الذي يقدّمه للمستخدم.

Python

# Create a function response part
function_response_part = types.Part.from_function_response(
    name=tool_call.name,
    response={"result": result},
)

# Append function call and result of the function execution to contents
contents.append(response.candidates[0].content) # Append the content from the model's response.
contents.append(types.Content(role="user", parts=[function_response_part])) # Append the function response

final_response = client.models.generate_content(
    model="gemini-2.5-flash",
    config=config,
    contents=contents,
)

print(final_response.text)

JavaScript

// Create a function response part
const function_response_part = {
  name: tool_call.name,
  response: { result }
}

// Append function call and result of the function execution to contents
contents.push(response.candidates[0].content);
contents.push({ role: 'user', parts: [{ functionResponse: function_response_part }] });

// Get the final response from the model
const final_response = await ai.models.generateContent({
  model: 'gemini-2.5-flash',
  contents: contents,
  config: config
});

console.log(final_response.text);

بهذا تنتهي عملية استدعاء الدوال. استخدم النموذج الدالة set_light_values بنجاح لتنفيذ الإجراء المطلوب من المستخدم.

تعريفات الدوال

عند تنفيذ ميزة "استدعاء الدوال" في طلب، يمكنك إنشاء عنصر tools يحتوي على function declarations واحد أو أكثر. يمكنك تحديد الدوال باستخدام JSON، وتحديدًا باستخدام مجموعة فرعية من عبارات الاختيار من تنسيق مخطط OpenAPI. يمكن أن يتضمّن تعريف الدالة الواحدة المَعلمات التالية:

  • name (string): اسم فريد للدالة (get_weather_forecast، send_email). استخدِم أسماء وصفية بدون مسافات أو أحرف خاصة (استخدِم الشرطات السفلية أو camelCase).
  • description (سلسلة): شرح واضح ومفصّل لغرض الدالة وإمكاناتها. وهذا أمر بالغ الأهمية لكي يفهم النموذج متى يجب استخدام الدالة. كن دقيقًا وقدِّم أمثلة إذا كان ذلك مفيدًا ("تعثر على دور السينما استنادًا إلى الموقع الجغرافي وعنوان الفيلم بشكل اختياري، والذي يتم عرضه حاليًا في دور السينما").
  • parameters (كائن): يحدّد مَعلمات الإدخال التي تتوقّعها الدالة.
    • type (سلسلة): يحدّد نوع البيانات العام، مثل object.
    • properties (عنصر): يدرج المَعلمات الفردية، ويتضمّن كل منها ما يلي:
      • type (string): نوع بيانات المَعلمة، مثل string أو integer أو boolean, array
      • description (سلسلة): وصف لغرض المَعلمة وتنسيقها. قدِّم أمثلة وقيودًا ("المدينة والولاية، مثل "القاهرة، مصر" أو رمز بريدي، مثل '95616'.").
      • enum (مصفوفة، اختياري): إذا كانت قيم المَعلمات من مجموعة ثابتة، استخدِم "enum" لإدراج القيم المسموح بها بدلاً من مجرد وصفها في الوصف. يؤدي ذلك إلى تحسين الدقة ("enum": ["daylight", "cool", "warm"]).
    • required (مصفوفة): مصفوفة من السلاسل النصية تسرد أسماء المَعلمات التي يجب توفّرها لكي تعمل الدالة.

يمكنك أيضًا إنشاء FunctionDeclarations من دوال Python مباشرةً باستخدام types.FunctionDeclaration.from_callable(client=client, callable=your_function).

استدعاء الدوال مع التفكير

يمكن أن يؤدي تفعيل ميزة "التفكير" إلى تحسين أداء استدعاء الدوال من خلال السماح للنموذج بالاستدلال على الطلب قبل اقتراح استدعاء الدوال. إنّ Gemini API غير مرتبط بحالة، وسيتم فقدان سياق الاستدلال الخاص بالنموذج بين الأدوار في محادثة متعدّدة الأدوار. للحفاظ على هذا السياق، يمكنك استخدام توقيعات الأفكار. توقيع الفكرة هو تمثيل مشفّر لعملية التفكير الداخلية للنموذج، ويتم إرساله مرة أخرى إلى النموذج في المحادثات اللاحقة.

النمط العادي لاستخدام الأدوات المتعددة الجولات هو إلحاق الرد السابق الكامل للنموذج بسجلّ المحادثات. يتضمّن العنصر content السمة thought_signatures تلقائيًا. في حال اتّباع هذا النمط، لن تحتاج إلى إجراء أي تغييرات على الرمز.

إدارة توقيعات الأفكار يدويًا

إذا عدّلت سجلّ المحادثات يدويًا بدلاً من إرسال الردّ السابق الكامل وأردت الاستفادة من ميزة "التفكير"، عليك التعامل بشكل صحيح مع thought_signature المضمّنة في ردّ النموذج.

اتّبِع هذه القواعد لضمان الحفاظ على سياق النموذج:

  • أرسِل دائمًا thought_signature إلى النموذج داخل Part الأصلي.
  • لا تدمج Part تحتوي على توقيع مع Part لا تحتوي على توقيع. يؤدي ذلك إلى إيقاف السياق الموضعي للفكرة.
  • لا تدمج بين ملفَي Parts يحتويان على تواقيع، لأنّه لا يمكن دمج سلاسل التواقيع.

فحص توقيعات الأفكار

مع أنّ ذلك ليس ضروريًا للتنفيذ، يمكنك فحص الردّ للاطّلاع على thought_signature لأغراض تصحيح الأخطاء أو تعليمية.

Python

import base64
# After receiving a response from a model with thinking enabled
# response = client.models.generate_content(...)

# The signature is attached to the response part containing the function call
part = response.candidates[0].content.parts[0]
if part.thought_signature:
  print(base64.b64encode(part.thought_signature).decode("utf-8"))

JavaScript

// After receiving a response from a model with thinking enabled
// const response = await ai.models.generateContent(...)

// The signature is attached to the response part containing the function call
const part = response.candidates[0].content.parts[0];
if (part.thoughtSignature) {
  console.log(part.thoughtSignature);
}

يمكنك الاطّلاع على مزيد من المعلومات حول القيود المفروضة على استخدام توقيعات الأفكار، وحول نماذج التفكير بشكل عام، في صفحة التفكير.

استدعاء الدوال بشكلٍ متوازٍ

بالإضافة إلى استدعاء الدوال في دورة واحدة، يمكنك أيضًا استدعاء دوال متعددة في الوقت نفسه. تتيح لك ميزة "تنفيذ الدوال بالتوازي" تنفيذ دوال متعددة في الوقت نفسه، ويتم استخدامها عندما لا تكون الدوال معتمدة على بعضها البعض. ويكون ذلك مفيدًا في حالات مثل جمع البيانات من مصادر مستقلة متعددة، مثل استرداد تفاصيل العملاء من قواعد بيانات مختلفة أو التحقّق من مستويات المخزون في مستودعات مختلفة أو تنفيذ إجراءات متعددة مثل تحويل شقتك إلى ديسكو.

Python

power_disco_ball = {
    "name": "power_disco_ball",
    "description": "Powers the spinning disco ball.",
    "parameters": {
        "type": "object",
        "properties": {
            "power": {
                "type": "boolean",
                "description": "Whether to turn the disco ball on or off.",
            }
        },
        "required": ["power"],
    },
}

start_music = {
    "name": "start_music",
    "description": "Play some music matching the specified parameters.",
    "parameters": {
        "type": "object",
        "properties": {
            "energetic": {
                "type": "boolean",
                "description": "Whether the music is energetic or not.",
            },
            "loud": {
                "type": "boolean",
                "description": "Whether the music is loud or not.",
            },
        },
        "required": ["energetic", "loud"],
    },
}

dim_lights = {
    "name": "dim_lights",
    "description": "Dim the lights.",
    "parameters": {
        "type": "object",
        "properties": {
            "brightness": {
                "type": "number",
                "description": "The brightness of the lights, 0.0 is off, 1.0 is full.",
            }
        },
        "required": ["brightness"],
    },
}

JavaScript

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

const powerDiscoBall = {
  name: 'power_disco_ball',
  description: 'Powers the spinning disco ball.',
  parameters: {
    type: Type.OBJECT,
    properties: {
      power: {
        type: Type.BOOLEAN,
        description: 'Whether to turn the disco ball on or off.'
      }
    },
    required: ['power']
  }
};

const startMusic = {
  name: 'start_music',
  description: 'Play some music matching the specified parameters.',
  parameters: {
    type: Type.OBJECT,
    properties: {
      energetic: {
        type: Type.BOOLEAN,
        description: 'Whether the music is energetic or not.'
      },
      loud: {
        type: Type.BOOLEAN,
        description: 'Whether the music is loud or not.'
      }
    },
    required: ['energetic', 'loud']
  }
};

const dimLights = {
  name: 'dim_lights',
  description: 'Dim the lights.',
  parameters: {
    type: Type.OBJECT,
    properties: {
      brightness: {
        type: Type.NUMBER,
        description: 'The brightness of the lights, 0.0 is off, 1.0 is full.'
      }
    },
    required: ['brightness']
  }
};

اضبط وضع "استدعاء الدوال" للسماح باستخدام جميع الأدوات المحدّدة. لمزيد من المعلومات، يمكنك الاطّلاع على مقالة ضبط ميزة "استدعاء الدوال".

Python

from google import genai
from google.genai import types

# Configure the client and tools
client = genai.Client()
house_tools = [
    types.Tool(function_declarations=[power_disco_ball, start_music, dim_lights])
]
config = types.GenerateContentConfig(
    tools=house_tools,
    automatic_function_calling=types.AutomaticFunctionCallingConfig(
        disable=True
    ),
    # Force the model to call 'any' function, instead of chatting.
    tool_config=types.ToolConfig(
        function_calling_config=types.FunctionCallingConfig(mode='ANY')
    ),
)

chat = client.chats.create(model="gemini-2.5-flash", config=config)
response = chat.send_message("Turn this place into a party!")

# Print out each of the function calls requested from this single call
print("Example 1: Forced function calling")
for fn in response.function_calls:
    args = ", ".join(f"{key}={val}" for key, val in fn.args.items())
    print(f"{fn.name}({args})")

JavaScript

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

// Set up function declarations
const houseFns = [powerDiscoBall, startMusic, dimLights];

const config = {
    tools: [{
        functionDeclarations: houseFns
    }],
    // Force the model to call 'any' function, instead of chatting.
    toolConfig: {
        functionCallingConfig: {
            mode: 'any'
        }
    }
};

// Configure the client
const ai = new GoogleGenAI({});

// Create a chat session
const chat = ai.chats.create({
    model: 'gemini-2.5-flash',
    config: config
});
const response = await chat.sendMessage({message: 'Turn this place into a party!'});

// Print out each of the function calls requested from this single call
console.log("Example 1: Forced function calling");
for (const fn of response.functionCalls) {
    const args = Object.entries(fn.args)
        .map(([key, val]) => `${key}=${val}`)
        .join(', ');
    console.log(`${fn.name}(${args})`);
}

تعكس كل نتيجة مطبوعة طلبًا واحدًا للدالة قد طلبه النموذج. لإعادة إرسال النتائج، يجب تضمين الردود بالترتيب نفسه الذي تم طلبها به.

تتيح حزمة تطوير البرامج (SDK) الخاصة بلغة Python استدعاء الدوال تلقائيًا، ما يؤدي إلى تحويل دوال Python تلقائيًا إلى تعريفات، والتعامل مع دورة تنفيذ استدعاء الدالة والاستجابة نيابةً عنك. في ما يلي مثال على حالة استخدام disco.

Python

from google import genai
from google.genai import types

# Actual function implementations
def power_disco_ball_impl(power: bool) -> dict:
    """Powers the spinning disco ball.

    Args:
        power: Whether to turn the disco ball on or off.

    Returns:
        A status dictionary indicating the current state.
    """
    return {"status": f"Disco ball powered {'on' if power else 'off'}"}

def start_music_impl(energetic: bool, loud: bool) -> dict:
    """Play some music matching the specified parameters.

    Args:
        energetic: Whether the music is energetic or not.
        loud: Whether the music is loud or not.

    Returns:
        A dictionary containing the music settings.
    """
    music_type = "energetic" if energetic else "chill"
    volume = "loud" if loud else "quiet"
    return {"music_type": music_type, "volume": volume}

def dim_lights_impl(brightness: float) -> dict:
    """Dim the lights.

    Args:
        brightness: The brightness of the lights, 0.0 is off, 1.0 is full.

    Returns:
        A dictionary containing the new brightness setting.
    """
    return {"brightness": brightness}

# Configure the client
client = genai.Client()
config = types.GenerateContentConfig(
    tools=[power_disco_ball_impl, start_music_impl, dim_lights_impl]
)

# Make the request
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents="Do everything you need to this place into party!",
    config=config,
)

print("\nExample 2: Automatic function calling")
print(response.text)
# I've turned on the disco ball, started playing loud and energetic music, and dimmed the lights to 50% brightness. Let's get this party started!

استدعاء الدوال التركيبية

تسمح ميزة "استدعاء الدوال التركيبي أو التسلسلي" لـ Gemini بربط عدة طلبات استدعاء دوال معًا لتلبية طلب معقّد. على سبيل المثال، للإجابة عن السؤال "ما هي درجة الحرارة في موقعي الجغرافي الحالي؟"، قد تستدعي Gemini API أولاً الدالة get_current_location() ثم الدالة get_weather() التي تأخذ الموقع الجغرافي كمعلَمة.

يوضّح المثال التالي كيفية تنفيذ استدعاء الدوال التركيبية باستخدام حزمة تطوير البرامج (SDK) الخاصة بلغة Python واستدعاء الدوال تلقائيًا.

Python

يستخدم هذا المثال ميزة استدعاء الدوال التلقائي في google-genai حزمة تطوير البرامج (SDK) الخاصة بلغة Python. تحوّل حزمة تطوير البرامج (SDK) تلقائيًا دوال Python إلى المخطط المطلوب، وتنفّذ طلبات استدعاء الدوال عند طلب النموذج، وترسل النتائج مرة أخرى إلى النموذج لإكمال المهمة.

import os
from google import genai
from google.genai import types

# Example Functions
def get_weather_forecast(location: str) -> dict:
    """Gets the current weather temperature for a given location."""
    print(f"Tool Call: get_weather_forecast(location={location})")
    # TODO: Make API call
    print("Tool Response: {'temperature': 25, 'unit': 'celsius'}")
    return {"temperature": 25, "unit": "celsius"}  # Dummy response

def set_thermostat_temperature(temperature: int) -> dict:
    """Sets the thermostat to a desired temperature."""
    print(f"Tool Call: set_thermostat_temperature(temperature={temperature})")
    # TODO: Interact with a thermostat API
    print("Tool Response: {'status': 'success'}")
    return {"status": "success"}

# Configure the client and model
client = genai.Client()
config = types.GenerateContentConfig(
    tools=[get_weather_forecast, set_thermostat_temperature]
)

# Make the request
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents="If it's warmer than 20°C in London, set the thermostat to 20°C, otherwise set it to 18°C.",
    config=config,
)

# Print the final, user-facing response
print(response.text)

الناتج المتوقّع

عند تشغيل الرمز، ستلاحظ أنّ حزمة تطوير البرامج (SDK) تنظّم عمليات استدعاء الدوال. يستدعي النموذج أولاً get_weather_forecast، ويتلقّى درجة الحرارة، ثم يستدعي set_thermostat_temperature بالقيمة الصحيحة استنادًا إلى المنطق الوارد في الطلب.

Tool Call: get_weather_forecast(location=London)
Tool Response: {'temperature': 25, 'unit': 'celsius'}
Tool Call: set_thermostat_temperature(temperature=20)
Tool Response: {'status': 'success'}
OK. I've set the thermostat to 20°C.

JavaScript

يوضّح هذا المثال كيفية استخدام حزمة تطوير البرامج (SDK) JavaScript/TypeScript لتنفيذ استدعاءات الدوال التركيبية باستخدام حلقة تنفيذ يدوية.

import { GoogleGenAI, Type } from "@google/genai";

// Configure the client
const ai = new GoogleGenAI({});

// Example Functions
function get_weather_forecast({ location }) {
  console.log(`Tool Call: get_weather_forecast(location=${location})`);
  // TODO: Make API call
  console.log("Tool Response: {'temperature': 25, 'unit': 'celsius'}");
  return { temperature: 25, unit: "celsius" };
}

function set_thermostat_temperature({ temperature }) {
  console.log(
    `Tool Call: set_thermostat_temperature(temperature=${temperature})`,
  );
  // TODO: Make API call
  console.log("Tool Response: {'status': 'success'}");
  return { status: "success" };
}

const toolFunctions = {
  get_weather_forecast,
  set_thermostat_temperature,
};

const tools = [
  {
    functionDeclarations: [
      {
        name: "get_weather_forecast",
        description:
          "Gets the current weather temperature for a given location.",
        parameters: {
          type: Type.OBJECT,
          properties: {
            location: {
              type: Type.STRING,
            },
          },
          required: ["location"],
        },
      },
      {
        name: "set_thermostat_temperature",
        description: "Sets the thermostat to a desired temperature.",
        parameters: {
          type: Type.OBJECT,
          properties: {
            temperature: {
              type: Type.NUMBER,
            },
          },
          required: ["temperature"],
        },
      },
    ],
  },
];

// Prompt for the model
let contents = [
  {
    role: "user",
    parts: [
      {
        text: "If it's warmer than 20°C in London, set the thermostat to 20°C, otherwise set it to 18°C.",
      },
    ],
  },
];

// Loop until the model has no more function calls to make
while (true) {
  const result = await ai.models.generateContent({
    model: "gemini-2.5-flash",
    contents,
    config: { tools },
  });

  if (result.functionCalls && result.functionCalls.length > 0) {
    const functionCall = result.functionCalls[0];

    const { name, args } = functionCall;

    if (!toolFunctions[name]) {
      throw new Error(`Unknown function call: ${name}`);
    }

    // Call the function and get the response.
    const toolResponse = toolFunctions[name](args);

    const functionResponsePart = {
      name: functionCall.name,
      response: {
        result: toolResponse,
      },
    };

    // Send the function response back to the model.
    contents.push({
      role: "model",
      parts: [
        {
          functionCall: functionCall,
        },
      ],
    });
    contents.push({
      role: "user",
      parts: [
        {
          functionResponse: functionResponsePart,
        },
      ],
    });
  } else {
    // No more function calls, break the loop.
    console.log(result.text);
    break;
  }
}

الناتج المتوقّع

عند تشغيل الرمز، ستلاحظ أنّ حزمة تطوير البرامج (SDK) تنظّم عمليات استدعاء الدوال. يستدعي النموذج أولاً get_weather_forecast، ويتلقّى درجة الحرارة، ثم يستدعي set_thermostat_temperature بالقيمة الصحيحة استنادًا إلى المنطق الوارد في الطلب.

Tool Call: get_weather_forecast(location=London)
Tool Response: {'temperature': 25, 'unit': 'celsius'}
Tool Call: set_thermostat_temperature(temperature=20)
Tool Response: {'status': 'success'}
OK. It's 25°C in London, so I've set the thermostat to 20°C.

استدعاء الدوال التركيبي هو إحدى الميزات الأصلية في Live API. وهذا يعني أنّ Live API يمكنه التعامل مع استدعاء الدوال بشكل مشابه لحزمة تطوير البرامج (SDK) الخاصة بلغة Python.

Python

# Light control schemas
turn_on_the_lights_schema = {'name': 'turn_on_the_lights'}
turn_off_the_lights_schema = {'name': 'turn_off_the_lights'}

prompt = """
  Hey, can you write run some python code to turn on the lights, wait 10s and then turn off the lights?
  """

tools = [
    {'code_execution': {}},
    {'function_declarations': [turn_on_the_lights_schema, turn_off_the_lights_schema]}
]

await run(prompt, tools=tools, modality="AUDIO")

JavaScript

// Light control schemas
const turnOnTheLightsSchema = { name: 'turn_on_the_lights' };
const turnOffTheLightsSchema = { name: 'turn_off_the_lights' };

const prompt = `
  Hey, can you write run some python code to turn on the lights, wait 10s and then turn off the lights?
`;

const tools = [
  { codeExecution: {} },
  { functionDeclarations: [turnOnTheLightsSchema, turnOffTheLightsSchema] }
];

await run(prompt, tools=tools, modality="AUDIO")

أوضاع استدعاء الدالة

تتيح لك Gemini API التحكّم في طريقة استخدام النموذج للأدوات المقدَّمة (تعريفات الدوال). على وجه التحديد، يمكنك ضبط الوضع ضمن function_calling_config.

  • AUTO (Default): يقرّر النموذج ما إذا كان سيقدّم ردًا باللغة الطبيعية أو سيقترح طلب وظيفة استنادًا إلى الطلب والسياق. هذا الوضع هو الأكثر مرونة ويُنصح به في معظم السيناريوهات.
  • ANY: يكون النموذج مقيّدًا بالتوقّع دائمًا لاستدعاء دالة، ويضمن الالتزام بمخطط الدالة. إذا لم يتم تحديد allowed_function_names، يمكن للنموذج الاختيار من أي من تعريفات الدوال المقدَّمة. إذا تم تقديم allowed_function_names كقائمة، يمكن للنموذج الاختيار فقط من الدوال في تلك القائمة. استخدِم هذا الوضع عندما تحتاج إلى استجابة من دالة لكل طلب (إذا كان ذلك منطبقًا).
  • NONE: محظور على النموذج إجراء استدعاءات الدوال. وهذا الإجراء مكافئ لإرسال طلب بدون أي تعريفات للدوال. يمكنك استخدام هذه السمة لإيقاف ميزة "استدعاء الدوال" مؤقتًا بدون إزالة تعريفات الأدوات.

Python

from google.genai import types

# Configure function calling mode
tool_config = types.ToolConfig(
    function_calling_config=types.FunctionCallingConfig(
        mode="ANY", allowed_function_names=["get_current_temperature"]
    )
)

# Create the generation config
config = types.GenerateContentConfig(
    tools=[tools],  # not defined here.
    tool_config=tool_config,
)

JavaScript

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

// Configure function calling mode
const toolConfig = {
  functionCallingConfig: {
    mode: FunctionCallingConfigMode.ANY,
    allowedFunctionNames: ['get_current_temperature']
  }
};

// Create the generation config
const config = {
  tools: tools, // not defined here.
  toolConfig: toolConfig,
};

استدعاء الدوال تلقائيًا (في Python فقط)

عند استخدام حزمة تطوير البرامج (SDK) الخاصة بلغة Python، يمكنك تقديم دوال Python مباشرةً كأدوات. تحوّل حزمة SDK هذه الدوال إلى تعريفات، وتدير عملية تنفيذ استدعاء الدالة، وتتعامل مع دورة الاستجابة نيابةً عنك. حدِّد الدالة باستخدام تلميحات الأنواع وسلسلة التوثيق. للحصول على أفضل النتائج، ننصحك باستخدام سلاسل مستندات بتنسيق Google. سيقوم حِزمة تطوير البرامج (SDK) بعد ذلك تلقائيًا بما يلي:

  1. رصد الردود على طلبات تنفيذ الدوال من النموذج
  2. استدعِ دالة Python المناسبة في الرمز البرمجي.
  3. أرسِل ردّ الدالة إلى النموذج.
  4. عرض الرد النصي النهائي للنموذج

لا تحلّل حزمة تطوير البرامج (SDK) حاليًا أوصاف الوسيطات إلى خانات وصف السمة في تعريف الدالة الذي تم إنشاؤه. بدلاً من ذلك، يرسل السلسلة بأكملها كوصف للدالة ذات المستوى الأعلى.

Python

from google import genai
from google.genai import types

# Define the function with type hints and docstring
def get_current_temperature(location: str) -> dict:
    """Gets the current temperature for a given location.

    Args:
        location: The city and state, e.g. San Francisco, CA

    Returns:
        A dictionary containing the temperature and unit.
    """
    # ... (implementation) ...
    return {"temperature": 25, "unit": "Celsius"}

# Configure the client
client = genai.Client()
config = types.GenerateContentConfig(
    tools=[get_current_temperature]
)  # Pass the function itself

# Make the request
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents="What's the temperature in Boston?",
    config=config,
)

print(response.text)  # The SDK handles the function call and returns the final text

يمكنك إيقاف استدعاء الدوال التلقائي باستخدام:

Python

config = types.GenerateContentConfig(
    tools=[get_current_temperature],
    automatic_function_calling=types.AutomaticFunctionCallingConfig(disable=True)
)

بيان مخطط الدالة التلقائي

يمكن لواجهة برمجة التطبيقات وصف أي من الأنواع التالية. يُسمح باستخدام أنواع Pydantic، طالما أنّ الحقول المحدّدة فيها تتألف أيضًا من أنواع مسموح بها. لا تتوافق أنواع القواميس (مثل dict[str: int]) مع هذه الميزة، لذا لا تستخدمها.

Python

AllowedType = (
  int | float | bool | str | list['AllowedType'] | pydantic.BaseModel)

للاطّلاع على شكل المخطط الاستنتاجي، يمكنك تحويله باستخدام from_callable:

Python

def multiply(a: float, b: float):
    """Returns a * b."""
    return a * b

fn_decl = types.FunctionDeclaration.from_callable(callable=multiply, client=client)

# to_json_dict() provides a clean JSON representation.
print(fn_decl.to_json_dict())

استخدام أدوات متعددة: الجمع بين الأدوات الأصلية واستدعاء الدوال

يمكنك تفعيل أدوات متعددة تجمع بين الأدوات المضمّنة واستدعاء الدوال في الوقت نفسه. في ما يلي مثال يفعّل أداتَين، الاستناد إلى معلومات من "بحث Google" وتنفيذ الرمز البرمجي، في طلب باستخدام Live API.

Python

# Multiple tasks example - combining lights, code execution, and search
prompt = """
  Hey, I need you to do three things for me.

    1.  Turn on the lights.
    2.  Then compute the largest prime palindrome under 100000.
    3.  Then use Google Search to look up information about the largest earthquake in California the week of Dec 5 2024.

  Thanks!
  """

tools = [
    {'google_search': {}},
    {'code_execution': {}},
    {'function_declarations': [turn_on_the_lights_schema, turn_off_the_lights_schema]} # not defined here.
]

# Execute the prompt with specified tools in audio modality
await run(prompt, tools=tools, modality="AUDIO")

JavaScript

// Multiple tasks example - combining lights, code execution, and search
const prompt = `
  Hey, I need you to do three things for me.

    1.  Turn on the lights.
    2.  Then compute the largest prime palindrome under 100000.
    3.  Then use Google Search to look up information about the largest earthquake in California the week of Dec 5 2024.

  Thanks!
`;

const tools = [
  { googleSearch: {} },
  { codeExecution: {} },
  { functionDeclarations: [turnOnTheLightsSchema, turnOffTheLightsSchema] } // not defined here.
];

// Execute the prompt with specified tools in audio modality
await run(prompt, {tools: tools, modality: "AUDIO"});

يمكن لمطوّري Python تجربة هذه الميزة في دفتر ملاحظات استخدام Live API Tool.

بروتوكول سياق النموذج (MCP)

بروتوكول سياق النموذج (MCP) هو معيار مفتوح لربط تطبيقات الذكاء الاصطناعي بأدوات وبيانات خارجية. يوفر MCP بروتوكولاً مشتركًا للنماذج للوصول إلى السياق، مثل الدوال (الأدوات) أو مصادر البيانات (الموارد) أو الطلبات المحدّدة مسبقًا.

تتضمّن حِزم تطوير البرامج (SDK) من Gemini إمكانية استخدام أدوات MCP مباشرةً، ما يقلّل من الرموز النموذجية ويوفّر ميزة استدعاء الأدوات تلقائيًا لأدوات MCP. عندما ينشئ النموذج طلبًا لاستخدام أداة MCP، يمكن لحزمة تطوير البرامج (SDK) الخاصة بلغة Python وJavaScript تنفيذ أداة MCP تلقائيًا وإرسال الردّ إلى النموذج في طلب لاحق، مع مواصلة هذه العملية إلى أن يتوقف النموذج عن إرسال طلبات لاستخدام الأدوات.

يمكنك هنا الاطّلاع على مثال حول كيفية استخدام خادم MCP محلي مع Gemini وmcp SDK.

Python

تأكَّد من تثبيت أحدث إصدار من حزمة تطوير البرامج (SDK)mcp على النظام الأساسي الذي تختاره.

pip install mcp
import os
import asyncio
from datetime import datetime
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from google import genai

client = genai.Client()

# Create server parameters for stdio connection
server_params = StdioServerParameters(
    command="npx",  # Executable
    args=["-y", "@philschmid/weather-mcp"],  # MCP Server
    env=None,  # Optional environment variables
)

async def run():
    async with stdio_client(server_params) as (read, write):
        async with ClientSession(read, write) as session:
            # Prompt to get the weather for the current day in London.
            prompt = f"What is the weather in London in {datetime.now().strftime('%Y-%m-%d')}?"

            # Initialize the connection between client and server
            await session.initialize()

            # Send request to the model with MCP function declarations
            response = await client.aio.models.generate_content(
                model="gemini-2.5-flash",
                contents=prompt,
                config=genai.types.GenerateContentConfig(
                    temperature=0,
                    tools=[session],  # uses the session, will automatically call the tool
                    # Uncomment if you **don't** want the SDK to automatically call the tool
                    # automatic_function_calling=genai.types.AutomaticFunctionCallingConfig(
                    #     disable=True
                    # ),
                ),
            )
            print(response.text)

# Start the asyncio event loop and run the main function
asyncio.run(run())

JavaScript

تأكَّد من تثبيت أحدث إصدار من حزمة تطوير البرامج (SDK) mcp على المنصة التي تختارها.

npm install @modelcontextprotocol/sdk
import { GoogleGenAI, FunctionCallingConfigMode , mcpToTool} from '@google/genai';
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";

// Create server parameters for stdio connection
const serverParams = new StdioClientTransport({
  command: "npx", // Executable
  args: ["-y", "@philschmid/weather-mcp"] // MCP Server
});

const client = new Client(
  {
    name: "example-client",
    version: "1.0.0"
  }
);

// Configure the client
const ai = new GoogleGenAI({});

// Initialize the connection between client and server
await client.connect(serverParams);

// Send request to the model with MCP tools
const response = await ai.models.generateContent({
  model: "gemini-2.5-flash",
  contents: `What is the weather in London in ${new Date().toLocaleDateString()}?`,
  config: {
    tools: [mcpToTool(client)],  // uses the session, will automatically call the tool
    // Uncomment if you **don't** want the sdk to automatically call the tool
    // automaticFunctionCalling: {
    //   disable: true,
    // },
  },
});
console.log(response.text)

// Close the connection
await client.close();

القيود المفروضة على التوافق المضمّن مع منصّات إدارة الموافقة

تتوفّر ميزة دعم MCP المضمّنة تجريبيًا في حِزم SDK، وتخضع للقيود التالية:

  • لا تتوفّر سوى الأدوات، وليس المراجع أو الطلبات
  • وهي متاحة لحزمة تطوير البرامج (SDK) الخاصة بلغة Python وJavaScript/TypeScript.
  • قد تحدث تغييرات غير متوافقة مع الإصدارات السابقة في الإصدارات المستقبلية.

يمكنك دائمًا دمج خوادم MCP يدويًا إذا كانت هذه الخوادم تفرض قيودًا على ما تنشئه.

النماذج المتوافقة

يسرد هذا القسم النماذج وإمكاناتها في استدعاء الدوال. ولا يتم تضمين النماذج التجريبية. يمكنك الاطّلاع على نظرة عامة شاملة حول الإمكانات في صفحة نظرة عامة على النموذج.

الطراز استدعاء الدوال استدعاء الدوال بشكل متوازٍ استدعاء الدوال التركيبية
Gemini 2.5 Pro ✔️ ✔️ ✔️
‫Gemini 2.5 Flash ✔️ ✔️ ✔️
‫Gemini 2.5 Flash-Lite ✔️ ✔️ ✔️
‫Gemini 2.0 Flash ✔️ ✔️ ✔️
‫Gemini 2.0 Flash-Lite X X X

أفضل الممارسات

  • أوصاف الدوال والمَعلمات: يجب أن تكون أوصافك واضحة ومحدّدة للغاية. ويعتمد النموذج على هذه المعلومات لاختيار الدالة الصحيحة وتقديم الوسيطات المناسبة.
  • التسمية: استخدِم أسماء دوال وصفية (بدون مسافات أو نقاط أو شرطات).
  • الكتابة القوية: استخدِم أنواعًا محدّدة (عدد صحيح، سلسلة، تعداد) للمَعلمات للحدّ من الأخطاء. إذا كانت إحدى المَعلمات تتضمّن مجموعة محدودة من القيم الصالحة، استخدِم نوع البيانات enum.
  • اختيار الأدوات: على الرغم من أنّ النموذج يمكنه استخدام عدد غير محدود من الأدوات، فإنّ توفير عدد كبير جدًا منها قد يزيد من خطر اختيار أداة غير صحيحة أو غير مثالية. للحصول على أفضل النتائج، احرص على توفير الأدوات ذات الصلة فقط بالسياق أو المهمة، مع الحرص على ألا يزيد عدد الأدوات النشطة عن 10 إلى 20 أداة. ننصحك باختيار الأدوات بشكل ديناميكي استنادًا إلى سياق المحادثة إذا كان لديك عدد كبير من الأدوات.
  • هندسة الطلبات:
    • توفير سياق: أخبر النموذج بدوره (مثلاً "أنت مساعد مفيد بشأن الطقس").
    • تقديم التعليمات: حدِّد كيفية استخدام الدوال ومتى (مثلاً لا تخمّن التواريخ، بل استخدِم دائمًا تاريخًا مستقبليًا للتوقّعات").
    • تشجيع التوضيح: اطلب من النموذج طرح أسئلة توضيحية إذا لزم الأمر.
  • درجة الحرارة: استخدِم درجة حرارة منخفضة (مثل ‫0) لإجراء عمليات استدعاء للدوال أكثر تحديدًا وموثوقية.
  • التحقّق من الصحة: إذا كان لطلب تنفيذ دالة عواقب كبيرة (مثل تقديم طلب)، يجب التحقّق من صحة الطلب مع المستخدم قبل تنفيذه.
  • التعامل مع الأخطاء: نفِّذ عملية التعامل مع الأخطاء بشكل فعّال في الدوال للتعامل مع الإدخالات غير المتوقّعة أو الأعطال في واجهة برمجة التطبيقات. عرض رسائل خطأ مفيدة يمكن للنموذج استخدامها لإنشاء ردود مفيدة للمستخدم.
  • الأمان: يُرجى مراعاة الأمان عند استدعاء واجهات برمجة التطبيقات الخارجية. استخدام آليات المصادقة والتفويض المناسبة تجنَّب عرض البيانات الحسّاسة في استدعاءات الدوال.
  • حدود الرموز المميزة: يتم احتساب أوصاف الدوال ومعلَماتها ضمن الحد الأقصى لعدد الرموز المميزة التي يمكنك إدخالها. إذا كنت تواجه حدودًا قصوى لعدد الرموز المميزة، ننصحك بالحدّ من عدد الدوال أو طول الأوصاف، وتقسيم المهام المعقّدة إلى مجموعات دوال أصغر وأكثر تركيزًا.

الملاحظات والقيود

  • يتوافق هذا الملف مع مجموعة فرعية من مخطط OpenAPI فقط.
  • أنواع المَعلمات المتوافقة في Python محدودة.
  • لا تتوفّر ميزة استدعاء الدوال تلقائيًا إلا في حزمة تطوير البرامج (SDK) الخاصة بلغة Python.