見出し画像

Google Colab で OpenAI API の Function Calling を試す

「Google Colab」で「OpenAI API」の「Assistant API」の「Function Calling」を試したので、まとめました。

前回


1. Function Calling

Assistant API」は、さまざまなタスクを実行できる強力な「AIアシスタント」を作成するためのAPIです。

「Assistant API」は現在、次の3つのツールをサポートしています。

・Code Interpreter : Pythonコードを作成して実行
・Retrieval : モデル外部からの知識を取得
・Function Calling : 関数のレスポンスを取得

今回は、「Function Calling」を使います。「Chat Completions API」と同様に、「Assistant API」は「Function Calling」をサポートしています。「Function Calling」は、アシスタントに関数定義を指定することで、呼び出す必要がある場合に、関数呼び出しの要求を返すことができます。関数呼び出しの要求時には「Run」は一時停止され、関数呼び出し結果を提供することで「Run」は続行されます。

2. セットアップ

Colabでのセットアップ手順は、次のとおりです。

(1) パッケージのインストール。

# パッケージのインストール
!pip install openai

(2) 環境変数の準備。
以下のコードの <OpenAI_APIキー> にはOpenAIのサイトで取得できるAPIキーを指定します。(有料)

import os
os.environ["OPENAI_API_KEY"] = "<OpenAI_APIキー>"

(3) クライアントの準備。
「クライアント」は「OpenAI API」にアクセスするインタフェースになります。

from openai import OpenAI

# クライアントの準備
client = OpenAI()

4. アシスタントの実行

アシスタントの実行手順は、次のとおりです。

(1) アシスタントの作成。
toolsに「function」と関数の定義を指定します。

# アシスタントの作成
assistant = client.beta.assistants.create(
    instructions="あなたはお天気ボットです。 提供されている関数を使用して質問に答えます。",
    model="gpt-4-1106-preview",
    tools=[{
        "type": "function",
        "function": {
            "name": "getCurrentTemperature",
            "description": "特定の場所の気温を取得",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {"type": "string", "description": "場所 (例:東京)"},
                    "unit": {"type": "string", "enum": ["c", "f"]}
                },
                "required": ["location"]
            }
        }
    }]
)

(2) スレッドの作成。
会話するためスレッドを作成します。

# スレッドの準備
thread = client.beta.threads.create()

(3) ユーザーメッセージの追加。

# ユーザーメッセージの追加
message = client.beta.threads.messages.create(
    thread_id=thread.id,
    role="user",
    content="群馬県の気温を教えてください。"
)

(4) スレッドのメッセージリストの確認。
ユーザーメッセージが1つ追加されています。

# スレッドのメッセージリストの確認
messages = client.beta.threads.messages.list(
    thread_id=thread.id,
    order="asc"
)
for message in messages:
    print(message.role, ":", message.content[0].text.value)
user : 群馬県の気温を教えてください。

(5) アシスタントにリクエスト。

# アシスタントにリクエスト
run = client.beta.threads.runs.create(
    thread_id=thread.id,
    assistant_id=assistant.id,
)

(6) アシスタントへのリクエストの実行状況の確認。
アシスタントは、関数をトリガーするユーザーメッセージを受け取ると、ステータス「require_action」に移行します。

# 実行状況の確認
run = client.beta.threads.runs.retrieve(
    thread_id=thread.id,
    run_id=run.id
)
print(run.status)
requires_action

require_action」になったら、10分以内に関数の出力を提出しないと期限切れ状態「expired」になります。

(7) require_actionのパラメータの取得。
今回は、ツールID、関数名、引数を取得します。

import json

# require_actionのパラメータの取得
tool_id = run.required_action.submit_tool_outputs.tool_calls[0].id
tool_function_name = run.required_action.submit_tool_outputs.tool_calls[0].function.name
tool_function_arguments = json.loads(run.required_action.submit_tool_outputs.tool_calls[0].function.arguments)

print("id:", tool_id)
print("name:", tool_function_name)
print("arguments:", tool_function_arguments)
id: call_6avyFMrvuLtLTr1BzYmVL8p7
name: getCurrentTemperature
arguments: {'location': '群馬県', 'unit': 'c'}

(8) パラメータをもとに関数を実行。
今回は簡易化のため、実処理を行わないダミー関数を使ってます。

# 特定の場所の気温を取得する関数 (ダミー)
def getCurrentTemperature(location, unit):
    print("location:", location)
    print("unit:", unit)
    return "22度"

# 特定の場所の気温を取得
tool_function_output = getCurrentTemperature(
    tool_function_arguments["location"], 
    tool_function_arguments["unit"]
)

(9) 関数の出力を提出。

# 関数の出力を提出
run = client.beta.threads.runs.submit_tool_outputs(
    thread_id=thread.id,
    run_id=run.id,
    tool_outputs=[
        {
            "tool_call_id": tool_id,
            "output": tool_function_output,
        }
    ]
)

(10) スレッドのメッセージリストの確認。
ステータス「completed」の場合は、メッセージリストにアシスタントメッセージが追加されています。

# スレッドのメッセージリストの確認
messages = client.beta.threads.messages.list(
    thread_id=thread.id,
    order="asc"
)
for message in messages:
    print(message.role, ":", message.content[0].text.value)
user : 群馬県の気温を教えてください。
assistant : 群馬県の気温は22度です。

5. Assistant Playground

作成した「アシスタント」は、「Assistant Playground」でも動作確認できます。関数のコールバックを入力するUIも提供しています。

【おまけ】 JSONモード と Function Calling の違い

「JSONモード」と「Function Calling」の違いは、「JSONモード」が JSON形式のみ検証しているのに対し、「Function Calling」のJSON形式を検証かつスキーマの準拠 (関数定義にあわせる) を強制しています。

次回



この記事が気に入ったらサポートをしてみませんか?