🤖
openai chat competion api function calling 概説
openai が chatGPT plugin に続いて function calling をサービスした。
ネーミングのせいで判りづらいが、この機能を「関数を実行する機能」だと思ってるとひどく混乱すると思われる。小生は混乱した。
ちなみに、apiの正式名称は "Chat Completion API" なので、"ChatGPT API"と呼ぶのは間違いである。
まあ伝わるけどね....
openai側の事情を忖度
- openai chat completion api としては、自然言語の処理そのものしかやるつもりがない。
- 例: 問い合わせにURLを書いてもそのサイトを読みに行くことはしない。できない。
- 例: 何かファイルを作っても何処かにアップロードしたりはしない。できない。
- 何か別のプログラムを動かしたいとすれば、openaiサービスの外で動かしてもらうしかない。
- chatGPT plugin の場合は、外部サーバに投げるという手段を採っている。 OpenAI Platform
じゃあ openai chat completion apiを使う場合はどうしたらいいのか?
一旦処理を中断して、クライアント側に処理を持ち帰り、必要な情報を付加してから処理を続ける。
ということにしたらしい。
function_calling の利用方法
オフィシャルのドキュメントもサンプルソースもあるにはある。英語でよければだが。
response = openai.ChatCompletion.create(...)
オフィシャルの前述のページではつぎのようなサンプルソースがあるが、これにfunctions関連が増える。
import openai
openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Who won the world series in 2020?"},
{"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."},
{"role": "user", "content": "Where was it played?"}
]
)
次の通りの名前付き引数を与える。
- "messages" 問い合わせ情報
- "functions" 関数テーブル
- "function_call" function_callを利用するか否か
ねんのためソースを確認してみたが、どうもこれそのままapiに渡しちゃってるようだ。
関数テーブル List[dict]
次のdictで関数1個の仕様を示す。
- "name" 関数名 英数字
- "description" 説明。日本語で可。おそらくGPTがこの仕様を読解してるのだと思われる。
- "parameters"
- "type" functionの戻り型
- "properties"
- パラメタ名: 型情報 "type", "enum", "description"
問い合わせ情報 message List[dict]
次のdictを含む配列。
- role: "user"
- content: 問い合わせ内容テキスト
初回はユーザからの質問だけが入ってるはず。
response : dict
- "id" 呼び出すたびに別の文字列が返ってくる。 GUIDっぽい。 課金情報と紐づいているのかもしれない
- "created" 事実上はサーバ時刻
- "usage" 処理トークン数が返ってくる。これの統計をとればおおまかな課金額がわかるはずだが、オープンソースでそれに留意してる例はあまり見ない
- choices[] 本件の目玉
response.choices[]
配列の1要素につき次の情報がある。
- ”finish_reason" 問い合わせに対する現在状態。
- openaiのサンプルソースですらこの値を参照してないが、本来はチェックするべきだろう。
- function calling利用時は "function_call"の文字列が返るので、後述するfunction callが必要。
- "stop" は正常終了
- openaiのサンプルソースですらこの値を参照してないが、本来はチェックするべきだろう。
- "message"
- "function_call"
- "name" 呼び出してほしい関数名
- create() の 関数テーブルの [].name に一致するはずである。
- サンプルソースですら決め打ちで関数を読んじゃってるが、本来は関数テーブルを参照して呼び出すべき。
- "arguments" 関数に渡してほしい引数のjson文字列
- JSONをデコードした後は、関数テーブルの parameters.properties.keys() に一致するキーを含んでいるはずである。
- "name" 呼び出してほしい関数名
- "function_call"
これもサンプルソース等では choices[0] を決め打ちで使ってるが、配列なので全て処理する必要があるはずだ。
function 呼び出し
- response.choice[].message.function_call.name に応じて処理を呼び出し、
- その結果を 問い合わせ情報に list.append() して、
- もう一度 openai.ChatCompletion.create を呼び出す。
オフィシャルのサンプルソースですら、2往復しか想定してないが、本来は毎回 choices[].finish_reason をチェックしつつ再リクエストを投げるべきだるろう。
Discussion