1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【入門編】OpenAI Function Callingとはなんぞや?

1
Last updated at Posted at 2025-12-06

はじめに

最近LangChainの勉強をやっており、そこでOpenAI Function Callingというものを知ったので自分の勉強も兼ねてまとめています。実装例もありますので、よければ見ていってください。

そもそもLangChainとは

LangChainとはLLMで開発を行うためのライブラリの一つ

ライブラリとは

ざっくり言うと
特定の言語でプログラミングをする際によく使いそうな機能をあらかじめ誰かが作ってくれていて、それを呼び出すだけで使えるようにしてくれている便利セット
みたいなものです。

OpenAI Function Calling

関数呼び出しに特化したOpenAIのモデルを活用して外部の関数を呼び出す方法のこと。
つまり入力内容から呼び出すべき関数を検知し通知してくれる仕組み。
image.png

実装例

サンプル実装について

OpenWeatherMapのAPIを実行し対象地域の天気を取得する。
OpenWeatherMapは下記サイトを参照。

なお本実装を行うにあたり以下が必要になります。
それぞれ検証として実行するだけなら無料でアカウント作成とキー発行ができます。(2025/12/06時点の情報です)

  • OpenAIのユーザ登録とAPIキーの発行。
  • OpenWeatherMapのユーザ登録とAPIキーの発行。

実装内容

OpenAI Function Callingを使用するには以下を実装する必要がある。

  1. functionsの定義
  2. 呼び出し関数
  3. ユーザメッセージ(プロンプト)の定義
  4. ユーザメッセージとfunctionsのモデル送信
  5. 実際に関数を実行する処理

pythonで実装する前に前提として以下はimportしてください。

from http.client import HTTPException
from openai import OpenAI
import json
import requests
import datetime
import calendar

functionsの定義について

これはGPTモデルに提供するための呼び出し関数定義リストです。
GPTモデルがユーザメッセージ(プロンプト)を処理する前に、どの関数を呼び出すべきか、その関数にどのような引数を渡すべきか判断するための定義です。
functionsの詳細を知りたい方を以下を参照。

天気予報APIを実行するための必要情報を取得したい場合は以下のように定義します。

functions = [
    {
        "type": "function",
        "function": {
            "type": "object",
            # 呼び出す関数を定義
            "name": "get_weather",
            # 関数の説明
            "description": "指定された都市と日付の天気を取得する",
            # パラメータ
            "parameters": {
                "type": "object",
                # 引数の詳細を定義
                "properties": {
                    "city_name": {
                        # パラメータの型定義
                        "type": "string",
                        # パラメータの説明定義
                        # 詳細に説明することで期待する値が設定される確率が高まる
                        "description": """
                        天気予報を取得したい都市の**名前のみ**を指定してください。
                        日本の住所のように都道府県と市区町村が入力された場合は、**OpenWeatherMapのGeocoding APIが認識できる範囲で最も大きな地域名(例: 東京都、大阪府、札幌、福岡など)**を抽出してください。
                        例: 東京都千代田区の場合、'東京都' または '東京' を使用してください。
                        """
                    },
                    "date": {
                        # パラメータの型定義
                        "type": "string",
                        "description": "YYYY/MM/DD形式で出力してください。例: 2020/12/11"
                    },
                },
                # 引数の中で必須項目を定義
                "required": ["city_name", "date"],
            },
        },
    }
]

呼び出し関数について

functionsから呼び出す関数を定義します。
ここでは関数で何を実施したいのか定義します。
OpenWeatherMapAPIで天気を取得する場合だと以下のような実装になります。
天気情報の取得までの流れはざっと以下の通り

  1. 対象の地域の経度、緯度を取得する(実装ではget_coordinatesの部分)
  2. その経度、緯度に対する天気情報をOpenWeatherMapのAPIを実行して取得する(実装ではget_weather_detail_infoの部分)
# OpenWeatherMapのAPIを呼び出し天気を取得
def get_weather(city_name, date):
    # APIキーの存在チェック
    if OPENWEATHERMAP_API_KEY is None:
        raise HTTPException(status_code=500,datail="API Key not configured.")
    # 都市名から経度・緯度を取得
    latitude, longitude = get_coordinates(city_name)

    # OpenWeatherのAPIを実行し天気情報を取得
    weather_info = get_weather_detail_info(latitude, longitude)
    unix_timestamp = date_to_unix_timestamp(date)

    # weather_infoのリストから取得したい日付(unix_timestamp)のみ取得
    # 取得した情報をレスポンスとして返却するという箇所は未実装なのでここから先は読者に実装をお任せします。
    
    return "" #筆者はここまで実装していないので戻り値は空文字

# 【API実行】 経度・緯度を取得
def get_coordinates(city_name):
    params = {
        "q": city_name,
        "limit": 1,
        "appid": OPENWEATHERMAP_API_KEY
    }
    try:
        response = requests.get(GEOCODING_URL, params=params)
        response.raise_for_status
        data = response.json()
    except requests.exceptions.RequestException as e:
        raise HTTPException(status_code=500,datail=f"Geocoding API connection error: {e}")
    
    if not data:
        # 都市が見つからなかった場合
        raise HTTPException(status_code=404,detail=f"City not found by Geocoding API: {city_name}")
    
    # 見つかった場合は最初の経度と緯度を返却
    return data[0]["lat"], data[0]["lon"]

# 【API実行】 対象地域の天気情報を取得
def get_weather_detail_info(latitude,longitude):
    params = {
            "lat": latitude,
            "lon": longitude,
            "appid": OPENWEATHERMAP_API_KEY,
            "units": "metric",  # 摂氏で取得
            "exclude": "current,minutely,hourly,alerts",  # 日次データのみを取得
        }
    try:
        response = requests.get(ONE_CALL_URL,params=params)
        response.raise_for_status
    except requests.exceptions.RequestException as e:
        raise HTTPException(status_code=500, detail=f"Weather API connection error:{e}")

    return response.json()

# 相対的な日付文字列をUnixタイムスタンプに変換する
def date_to_unix_timestamp(date_string):
    try:
        print(date_string)  
        # タイムゾーン情報を持たないdatetimeオブジェクト(naive object)
        dt_naive = datetime.datetime.strptime(date_string, "%Y/%m/%d")
        utc_time_tuple = dt_naive.utctimetuple()
        unix_timestamp = calendar.timegm(utc_time_tuple)
        return unix_timestamp

    except ValueError:
            # 指定された形式(YYYY/MM/DD)で解析できなかった場合
            print(f"エラー: 無効な日付形式です -> {date_string}")
            return None
            
# functionsの関数名と実際の関数を紐付けするリスト定義
OPENAI_FUNCTIONS = {
    "get_weather": get_weather
}

ユーザメッセージ(プロンプト)の定義について

外部入力、API連携などいろいろメッセージの連携方法はありますが今回は簡易的に定義。

messages = [
    {
        "role": "user",
        "content": "2025/12/06の東京の天気を教えてください。",
    }
]

ユーザメッセージとfunctionsのモデル送信

こんな感じで対象のGPTモデルにfunctionsとメッセージを渡します。

response = client.chat.completions.create(
    model="gpt-3.5-turbo-1106", # 関数呼び出しに特化したモデル
    messages=messages,
    tools=functions,
    tool_choice="auto"
)
# レスポンス定義
response = response.choices[0].message

実際に関数を実行する処理

# GPTモデルの実行結果から呼び出し関数を判定
if response.tool_calls:
    # もしユーザメッセージに紐づく関数が複数ある場合を考慮してループ処理
    for tool_call in response.tool_calls:
        # 関数名と引数を取得
        function_name = tool_call.function.name
        function_args = json.loads(tool_call.function.arguments)
        # 関数を呼び出し
        function = OPENAI_FUNCTIONS.get(function_name)

        if not function:
            raise Exception(f"Function {function_name} not found.")        
        function_response = function(**function_args)

最後に

最後まで読んでいただきありがとうございます。
まだまだ勉強中の身なので、新しい知識をインプットしたら適宜投稿続けていこうと思います。
本記事が少しでも参考になりましたら「いいね」押していただけますと今後の励みになります。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?