本文へ移動
カテゴリ

Webマーケ

Webマーケの記事すべてSEOサイト運営データマネジメントビジネス・マーケ概論広告

インタビュー

インタビューの記事すべて

おすすめサービス

おすすめサービスの記事すべて

おすすめ勉強法

おすすめ勉強法の記事すべて

おすすめ書籍

おすすめ書籍の記事すべて

データサイエンス

データサイエンスの記事すべてデータ解析品質工学多変量解析機械学習統計学

プログラミング

プログラミングの記事すべてPythonRSQLプログラミングスクール

スタビジについて

記事一覧運営者情報お問い合わせ

ChatGPTの便利API機能「Function calling」をPythonで実装!自分だけのAI Agentを作ってみよう!

目次
ウマたんウマたん

当サイト【スタビジ】の本記事では、ChatGPT(正確にはGPTモデル)のAPIにおいて非常に便利なFunction callingという機能について解説していきたいと思います。実際にPythonを使ってFunction callingでどんな処理が構築できるのか実装していきますよ!

こんにちは!

データサイエンティストのウマたん(@statistics1012)です!

この記事ではChatGPTの話題のFunction callingについてどんなことができるか実装例とともに見ていきたいと思います!

Function callingを使うとChatGPTのAPIを利用してプログラムを構築する際の幅がめちゃくちゃ広がるのでぜひおさえておきましょう!

ちなみにFunction Callingを使ったエージェントの詳しい作り方は以下のUdemyの講座で僕自身が詳しく解説していますのでもっと深く知りたい方はチェックしてみてください!

Function callingとは?

robot

Function callingはOpenAIが2023年6月13日に公開したChatGPT(正確にはChatGPTというかGPTモデル)のAPI新機能であり(現在はTool calling=ツール呼び出しとも呼ばれています)、処理の幅が広がるため界隈で非常に話題になっている機能です。

ざっくり言うと、あらかじめ特定の関数をこちらで定義して渡しておけば、人間の指示に対してGPTモデル側がよしなに必要な関数をピックアップして処理を行い結果を返してくれるというもの。

たとえば、色んな人のスケジュールが格納されているデータベースがありそこから特定の人の特定の日付のスケジュールを取得する関数を作成したとしましょう。

その関数をGPTのAPIに渡してFunction callingの設定をしてあげると・・・

自然言語で”田中さんの6/30のスケジュールを教えてー!”と入力すると、その結果を元に関数を呼び出すかどうか判断して必要であれば関数を呼んでその情報をもとに出力を返してくれる優れものなのです!

Function calling

複数の関数を定義することが可能で、GmailのAPIを利用してメールを送る関数などを定義しておくと”田中さんの6/30のスケジュールをxxxxx.gmail.comにおくってー”などと伝えるだけで、特定の関数を呼び出して実行してくれます。

めちゃくちゃすごいです。

このような処理を自然言語の指示で出来てしまうのは画期的ですし、ChatGPTのAPIを利用する幅が大きく広がりました!

Function callingの実装例

それでは実際にどうやってFunction callingを実装するのか見ていきましょう!

今回は、先ほどお伝えした「誰かの特定日付のスケジュールを取得する」ような処理を簡単なデモで実装していきます。

この時、処理構築の流れとしては以下です。

まず処理構築に入る前に例によって以下のように各種必要なライブラリやAPIキーの設定をしておきましょう!

from openai import OpenAI
import json
client = OpenAI(api_key="<自分のOpenAIのAPIキーを入れる>")

独自functionの定義

まずは独自functionを定義していきましょう!以下のように記述していきます!

def get_schedule(date, person):
    """
    スケジュール取得用の関数を定義
    - ここではdateとpersonがパラメータとして渡りそれに対するscheduleが返ってくる仕様
    - 本来であればパラメータを元に適切なスケジュールが返ってくるようになるべきだが簡単のために今回は固定値を返す
    """
    schedule_info = {
        "date": date,
        "person": person,
        "schedule": "10時:A社とMTG、12時:友人Bとランチ"
    }
    return json.dumps(schedule_info)

get_scheduleはまさにスケジュールを取得する関数であり、dateとpersonを引数としてscheduleを取得します。

今回は簡単のためscheduleは固定値を入れています。

GPTのAPIを呼ぶ処理

続いてGPTのAPIを呼ぶ処理を作っていきます。ここでは、OpenAIが今おすすめしているResponses API(client.responses.create)を使います。

def run_conversation(prompt):
    # GPTのAPIへのリクエストを定義
    input_list = [{"role": "user", "content": prompt}]
    tools = [
        {
            "type": "function",
            "name": "get_schedule",
            "description": "特定の日付のスケジュールを取得して返す",
            "parameters": {
                "type": "object",
                "properties": {
                    "date": {
                        "type": "string",
                        "description": "日付"
                    },
                    "person": {
                        "type": "string",
                        "description": "人の名前"
                    },
                },
                "required": ["date","person"]
            }
        }
    ]
    response = client.responses.create(
        model="gpt-6-luna",
        input=input_list,
        tools=tools,
        tool_choice="auto",
    )

toolsには独自関数名や関数の説明や関数に必要なパラメータなどをセットしていきます(以前はfunctionsという引数でしたが、今は”type”: ”function”をつけてtoolsに渡します)。

tool_choice=”auto”とすることで独自関数を使うか使わないかをGPTモデルが自動で選定してくれるようになります。モデルには、安くて速い”gpt-6-luna”を指定しています。

引数promptにはユーザーが入力する自然言語が入るようになってます。

独自functionを呼ぶ選択をしたかどうか判断し処理

続いて独自定義したfunctionを呼ぶかどうかを判断し次の処理に移ります。

先ほどのコードの続きであり、run_conversation関数の中に書いていきます。

    # 独自定義したfunctionを呼ぶのかどうか判断し処理
    function_calls = [item for item in response.output if item.type == "function_call"]
    if function_calls:
        available_functions = {
            "get_schedule": get_schedule,
        }
        # 独自関数のレスポンスを渡す
        input_list += response.output
        for function_call in function_calls:
            function_name = function_call.name
            fuction_to_call = available_functions[function_name]
            function_args = json.loads(function_call.arguments)
            function_response = fuction_to_call(
                date=function_args.get("date"),
                person=function_args.get("person")
            )
            input_list.append(
                {
                    "type": "function_call_output",
                    "call_id": function_call.call_id,
                    "output": function_response,
                }
            )
        # 独自関数のレスポンスをもとに改めてAPIにリクエスト
        second_response = client.responses.create(
            model="gpt-6-luna",
            input=input_list,
            tools=tools,
        )  # get a new response from GPT where it can see the function response
        return second_response

    else:
        return response

ここでは、functionを呼ぶ選択をした場合は、よしなにユーザーが入力したpromptから名前や日付を取得してそれを元に関数を呼び出し結果を返してくれます。

モデルが関数を呼ぶと決めたときは、response.outputの中にtypeが”function_call”の要素が入ってくるので、それを見て判断しています。関数の結果は、call_idをつけて”function_call_output”としてモデルに返します。

検証

それでは検証していきましょう!

最終的なコードは以下のようになります!

def get_schedule(date, person):
    """
    スケジュール取得用の関数を定義
    - ここではdateとpersonがパラメータとして渡りそれに対するscheduleが返ってくる仕様
    - 本来であればパラメータを元に適切なスケジュールが返ってくるようになるべきだが簡単のために今回は固定値を返す
    """
    schedule_info = {
        "date": date,
        "person": person,
        "schedule": "10時:A社とMTG、12時:友人Bとランチ"
    }
    return json.dumps(schedule_info)


def run_conversation(prompt):
    # GPTのAPIへのリクエストを定義
    input_list = [{"role": "user", "content": prompt}]
    tools = [
        {
            "type": "function",
            "name": "get_schedule",
            "description": "特定の日付のスケジュールを取得して返す",
            "parameters": {
                "type": "object",
                "properties": {
                    "date": {
                        "type": "string",
                        "description": "日付"
                    },
                    "person": {
                        "type": "string",
                        "description": "人の名前"
                    },
                },
                "required": ["date","person"]
            }
        }
    ]
    response = client.responses.create(
        model="gpt-6-luna",
        input=input_list,
        tools=tools,
        tool_choice="auto",
    )

    # 独自定義したfunctionを呼ぶかどうかの処理
    function_calls = [item for item in response.output if item.type == "function_call"]
    if function_calls:
        available_functions = {
            "get_schedule": get_schedule,
        }
        # 独自関数のレスポンスを渡す
        input_list += response.output
        for function_call in function_calls:
            function_name = function_call.name
            fuction_to_call = available_functions[function_name]
            function_args = json.loads(function_call.arguments)
            function_response = fuction_to_call(
                date=function_args.get("date"),
                person=function_args.get("person")
            )
            input_list.append(
                {
                    "type": "function_call_output",
                    "call_id": function_call.call_id,
                    "output": function_response,
                }
            )
        # 独自関数のレスポンスをもとに改めてAPIにリクエスト
        second_response = client.responses.create(
            model="gpt-6-luna",
            input=input_list,
            tools=tools,
        )  # get a new response from GPT where it can see the function response
        return second_response

    else:
        return response

では定義したrun_conversationを呼び出して実際にどんな回答が返ってくるのか検証してみましょう!

print(run_conversation("田中さんの6/30のスケジュールを教えて").output_text)

結果は以下のようになりました!!

Function calling

ちゃんといい感じに回答を返してくれていることが分かります。

今回は固定値を返すというシンプルな方法で実装を試みましたが、これでもFunction callingの実装イメージが掴めたかと思います。

ぜひ色んな関数を定義してFunction callingを駆使して面白いプログラムを作ってみてください!

以下がOpenAIのFunction callingのドキュメントであり実装方法などが詳しく記載されているので是非参考にしてみてください。

ちなみにFunction callingと似たことができるライブラリとしてLangChainが存在しました。

Function callingとLangChainの違いはどんなところにあるのでしょうか?

個人的にはFunction callingの方が処理構築が分かりやすいのと出力が正確かつOpenAIが提供している公式機能であることから出来るだけFunction callingを利用した方がいいかなと思っています。

LangChainについては以下の記事で詳しく解説していますので是非チェックしてみてください!

【5分で分かる】LangChainのPythonでの使い方 -チュートリアル-当サイト【スタビジ】の本記事では、大規模言語モデル(LLM)を上手く扱う上で非常に便利なLangChainというライブラリについて概要からPythonでの使い方まで見ていきたいと思います。LangChainを使うことで複雑な処理に対応したプログラムを簡潔に書くことができるのでLLMを組み込んだサービスを作るときなどに重宝します!

Function calling まとめ

ここまでで、ChatGPTのAPIをフル活用するのに重要なFunction callingについてまとめてきました!

冒頭でもお伝えしましたが、Function Callingを使ったエージェントの詳しい作り方は以下のUdemyの講座で僕自身が詳しく解説していますのでもっと深く知りたい方はチェックしてみてください!

また、最近話題の生成系AIやLLMの実装方法についてより詳しくは当メディアが運営するスタアカの以下のコースを是非チェックしてみてください!

GPTモデルをはじめとした大規模言語モデルの理論やPythonでの扱い方などを幅広く学んでいきます!

スタアカは業界最安級のAIデータサイエンススクールです。

スタアカトップ

【価格】 ライトプラン:1280円/月
プレミアムプラン:129,800円(通常149,800円)
【オススメ度】
【サポート体制】
【受講形式】 オンライン形式
【学習範囲】 データサイエンスを網羅的に学ぶ
実践的なビジネスフレームワークを学ぶ
SQLとPythonを組みあわせて実データを使った様々なワークを行う
マーケティングの実行プラン策定
マーケティングとデータ分析の掛け合わせで集客マネタイズ

\今すぐ試す/

AIデータサイエンスを学んで市場価値の高い人材になりましょう!

データサイエンスやAIの勉強方法は以下の記事でまとめています。

【5分で分かる】データサイエンティストに必要なスキルと独学勉強ロードマップ!当サイト【スタビジ】の本記事では、データサイエンティストに求められるスキルとそれを身に付けるための勉強法について徹底的にまとめていきます!入門者でも、しっかりデータサイエンティストについて理解しある程度独学で駆け出しの状態までいけることを目指します。 【これだけ!】AI(人工知能)の勉強ロードマップを徹底的に解説!当サイト【スタビジ】の本記事では、AIを勉強するロードマップについて徹底的に解説していきます。まずは、AIの概要について理解して統計学の基本知識・機械学習の基本知識・Pythonでの実装・インフラ周りの知識などを包括的に理解していきましょう!

PythonでのAPI開発にFastAPIを使った方法を以下の記事で解説しています。

【入門】PythonのFastAPIの使い方についてわかりやすく解説!当サイト【スタビジ】の本記事では、FastAPIの使い方を解説していきます!FastAPIはPythonでWeb APIを構築するためのフレームワーク!実際にFastAPIを触りながら使い方をマスターしていきましょう!
スポンサーリンク

ウマたんスタビジ編集長

大学院は理系の統計科学研究室で、ベイズ統計学・時系列分析・異常検知を研究。日系・外資の消費財メーカーのデータサイエンティストを経て、現在は会社を経営しながらデータサイエンティストとして働いています。

スタビジアカデミー

読んだ内容を、手を動かして身につける

データサイエンス・AIを、動画と課題で体系的に学べるオンラインスクール。

スタアカを見てみる