関数呼び出しのチュートリアル

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

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

まだ利用していない場合は、関数呼び出しの概要で詳細をご確認ください。

照明制御用の 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 関数を定義します。

func setLightValues(brightness: String,
                    colorTemp: String) -> JSONObject {
  // This mock API returns the requested lighting values
  return [
    "brightness": .string(brightness),
    "colorTemperature": .string(colorTemp)
  ]
}

関数宣言を作成する

生成モデルに渡す関数宣言を作成します。モデルで使用する関数を宣言する場合は、関数とパラメータの説明に可能な限り詳細な情報を含める必要があります。生成モデルはこの情報を使用して、選択する関数と、関数呼び出しのパラメータの値を指定する方法を決定します。次のコードは、照明制御関数を宣言する方法を示しています。

let controlLightFunctionDeclaration = FunctionDeclaration(
  name: "controlLight",
  description: "Set the brightness and color temperature of a room light.",
  parameters: [
    "brightness": Schema(
      type: .string,
      description: "Light level from 0 to 100. Zero is off and 100 is full brightness."
    ),
    "colorTemperature": Schema(
      type: .string,
      description: "Color temperature of the light fixture which can be `daylight`, `cool` or `warm`."
    ),
  ],
  requiredParameters: ["brightness", "colorTemperature"]
)

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

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

// Use a model that supports function calling, like a Gemini 1.5 model
let generativeModel = GenerativeModel(
  name: "gemini-1.5-flash",
  apiKey: apiKey,
  // Specify the function declaration.
  tools: [Tool(functionDeclarations: [controlLightFunctionDeclaration])]
)

関数呼び出しを生成する

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

let chat = generativeModel.startChat()

let prompt = "Dim the lights so the room feels cozy and warm."

// Send the message to the generative model
let response1 = try await chat.sendMessage(prompt)

// Check if the model responded with a function call
guard let functionCall = response1.functionCalls.first else {
  fatalError("Model did not respond with a function call.")
}
// Print an error if the returned function was not declared
guard functionCall.name == "controlLight" else {
  fatalError("Unexpected function called: \(functionCall.name)")
}
// Verify that the names and types of the parameters match the declaration
guard case let .string(brightness) = functionCall.args["brightness"] else {
  fatalError("Missing argument: brightness")
}
guard case let .string(colorTemp) = functionCall.args["colorTemperature"] else {
  fatalError("Missing argument: colorTemperature")
}

// Call the hypothetical API
let apiResponse = setLightValues(brightness: brightness, colorTemperature: colorTemp)

// Send the API response back to the model so it can generate a text response that can be
// displayed to the user.
let response = try await chat.sendMessage([ModelContent(
  role: "function",
  parts: [.functionResponse(FunctionResponse(
    name: functionCall.name,
    response: apiResponse
  ))]
)])

// Log the text response.
guard let modelResponse = response.text else {
  fatalError("Model did not respond with text.")
}
print(modelResponse)