概要
2023/6/13にOpenAIのAPIの新機能「Function Calling」が出たらしい😳
何ができるようになったのか気になったので調べてみた!
Function Callingでできること
一言で説明すると…
ただしこれだけだとよく分からない😢
もう少し詳しく
例:「天気予報を取得する関数」を用意した場合✅
- 質問するときに「天気予報を取得する関数もあるよ〜👍」と教えてあげる。
- モデルはいつも通りユーザーの質問に答える。→もしモデルが「天気予報知りたい!」となった場合、「天気予報を取得する関数を使いたいよ〜🤖」と言ってくれる。 
※モデルが関数を実行するわけではない。
具体例
具体的には以下のようなことができる。
最新の天気予報を回答する
- 事前にリアルタイムの天気予報を取得する関数を用意しておく。
- 回答に天気予報の情報が必要なときにこの関数を使って、最新の天気予報を答える。
Todoリストにタスクを自動追加する
- 事前にTodoリストにタスクを追加する関数を用意しておく。
- 回答の中でタスク追加が必要なときにこの関数を使って、Todoリストにタスクを追加する。
流れで理解する
以下のような5ステップで使用する✅
関数の準備
開発者は事前に、モデルを強化するための関数を作成しておく。
最新の天気予報を取得する関数
質問する
モデルに「天気予報を取得する関数もあるよ〜👍」と教えてあげる。
具体的には 質問 + 関数名 + 関数の説明文 + 関数の引数 の4つを渡して質問する。
質問     : 東京の天気は?
関数名    : get_current_weather (事前に開発者が作った関数名)
関数の説明文:指定した場所の現在の天気を取得する
関数の引数 :string型(都市名)
回答を確認
モデルから回答が返ってくる。
もしモデルが関数が必要だと判断していたら、「関数を使いたいよ〜🤖」という回答になっている✅
天気予報を取得する関数を使いたいよ〜🤖
※関数名はget_current_weatherだよ。
※引数は”東京”だよ。
※もし「関数を使いたいよ〜🤖」と言ってなければここで終了(普通の質問→回答の流れと一緒)
関数実行
「関数を使いたいよ〜🤖」という回答だった場合、モデルが臨んでいるとおりに関数を実行してあげる😊
最新の天気予報を取得する関数get_current_weather(”東京”)を実行してあげる。
再度質問
モデルに 質問 + 回答 + 関数名 + 関数の実行結果 の4つを渡して再度質問する。
質問     : 東京の天気は?
回答     :天気予報を取得する関数を使いたいよ〜🤖
関数名     : get_current_weather (事前に開発者が作った関数名)
関数の実行結果:晴れ
コードで理解する
続いてサンプルコードも見てみる✅
人によっては実際のコードを見たほうがイメージしやすいかも。
import openai
import json
# 天気を返す関数を準備(関数の中身はダミー)
# 実際はもっと実用的なAPIを使った関数などを用意しておく
def get_current_weather(location, unit="fahrenheit"):
    """Get the current weather in a given location"""
    weather_info = {
        "location": location,
        "temperature": "72",
        "unit": unit,
        "forecast": ["sunny", "windy"],
    }
    return json.dumps(weather_info)
# Step 1, 質問する
# 通常の質問情報(model, messages)に加えて、関数情報(functions 天気予報を取得する関数もあるよ〜👍)を渡す
def run_conversation():
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo-0613",
        messages=[{"role": "user", "content": "What's the weather like in Boston?"}],
        functions=[
            {
                "name": "get_current_weather",
                "description": "Get the current weather in a given location",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "The city and state, e.g. San Francisco, CA",
                        },
                        "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
                    },
                    "required": ["location"],
                },
            }
        ],
        function_call="auto",
    )
    message = response["choices"][0]["message"]
    # Step 2, モデルが「関数を使いたいよ〜🤖」と回答したかどうかチェック
    if message.get("function_call"):
        function_name = message["function_call"]["name"]
        # Step 3, 関数を呼び出す
        # 注意:モデルからのJSONレスポンスは有効なJSONでない可能性がある
        function_response = get_current_weather(
            location=message.get("location"),
            unit=message.get("unit"),
        )
        # Step 4, 関数の実行結果をモデルに渡して再度質問する
        second_response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo-0613",
            messages=[
                {"role": "user", "content": "What is the weather like in boston?"},
                message,
                {
                    "role": "function",
                    "name": function_name,
                    "content": function_response,
                },
            ],
        )
        return second_response
print(run_conversation())引用元:OpneAI ドキュメント
図で理解する
まとめ・感想
- Functioin Callingはその名の通り、(必要に応じて)関数を呼び出すことができる機能だと分かった😊
- ただしモデルは(関数を実行するために必要な)JSONデータを返すだけで、関数を実行するのは自分のプログラム側💦if文で条件分岐して、必要なときだけ関数を実行するように書いておけばよさそう。 
- LangChainに備わっているエージェントに似た機能だと感じた💭ちなみにLangChainでも早速Function Callingがサポートされているみたい。 






