業界・業務から探す
導入目的・課題から探す
データ・AIについて学ぶ
News
Hakkyについて
ウェビナーコラム
◆トップ【AI・機械学習】
AI

執筆者:Handbook編集部

関数の選択もGPTがやってくれる!function calling を使ってみた

はじめに

2023 年 6 月 13 日、OpenAI の新たな アップデート が公開されました。 このアップデートの中に新たな機能**「function calling」**が含まれています。function calling は、自作の関数や外部 API を呼び出すための引数を含む JSON オブジェクトを GPT に作成させることができる機能です。ユーザーの入力によって、関数を使用するかどうかを GPT 側が判断して出力を行います。
本記事では、function calling を OpenAI のチュートリアルにあるコードを参考に具体的に動かしてみたいと思います。 ぜひ最後までお読みいただき、今後の OpenAI を使ったサービスを対外に対してアピールする際に役立ててください。

function calling とは何か

function calling という機能は、上述の通り、自作の関数や外部 API を呼び出すための引数を含む JSON オブジェクトを GPT に作成させることができる機能です。 関数や API を呼び出すためには引数を作成する必要があります。function calling ではユーザーからの入力に対して、回答するのに有用そうな関数を選び、それに対して必要と思われる引数を作成してくれます。 関数や API の候補は複数設定することができ、入力に合わせてよさそうな関数を自動で選んでくれます。

function calling の実装

以下では、function calling の実装例を提示します。 事前に、OpenAI API の API キーを環境変数に設定する必要があります。API キー についてはこちらの記事でも解説していますので、併せてご覧ください。

function calling の実装例は以下のようになります。OpenAI の function calling のチュートリアル を参考にしています。

import openai
import json

# 同じ天気を返すように設定されたダミー関数の例
# 本番では、バックエンドのAPIや外部のAPIを利用することができます
def get_current_weather(location, unit=["摂氏"]):
    """指定した場所の現在の天気を取得する関数です"""
    weather_info = {
        "location": location,
        "temperature": "72",
        "unit": unit,
        "forecast": ["晴れ", "風が強い"],
    }
    return json.dumps(weather_info)

# 関数に関する情報
functions = [
    {
        "name": "get_current_weather",
        "description": "指定した場所の現在の天気を取得する",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "都道府県や市町村 例:東京、大阪、港区",
                },
                "unit": {"type": "string", "enum": ["摂氏", "華氏"]},
            },
            "required": ["location"],
        },
    }
]

def run_conversation(question, functions):
    # Step 1: 会話と使用可能な機能をGPTに送信する
    messages = [{"role": "user", "content": question}]
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo-0613",
        messages=messages,
        functions=functions, # 定義したfunctionsを引数として与えます
        function_call="auto",  # autoはデフォルトですが、ここでは明示しています
    )
    response_message = response["choices"][0]["message"]

    # Step 2: GPTが関数を呼び出したいかどうかを確認します
    if response_message.get("function_call"):
        # Step 3: 関数の呼び出し
        available_functions = {
            "get_current_weather": get_current_weather,
        }  # ここでは関数は1つですが、複数設定することもできます
        function_name = response_message["function_call"]["name"]
        fuction_to_call = available_functions[function_name]
        function_args = json.loads(response_message["function_call"]["arguments"])
        function_response = fuction_to_call(
            location=function_args.get("location"),
            unit=function_args.get("unit"),
        )

        # Step 4: function call と response を GPTに送信します
        messages.append(response_message)
        messages.append(
            {
                "role": "function",
                "name": function_name,
                "content": function_response,
            }
        )  # 会話を広げています
        second_response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo-0613",
            messages=messages,
        )  # GPTからfunction call を確認できる新しいresponse を得る
        return second_response


answer = run_conversation("東京の天気はどうなんだろう?", functions)
print(answer["choices"][0]["message"]["content"])

コードを部分的にいくつか取り出して確認してみたいと思います。

自作関数の作成

  • 指定した場所の天気を取得させる自作の関数です。ここではダミー関数として作成していて、あり得ない気温(72 度)を含む天気情報を返す関数になっています。
# 同じ天気を返すように設定されたダミー関数の例
# 本番では、バックエンドのAPIや外部のAPIを利用することができます
def get_current_weather(location, unit=["摂氏"]):
    """指定した場所の現在の天気を取得する関数です"""
    weather_info = {
        "location": location,
        "temperature": "72",
        "unit": unit,
        "forecast": ["晴れ", "風が強い"],
    }
    return json.dumps(weather_info)

関数に関する情報

  • 次に、関数に関する情報を与えます。"description"では関数の概要を記し、必要なパラメータの型や情報を明記します。モデルがその情報に基づいて、引数を作成しますので、詳しい説明が必要です。これによって、function calling 時に適切な引数が作成され、関数に渡されます。
functions = [
    {
        "name": "get_current_weather",
        "description": "指定した場所の現在の天気を取得する",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "都道府県や市町村 例:東京、大阪、港区",
                },
                "unit": {"type": "string", "enum": ["摂氏", "華氏"]},
            },
            "required": ["location"],
        },
    }
]

GPT への指示

  • GPT モデルに、会話 question と関数 function を渡します。GPT では message の内容を会話として受けとり、有用な function があればそれを使用するための引数を作成してくれます。なお、function calling が使えるのはいまのところ、今回のアップデートでリリースされた gpt-4-0613gpt-3.5-turbo-0613 のみです。
  • それ以降は、作成された引数をもとに GPT が処理を進めるようなコードになっています。
def run_conversation(question, functions):
    # Step 1: 会話と使用可能な機能をGPTに送信する
    messages = [{"role": "user", "content": question}]
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo-0613",
        messages=messages,
        functions=functions, # 定義したfunctionsを引数として与えます
        function_call="auto",  # autoはデフォルトですが、ここでは明示しています(使用しない場合はnoneに)
    )
    response_message = response["choices"][0]["message"]

(以下省略)

出力の確認

上記のコードを実行すると、次のような出力が得られます。 気温を見ると、関数「get_current_weather」が実行されたことが分かります。

複数の function の実装

つぎに、複数の関数を与えて、会話の内容に合わせて GPT 側が関数を選択する様子を確認してみたいと思います。

def get_current_weather_japan(location, unit=["摂氏"]):
    """指定した場所の現在の天気を取得する関数です"""
    weather_info = {
        "location": location,
        "temperature": "72",
        "unit": unit,
        "forecast": ["晴れ", "風が強い"],
    }
    return json.dumps(weather_info)

def get_current_weather_usa(location, unit=["摂氏"]):
    """指定した場所の現在の天気を取得する関数です"""
    weather_info = {
        "location": location,
        "temperature": "100",
        "unit": unit,
        "forecast": ["雨", "台風"],
    }
    return json.dumps(weather_info)

functions = [
    {
        "name": "get_current_weather_japan",
        "description": "指定した場所の現在の天気を取得する。ただし、場所が日本の場合に限る。",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "都道府県や市町村 例:東京、大阪、港区",
                },
                "unit": {"type": "string", "enum": ["摂氏", "華氏"]},
            },
            "required": ["location"],
        },
    },
    {
    "name": "get_current_weather_usa",
    "description": "指定した場所の現在の天気を取得する。ただし、場所がUSAの場合に限る。",
    "parameters": {
        "type": "object",
        "properties": {
            "location": {
                "type": "string",
                "description": "州や都市 例:サンフランシスコ、カリフォルニア",
            },
            "unit": {"type": "string", "enum": ["摂氏", "華氏"]},
        },
        "required": ["location"],
    },
    }
]

def run_conversation(question, functions):
    # Step 1: 会話と使用可能な機能をGPTに送信する
    messages = [{"role": "user", "content": question}]
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo-0613",
        messages=messages,
        functions=functions, # 定義したfunctionsを引数として与えます
        function_call="auto",  # autoはデフォルトですが、ここでは明示しています
    )
    response_message = response["choices"][0]["message"]

    # Step 2: GPTが関数を呼び出したいかどうかを確認します
    if response_message.get("function_call"):
        # Step 3: 関数の呼び出し
        available_functions = {
            "get_current_weather_japan": get_current_weather_japan,
            "get_current_weather_usa": get_current_weather_usa,
        }  # 関数を複数設定しています。
        function_name = response_message["function_call"]["name"]
        fuction_to_call = available_functions[function_name]
        function_args = json.loads(response_message["function_call"]["arguments"])
        function_response = fuction_to_call(
            location=function_args.get("location"),
            unit=function_args.get("unit"),
        )

        # Step 4: function call と response を GPTに送信します
        messages.append(response_message)
        messages.append(
            {
                "role": "function",
                "name": function_name,
                "content": function_response,
            }
        )  # 会話を広げています
        second_response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo-0613",
            messages=messages,
        )  # GPTからfunction call を確認できる新しいresponse を得る
        return second_response

answer1 = run_conversation("東京の天気はどうなんだろう?", functions)
answer2 = run_conversation("ボストンの天気はどうなんだろう?", functions)

print(answer1["choices"][0]["message"]["content"])
print(answer2["choices"][0]["message"]["content"])

変更箇所を取り上げます。

新たな関数の作成と functions の更新

  • 関数として、日本の天気に関するものとアメリカの天気に関するものをそれぞれ用意し、functions として 2 つの関数の情報を与えます。
  • アメリカの天気は、気温が 100 度、"雨" や "台風" というキーワードを与えました。
def get_current_weather_japan(location, unit=["摂氏"]):
    """指定した場所の現在の天気を取得する関数です"""
    weather_info = {
        "location": location,
        "temperature": "72",
        "unit": unit,
        "forecast": ["晴れ", "風が強い"],
    }
    return json.dumps(weather_info)

def get_current_weather_usa(location, unit=["摂氏"]):
    """指定した場所の現在の天気を取得する関数です"""
    weather_info = {
        "location": location,
        "temperature": "100",
        "unit": unit,
        "forecast": ["雨", "台風"],
    }
    return json.dumps(weather_info)

functions = [
    {
        "name": "get_current_weather_japan",
        "description": "指定した場所の現在の天気を取得する。ただし、場所が日本の場合に限る。",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "都道府県や市町村 例:東京、大阪、港区",
                },
                "unit": {"type": "string", "enum": ["摂氏", "華氏"]},
            },
            "required": ["location"],
        },
    },
    {
    "name": "get_current_weather_usa",
    "description": "指定した場所の現在の天気を取得する。ただし、場所がUSAの場合に限る。",
    "parameters": {
        "type": "object",
        "properties": {
            "location": {
                "type": "string",
                "description": "州や都市 例:サンフランシスコ、カリフォルニア",
            },
            "unit": {"type": "string", "enum": ["摂氏", "華氏"]},
        },
        "required": ["location"],
    },
    }
]

available_functions の更新

  • 引数 available_functions を新しい関数の情報に更新し、呼び出し可能な関数を複数設定します。
    # Step 2: GPTが関数を呼び出したいかどうかを確認します
    if response_message.get("function_call"):
        # Step 3: 関数の呼び出し
        available_functions = {
            "get_current_weather_japan": get_current_weather_japan,
            "get_current_weather_usa": get_current_weather_usa,
        }  # 関数を複数設定しています。

異なる条件の入力

  • 東京の天気とボストンの天気をそれぞれ出力させています。
answer1 = run_conversation("東京の天気はどうなんだろう?", functions)
answer2 = run_conversation("ボストンの天気はどうなんだろう?", functions)

print(answer1["choices"][0]["message"]["content"])
print(answer2["choices"][0]["message"]["content"])

出力の確認

出力結果は次のようになります。場所に応じて使用する関数が変わっていることが分かると思います。

まとめ

この記事では、GPT で新たに追加された機能 function calling について具体例とともに取り上げました。今回は自作の簡単な関数でしたが、外部 API などを呼び出すように(それに合う引数を作成させるように)GPT に指示を与えることもできます。 これからのビジネスシーンでは、AI 技術の活用がますます重要になります。ChatGPT を使いこなすことで、競争力のあるビジネスパーソンになることができるでしょう。

参考

info
備考

ChatGPT を業務で活用したい場合、機密情報を入力することがセキュリティの観点から NG だったり、自社のシステムに組み込まないと効率が悪かったりする場合があります。Hakky では、ChatGPT を用いた企業独自のシステムを構築するご支援を行っています。 ソリューションサイト:https://www.about.st-hakky.com/chatgpt-solution

「どんなことが出来るのか」「いま考えているこのようなことは本当に実現可能か」など、ご検討段階でも構いませんので、ぜひお気軽にフォームよりお問い合わせくださいませ。

Hakkyへのお問い合わせ
2025年06月13日に最終更新
読み込み中...