OpenAIのFunction Callingについて試してみた
2023/6/14にFunction callingなるものが出てきましたので、早速簡単に試してみました。
実装コード
Function callingチュートリアルの参考として、API Docsのこちらの部分を参考にしました。少しコードを変えて見やすくしています。
!pip install openai
import os
os.environ['OPENAI_API_KEY'] = "your-open-api-key"
import openai
import json
import openai
import json
def get_current_weather(location, unit="celsius"):
"""指定された場所の現在の天気を取得する"""
weather_info = {
"location": location,
"temperature": "22",
"unit": unit,
"forecast": ["晴れ", "風"],
}
return json.dumps(weather_info, ensure_ascii=False)
def run_conversation(user_query):
# リクエストのログ
print(f"ChatGPTにユーザーメッセージを送信中: {user_query}\n")
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613",
messages=[{"role": "user", "content": user_query}],
functions=[
{
"name": "get_current_weather",
"description": "指定された場所の現在の天気を取得する",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "都市と都道府県、例えば 東京都",
},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
},
"required": ["location"],
},
}
],
function_call="auto",
)
# レスポンスのログ
print(f"ChatGPTからのレスポンスを受信: {response}\n")
message = response["choices"][0]["message"]
if message.get("function_call"):
function_name = message["function_call"]["name"]
args = json.loads(message["function_call"]["arguments"])
function_response = get_current_weather(
location=args.get("location"),
unit=args.get("unit"),
)
second_response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613",
messages=[
{"role": "user", "content": user_query},
message,
{
"role": "function",
"name": function_name,
"content": function_response,
},
],
)
# レスポンスのログ
print(f"ChatGPTからの二回目のレスポンスを受信: {second_response}\n")
return second_response
user_query = "東京の天気はどうですか?"
response = run_conversation(user_query)
# レスポンスメッセージの取得
response_message = response["choices"][0]["message"]["content"]
print(f"レスポンスメッセージ: {response_message}")
このコードは、ユーザーからの問い合わせに対して現在の天気情報を取得し、その結果をユーザーに返すという処理を行います。具体的には以下のようなステップで動作します。
ユーザーからの問い合わせを受け取ります。
問い合わせをGPT-3.5-turboモデルに送信します。
モデルからの応答を解析し、天気情報の取得が必要か判断します。
必要があれば天気情報を取得し、それを含む新たなメッセージをモデルに送信します。
モデルからの最終的な応答をユーザーに返します。
get_current_weather関数:
指定された場所と単位(デフォルトは摂氏)に基づいて天気情報を作成します。
作成した天気情報をJSON形式で返します。
run_conversation関数:
ユーザーからの問い合わせを受け取り、それをGPT-3.5-turboモデルに送信します。
モデルからの応答を解析し、天気情報の取得が必要かどうかを判断します。
必要があれば、get_current_weather関数を呼び出して天気情報を取得します。
取得した天気情報を含む新たなメッセージをモデルに送信します。
モデルからの最終的な応答を返します。
以下、出力結果です。
分かったこと
ツールの扱いについては、既存の手法のメンタルモデルと似てる
ユーザーからのメッセージに対して、関数を使うべきかという判断をchagpt API側で行える。
また利用できるツール(関数)はシステムメッセージとして事前に伝えることで拡張が可能。
関数を扱うと判定した場合のレスポンスについて
従来の `response["choices"][0]["message"]["content"]` は null として扱われる
その代わり、以下のような形で function_call に name, arguments が格納されて返却される(locationはUnicodeエスケープされた文字列で、デコードすると"東京都"です)
引数には型指定をすることができ、ここで生成するデータの(ある程度)強制することができそう
parameters.propertiesで引数名・型指定・詳細を指示している。またenumも使えるので、二値分類(yes/no)や多値分類タスクも扱うことができそう
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613",
messages=[{"role": "user", "content": user_query}],
functions=[
{
"name": "get_current_weather",
"description": "指定された場所の現在の天気を取得する",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "都市と都道府県、例えば 東京都",
},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
},
"required": ["location"],
},
}
],
function_call="auto",
)
おわりに
結構エージェント的な振る舞いではあるものの、生成するデータを指定することができるので、活用の幅は広いなと感じました。
以下のnotebookや、openai.ChatCompletion.createの中身を見たりして、もう少し理解を深めていこうと思います。
この記事が気に入ったらサポートをしてみませんか?