関数呼び出し SDK プラットフォームのチュートリアル

関数呼び出しを使用すると、生成モデルから構造化データの出力を簡単に取得できます。これらの出力を使用して他の API を呼び出し、関連するレスポンス データをモデルに返すことができます。つまり、関数呼び出しを使用すると、生成モデルを外部システムに接続し、生成されたコンテンツに最新かつ正確な情報を含めることができます。

Gemini モデルに関数の説明を提供できます。これらは、アプリの言語で記述する関数です(Google Cloud Functions ではありません)。モデルがクエリを処理できるように、関数を呼び出して結果を返信するようモデルから求められることがあります。

まだ利用していない場合は、関数呼び出しの概要で詳細をご確認ください。 Google Colab でこの機能を試すか、Gemini API クックブック リポジトリでサンプルコードを確認できます。

照明制御用の API の例

アプリケーション プログラミング インターフェース(API)を備えた基本的な照明制御システムがあり、ユーザーが単純なテキスト リクエストを通じて照明を制御できるようにするとします。関数呼び出し機能を使用すると、ユーザーからの照明の変更リクエストを解釈し、API 呼び出しに変換して照明値を設定できます。この架空の照明制御システムを使用すると、照明の明るさと色温度を 2 つの個別のパラメータとして制御できます。

パラメータ タイプ 必須 説明
brightness 数値 あり 光レベル(0 ~ 100)。ゼロがオフで、100 が最大の明るさです。
colorTemperature string あり 照明器具の色温度(daylightcoolwarm)。

わかりやすくするため、この架空の照明システムにはライトが 1 つしかないため、ユーザーは部屋や場所を指定する必要はありません。次に示す JSON リクエストの例を照明制御 API に送信し、昼光色温度を使用して照明レベルを 50% に変更します。

{
  "brightness": "50",
  "colorTemperature": "daylight"
}

このチュートリアルでは、ユーザーの照明リクエストを解釈し、それらを API 設定にマッピングしてライトの明るさと色温度の値を制御するために、Gemini API の関数呼び出しを設定する方法について説明します。

始める前に: プロジェクトと API キーを設定する

Gemini API を呼び出す前に、プロジェクトをセットアップして API キーを構成する必要があります。

API 関数を定義する

API リクエストを行う関数を作成します。この関数はアプリのコード内で定義する必要がありますが、アプリの外部でサービスや API を呼び出すこともできます。Gemini API はこの関数を直接呼び出しません。そのため、アプリケーション コードでこの関数を実行する方法とタイミングを制御できます。このチュートリアルではデモを目的として、リクエストされたライティング値を返すだけのモック API 関数を定義します。

def set_light_values(brightness, color_temp):
    """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
    }

モデルによる関数呼び出しで使用する関数を作成する際は、関数とパラメータの説明に可能な限り詳細を含める必要があります。生成モデルはこの情報を使用して、選択する関数と、関数呼び出しのパラメータの値を指定する方法を決定します。

モデルの初期化時に関数を宣言する

モデルで関数呼び出しを使用する場合は、モデル オブジェクトを初期化するときに関数を宣言する必要があります。関数を宣言するには、モデルの tools パラメータを設定します。

model = genai.GenerativeModel(model_name='gemini-1.5-flash',
                              tools=[set_light_values])

関数呼び出しを生成する

関数宣言でモデルを初期化したら、定義済みの関数を使用してモデルにプロンプトを送信できます。関数呼び出しでは、一般的に以前のプロンプトとレスポンスのコンテキストを活用するメリットがあるため、チャット プロンプト(sendMessage())を使用した関数呼び出しを使用する必要があります。

chat = model.start_chat()
response = chat.send_message('Dim the lights so the room feels cozy and warm.')
response.text

Python SDK の ChatSession オブジェクトは、会話履歴を処理することで、チャット セッションの管理を簡素化します。enable_automatic_function_calling を使用すると、SDK が自動的にインストールされるようになります。

# Create a chat session that automatically makes suggested function calls
chat = model.start_chat(enable_automatic_function_calling=True)

並列関数呼び出し

上記の基本的な関数呼び出しに加えて、1 回のターンで複数の関数を呼び出すこともできます。このセクションでは、並列関数呼び出しの使用方法の例を示します。

ツールを定義する。

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-flash", 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 = [
    genai.protos.Part(function_response=genai.protos.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! 🕺💃

関数呼び出しのデータ型マッピング

Python 関数からのスキーマの自動抽出は、すべてのケースで機能するとは限りません。たとえば、ネストされた辞書オブジェクトのフィールドを記述するケースは処理されませんが、API はこれをサポートしています。API は、次のいずれかのタイプを記述できます。

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

google.ai.generativelanguage クライアント ライブラリでは、下位レベルの型にアクセスして詳細に制御できます。

まず、モデルの _tools 属性の内部をご覧ください。モデルに渡した関数がどのように記述されているかを確認できます。

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

model = genai.GenerativeModel(model_name='gemini-1.5-flash',
                             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"
   }
 }]

これにより、API に送信される genai.protos.Tool オブジェクトのリストが返されます。表示された形式に馴染みがないかもしれませんが、これは Google の protobuf クラスだからです。各 genai.protos.Tool(この場合は 1)には、関数とその引数を記述する genai.protos.FunctionDeclarations のリストが含まれます。

genai.protos クラスを使用して記述した同じ乗算関数の宣言は次のとおりです。これらのクラスは API の関数を記述するだけであり、API の実装は含まれません。したがって、自動関数呼び出しではこの関数は機能しませんが、関数に実装が必要なとは限りません。

calculator = genai.protos.Tool(
    function_declarations=[
      genai.protos.FunctionDeclaration(
        name='multiply',
        description="Returns the product of two numbers.",
        parameters=genai.protos.Schema(
            type=genai.protos.Type.OBJECT,
            properties={
                'a':genai.protos.Schema(type=genai.protos.Type.NUMBER),
                'b':genai.protos.Schema(type=genai.protos.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']} }]}
genai.protos.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"
  }
}

どちらの場合も、genai.protos.Tool またはツールのリストの表現を

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

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

前の例と同様に、モデルは計算機の multiply 関数を呼び出す genai.protos.FunctionCall を返します。

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(
    genai.protos.Content(
    parts=[genai.protos.Part(
        function_response = genai.protos.FunctionResponse(
          name='multiply',
          response={'result': result}))]))