OpenAI APIのFunction callingで関数が呼ばれる条件を確認してみた

2023.06.14

はじめに

新規事業統括部の山本です。

今日(6/14)にOpenAI APIがアップデートがされました。この記事では、新しい機能であるFunction callingについての簡単な解説と、渡したfunctionが実行される条件について簡単に調べてみた内容について記載します。

早速、中村さんが速報の記事を書かれているので、他のアップデートの詳細が気になる方はこちらをご覧ください。

https://dev.classmethod.jp/articles/openai-api-gpt-update-ver-0613/

Function callingとは

通常、LLMは学習したときのデータに含まれている内容以外に関する質問や指示には回答できません。その対策として、ChatGPT pluginsやLangChainのToolなどのように、外部から情報を取得できるようにすることで、そういった質問や指示に答えられるようにすることができます。

Function callingはこれらと同様に外部から情報を取得して回答を得るための方法です。ただ、機能としては以下のような違いがあり、Function callingは判断だけをします。

  • Web版のplugin:追加機能がすでに用意されている。モデルが必要な機能を判断し、それらが自動で実行される。
  • Function calling:追加の機能は自分で用意する。モデルにどういう機能があるか伝える。モデルが必要な機能を判断する。判断結果をもとに呼び出し元(自分)が機能を実行する。

(太字が用意されている機能)

Function callingでは、LLM以外の機能は自分のプログラムの中で実行できるため、以下のような状況で利用できそうです。

  • 用意した機能を公開したくない
  • 認証情報を追加機能(プラグイン)などに置きたくない

補足

LangChainの(今までの)Agentとの比較を調べて書こうと思っていたのですが、こちらも早速対応されていました。agentのパラメータとして、OPENAI_FUNCTIONSを設定すれば使用できるようです。

https://github.com/hwchase17/langchain/blob/master/docs/modules/agents/agents/examples/openai_functions_agent.ipynb

mrkl = initialize_agent(tools, llm, agent=AgentType.OPENAI_FUNCTIONS, verbose=True)

まだ使用してはいない&コードの詳細を見ていないため推測なのですが、おそらく下のページのサンプルのコードのような処理(responseの内容をもとにfunctionを実行する処理)をラップしていると思われるので、これを利用すれば良さそうです。

https://platform.openai.com/docs/guides/gpt/function-calling

functionが実行される条件

Function callingを使用するには、使用すべきfunctionが適切に判断されるかが気になります。中村さんの書かれた記事の中では「functionのdecscriptionを適当に書き換えても実行された」と書かれていたので、この条件についてもう少し調べてみました。

サンプルコードをもとに、functionの内容を以下のように変更したとき、response内にfunction_callが有ったか(サンプルコード内の「if message.get("function_call"):」節に入ったか)を調べました。openai.ChatCompletion.createのfunction_callパラメータはautoにしました。

変更内容としては、以下のとおりです

  • 変更点1:functionのnameを変える
  • 変更点2:functionのdescritionを変える
  • 変更点3:propetiesの名前を変える(requiredも変える)
  • 変更点4:languageのdescriptionを変える
  • 変更点5:unitのenumを削除する
functions=[
    {
        # "name": "get_current_weather",
        "name": "ask_how_to_programming", # functionのnameを変える
        # "description": "Get the current weather in a given location",
        "description": "ask how to programming",  # functionのdescriptionを変える
        "parameters": {
            "type": "object",
            "properties": {
                # "location": {
                "language": {  # propetiesの名前を変える(requiredも変える)
                    "type": "string",
                    # "description": "The city and state, e.g. San Francisco, CA",
                    "description": "",  # languageのdescriptionを変える
                },
                "unit": {
                    "type": "string",
                    # "enum": ["celsius", "fahrenheit"],  # unitのenumを削除する
                },
            },
            # "required": ["location"],
            "required": ["language"],  # propetiesの名前を変える(requiredも変える)
        },
    }
],

結果は以下のとおりでした。(本来は32通り試したいところですが、大変なので割愛しました)

変更点1 変更点2 変更点3 変更点4 変更点5 response内のfunction_call
なし なし なし なし なし あり
あり なし なし なし なし あり
なし あり なし なし なし あり
なし なし あり なし なし あり
なし なし なし あり なし あり
なし なし なし なし あり あり
なし あり あり あり あり あり
あり なし あり あり あり あり
あり あり なし あり あり あり
あり あり あり なし あり あり
あり あり あり あり なし あり
あり あり あり あり あり なし

全てを変更した場合にのみ実行されないという結果でした。このときのメッセージは以下のとおりでした。

I'm sorry, but I am a language model and I don't have real-time information. However, you can easily check the weather in Boston by using a weather website or app.

人間的な解釈を(無理やり)すると、Bostonの今の天気を知らないことをわかっていて、できる限り天気に関連しそうなfunctionを実行しようとした、という動作のように思えます。

※ 今回渡したツールが1つだったため上記の結果になった可能性があり、ツールを増やした場合の動作は変わるかも知れません。

補足

LangChainのAgentでは、最終的なプロンプトにツールの名前・説明(description)・パラメータの説明などが入力されています(それをもとにLLMがどのツールをどういうパラメータで実行するか判断します)。

Function callingでも同様にツールの説明が全部渡され、モデルが判断していそうです。

補足2

おそらくOpenAIのページに記載されているサンプルコードにおけるパラメータを受け取る処理が間違っています(6/14 現在)。正しくは以下のようにする必要がありそうです。

arguments=json.loads(message["function_call"]["arguments"])
function_response = get_current_weather(
    location=arguments.get("location"),
    unit=arguments.get("unit"),
)

まとめ

functionを実行するかどうかには、functionで渡した情報全体が考慮されているようです。モデルに適切な判断をさせるには、命名や説明などの情報の渡し方を試行錯誤することが必要になりそうです。