chatgptのFunction callingを試してみました (複数funcあり)
はじめまして
ジーニーのCTO 孟です。
今朝3時頃にopenaiの更新アナウンスが出されまして、gpt-3.5-turboの16k対応も大変注目すべきですが、
やっぱり一番気になるのがfunction calling機能ですね、どんなことができるか軽く試してみました。
※ function callingとは
ChatGPTの公式pluginとは違って、あらかじめ関数を用意してGPTに実行可否を判断させることが可能です。ただし、レスポンスの結果に基づいて手動で実行させる必要があります。まずはコードから:
import openai
openai.api_key = "KEYを入れてね"
DEFAULT_MODEL_NAME = "gpt-3.5-turbo-0613"
def get_value(input_num):
if not input_num:
return None
return int(input_num) * 2
def chat():
response = openai.ChatCompletion.create(
model=DEFAULT_MODEL_NAME,
messages=[{"role": "user", "content": "888のget_valueの値を教えてください"}],
functions=[
{
"name": "get_value",
"parameters": {
"type": "object",
"properties": {
"input_num": {
"type": "string",
},
},
"required": ["input_num"],
},
}
],
function_call="auto",
)
full_res = response["choices"][0]
if full_res["finish_reason"] == "function_call":
if full_res["message"]["function_call"]["name"] == "get_value":
call_data = full_res["message"]["function_call"]
func_name = call_data["name"]
args = eval(call_data["arguments"])
print(f"func_name: {func_name}, args: {args}")
func = globals()[func_name]
rst = func(**args)
print(f"rst: {rst}")
return response
chat()
実行している処理は単純ですが、
チャットの内容から、get_valueに渡せる値を見つけてもらって、
実行していいかどうかの判断もGPT任せにして、trueだったらpythonのリフレクションでコマンドを実行させただけのサンプルですが、
まぁこれは凄いです!
実質pluginの開発が作り放題になるだけではなく、
function callingを階層的に実装しておけば、データinput層, output(action層)の実現もできるようになるので、ほぼほぼGPTを通してやりたいことが可能にしてくれるようになると思います。
例えばslackと連携してchat経由で 「python開発経験が3年以上、DBA経験2年以上の開発エンジニアのJDを書いてください、その結果をコーポレートサイトの「採用情報」にも非公開の状態で投稿してください」
的なことをslack+gptだけで実現可能になります。
他のユースケースもたくさんあると思うので、しばらくその可能性を模索して行きたいと思います。
以上、
よろしくお願いします。
※ 2023.6.16追記
chatgpt function callingのマルチfunctionの呼び出し方のやりかたについて
import openai
openai.api_key = "キーを入れてね"
DEFAULT_MODEL_NAME = "gpt-3.5-turbo-0613"
def double_value(input_num):
if not input_num:
return None
return int(input_num) * 2
def three_value(input_num):
if not input_num:
return None
return int(input_num) * 3
def chat(msg):
response = openai.ChatCompletion.create(
model=DEFAULT_MODEL_NAME,
messages=[{"role": "user", "content": msg}],
functions=[
{
"name": "double_value",
"description": "input_numの値を2倍にして返す",
"parameters": {
"type": "object",
"properties": {
"input_num": {
"type": "string",
},
},
"required": ["input_num"],
},
},
{
"name": "three_value",
"description": "input_numの値を3倍にして返す",
"parameters": {
"type": "object",
"properties": {
"input_num": {
"type": "string",
},
},
"required": ["input_num"],
},
}
],
function_call="auto",
)
full_res = response["choices"][0]
if full_res["finish_reason"] == "function_call":
if full_res["message"]["function_call"]["name"]:
call_data = full_res["message"]["function_call"]
func_name = call_data["name"]
args = eval(call_data["arguments"])
print(f"func_name: {func_name}, args: {args}")
func = globals()[func_name]
rst = func(**args)
print(f"rst: {rst}")
return response
else:
return response
chat("100のダブル値を教えて")
chat("100の3倍にしたらいくつになる?")
functionをどのように決めて選んでるかまだはっきり分かってないが、
精度の検証恐らく必要な気がしたのと、
function名やdescriptionにどんなfunctionなのか、ある程度細かく書いたほうがいいかもしれません。
複数functionを1箇所で実現できるのがとても実用的で、
今後実行する前にhumanの承認プロセスを足したりするような工夫もしてみるのも良いと思います。
Discussion