آموزش: با Gemini API تماس را انجام دهید


مشاهده در 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 یک کلید ایجاد کنید.

یک کلید API دریافت کنید

در 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 ): نتیجه ای که کاربر پس از اجرای تابع درخواستی برمی گرداند.

در مثال قبلی با محاسبه دستکش، تاریخچه دنباله زیر را نشان می دهد:

  1. کاربر : درباره تعداد کل دستکش ها سوال می پرسد.
  2. Model : تعیین می کند که تابع ضرب مفید است و یک درخواست FunctionCall برای کاربر ارسال می کند.
  3. کاربر : ChatSession به طور خودکار این تابع را اجرا می کند (به دلیل تنظیم enable_automatic_function_calling ) و یک FunctionResponse با نتیجه محاسبه شده برمی گرداند.
  4. 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.'}
--------------------------------------------------------------------------------

به طور کلی نمودار حالت به صورت زیر است:

مدل همیشه می تواند با متن یا FunctionCall پاسخ دهد. اگر مدل یک FunctionCall ارسال کند، کاربر باید با یک FunctionResponse پاسخ دهد

این مدل می‌تواند قبل از بازگرداندن یک پاسخ متنی با چندین فراخوانی تابع پاسخ دهد و فراخوانی‌های تابع قبل از پاسخ متنی می‌آیند.

در حالی که همه اینها به صورت خودکار انجام می شد، اگر به کنترل بیشتری نیاز دارید، می توانید:

  • 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 پشتیبانی می شود. به یاد داشته باشید که مدیریت با استفاده از حالت چت به دلیل ساختار طبیعی عقب و جلو آسان تر است. شما مسئول فراخوانی توابع و ارسال نتایج به مدل هستید تا بتواند یک پاسخ متنی ایجاد کند.