テックブログ

エルカミーの技術ブログです

OpenAI の Function calling とは

はじめに


今回は、ChatGPTの機能であるFunction callingについて説明していきたいと思います。本記事では、理解しずらいFunction callingを理解できるように、Function callingとはどんな機能であるのか、具体的な実装を交えて紹介します。

Function callingとは


「Function calling」は、ChatGPTに自作した関数のdescriptionを提供することで、モデルがその関数を呼び出すための引数を含むJSONオブジェクトを出力する機能です。使えるモデルは以下の2種類です。

  • gpt-4-0613
  • gpt-3.5-turbo-0613

これにより、GPTの能力を外部のツールやAPIとより確実に連携させることが可能になります。

このモデルは、関数が呼び出される必要があるタイミングを検出するとともに、関数のシグネチャに従ったJSONを返答するように最適化されています。Function callingを使用することで、開発者はモデルからより確実に構造化されたデータを取得できます。

Function callingの流れ


具体例として、現在の天気を取得する関数を自作し、ChatGPTにボストンの現在の天気を聞く場合を考えます。

現在の天気を取得する関数は以下のようなものを想定しています。

  • get_current_weather(location: string, unit: 'celsius' | 'fahrenheit')を作成している
  • この関数により、天気を取得するAPIにアクセスし、天気を取得する。
全体の流れ
ボストンの現在の天気を教えて下さい。
Step1: OpenAI API

ユーザーの入力と、自作した関数(get_current_weather)を持った状態でモデルを呼び出します。

Step2: Third party API

モデルのレスポンスを使用して、天気を取得するAPIを呼び出します。

Step3: OpenAI API

サマリーを作成するために、レスポンスをモデルに戻します。

ボストンの天気は現在、晴れで、気温は22度です。
流れの説明
Step1: OpenAI API

Step1では、ユーザからのメッセージと、自作した関数内容を含むJsonファイルにより、OpenAIのAPIにリクエストを送信します。

そして、質問に関連した関数を選択し、その関数を呼び出すためのJSONオブジェクト(引数を含む)を出力します。質問に関連する関数がない場合は、ChatGPTが回答を生成します。

以下にリクエストとレスポンスの内容を示します。

Request
curl https://api.openai.com/v1/chat/completions -u :$OPENAI_API_KEY -H 'Content-Type: application/json' -d '{
  "model": "gpt-3.5-turbo-0613",
  "messages": [
    {"role": "user", "content": "ボストンの現在の天気を教えて下さい。"}
  ],
  "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"]
      }
    }
  ]
}'
Response
{
  "id": "chatcmpl-123",
  ...
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": null,
      "function_call": {
        "name": "get_current_weather",
        "arguments": "{ \"location\": \"Boston, MA\"}"
      }
    },
    "finish_reason": "function_call"
  }]
}
Step2: Third party API

Step2では、自作した関数が呼び出され、天気を取得するAPIにリクエストを送信し、APIからレスポンスが返ってきます。

以下にリクエストとレスポンスの内容を示します。

Request
curl https://weatherapi.com/...
Response
{ "temperature": 22, "unit": "celsius", "description": "Sunny" }

Step3: OpenAI API

Step3では、外部ツールなどから出力された内容をモデルに再度リクエストし、最終的な回答を生成します。

以下にリクエストとレスポンスの内容を示します。

Request
curl <https://api.openai.com/v1/chat/completions> -u :$OPENAI_API_KEY -H 'Content-Type: application/json' -d '{
  "model": "gpt-3.5-turbo-0613",
  "messages": [
    {"role": "user", "content": "ボストンの現在の天気を教えて下さい"},
    {"role": "assistant", "content": null, "function_call": {"name": "get_current_weather", "arguments": "{ \\"location\\": \\"Boston, MA\\"}"}},
    {"role": "function", "name": "get_current_weather", "content": "{\\"temperature\\": "22", \\"unit\\": \\"celsius\\", \\"description\\": \\"Sunny\\"}"}
  ],
  "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"]
      }
    }
  ]
}'
Response
{
  "id": "chatcmpl-123",
  ...
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": "ボストンの天気は現在、晴れで、気温は22度です",
    },
    "finish_reason": "stop"
  }]
}

Function callingを使ってみる


Function callingを実装し、デモを行いたいと思います。今回は簡単なデモを行いたいので、簡易的な関数を実装します。

用意した関数は以下の2種類です。

  • 天気を取得する関数
  • スケジュールを取得する関数

本来であれば、関数内で天気やスケジュールを取得する操作を行う必要がありますが、今回はデモとして返す内容をあらかじめ決めています。

デモのコードは以下のようになります。

デモコード
import json
import openai

openai.api_key = "API_KEY"


def get_current_weather(location, unit):
    return json.dumps({
        "location": location,
        "temperature": "20",
        "unit": unit,
        "forecast": ["晴れ", "風が強い"]
    })


def get_schedule(date, person):
    return json.dumps({
        "date": date,
        "person": person,
        "schedule": "11時:A社とMTG、14時:B社とMTG"
    })


def define_functions():
    return [
        {
            "name": "get_current_weather",
            "description": "指定された地域の天気を取得する",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "都市と州、例:サンフランシスコ、CA"
                    },
                    "unit": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"]
                    }
                },
                "required": ["location", "unit"]
            }
        },
        {
            "name": "get_schedule",
            "description": "特定の日付のスケジュールを取得して返す",
            "parameters": {
                "type": "object",
                "properties": {
                    "date": {
                        "type": "string",
                        "description": "日付"
                    },
                    "person": {
                        "type": "string",
                        "description": "人の名前"
                    }
                },
                "required": ["date", "person"]
            }
        }
    ]


def call_function_based_on_response(response_message):
    available_functions = {
        "get_schedule": get_schedule,
        "get_current_weather": get_current_weather
    }
    function_name = response_message["function_call"]["name"]
    function_args = json.loads(response_message["function_call"]["arguments"])
    
    if function_name in available_functions:
        function_response = available_functions[function_name](**function_args)
        return function_response, function_name


def run_conversation(prompt, model):
    messages = [{"role": "user", "content": prompt}]
    functions = define_functions()
    
    response = openai.ChatCompletion.create(
        model=model,
        messages=messages,
        functions=functions,
        function_call="auto"
    )
    
    response_message = response["choices"][0]["message"]
    
    if response_message.get("function_call"):
        function_response, function_name = call_function_based_on_response(response_message)
        
        # 独自関数のレスポンスを渡す
        messages.append(response_message)
        messages.append(
            {
                "role": "function",
                "name": function_name,
                "content": function_response,
            }
        )
        
        # 独自関数のレスポンスをもとに改めてAPIにリクエスト
        second_response = openai.ChatCompletion.create(
            model=model,
            messages=messages
        )
        return second_response

    else:
        return response


if __name__ == "__main__":
    model = "gpt-3.5-turbo-0613"
    prompt = "東京の天気は?"
    print(run_conversation(prompt, model)["choices"][0]["message"]["content"])

デモの結論
  • 質問に応じて、使う関数を変更してくれました。
  • 関数内で返した情報をもとに回答を生成してくれました。
  • 関数に関係のない質問は、ChatGPTが関数を使用せずに答えてくれました。
実験結果
  • 関数に関係のある質問をしてみる
    • 質問1: 田中さんの6/30のスケジュールを教えて
      田中さんの6/30のスケジュールは以下の通りです:
      
      - 11時:A社とのミーティング
      - 14時:B社とのミーティング
      
      以上が田中さんの6/30のスケジュールです。
    • 質問2: 東京の天気を教えて下さい。
      東京の天気は晴れで、気温は20℃です。また、風も強く吹いています。
  • 関数に関係ない質問をする
    • 質問3: ChatGPTとは何ですか?
      ChatGPTは、OpenAIが開発した自然言語処理モデルです。このモデルは大規模なトレーニングデータセット を用いて学習され、ユーザーとの対話に基づいて生成されたテキストを返すことができます。ChatGPTは、 質問への回答、説明、アドバイス、創造的な文章の生成など、さまざまなタスクに使用することができます。また、ChatGPTはリアルタイムの対話にも対応しており、ユーザーとの対話の流れを維持しながら返答を 生成することができます。このような特徴により、ChatGPTはオンラインチャットボットや仮想アシスタン トなど、さまざまな応用分野で利用されています。
      ChatGPTは、OpenAIが開発した自然言語処理(NLP)モデルです。ChatGPTは、大量のトレーニングデータと 深層学習の手法を用いて訓練されており、ユーザーとの対話を通じてテキストを生成することができます。ChatGPTは、質問への回答、説明、会話の続きを生成するなど、多くのタスクに利用できます。
      
      ChatGPTは、柔軟で対話的なインタフェースを持っており、ユーザーとのリアルタイムな対話をサポートし ています。また、ChatGPTは事前にトレーニングされているため、一般的な知識を持っており、文脈に基づ いて論理的な回答を生成することができます。
      
      ChatGPTは、オンラインカスタマーサポート、仮想アシスタント、情報検索、エンターテイメントなど、さ まざまな分野で利用されています。ただし、ChatGPTはあくまで言語モデルであり、倫理的な問題や情報の 正確性などについては注意が必要です。OpenAIでは、ChatGPTなどのモデルの適切な利用方法に関するガイ ドラインを提供しています。

まとめ


今回はFunction callingについて説明しました。Function callingを使うことで、ChatGPTでは対応できない最新情報、専門的な知識に対応させることができます。また、様々なユースケースに合わせて、ChatGPTを拡張することができるので、試してみてください。

参考