概要
2023/6/13にOpenAIのAPIの新機能「Function Calling」が出たらしい😳
何ができるようになったのか気になったので調べてみた!
Function Callingでできること
一言で説明すると…
ただしこれだけだとよく分からない😢
もう少し詳しく
例:「天気予報を取得する関数」を用意した場合✅
- 質問するときに「天気予報を取得する関数もあるよ〜👍」と教えてあげる。
-
モデルはいつも通りユーザーの質問に答える。
→もしモデルが「天気予報知りたい!」となった場合、「天気予報を取得する関数を使いたいよ〜🤖」と言ってくれる。
※モデルが関数を実行するわけではない。
具体例
具体的には以下のようなことができる。
最新の天気予報を回答する
- 事前にリアルタイムの天気予報を取得する関数を用意しておく。
- 回答に天気予報の情報が必要なときにこの関数を使って、最新の天気予報を答える。
Todoリストにタスクを自動追加する
- 事前にTodoリストにタスクを追加する関数を用意しておく。
- 回答の中でタスク追加が必要なときにこの関数を使って、Todoリストにタスクを追加する。
流れで理解する
以下のような5ステップで使用する✅
関数の準備
開発者は事前に、モデルを強化するための関数を作成しておく。
最新の天気予報を取得する関数
質問する
モデルに「天気予報を取得する関数もあるよ〜👍」と教えてあげる。
具体的には 質問 + 関数名 + 関数の説明文 + 関数の引数 の4つを渡して質問する。
質問 : 東京の天気は?
関数名 : get_current_weather (事前に開発者が作った関数名)
関数の説明文:指定した場所の現在の天気を取得する
関数の引数 :string型(都市名)
回答を確認
モデルから回答が返ってくる。
もしモデルが関数が必要だと判断していたら、「関数を使いたいよ〜🤖」という回答になっている✅
天気予報を取得する関数を使いたいよ〜🤖
※関数名はget_current_weather
だよ。
※引数は”東京”
だよ。
※もし「関数を使いたいよ〜🤖」と言ってなければここで終了(普通の質問→回答の流れと一緒)
関数実行
「関数を使いたいよ〜🤖」という回答だった場合、モデルが臨んでいるとおりに関数を実行してあげる😊
最新の天気予報を取得する関数get_current_weather(”東京”)
を実行してあげる。
再度質問
モデルに 質問 + 回答 + 関数名 + 関数の実行結果 の4つを渡して再度質問する。
質問 : 東京の天気は?
回答 :天気予報を取得する関数を使いたいよ〜🤖
関数名 : get_current_weather (事前に開発者が作った関数名)
関数の実行結果:晴れ
コードで理解する
続いてサンプルコードも見てみる✅
人によっては実際のコードを見たほうがイメージしやすいかも。
import openai
import json
# 天気を返す関数を準備(関数の中身はダミー)
# 実際はもっと実用的なAPIを使った関数などを用意しておく
def get_current_weather(location, unit="fahrenheit"):
"""Get the current weather in a given location"""
weather_info = {
"location": location,
"temperature": "72",
"unit": unit,
"forecast": ["sunny", "windy"],
}
return json.dumps(weather_info)
# Step 1, 質問する
# 通常の質問情報(model, messages)に加えて、関数情報(functions 天気予報を取得する関数もあるよ〜👍)を渡す
def run_conversation():
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613",
messages=[{"role": "user", "content": "What's the weather like in Boston?"}],
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"],
},
}
],
function_call="auto",
)
message = response["choices"][0]["message"]
# Step 2, モデルが「関数を使いたいよ〜🤖」と回答したかどうかチェック
if message.get("function_call"):
function_name = message["function_call"]["name"]
# Step 3, 関数を呼び出す
# 注意:モデルからのJSONレスポンスは有効なJSONでない可能性がある
function_response = get_current_weather(
location=message.get("location"),
unit=message.get("unit"),
)
# Step 4, 関数の実行結果をモデルに渡して再度質問する
second_response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613",
messages=[
{"role": "user", "content": "What is the weather like in boston?"},
message,
{
"role": "function",
"name": function_name,
"content": function_response,
},
],
)
return second_response
print(run_conversation())
引用元:OpneAI ドキュメント
図で理解する
処理の流れをイメージ図にしてみる✅
関数呼び出しが発生しなかった場合
関数情報を渡したものの、モデルが「関数は不要🤖」と判断した場合。
関数呼び出しが発生した場合
モデルが「関数を使いたいよ〜🤖」と判断した場合。
まとめ・感想
- Functioin Callingはその名の通り、(必要に応じて)関数を呼び出すことができる機能だと分かった😊
-
ただしモデルは(関数を実行するために必要な)JSONデータを返すだけで、関数を実行するのは自分のプログラム側💦
if文で条件分岐して、必要なときだけ関数を実行するように書いておけばよさそう。
-
LangChainに備わっているエージェントに似た機能だと感じた💭
ちなみにLangChainでも早速Function Callingがサポートされているみたい。
参考サイト