Tutorial: Panggilan fungsi dengan Gemini API


Lihat di ai.google.dev Menjalankan di Google Colab Lihat sumber di GitHub

Menggunakan panggilan fungsi untuk menentukan fungsi kustom dan meneruskannya ke Gemini. Model tidak langsung memanggil fungsi ini, tetapi menghasilkan output data terstruktur yang menentukan nama fungsi dan argumen yang disarankan. Output ini memungkinkan panggilan API eksternal, dan output API yang dihasilkan kemudian dapat dimasukkan kembali ke dalam model, sehingga memungkinkan respons kueri yang lebih komprehensif. Panggilan fungsi mendukung LLM untuk berinteraksi dengan berbagai layanan dan informasi real-time, seperti database, sistem pengelolaan hubungan pelanggan, dan repositori dokumen, sehingga meningkatkan kemampuan LLM untuk memberikan jawaban yang relevan dan kontekstual. Anda dapat memberikan deskripsi fungsi kepada model Gemini. Model ini mungkin meminta Anda untuk memanggil fungsi dan mengirim kembali hasilnya untuk membantu model menangani kueri Anda.

Jika Anda belum melakukannya, lihat Pengantar panggilan fungsi untuk mempelajari lebih lanjut.

Penyiapan

Menginstal Python SDK

Python SDK untuk Gemini API terdapat dalam paket google-generativeai. Instal dependensi menggunakan pip:

pip install -U -q google-generativeai

Mengimpor paket

Impor paket yang diperlukan.

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))

Menyiapkan kunci API

Sebelum dapat menggunakan Gemini API, Anda harus mendapatkan kunci API terlebih dahulu. Jika Anda belum memilikinya, buat kunci dengan sekali klik di Google AI Studio.

Mendapatkan kunci API

Di Colab, tambahkan kunci ke secret manager di bawah "mo" di panel kiri. Beri nama API_KEY.

Setelah Anda memiliki kunci API, teruskan ke SDK. Anda dapat melakukannya dengan dua cara:

  • Masukkan kunci di variabel lingkungan GOOGLE_API_KEY (SDK akan otomatis mengambilnya dari sana).
  • Teruskan kunci ke 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)

Dasar-dasar panggilan fungsi

Untuk menggunakan panggilan fungsi, teruskan daftar fungsi ke parameter tools saat membuat GenerativeModel. Model ini menggunakan anotasi nama fungsi, docstring, parameter, dan jenis parameter untuk menentukan apakah diperlukan fungsi tersebut untuk menjawab perintah dengan cara terbaik.

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>,
)

Sebaiknya gunakan panggilan fungsi melalui antarmuka chat. Hal ini karena panggilan fungsi secara alami cocok dengan chat multi-giliran karena panggilan tersebut merekam interaksi bolak-balik antara pengguna dan model. ChatSession Python SDK adalah antarmuka yang bagus untuk chat karena menangani histori percakapan untuk Anda, dan menggunakan parameter enable_automatic_function_calling akan semakin menyederhanakan panggilan fungsi:

chat = model.start_chat(enable_automatic_function_calling=True)

Dengan panggilan fungsi otomatis yang diaktifkan, chat.send_message akan otomatis memanggil fungsi Anda jika model memintanya.

Tampaknya hanya mengembalikan respons teks, yang berisi jawaban yang benar:

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

Periksa histori chat untuk melihat alur percakapan dan bagaimana panggilan fungsi diintegrasikan di dalamnya.

Properti ChatSession.history menyimpan catatan kronologis percakapan antara pengguna dan model Gemini. Setiap giliran dalam percakapan diwakili oleh objek glm.Content, yang berisi informasi berikut:

  • Peran: Mengidentifikasi apakah konten berasal dari "pengguna" atau "model".
  • Bagian: Daftar objek glm.Part yang mewakili setiap komponen pesan. Dengan model khusus teks, bagian ini dapat berupa:
    • Teks: Pesan teks biasa.
    • Panggilan Fungsi (glm.FunctionCall): Permintaan dari model untuk mengeksekusi fungsi tertentu dengan argumen yang diberikan.
    • Respons Fungsi (glm.FunctionResponse): Hasil yang ditampilkan oleh pengguna setelah menjalankan fungsi yang diminta.

Pada contoh sebelumnya dengan penghitungan sarung tangan, histori menampilkan urutan berikut:

  1. Pengguna: Mengajukan pertanyaan tentang jumlah total sarung tangan.
  2. Model: Menentukan apakah fungsi pengali berguna dan mengirim permintaan FunctionCall kepada pengguna.
  3. Pengguna: ChatSession otomatis menjalankan fungsi (karena enable_automatic_function_calling ditetapkan) dan mengirimkan kembali FunctionResponse dengan hasil yang dihitung.
  4. Model: Menggunakan output fungsi untuk merumuskan jawaban akhir dan menampilkannya sebagai respons teks.
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.'}
--------------------------------------------------------------------------------

Secara umum, diagram status adalah:

Model selalu dapat membalas dengan teks, atau FunctionCall. Jika model mengirim FunctionCall, pengguna harus membalas dengan FunctionResponse

Model ini bisa merespons dengan beberapa panggilan fungsi sebelum menampilkan respons teks, dan panggilan fungsi muncul sebelum respons teks.

Meskipun semua ini ditangani secara otomatis, jika Anda memerlukan kontrol lebih besar, Anda dapat:

  • Biarkan enable_automatic_function_calling=False default dan proses sendiri respons glm.FunctionCall.
  • Atau gunakan GenerativeModel.generate_content, di mana Anda juga perlu mengelola histori chat.

Panggilan fungsi paralel

Selain panggilan fungsi dasar yang dijelaskan di atas, Anda juga dapat memanggil beberapa fungsi dalam satu giliran. Bagian ini menunjukkan contoh cara menggunakan panggilan fungsi paralel.

Mendefinisikan alat.

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

Sekarang, panggil model dengan instruksi yang dapat menggunakan semua alat yang ditentukan.

# 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)

Setiap hasil yang dicetak mencerminkan satu panggilan fungsi yang diminta model. Untuk mengirim kembali hasilnya, sertakan respons dalam urutan yang sama seperti yang diminta.

# 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! 🕺💃

(Opsional) Akses tingkat rendah

Ekstraksi skema secara otomatis dari fungsi Python tidak berfungsi pada semua kasus. Misalnya: API ini tidak menangani kasus saat Anda menjelaskan kolom objek kamus bertingkat, tetapi API mendukung hal ini. API dapat menjelaskan jenis berikut:

AllowedType = (int | float | bool | str | list['AllowedType'] | dict[str, AllowedType]

Library klien google.ai.generativelanguage memberikan akses ke jenis tingkat rendah yang memberi Anda kontrol penuh.

import google.ai.generativelanguage as glm

Lihat sekilas ke dalam atribut _tools model, Anda dapat melihat cara atribut tersebut menjelaskan fungsi yang Anda teruskan ke model:

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"
   }
 }]

Tindakan ini akan menampilkan daftar objek glm.Tool yang akan dikirim ke API. Format cetak tidak dikenal karena format tersebut adalah class protobuf Google. Setiap glm.Tool (dalam hal ini 1) berisi daftar glm.FunctionDeclarations, yang menjelaskan fungsi dan argumennya.

Berikut adalah deklarasi untuk fungsi perkalian yang sama yang ditulis menggunakan class glm.

Perhatikan bahwa class tersebut hanya menjelaskan fungsi untuk API, tetapi tidak menyertakan implementasinya. Jadi, penggunaan ini tidak berfungsi dengan panggilan fungsi otomatis, tetapi fungsi tidak selalu memerlukan implementasi.

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']
        )
      )
    ])

Pada dasarnya, Anda dapat mendeskripsikan ini sebagai objek yang kompatibel dengan 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"
  }
}

Apa pun itu, Anda meneruskan representasi glm.Tool atau daftar alat untuk

model = genai.GenerativeModel('gemini-pro', tools=calculator)
chat = model.start_chat()

response = chat.send_message(
    f"What's 234551 X 325552 ?",
)

Seperti sebelum model menampilkan glm.FunctionCall yang memanggil fungsi multiply kalkulator:

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
]

Jalankan fungsi sendiri:

fc = response.candidates[0].content.parts[0].function_call
assert fc.name == 'multiply'

result = fc.args['a'] * fc.args['b']
result
76358547152.0

Kirim hasilnya ke model untuk melanjutkan percakapan:

response = chat.send_message(
    glm.Content(
    parts=[glm.Part(
        function_response = glm.FunctionResponse(
          name='multiply',
          response={'result': result}))]))

Ringkasan

Panggilan fungsi dasar didukung di SDK. Perlu diingat bahwa pengelolaan menggunakan mode chat akan lebih mudah karena struktur bolak-balik yang alami. Anda bertanggung jawab untuk memanggil fungsi dan mengirimkan hasilnya kembali ke model sehingga model bisa menghasilkan respons teks.