はじめに
callingといえばダーク・コーリング。覇王十代! nikkieです。
OpenAIから先日発表された「Function calling」を完全に理解しました!
※エンジニアミームの「完全に理解した」ですので、近日中に何も分からなくなるやつです
目次
それ(Function calling)は突然やってきた
GPT-4 and GPT-3.5 Turbo models in the API now support calling your custom functions, allowing the model to use tools you design for it. Also — reduced pricing & new model versions (including 16k context for 3.5 Turbo): https://t.co/dalfgEQ9k2
— OpenAI (@OpenAI) 2023年6月13日
6/14に目が覚めたらOpenAIからAPI利用者向けにメールが来ていて、「なにか重要そうなことを言っているが、さっぱりわからない。関数(function)って何?どういうこと?」となりました。
そうして完全に理解するための素振りというTODOが積まれたのです
ありがとう、先人の日本語で読めるアウトプット
Function callingという概念から分からなかったので、日本語で読める記事にいくつかあたりました。
はてなブックマークのテクノロジータブを中心に、話題になっているものを手当たり次第読んでいます。
- [OpenAI] Function callingで遊んでみたら本質が見えてきたのでまとめてみた | DevelopersIO
- 3段階の処理!
(AIが)質問に必要な関数を選び、引数を作成する
(プログラムが)関数を実行
(AIが)関数結果も入力に入れて質問に回答する
- 【ChatGPT】新機能「Function calling」が凄すぎた - Qiita
- OpenAI Function callingで複雑なタスクを簡単に実現 - Qiita
Function callingを使うと、特にフレームワークを用意しなくても非常に簡単に思考連鎖(chain of thought)が実現できるようになります。
- ChatGPT最新機能 Function CallingでQiitaへの理解が深いLINE Botを作る - Qiita
情報収集の中で、「GPTを呼び出すアプリケーションが持っている関数を、GPTがFunction callingで呼び出せる」らしいという仮説を持ちます。
OpenAIのドキュメントの例
公式ドキュメントにあたって手を動かし仮説を検証します。
https://platform.openai.com/docs/guides/gpt/function-calling
公式ドキュメントから案内されたクックブックも参考にしました。
ボストンの天気を日本語で聞く
今回の題材はN番煎じですが、ドキュメントの例を写経する中で「日本語でも動作するだろうな」と思ったので、日本語にしたバージョンを公開します。
- 1つ目のリクエスト
- 1つ目のレスポンスから関数呼び出しする実装は、ウォルラス2(代入式)を使って重複を減らしています
- ref: https://docs.python.org/ja/3/whatsnew/3.8.html#assignment-expressions
- 関数を呼び出すためにGPTが返した引数は、プログラム中で辞書として扱えるので、辞書アンパック演算子で関数にキーワード引数として渡せばいいんじゃないかと思います:
function_to_call(**function_args)
3
- OpenAIのChat completion API呼び出しでは
temperature=0
を指定(検証なので返り値がブレないように)4 - termcolorはcookbook5から6
- 経過が色付きで見えるの、裏で何が起きているかわかりやすい!
動作例
今回の動作環境です
- Python 3.10.9
- openai 0.27.8
- termcolor 2.3.0
環境変数OPENAI_API_KEY
を設定しています(openaiライブラリが見るので、Pythonコードでの設定は不要)
「こんにちは」にはFunction calling不要
毎回Function callingされるわけではないことの確認です。
最初のプロンプトを「ボストンの天気は?」から「こんにちは。あなたの名前は?」に変えてみます。
% python ja_docs_example.py こんにちは!私は名前を持っていません。私はAIアシスタントです。どのようにお手伝いできますか?
Chat Completion APIからは以下のJSONが返っています。
Function callingしていませんね。
{ "id": "chatcmpl-7SlBqmUItQTBDOQL18bwqZTT8f03z", "object": "chat.completion", "created": 1687088938, "model": "gpt-3.5-turbo-0613", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "\u3053\u3093\u306b\u3061\u306f\uff01\u79c1\u306f\u540d\u524d\u3092\u6301\u3063\u3066\u3044\u307e\u305b\u3093\u3002\u79c1\u306fAI\u30a2\u30b7\u30b9\u30bf\u30f3\u30c8\u3067\u3059\u3002\u3069\u306e\u3088\u3046\u306b\u304a\u624b\u4f1d\u3044\u3067\u304d\u307e\u3059\u304b\uff1f" }, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 113, "completion_tokens": 40, "total_tokens": 153 } }
GPTにボストンの天気を聞くとFunction callingして答えてくれる
「ボストンの天気は?」と聞いてみます。
% python ja_docs_example.py
ボストンの天気は晴れで、風も強いです。現在の気温は72°Fです。
Chat Completion APIの一度目の呼び出しでは、get_current_weather
を呼び出すというJSONが返っています。
ボストンはマサチューセッツ州の州都なので、"Boston, MA"
と例に沿った形に変換してget_current_weather
を呼び出しています!
{ "id": "chatcmpl-7SlE7IIr62tTCLxZPMVLno9dPUerK", "object": "chat.completion", "created": 1687089079, "model": "gpt-3.5-turbo-0613", "choices": [ { "index": 0, "message": { "role": "assistant", "content": null, "function_call": { "name": "get_current_weather", "arguments": "{\n \"location\": \"Boston, MA\"\n}" } }, "finish_reason": "function_call" } ], "usage": { "prompt_tokens": 112, "completion_tokens": 18, "total_tokens": 130 } }
スクリプト内にあるget_current_weather
の呼び出しでは(この関数はほぼモックなので)、以下のJSONが返ります。
{"location": "Boston, MA", "temperature": "72", "unit": "fahrenheit", "forecast": ["sunny", "windy"]}
これをmessagesに追加し、再度Chat Completion APIを呼び出します。
messagesには「ボストンの天気は?」「Function calling」「関数の呼び出し結果」の3つが入っています。
返ってくるのは以下のJSON。
{ "id": "chatcmpl-7SlE9QzevQWe2uF28FrwaHJppoT6W", "object": "chat.completion", "created": 1687089081, "model": "gpt-3.5-turbo-0613", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "\u30dc\u30b9\u30c8\u30f3\u306e\u5929\u6c17\u306f\u6674\u308c\u3067\u3001\u98a8\u3082\u5f37\u3044\u3067\u3059\u3002\u73fe\u5728\u306e\u6c17\u6e29\u306f72\u00b0F\u3067\u3059\u3002" }, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 75, "completion_tokens": 33, "total_tokens": 108 } }
こうしてGPTはFunction callingして、「ボストンの天気は?」というプロンプトに(生成によるハルシネーションなく)答えることができました!
termcolorで色を付けたことで、裏で何が起きているかとてもわかりやすかったです。
レスポンスの日本語はencodeされていてそのままでは読めない出力になっているのが宿題事項です。
終わりに
Function calling、完全に理解した!
get_current_weather
の例の関数はたいしたことなかったですが、cookbookではDB(SQLite)を使った例もあります!
また肝は(途中で引いた)「非常に簡単に思考連鎖(chain of thought)が実現できる」というところかなと思っています。
関数の実装は自由度が非常に高いので、DBに接続してもよし、LLMに質問してもよし、人に聞くなんてこともできちゃうかもしれません。
Function callingでPluginsに相当する機能の手元の関数を呼び出すこともできるはず!
引き続き手を動かして、このあたりの感触(仮説)を検証していくぞ〜
- cookbookではInfer this from the users location.(ユーザの場所から推論してください)と伝えていました。こんなこともできるのか!↩
-
:=
は「ウォルラス」って読むんです!『Effective Python 第2版』項目10をどうぞ↩ - PyCon JP 2022で「Pythonとアスタリスク」として話した事項の中の1つです↩
- Ngセンセの教え ↩
-
cookbookの実装ですが、
requests
を使っているのが謎です。openai.ChatCompletion.create
の方が楽なんじゃなかろうか↩ - coloramaのほかにtermcolorもあるのか〜 ↩