OpenAIの新機能Function Callingを誰でも分かるようイメージを解説

Featured image of the post

概要

2023/6/13にOpenAIのAPIの新機能「Function Calling」が出たらしい😳

何ができるようになったのか気になったので調べてみた!

💡
イメージを理解することを目標に簡潔にまとめる!

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 ドキュメント

図で理解する

処理の流れをイメージ図にしてみる✅

関数呼び出しが発生しなかった場合

関数情報を渡したものの、モデルが「関数は不要🤖」と判断した場合。

Image in a image block

💡
通常の質問 → 回答の流れと同じ!

関数呼び出しが発生した場合

モデルが「関数を使いたいよ〜🤖」と判断した場合。

Image in a image block

💡
モデルに関数の実行結果を渡して再度質問すると、いい回答が得られる!

まとめ・感想

  • Functioin Callingはその名の通り、(必要に応じて)関数を呼び出すことができる機能だと分かった😊

  • ただしモデルは(関数を実行するために必要な)JSONデータを返すだけで、関数を実行するのは自分のプログラム側💦

    if文で条件分岐して、必要なときだけ関数を実行するように書いておけばよさそう。

参考サイト