1. 関数呼び出しの概要

GPTモデルにおいて、関数呼び出し(Function Calling)とは、APIを介してモデルに記述的な関数を提供し、1つまたは複数の関数を呼び出すためのパラメータを含むJSONオブジェクトを知能的に出力させることを指します。重要なのは、チャット補完APIは関数呼び出しを直接実行せず、コード内で関数を実行するためのJSONを生成するという点です。

要するに、関数呼び出しの機能は、GPTモデルに関数の定義(関数の説明とパラメータの説明を含む)を提供することを意味します。その後、モデルはユーザーのクエリに基づいてどの関数を呼び出すかを決定します。モデルは外部の関数を実行できないため、関数の呼び出しを要求するだけで、つまり関数呼び出しのパラメータを含む要求結果を受け取ります。モデルの要求結果を受け取った後、プログラムがローカルで関数の呼び出しを実行します。その結果はプロンプトと結合され、最終的な結果をユーザーに返す前にモデルに返送されます。

2. 関数呼び出しの応用シナリオ

以下はその実用例のいくつかです。

  • send_email(to: string, body: string)get_current_weather(location: string, unit: 'celsius' | 'fahrenheit')のような関数を定義して外部APIを呼び出し、質問に答えるアシスタントの作成。
  • "Who are my top customers?"をget_customers(min_revenue: int, created_before: string, limit: int)に変換し、内部APIを呼び出すことで自然言語をAPI呼び出しに変換。
  • テキストから構造化データを抽出し、extract_data(name: string, birthday: string)sql_query(query: string)などの関数を定義することで、構造化されたデータを抽出。

関数呼び出しの機能を活用することで、AIエージェントを利用して最新の天気を照会したり、株価を確認したり、テイクアウトを注文したり、フライトを予約したりするなど、ローカルシステムやデータベースとやり取りすることができます。

3. 関数呼び出しをサポートするモデル

すべてのモデルのバージョンが関数呼び出しデータでトレーニングされているわけではありません。現在、関数呼び出しをサポートするモデルは次の通りです:gpt-4, gpt-4-turbo-preview, gpt-4-0125-preview, gpt-4-1106-preview, gpt-4-0613, gpt-3.5-turbo, gpt-3.5-turbo-1106, gpt-3.5-turbo-0613

さらに、gpt-4-turbo-preview, gpt-4-0125-preview, gpt-4-1106-preview, gpt-3.5-turbo-1106モデルは並列関数呼び出しをサポートし、複数の関数呼び出しを同時に実行し、これらの関数呼び出しを効果的かつ効率的に処理できます。

注:関数呼び出し機能に関連する潜在的なリスクは、モデルが誤ったパラメータ(つまり、幻のパラメータ)を生成する可能性があることです。そのため、メール送信、オンライン掲載、購入などの実世界に影響を与える行動を取る前に、製品レベルでユーザー確認プロセスを組み込むことが望ましいです。これにより、ユーザーの確認後にのみ関数が実行されることが保証されます。

4. 関数呼び出しの例

4.1 Pythonの例

OpenAIプラットフォームでの関数呼び出しの実装は、通常、以下の基本的な手順に従います。以下では、Pythonコードの例を使用して、天気の照会に焦点を当て、このプロセス全体を詳しく説明します。

Step 1: モデル用の呼び出し可能な関数と関数の定義を準備

まず、GPTモデルによって呼び出すことができる関数を定義する必要があります。通常、これは、特定の操作を実行できる独自の関数を準備することを意味します。例えば、サードパーティのAPIと通信するなどの操作が含まれます。

import json

def get_current_weather(location, unit="fahrenheit"):
    return json.dumps({
        "location": location, 
        "temperature": "18", 
        "unit": unit
    })

ステップ2: クエリとツールパラメータに基づいてモデルを呼び出す

次に、Chat Completion API を介して GPT モデルを呼び出し、ユーザーのクエリ(例: "現在の天気は何ですか")と、get_current_weather 関数の説明を含む tools パラメータを渡す必要があります。

from openai import OpenAI

client = OpenAI()

tools = [{
    "type": "function",
    "function": {
        "name": "get_current_weather",
        "description": "指定した場所の現在の天気を取得する",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "例: 'サンフランシスコ、カリフォルニア'"
                },
                "unit": {
                    "type": "string",
                    "enum": ["セ氏", "華氏"]
                }
            },
            "required": ["location"]
        }
    }
}]

response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[{"role": "user", "content": "サンフランシスコの現在の天気は何ですか?"}],
    tools=tools
)

ステップ3: ローカルで関数を実行する

モデルから返された結果には、通常 tool_calls 応答パラメータに含まれるモデルが呼び出したい関数に関する情報が含まれます。その後、tool_calls パラメータで記述された関数呼び出し情報に基づいて、対応する関数呼び出しをローカルで実行することができます。

tool_calls = response.choices[0].message.tool_calls

if tool_calls:
    arguments = json.loads(tool_calls[0].function.arguments)
    weather_info = get_current_weather(**arguments)
    print(weather_info) # ここでは、関数呼び出しで問い合わせた天気情報を見ることができます

ステップ4: 関数の戻り値を使ってモデルを再度呼び出す

これで、関数の戻り値を新しいメッセージとしてモデルに送信し、モデルがこれらの結果を処理し、ユーザーに適した応答を生成できるようになります。

follow_up_response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[
        {"role": "user", "content": "サンフランシスコの現在の天気は何ですか?"},
        {"role": "function", "name": "get_current_weather", "content": weather_info}
    ],
    tools=tools
)

説明: 上記の例では、関数の戻り値内容が以下のように関数メッセージを通じてGPT モデルに送信されます:

{"role": "function", "name": "get_current_weather", "content": weather_info}

実際には、AI が質問に答える際に関数の戻り値内容を単にシステムメッセージのプロンプトに参照内容として置くこともできます。

ステップ5: モデルから最終応答を取得する

最後に、モデルの最終応答を取得し、ユーザーに提供することができます。このステップでは、モデルは提供した天気情報に基づいてユーザーフレンドリーな回答を出力します。

final_output = follow_up_response.choices[0].message.content
print(final_output) # この出力がユーザーに表示したい天気情報です

上記の手順に従うことで、GPT モデルと関数呼び出しを使用して天気を問い合わせる完全な例を完成させました。

4.2. 関数呼び出し関数の定義説明

4.2.1 'Tools' パラメータフィールドの意味

関数呼び出しの際には、tools パラメータに関数の関連情報を定義する必要があります。tools パラメータは複数の関数定義を含む配列であり、各関数定義には以下のフィールドが含まれます。

  1. type: このフィールドはツールのタイプを表します。関数の呼び出しでは、このフィールドは"function"に設定する必要があります。
  2. function: このフィールドには関数の詳細情報が含まれており、以下の具体的なフィールドを持つオブジェクトです:
    • name: 関数の名前。これは文字列です。
    • description: 関数の目的を説明したもので、モデルがユーザの期待に適ったパラメータを生成するのに役立ちます。
    • parameters: 関数のパラメータ定義を記述し、以下のサブフィールドを含むオブジェクトです:
      • type: パラメータのタイプを定義し、ほとんどは"object"に設定する必要があります。
      • properties: 各関数パラメータの具体的な定義であり、各パラメータ定義は通常以下のサブフィールドを含むオブジェクトです:
        • type: パラメータのデータ型(例:"string""integer""boolean"など)。
        • description: パラメータの目的をモデルが理解するのに役立つ説明。
        • enum(オプション): type"string"の場合、enum フィールドは有効な値のセットを表す文字列の配列を指定できます。
      • required: 必須パラメータの名前を含む文字列の配列。

4.2.2 ツール定義の例

次に、各フィールドの使用方法を理解するためのtools 定義の例をいくつか提供します。

例 1: 現在の天気情報を取得する

{
    "type": "function",
    "function": {
        "name": "get_current_weather",
        "description": "指定された場所の現在の天気情報を取得します",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "天気を問い合わせる都市、例: 'サンフランシスコ、CA'"
                },
                "unit": {
                    "type": "string",
                    "enum": ["celsius", "fahrenheit"],
                    "description": "温度単位、'celsius' は摂氏、'fahrenheit' は華氏"
                }
            },
            "required": ["location", "unit"]
        }
    }
}

上記の例では、指定された場所の現在の天気情報を取得するget_current_weather 関数を定義しています。パラメータにはlocationunitが含まれており、unit は "celsius"(摂氏)と "fahrenheit"(華氏)の2つの有効な値を持ちます。

例 2: 特定のアーティストのアルバムを検索する

{
    "type": "function",
    "function": {
        "name": "find_artist_albums",
        "description": "特定のアーティストのすべてのアルバムを検索します",
        "parameters": {
            "type": "object",
            "properties": {
                "artist_name": {
                    "type": "string",
                    "description": "アーティストの名前"
                }
            },
            "required": ["artist_name"]
        }
    }
}

この例では、特定のアーティストのすべてのアルバムを検索するfind_artist_albums 関数を作成しました。この関数には1つだけパラメータが必要で、それがartist_name(アーティストの名前)です。

4.3. HTTPリクエスト関数呼び出しの例

OpenAIはHTTPプロトコルを介してアクセス可能なAPIを提供しています。以下では、HTTPAPIを介した関数呼び出し機能の使用方法について説明します。他のプログラミング言語の開発者は、この例を参照することができます。

4.3.1. ステップ 1:ユーザークエリと関数宣言を使用してモデルを呼び出す

最初に、ユーザーのクエリとサポートする関数のリストをGPTモデルに送信して、モデルがユーザーの質問に基づいてどの関数を呼び出してユーザーのクエリに答えるかを自動的に解析できるようにします。

次の例では、私たちがget_current_weather関数を持っていて、指定した都市の天気情報をクエリするために使用できることをGPTに伝えています。

curl --location 'https://api.aiproxy.io/v1/chat/completions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {OPENAI_KEY}' \
--data '{
    "model": "gpt-3.5-turbo",
    "messages": [
        {
            "role": "user",
            "content": "上海の今日の天気はどうですか?"
        }
    ],
    "tools": [
        {
            "type": "function",
            "function": {
                "name": "get_current_weather",
                "description": "指定した場所の現在の天気情報を取得します",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "天気を問い合わせる都市、例:「サンフランシスコ、カリフォルニア」"
                        },
                        "unit": {
                            "type": "string",
                            "enum": [
                                "celsius",
                                "fahrenheit"
                            ],
                            "description": "温度単位、「celsius」は摂氏、「fahrenheit」は華氏"
                        }
                    },
                    "required": [
                        "location",
                        "unit"
                    ]
                }
            }
        }
    ]
}'

リクエストパラメータの説明:

{
    "model": "gpt-3.5-turbo", // 呼び出されるGPTモデル
    "messages": [ // ユーザーのクエリを含むメッセージのリストです
        {
            "role": "user",
            "content": "上海の今日の天気はどうですか?"
        }
    ],
    "tools": [
	  // 使用可能な関数をGPTに通知するための関数定義です
    ]
}

toolsパラメータの定義については、セクション4.2.2を参照してください。

GPTモデルによる通常の処理では、次のようなAPIレスポンスを受け取ります:

{
    "model": "gpt-3.5-turbo-0613",
    "object": "chat.completion",
    "usage": {
        "prompt_tokens": 122,
        "completion_tokens": 27,
        "total_tokens": 149
    },
    "id": "chatcmpl-8mL4hS4zNMocyR2ajKyAvSTcbNaao",
    "created": 1706531447,
    "choices": [
        {
            "index": 0,
            "delta": null,
            "message": {
                "role": "assistant",
                "tool_calls": [ // tool_callsパラメータは、GPTが呼び出したい関数のリストを表します
                    {
                        "id": "call_1iF09ttX1R9ESR18Ul2nLe1R",
                        "type": "function",
                        "function": {
                            "name": "get_current_weather",  // GPTがget_current_weather関数を呼び出してユーザーのクエリに答えたいことを示します
                            "arguments": "{\n  \"location\": \"上海、中国\",\n  \"unit\": \"celsius\"\n}" // これはget_current_weather関数を呼び出すための入力パラメータです
                        }
                    }
                ]
            },
            "finish_reason": "tool_calls"
        }
    ]
}

4.3.2. ステップ 2:ローカル関数の実行

GPTモデル自体は特定の関数の呼び出しを実行することができず、呼び出したい関数を通知するだけです。そのため、ローカルプログラムはモデルによって返されたtool_callsパラメータに基づいて特定の関数呼び出しを実行する必要があります。ローカル関数の実行方法はプログラミング言語によって異なります。例えば、Pythonでは、前のセクションを参照してください。

4.3.3. ステップ 3: 関数の戻り値を使ってモデルを再度呼び出す

関数の呼び出しがローカルで実行されるため、関数の実行結果とユーザーの質問をGPTモデルに戻して最終的な応答を作成する必要があります。

curl --location 'https://api.aiproxy.io/v1/chat/completions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer sk-Roc5MX1zEuVxiuaMaETV6wZ2jXcCehjUCzwP9AcNErUiwppQ' \
--data '{
    "model": "gpt-3.5-turbo",
    "messages": [
        {
            "role": "user",
            "content": "今日の上海の天気はどうですか?"
        },
        {
            "role": "function",
            "name": "get_current_weather",
            "content": "{\"city\":\"上海\", \"temperature\":\"25度\"}"
        }
    ],
    "tools": [
        {
            "type": "function",
            "function": {
                "name": "get_current_weather",
                "description": "指定した場所の現在の天気情報を取得します",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "天気を調べる都市、例: '東京'"
                        },
                        "unit": {
                            "type": "string",
                            "enum": [
                                "celsius",
                                "fahrenheit"
                            ],
                            "description": "温度の単位、'celsius' なら摂氏、'fahrenheit' なら華氏"
                        }
                    },
                    "required": [
                        "location",
                        "unit"
                    ]
                }
            }
        }
    ]
}'

上記のリクエストには、関数のメッセージが追加されており、GPTに関数の戻り値を通知しています。GPTは関数の戻り情報に基づいてユーザーの質問に直接回答し、関数を再度呼び出すことはありません。

関数メッセージは以下の形式に従います:

{
    "role": "function", // メッセージの種類はfunctionであり、関数の戻り値であることを示します
    "name": "get_current_weather", // 現在のメッセージがget_current_weather関数の戻り値であることをGPTに通知
    "content": "{\"city\":\"上海\", \"temperature\":\"25度\"}" // 関数の戻り内容、JSON形式やその他のテキストコンテンツで表現できます
}

以下はGPTによって生成された最終的な応答です:

{
    "model": "gpt-3.5-turbo-0613",
    "object": "chat.completion",
    "usage": {
        "prompt_tokens": 144,
        "completion_tokens": 17,
        "total_tokens": 161
    },
    "id": "chatcmpl-8mLmvvKAjSql7rGF8fvQeddKhWYvr",
    "created": 1706534189,
    "choices": [
        {
            "index": 0,
            "delta": null,
            "message": {
                "role": "assistant",
                "content": "今日の上海の天気は25度です。"
            },
            "finish_reason": "stop"
        }
    ]
}