مشاهده در ai.google.dev | در Google Colab اجرا شود | مشاهده منبع در GitHub |
از فراخوانی تابع برای تعریف توابع سفارشی و ارسال آنها به Gemini استفاده کنید. مدل مستقیماً این توابع را فراخوانی نمی کند، بلکه در عوض خروجی داده های ساختار یافته ای تولید می کند که نام تابع و آرگومان های پیشنهادی را مشخص می کند. این خروجی فراخوانی APIهای خارجی را ممکن میسازد و خروجی API حاصل میتواند دوباره در مدل گنجانده شود و پاسخهای پرس و جو جامعتری را ممکن میسازد. فراخوانی تابع به LLM ها قدرت می دهد تا با اطلاعات بلادرنگ و خدمات مختلف مانند پایگاه های داده، سیستم های مدیریت ارتباط با مشتری و مخازن اسناد تعامل داشته باشند و توانایی آنها را برای ارائه پاسخ های مرتبط و متنی افزایش دهد. می توانید مدل های Gemini را با توضیحاتی در مورد عملکردها ارائه دهید. مدل ممکن است از شما بخواهد که یک تابع را فراخوانی کنید و نتیجه را برای کمک به مدل در رسیدگی به درخواست شما ارسال کنید.
اگر قبلاً این کار را نکردهاید، برای کسب اطلاعات بیشتر ، مقدمه فراخوانی تابع را بررسی کنید.
برپایی
Python SDK را نصب کنید
Python SDK برای Gemini API در بسته google-generativeai
موجود است. وابستگی را با استفاده از pip نصب کنید:
pip install -U -q google-generativeai
بسته های وارداتی
بسته های لازم را وارد کنید.
import pathlib
import textwrap
import time
import google.generativeai as genai
from IPython import display
from IPython.display import Markdown
def to_markdown(text):
text = text.replace('•', ' *')
return Markdown(textwrap.indent(text, '> ', predicate=lambda _: True))
کلید API خود را تنظیم کنید
قبل از اینکه بتوانید از Gemini API استفاده کنید، ابتدا باید یک کلید API دریافت کنید. اگر قبلاً یکی ندارید، با یک کلیک در Google AI Studio یک کلید ایجاد کنید.
در Colab، کلید را به مدیر مخفی زیر "🔑" در پانل سمت چپ اضافه کنید. نام API_KEY
را به آن بدهید.
هنگامی که کلید API را دارید، آن را به SDK منتقل کنید. شما می توانید این کار را به دو صورت انجام دهید:
- کلید را در متغیر محیطی
GOOGLE_API_KEY
قرار دهید (SDK به طور خودکار آن را از آنجا دریافت می کند). - کلید را به
genai.configure(api_key=...)
بدهید
try:
# Used to securely store your API key
from google.colab import userdata
# Or use `os.getenv('API_KEY')` to fetch an environment variable.
GOOGLE_API_KEY=userdata.get('GOOGLE_API_KEY')
except ImportError:
import os
GOOGLE_API_KEY = os.environ['GOOGLE_API_KEY']
genai.configure(api_key=GOOGLE_API_KEY)
اصول فراخوانی تابع
برای استفاده از فراخوانی تابع، هنگام ایجاد GenerativeModel
، فهرستی از توابع را به پارامتر tools
ارسال کنید. این مدل از نام تابع، رشته docstring، پارامترها و حاشیهنویسیهای نوع پارامتر استفاده میکند تا تصمیم بگیرد که آیا به تابع برای بهترین پاسخ به یک درخواست نیاز دارد یا خیر.
def multiply(a:float, b:float):
"""returns a * b."""
return a*b
model = genai.GenerativeModel(model_name='gemini-1.0-pro',
tools=[multiply])
model
genai.GenerativeModel( model_name='models/gemini-1.0-pro', generation_config={}, safety_settings={}, tools=<google.generativeai.types.content_types.FunctionLibrary object at 0x10e73fe90>, )
توصیه می شود از تماس های تابع از طریق رابط چت استفاده کنید. این به این دلیل است که فراخوانی های تابع به طور طبیعی با چت های چند نوبتی مطابقت دارند زیرا تعامل رفت و برگشت بین کاربر و مدل را ثبت می کنند. ChatSession
Python SDK یک رابط عالی برای چت است زیرا تاریخچه مکالمه را برای شما مدیریت می کند و استفاده از پارامتر enable_automatic_function_calling
فراخوانی تابع را حتی بیشتر ساده می کند:
chat = model.start_chat(enable_automatic_function_calling=True)
با فعال کردن فراخوانی عملکرد خودکار chat.send_message
به طور خودکار تابع شما را در صورت درخواست مدل، فراخوانی می کند.
به نظر می رسد که به سادگی یک پاسخ متنی حاوی پاسخ صحیح را برمی گرداند:
response = chat.send_message('I have 57 cats, each owns 44 mittens, how many mittens is that in total?')
response.text
'The total number of mittens is 2508.'
57*44
2508
برای مشاهده جریان مکالمه و نحوه ادغام فراخوانی های تابع در آن، تاریخچه چت را بررسی کنید.
ویژگی ChatSession.history
یک رکورد زمانی از مکالمه بین کاربر و مدل Gemini را ذخیره می کند. هر نوبت در مکالمه با یک شی glm.Content
نشان داده می شود که حاوی اطلاعات زیر است:
- نقش : مشخص می کند که محتوا از "کاربر" یا "مدل" منشا گرفته است.
- Parts : فهرستی از اشیاء
glm.Part
که اجزای جداگانه پیام را نشان می دهد. با یک مدل فقط متنی، این بخش ها می توانند:- متن : پیام های متنی ساده.
- فراخوانی تابع (
glm.FunctionCall
): درخواستی از مدل برای اجرای یک تابع خاص با آرگومان های ارائه شده. - Function Response (
glm.FunctionResponse
): نتیجه ای که کاربر پس از اجرای تابع درخواستی برمی گرداند.
در مثال قبلی با محاسبه دستکش، تاریخچه دنباله زیر را نشان می دهد:
- کاربر : درباره تعداد کل دستکش ها سوال می پرسد.
- Model : تعیین می کند که تابع ضرب مفید است و یک درخواست FunctionCall برای کاربر ارسال می کند.
- کاربر :
ChatSession
به طور خودکار این تابع را اجرا می کند (به دلیل تنظیمenable_automatic_function_calling
) و یکFunctionResponse
با نتیجه محاسبه شده برمی گرداند. - Model : از خروجی تابع برای فرمول بندی پاسخ نهایی استفاده می کند و آن را به عنوان پاسخ متنی ارائه می دهد.
for content in chat.history:
part = content.parts[0]
print(content.role, "->", type(part).to_dict(part))
print('-'*80)
user -> {'text': 'I have 57 cats, each owns 44 mittens, how many mittens is that in total?'} -------------------------------------------------------------------------------- model -> {'function_call': {'name': 'multiply', 'args': {'a': 57.0, 'b': 44.0} } } -------------------------------------------------------------------------------- user -> {'function_response': {'name': 'multiply', 'response': {'result': 2508.0} } } -------------------------------------------------------------------------------- model -> {'text': 'The total number of mittens is 2508.'} --------------------------------------------------------------------------------
به طور کلی نمودار حالت به صورت زیر است:
این مدل میتواند قبل از بازگرداندن یک پاسخ متنی با چندین فراخوانی تابع پاسخ دهد و فراخوانیهای تابع قبل از پاسخ متنی میآیند.
در حالی که همه اینها به صورت خودکار انجام می شد، اگر به کنترل بیشتری نیاز دارید، می توانید:
-
enable_automatic_function_calling=False
پیشفرض بگذارید و پاسخهایglm.FunctionCall
را خودتان پردازش کنید. - یا از
GenerativeModel.generate_content
استفاده کنید، جایی که باید سابقه چت را نیز مدیریت کنید.
فراخوانی تابع موازی
علاوه بر فراخوانی تابع اصلی که در بالا توضیح داده شد، می توانید چندین تابع را در یک نوبت فراخوانی کنید. این بخش مثالی را نشان می دهد که چگونه می توانید از فراخوانی تابع موازی استفاده کنید.
ابزارها را تعریف کنید.
def power_disco_ball(power: bool) -> bool:
"""Powers the spinning disco ball."""
print(f"Disco ball is {'spinning!' if power else 'stopped.'}")
return True
def start_music(energetic: bool, loud: bool, bpm: int) -> str:
"""Play some music matching the specified parameters.
Args:
energetic: Whether the music is energetic or not.
loud: Whether the music is loud or not.
bpm: The beats per minute of the music.
Returns: The name of the song being played.
"""
print(f"Starting music! {energetic=} {loud=}, {bpm=}")
return "Never gonna give you up."
def dim_lights(brightness: float) -> bool:
"""Dim the lights.
Args:
brightness: The brightness of the lights, 0.0 is off, 1.0 is full.
"""
print(f"Lights are now set to {brightness:.0%}")
return True
اکنون مدل را با دستورالعملی فراخوانی کنید که بتواند از تمام ابزارهای مشخص شده استفاده کند.
# Set the model up with tools.
house_fns = [power_disco_ball, start_music, dim_lights]
model = genai.GenerativeModel(model_name="gemini-1.5-pro-latest", tools=house_fns)
# Call the API.
chat = model.start_chat()
response = chat.send_message("Turn this place into a party!")
# Print out each of the function calls requested from this single call.
for part in response.parts:
if fn := part.function_call:
args = ", ".join(f"{key}={val}" for key, val in fn.args.items())
print(f"{fn.name}({args})")
power_disco_ball(power=True) start_music(energetic=True, loud=True, bpm=120.0) dim_lights(brightness=0.3)
هر یک از نتایج چاپ شده منعکس کننده یک فراخوانی تابعی است که مدل درخواست کرده است. برای بازگرداندن نتایج، پاسخها را به همان ترتیبی که درخواست شده است وارد کنید.
# Simulate the responses from the specified tools.
responses = {
"power_disco_ball": True,
"start_music": "Never gonna give you up.",
"dim_lights": True,
}
# Build the response parts.
response_parts = [
glm.Part(function_response=glm.FunctionResponse(name=fn, response={"result": val}))
for fn, val in responses.items()
]
response = chat.send_message(response_parts)
print(response.text)
Let's get this party started! I've turned on the disco ball, started playing some upbeat music, and dimmed the lights. 🎶✨ Get ready to dance! 🕺💃
(اختیاری) دسترسی سطح پایین
استخراج خودکار طرحواره از توابع پایتون در همه موارد کار نمی کند. به عنوان مثال: مواردی را که شما فیلدهای یک دیکشنری-شیء تودرتو را توصیف میکنید کنترل نمیکند، اما API از این پشتیبانی میکند. API قادر است هر یک از انواع زیر را توصیف کند:
AllowedType = (int | float | bool | str | list['AllowedType'] | dict[str, AllowedType]
کتابخانه مشتری google.ai.generativelanguage
دسترسی به انواع سطح پایین را فراهم می کند و به شما کنترل کامل می دهد.
import google.ai.generativelanguage as glm
ابتدا به داخل ویژگی _tools
مدل نگاه کنید، می توانید ببینید که چگونه تابع(هایی) را که به مدل ارسال کرده اید، توصیف می کند:
def multiply(a:float, b:float):
"""returns a * b."""
return a*b
model = genai.GenerativeModel(model_name='gemini-1.0-pro',
tools=[multiply])
model._tools.to_proto()
[function_declarations { name: "multiply" description: "returns a * b." parameters { type_: OBJECT properties { key: "b" value { type_: NUMBER } } properties { key: "a" value { type_: NUMBER } } required: "a" required: "b" } }]
این لیستی از اشیاء glm.Tool
را که به API ارسال می شوند، برمی گرداند. اگر قالب چاپ شده آشنا نیست، به این دلیل است که این کلاسهای پروتوباف گوگل هستند. هر glm.Tool
(در این مورد 1) حاوی لیستی از glm.FunctionDeclarations
است که یک تابع و آرگومان های آن را توصیف می کند.
در اینجا یک اعلان برای همان تابع ضرب نوشته شده با استفاده از کلاس های glm
است.
توجه داشته باشید که این کلاسها فقط عملکرد API را توصیف میکنند، و پیادهسازی آن را شامل نمیشوند. بنابراین استفاده از این با فراخوانی خودکار تابع کار نمی کند، اما توابع همیشه به پیاده سازی نیاز ندارند.
calculator = glm.Tool(
function_declarations=[
glm.FunctionDeclaration(
name='multiply',
description="Returns the product of two numbers.",
parameters=glm.Schema(
type=glm.Type.OBJECT,
properties={
'a':glm.Schema(type=glm.Type.NUMBER),
'b':glm.Schema(type=glm.Type.NUMBER)
},
required=['a','b']
)
)
])
به طور معادل، می توانید این را به عنوان یک شی سازگار با JSON توصیف کنید:
calculator = {'function_declarations': [
{'name': 'multiply',
'description': 'Returns the product of two numbers.',
'parameters': {'type_': 'OBJECT',
'properties': {
'a': {'type_': 'NUMBER'},
'b': {'type_': 'NUMBER'} },
'required': ['a', 'b']} }]}
glm.Tool(calculator)
function_declarations { name: "multiply" description: "Returns the product of two numbers." parameters { type_: OBJECT properties { key: "b" value { type_: NUMBER } } properties { key: "a" value { type_: NUMBER } } required: "a" required: "b" } }
در هر صورت، شما نمایشی از glm.Tool
یا لیستی از ابزارها را به آن ارسال می کنید
model = genai.GenerativeModel('gemini-pro', tools=calculator)
chat = model.start_chat()
response = chat.send_message(
f"What's 234551 X 325552 ?",
)
مانند قبل از اینکه مدل یک glm.FunctionCall
را با فراخوانی تابع multiply
ماشین حساب برمی گرداند:
response.candidates
[index: 0 content { parts { function_call { name: "multiply" args { fields { key: "b" value { number_value: 325552 } } fields { key: "a" value { number_value: 234551 } } } } } role: "model" } finish_reason: STOP ]
تابع را خودتان اجرا کنید:
fc = response.candidates[0].content.parts[0].function_call
assert fc.name == 'multiply'
result = fc.args['a'] * fc.args['b']
result
76358547152.0
برای ادامه گفتگو، نتیجه را برای مدل ارسال کنید:
response = chat.send_message(
glm.Content(
parts=[glm.Part(
function_response = glm.FunctionResponse(
name='multiply',
response={'result': result}))]))
خلاصه
فراخوانی تابع اصلی در SDK پشتیبانی می شود. به یاد داشته باشید که مدیریت با استفاده از حالت چت به دلیل ساختار طبیعی عقب و جلو آسان تر است. شما مسئول فراخوانی توابع و ارسال نتایج به مدل هستید تا بتواند یک پاسخ متنی ایجاد کند.