راهنمای کدنویسی روش‌های مختلف فراخوانی تابع برای ایجاد عوامل هوش مصنوعی مکالمه‌ای مجهز به ابزار و بی‌درنگ

فراخوانی تابع (Function calling) به یک مدل زبانی بزرگ (LLM) اجازه می‌دهد تا به عنوان پلی بین درخواست‌های زبان طبیعی و کد یا APIهای دنیای واقعی عمل کند. به جای تولید صرف متن، مدل تصمیم می‌گیرد چه زمانی یک تابع از پیش تعریف شده را فراخوانی کند، یک فراخوانی JSON ساختاریافته با نام تابع و آرگومان‌ها ارسال می‌کند و سپس منتظر می‌ماند تا برنامه شما آن فراخوانی را اجرا کرده و نتایج را برگرداند. این رفت و برگشت می‌تواند به صورت حلقه‌ای انجام شود و به طور بالقوه چندین تابع را به صورت متوالی فراخوانی کند، که این امر تعاملات غنی و چند مرحله‌ای را به طور کامل تحت کنترل مکالمه‌ای امکان‌پذیر می‌کند. در این آموزش، ما یک دستیار هواشناسی را با Gemini 2.0 Flash پیاده‌سازی خواهیم کرد تا نشان دهیم چگونه این چرخه فراخوانی تابع را تنظیم و مدیریت کنیم. ما انواع مختلفی از فراخوانی تابع را پیاده‌سازی خواهیم کرد. با ادغام فراخوانی‌های تابع، ما یک رابط چت را به یک ابزار پویا برای کارهای بی‌درنگ تبدیل می‌کنیم، چه واکشی داده‌های زنده هواشناسی، بررسی وضعیت سفارش، برنامه‌ریزی قرار ملاقات یا به‌روزرسانی پایگاه‌های داده. کاربران دیگر فرم‌های پیچیده را پر نمی‌کنند یا در چندین صفحه پیمایش نمی‌کنند؛ آنها به سادگی آنچه را که نیاز دارند توصیف می‌کنند و LLM اقدامات اساسی را به طور یکپارچه سازماندهی می‌کند. این اتوماسیون زبان طبیعی، ساخت آسان عوامل هوش مصنوعی را امکان‌پذیر می‌کند که می‌توانند به منابع داده خارجی دسترسی داشته باشند، تراکنش‌ها را انجام دهند یا گردش‌های کاری را راه‌اندازی کنند، همه اینها در یک مکالمه واحد انجام می‌شود.

فراخوانی تابع با Google Gemini 2.0 Flash

!pip install "google-genai>=1.0.0" geopy requests

ما Gemini Python SDK (google-genai = 1.0.0) را به همراه geopy برای تبدیل نام مکان‌ها به مختصات و requests برای ایجاد فراخوانی‌های HTTP نصب می‌کنیم، و اطمینان حاصل می‌کنیم که تمام وابستگی‌های اصلی برای دستیار هواشناسی Colab ما در جای خود قرار دارند.

import os from google import genai GEMINI_API_KEY = "Use_Your_API_Key" client = genai.Client(api_key=GEMINI_API_KEY) model_id = "gemini-2.0-flash"

ما Gemini SDK را وارد می‌کنیم، کلید API خود را تنظیم می‌کنیم و یک نمونه genai.Client پیکربندی شده برای استفاده از مدل “gemini-2.0-flash” ایجاد می‌کنیم، و پایه‌ای برای تمام درخواست‌های فراخوانی تابع بعدی ایجاد می‌کنیم.

res = client.models.generate_content( model=model_id, contents=["Tell me 1 good fact about Nuremberg."] ) print(res.text)

ما یک درخواست کاربر (“Tell me 1 good fact about Nuremberg.”) را از طریق generate_content به مدل Gemini 2.0 Flash ارسال می‌کنیم، سپس پاسخ متنی مدل را چاپ می‌کنیم، که یک فراخوانی اساسی و سرتاسری تولید متن را با استفاده از SDK نشان می‌دهد.

فراخوانی تابع با طرحواره JSON

weather_function = { "name": "get_weather_forecast", "description": "Retrieves the weather using Open-Meteo API for a given location (city) and a date (yyyy-mm-dd). Returns a list dictionary with the time and temperature for each hour.", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "The city and state, e.g., San Francisco, CA" }, "date": { "type": "string", "description": "the forecasting date for when to get the weather format (yyyy-mm-dd)" } }, "required": ["location","date"] } }

در اینجا، ما یک طرحواره JSON برای ابزار get_weather_forecast خود تعریف می‌کنیم، نام آن، یک درخواست توصیفی برای راهنمایی Gemini در مورد زمان استفاده از آن، و پارامترهای ورودی دقیق (location و date) با انواع، توضیحات و فیلدهای مورد نیاز آنها را مشخص می‌کنیم، تا مدل بتواند فراخوانی‌های تابع معتبر را ارسال کند.

from google.genai.types import GenerateContentConfig config = GenerateContentConfig( system_instruction="You are a helpful assistant that use tools to access and retrieve information from a weather API. Today is 2025-03-04.", tools=[{"function_declarations": [weather_function]}], )

ما یک GenerateContentConfig ایجاد می‌کنیم که به Gemini می‌گوید به عنوان یک دستیار بازیابی آب و هوا عمل می‌کند و تابع آب و هوای شما را تحت tools ثبت می‌کند. از این رو، مدل می‌داند که چگونه هنگام درخواست داده‌های پیش‌بینی، فراخوانی‌های ساختاریافته ایجاد کند.

response = client.models.generate_content( model=model_id, contents='Whats the weather in Berlin today?' ) print(response.text)

این فراخوانی درخواست خالی (“What’s the weather in Berlin today?”) را بدون گنجاندن config شما (و بنابراین بدون تعریف تابع) ارسال می‌کند، بنابراین Gemini به تکمیل متن ساده بازمی‌گردد و به جای فراخوانی ابزار پیش‌بینی آب و هوای شما، توصیه‌های کلی ارائه می‌دهد.

response = client.models.generate_content( model=model_id, config=config, contents='Whats the weather in Berlin today?' ) for part in response.candidates[0].content.parts: print(part.function_call)

با ارسال config (که شامل ابزار طرحواره JSON شما می‌شود)، Gemini تشخیص می‌دهد که باید get_weather_forecast را فراخوانی کند تا اینکه به صورت متن ساده پاسخ دهد. حلقه روی response.candidates[0].content.parts سپس شیء .function_call هر قسمت را چاپ می‌کند، و به شما نشان می‌دهد دقیقاً کدام تابع توسط مدل فراخوانی شده است (با نام و آرگومان‌های آن).

from google.genai import types from geopy.geocoders import Nominatim import requests geolocator = Nominatim(user_agent="weather-app") def get_weather_forecast(location, date): location = geolocator.geocode(location) if location: try: response = requests.get(f"https://api.open-meteo.com/v1/forecast?latitude={location.latitude}&longitude={location.longitude}&hourly=temperature_2m&start_date={date}&end_date={date}") data = response.json() return {time: temp for time, temp in zip(data["hourly"]["time"], data["hourly"]["temperature_2m"])} except Exception as e: return {"error": str(e)} else: return {"error": "Location not found"} functions = { "get_weather_forecast": get_weather_forecast } def call_function(function_name, **kwargs): return functions[function_name](**kwargs) def function_call_loop(prompt): contents = [types.Content(role="user", parts=[types.Part(text=prompt)])] response = client.models.generate_content( model=model_id, config=config, contents=contents ) for part in response.candidates[0].content.parts: contents.append(types.Content(role="model", parts=[part])) if part.function_call: print("Tool call detected") function_call = part.function_call print(f"Calling tool: {function_call.name} with args: {function_call.args}") tool_result = call_function(function_call.name, **function_call.args) function_response_part = types.Part.from_function_response( name=function_call.name, response={"result": tool_result}, ) contents.append(types.Content(role="user", parts=[function_response_part])) print(f"Calling LLM with tool results") func_gen_response = client.models.generate_content( model=model_id, config=config, contents=contents ) contents.append(types.Content(role="model", parts=[func_gen_response])) return contents[-1].parts[0].text.strip() result = function_call_loop("Whats the weather in Berlin today?") print(result)

ما یک حلقه کامل “agentic” پیاده‌سازی می‌کنیم: درخواست شما را به Gemini ارسال می‌کند، پاسخ را برای فراخوانی تابع بررسی می‌کند، get_weather_forecast را اجرا می‌کند (با استفاده از Geopy به علاوه یک درخواست HTTP Open-Meteo) و سپس نتیجه ابزار را دوباره به مدل وارد می‌کند تا پاسخ مکالمه‌ای نهایی را تولید و برگرداند.

فراخوانی تابع با استفاده از توابع پایتون

from geopy.geocoders import Nominatim import requests geolocator = Nominatim(user_agent="weather-app") def get_weather_forecast(location: str, date: str) -> str: """ Retrieves the weather using Open-Meteo API for a given location (city) and a date (yyyy-mm-dd). Returns a list dictionary with the time and temperature for each hour." Args: location (str): The city and state, e.g. San Francisco, CA date (str): The forecasting date for when to get the weather format (yyyy-mm-dd) Returns: Dict[str, float]: A dictionary with the time as key and the temperature as value """ location = geolocator.geocode(location) if location: try: response = requests.get(f"https://api.open-meteo.com/v1/forecast?latitude={location.latitude}&longitude={location.longitude}&hourly=temperature_2m&start_date={date}&end_date={date}") data = response.json() return {time: temp for time, temp in zip(data["hourly"]["time"], data["hourly"]["temperature_2m"])} except Exception as e: return {"error": str(e)} else: return {"error": "Location not found"}

تابع get_weather_forecast ابتدا از Nominatim متعلق به Geopy برای تبدیل یک رشته شهر و ایالت به مختصات استفاده می‌کند، سپس یک درخواست HTTP به API Open-Meteo ارسال می‌کند تا داده‌های دمای ساعتی را برای تاریخ مشخص شده بازیابی کند، و یک دیکشنری برمی‌گرداند که هر مُهر زمانی را به دمای مربوطه نگاشت می‌کند. همچنین خطاها را به خوبی مدیریت می‌کند و در صورت عدم یافتن مکان یا عدم موفقیت در فراخوانی API، یک پیام خطا برمی‌گرداند.

from google.genai.types import GenerateContentConfig config = GenerateContentConfig( system_instruction="You are a helpful assistant that can help with weather related questions. Today is 2025-03-04.", # to give the LLM context on the current date. tools=[get_weather_forecast], automatic_function_calling={"disable": True} )

این config تابع get_weather_forecast پایتون شما را به عنوان یک ابزار قابل فراخوانی ثبت می‌کند. یک اعلان سیستم واضح (شامل تاریخ) را برای زمینه تنظیم می‌کند، در حالی که “automatic_function_calling” را غیرفعال می‌کند تا Gemini به جای فراخوانی داخلی آن، بار فراخوانی تابع را ارسال کند.

r = client.models.generate_content( model=model_id, config=config, contents='Whats the weather in Berlin today?' ) for part in r.candidates[0].content.parts: print(part.function_call)

با ارسال درخواست با config سفارشی خود (شامل ابزار پایتون اما با غیرفعال کردن فراخوانی‌های خودکار)، این قطعه تصمیم فراخوانی تابع خام Gemini را می‌گیرد. سپس بر روی هر قسمت پاسخ حلقه می‌زند تا شیء .function_call را چاپ کند، و به شما امکان می‌دهد دقیقاً کدام ابزار را می‌خواهد فراخوانی کند و با چه آرگومان‌هایی بررسی کنید.

from google.genai.types import GenerateContentConfig config = GenerateContentConfig( system_instruction="You are a helpful assistant that use tools to access and retrieve information from a weather API. Today is 2025-03-04.", # to give the LLM context on the current date. tools=[get_weather_forecast], ) r = client.models.generate_content( model=model_id, config=config, contents='Whats the weather in Berlin today?' ) print(r.text)

با این config (که شامل تابع get_weather_forecast شما می‌شود و فراخوانی خودکار را به طور پیش‌فرض فعال می‌گذارد)، فراخوانی generate_content باعث می‌شود Gemini ابزار آب و هوای شما را در پشت صحنه فراخوانی کند و سپس یک پاسخ زبان طبیعی برگرداند. چاپ r.text آن پاسخ نهایی، از جمله پیش‌بینی دمای واقعی برای برلین در تاریخ مشخص شده را خروجی می‌دهد.

from google.genai.types import GenerateContentConfig config = GenerateContentConfig( system_instruction="You are a helpful assistant that use tools to access and retrieve information from a weather API.", tools=[get_weather_forecast], ) prompt = f""" Today is 2025-03-04. You are chatting with Andrew, you have access to more information about him. User Context: - name: Andrew - location: Nuremberg User: Can i wear a T-shirt later today?""" r = client.models.generate_content( model=model_id, config=config, contents=prompt ) print(r.text)

ما دستیار شما را با زمینه شخصی گسترش می‌دهیم، به Gemini نام و مکان اندرو (نورنبرگ) را می‌گوییم و می‌پرسیم که آیا هوا برای پوشیدن تی‌شرت مناسب است یا خیر، در حالی که همچنان از ابزار get_weather_forecast در زیر استفاده می‌کنیم. سپس توصیه زبان طبیعی مدل را بر اساس پیش‌بینی واقعی برای آن روز چاپ می‌کند.

در نتیجه، ما اکنون می‌دانیم که چگونه توابع را تعریف کنیم (از طریق طرحواره JSON یا امضاهای پایتون)، Gemini 2.0 Flash را پیکربندی کنیم تا فراخوانی‌های تابع را تشخیص داده و ارسال کند، و حلقه “agentic” را پیاده‌سازی کنیم که این فراخوانی‌ها را اجرا می‌کند و پاسخ نهایی را می‌سازد. با این بلوک‌های سازنده، می‌توانیم هر LLM را به یک دستیار توانا و مجهز به ابزار گسترش دهیم که گردش‌های کاری را خودکار می‌کند، داده‌های زنده را بازیابی می‌کند و با کد یا APIهای شما به آسانی چت کردن با یک همکار تعامل برقرار می‌کند.