💼

Azure OpenAI Service の Assistants API を理解する

2024/02/14に公開

はじめに

OpenAI DevDay にて本家 OpenAI の β 版機能として発表された Assistants API が Azure OpenAI Service (AOAI) でも Assistants API (プレビュー) として利用可能になりました。そこで、自分自身の理解や言語化も兼ねて情報をまとめました。

なお、本記事は AOAI の基本的な部分をある程度理解できている開発者を想定して書かれています。

【追記】API の正式名称は Assistants API でしたので全般的に修正を行いました。

Assistants API

Assistants API とは何か

Assistants API は 開発者による独自のアシスタント (Microsoft 的な表現をすると Copilot) アプリケーションの開発を効率化することができる API です。以前から存在していた Chat Completions API はステートレスな API であるため、Copilot stack の "オーケストレーションレイヤー" の全てを開発者が気にしなければなりませんでした。具体的には以下のような処理です。

  • アシスタントと利用者の間のメッセージ履歴の管理
  • モデルの最大トークンに合わせたメッセージの切り捨て
  • 実行すべきツール (Code interpreter 等のビルトイン機能や Function calling で定義された外部 API) の推論および実行制御 (Reasoning and Acting; ReAct)

Assistants API はこうした処理を抽象化してくれます。これにより、開発者は以下のようなごく限られた情報を API に渡すだけでステートフルな処理を簡単に実装することができるようになりました。

  • アシスタントの名前
  • アシスタントへの指示 (アシスタントの定義や目的など。Chat completions API の system message のようなもの。)
  • アシスタントが使用可能なツールのリスト
  • アシスタントが使用するモデル (AOAI のデプロイを指定)

厳密には異なるかもしれませんが、Assistants API は OSS ライブラリである LangChain でいうところの AgentSemanic Kernel でいうところの Planner と近い立ち位置の OpenAI ネイティブ版機能と考えるとイメージがしやすいかもしれません。

イメージ図

参考

[補足] Reasoning and Acting (ReAct)

言語モデルにユーザーからのリクエストに応えるために必要なステップを推論させ (Reasoning)、与えられたツールを実行して (Acting) その結果をもとに回答を生成するプロンプティング手法は Reasoning and Acting (ReAct) と呼ばれています。詳細は以下のリンク先を参照してください。

参考

オブジェクト

Assistants API はオブジェクト指向です。Assistants API には下記のオブジェクトが存在しており、これらを Python や REST API を介して扱います。具体的な使い方に関しては後述します。

オブジェクト 説明
Assistant
(アシスタント)
Azure OpenAI モデルをツールと組み合わせて使うカスタム AI のオブジェクトです。instruction (Chat completions API の system message のようなもの)、model (アシスタントが使用する AOAI モデルのデプロイ)、tools (アシスタントが使用できるツールのリスト)、file_ids (アシスタントがに使用するためにアップロードされたファイル) などの構成情報を格納します。
Thread
(スレッド)
アシスタントとユーザーの間の会話セッションのオブジェクトです。スレッドはメッセージを格納し、スレッド長をモデルの最大トークンに合わせるために自動的にメッセージの切り捨てを行います。
Message
(メッセージ)
アシスタントまたはユーザーによって作成されたメッセージのオブジェクトです。メッセージにはテキスト、画像、その他のファイルを含めることができます。メッセージはスレッドにリストとして格納されます。
Run
(実行)
スレッド上でのアシスタントの呼び出しのオブジェクトです。アシスタントはその構成情報とスレッドのメッセージを使って、モデルとツールを呼び出してタスクを実行します。実行の一部として、アシスタントはスレッドにメッセージを追加します。
Run Step
(実行ステップ)
アシスタントが実行の一部として実行したステップの詳細なリストのオブジェクトです。アシスタントは実行中にツールを呼び出したりメッセージを作成したりします。実行ステップを調べるとアシスタントがどのように最終結果に到達したかを調べることができます。

参考

ツール

Assistants API にて開発者がアシスタントに与えることができるツールには大きく分けて 2 種類があります。

  1. AOAI によってホストされているツール
  2. 外部 API (ユーザーがホストしている独自 API など)

執筆時点で、単一のアシスタントに指定することができるツールの仕様上の最大数は 128 です。ただし、ツールの選択肢が増えるほどユーザーの意図と違うツールが選択される可能性が高まるため、闇雲にツールを追加するのではなく目的に応じた最低限のツールを指定した方が良いと思われます。

参考

1. AOAI によってホストされているツール

1.1. Code interpreter

Code interpreter はその名のとおり AOAI によってホストされたサンドボックス環境で Python コードを実行することができる機能です。アシスタントのツールとして Code interpreter を有効化すると、アシスタントは目的を達成するために実行できるコードが生成されるまで試行錯誤を繰り返し、結果を返します。

また、Code interpreter はアシスタントに対してアップロードされたファイルを扱うことができます。そのため、ユーザーによってアップロードされたデータファイルを分析してプロットさせるような使い方をすることもできます。

なお、Code interpreter がサポートされているモデル、API バージョン、扱えるファイルの拡張子には指定があります。詳細に関しては下記リンク先を参照してください。

参考

[補足] 1.2. Knowledge retrieval

本家 OpenAI で指定できるツールのうち Knowledge retrieval は 執筆時点で AOAI の Assistants API ではまだ coming soon とされていました。

Support for new features, including an improved knowledge retrieval tool, is coming soon.

この Knowledge retrieval はアシスタントにアップロードしたファイルの情報に基づいてユーザーへの質問に回答する Retrieval Augmented Generation (RAG) を行う機能です。AOAI には Azure AI Search をバックエンドで使用する On your data という独自機能が既に存在していますので、RAG を行いたい状況ではそちらから検証した方が良いかもしれません。

参考

2. 外部 API

2.1. Function calling

Function calling は ReAct の Reasoning の部分を行ってくれるツールです。具体的には、ツールで指定した外部 API のリストの中からどれを使うとユーザーの目的を達成できるかどうかの推論、選択、および外部 API に与える引数の抽出を行ってくれます。

ややこしいポイントとしては、Function calling は AOAI によってホストされている Code interpreter とは異なり、Assistants API は自分で外部 API の "実行" をすることができません。(どの外部 API を使うべきかという "選択" だけを行う) そのため、Run Steps における外部 API 実行のステップでは、Assistants API はアプリケーションが外部 API を実行して結果を送ってくれるまで待つ挙動をします。

イメージ図

また、もうひとつややこしいポイントとしては、執筆時点で Code interpreter と Function calling の両方に対応しているモデルバージョンが完全に一致していませんので、ツールに Code interpreter と Function calling の両方を指定したい場合は下図の赤線で囲ったモデルバージョンを使う必要があります。

参考

利用可能なリージョン

執筆時点で Assistants API は Sweden CentralEast US 2Australia East リージョンで利用可能です。ただし、前述のとおり使用したいツールによってモデルの対応状況が異なるため注意が必要です。

参考

料金

Assistants API の利用時には通常のモデル利用時の入出力トークンに応じた課金に加えて、Code interpreter の料金がセッション単位で加算されます。

Sweden Central リージョンの場合

なお、執筆時点では Assistants API 利用時のその他の課金要素 (e.g. アップロードしたファイルや各オブジェクトのストレージ費用) は見つかりませんでした。

参考

[補足] 制限

執筆時点では Assistants API に関連する制限として以下の 3 つが記載されていました。

制限名 制限値 コメント
Max files per Assistant/thread 20 例えば、アシスタントに 5 つのファイルをアップロードした場合、そのアシスタントが扱うスレッドでは残り 15 のファイルをアップロードできる
Max file size for Assistants 512 MB これもアシスタント + スレッドの合計?
Assistants token limit 2,000,000 token limit Assitants token が何の合計なのか?

参考

使い方

公式クイックスタートやサンプルコードをベースにして、Python による使い方を確認していきます。

参考

1. 事前準備

1.1. Azure OpenAI Service リソース作成

Assistants API が利用可能な任意のリージョンを選択して AOAI のリソースを作成します。なお、AOAI を使うためには利用申請が承認されている必要があります。

  • Sweden Central
  • East US 2
  • Australia East

参考

1.2. モデルデプロイ

クイックスタートの前提条件と同じ gpt-4、モデルバージョン 1106-Preview を選択してデプロイを行います。デプロイ名 (任意) は後ほど使用しますので控えておきます。

参考

1.3. Python 実行環境

以下の Python 実行環境を準備します。

  • Python 3.7.1 以降のバージョン
  • Python ライブラリ: openai (バージョン 1.x が必要)

参考

1.4. 環境変数の設定

AOAI のキーとエンドポイントを確認して Python 実行環境の環境変数に登録しておきます。

import os

os.environ["AZURE_OPENAI_ENDPOINT"] = "<your-aoai-endpoint>"
os.environ["AZURE_OPENAI_KEY"] = "<your-aoai-key>"

参考

2. Code interpreter 使いの数学家庭教師アシスタント

ここからは、ツールとして Code interpreter を使うアシスタントを実際に作成していきます。流れは以下のとおりです。

  1. AOAI に接続するクライアントインスタンスを作成する
  2. どのようなアシスタントかを定義した Assistant インスタンスを作成する
  3. ユーザーとアシスタント間のメッセージを保持する Thread インスタンスを作成する
  4. ユーザーからの問いかけの Message インスタンスを作成して Thread に追加する
  5. Thread を実行して Run インスタンスを作成する
  6. Assistants API は Thread の文脈に応じてツール (今回は Code interpreter) を利用しつつ回答の Message インスタンスを作成して Thread に追加する
  7. Run のステータスを確認して完了したら Thread を確認する
  8. ユーザーからの追加の問いかけを行う

2.1. AOAI クライアント作成

コード

import os
import time
import json
from openai import AzureOpenAI

client = AzureOpenAI(
    api_key=os.getenv("AZURE_OPENAI_KEY"),
    api_version="2024-02-15-preview", # 執筆時点ではこのバージョンのみ対応
    azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
)

2.2. Assistant 作成

コード

# アシスタントの作成
assistant_1 = client.beta.assistants.create(
    name="Sugaku-no-sensei", # アシスタント名
    instructions="あなたは数学の家庭教師です。コードを書いて実行し、数学の質問に答えてください。", # 指示 (アシスタントの定義や目的など)
    tools=[{"type": "code_interpreter"}] # アシスタントが使用できるツールのリスト (ここでは Code interpreter のみ)
    model="<your-model-deployment-name>" # モデルのデプロイ名
)

コード

# 確認
for k,v in dict(assistant_1).items():
    print(k + ": ", v)

出力例

id:  asst_7gZPjuHKgZJCBWW4tmNj5mhG
created_at:  1707886161
description:  None
file_ids:  []
instructions:  あなたは数学の家庭教師です。コードを書いて実行し、数学の質問に答えてください。
metadata:  {}
model:  gpt-4-1106
name:  Sugaku-no-sensei
object:  assistant
tools:  [ToolCodeInterpreter(type='code_interpreter')]

2.3. Thread 作成

コード

# スレッドの作成
thread_1 = client.beta.threads.create()

2.4. Message 追加

コード

# ユーザーからのメッセージをスレッドに追加
message_1_1 = client.beta.threads.messages.create(
    thread_id=thread_1.id, # 事前作成したスレッド
    role="user", # ユーザーからの問いかけ
    content="方程式 `3x + 11 = 14` を解きたいです。助けてくれますか?" # 問いかけの内容
)

2.5. Thread 実行

コード

# スレッドの実行
run_1_1 = client.beta.threads.runs.create(
  thread_id=thread_1.id,
  assistant_id=assistant_1.id
)

2.6. 結果待ち

コード

# アシスタントが回答のメッセージを返すまで待つ関数
def wait_for_assistant_response(thread_id, run_id):
    while True:
        time.sleep(5)
        # 実行ステータスの取得
        run = client.beta.threads.runs.retrieve(
            thread_id=thread_id,
            run_id=run_id
        )
        status = run.status
        if status in ["completed", "cancelled", "expired", "failed"]:
            print(status)
            break

# アシスタントが回答のメッセージを返すまで待つ
wait_for_assistant_response(thread_1.id, run_1_1.id)

出力例

completed

参考

2.7. 結果確認

コード

# スレッドのメッセージを確認する関数
def print_thread_messages(thread_id):
    msgs = client.beta.threads.messages.list(thread_id=thread_id)
    for m in msgs:
        assert m.content[0].type == "text"
        print({"role": m.role, "message": m.content[0].text.value})

# スレッドのメッセージを確認
print_thread_messages(thread_1.id)

出力例

{'role': 'assistant', 'message': '方程式 `3x + 11 = 14` の解は `x = 1` です。'}
{'role': 'user', 'message': '方程式 `3x + 11 = 14` を解きたいです。助けてくれますか?'}

※ メッセージは新しいものから順に格納される

[補足] 2.7.1. JSON フォーマットでの確認

コード

# スレッドのメッセージをJSONフォーマットで確認する関数
def print_thread_messages_with_json(thread_id):
    msgs = client.beta.threads.messages.list(thread_id=thread_id)
    print(msgs.model_dump_json(indent=2))

print_thread_messages_with_json(thread_1.id)

出力例

{
  "data": [
    {
      "id": "msg_VWLczojSp5dADposhMrr0lle",
      "assistant_id": "asst_7gZPjuHKgZJCBWW4tmNj5mhG",
      "content": [
        {
          "text": {
            "annotations": [],
            "value": "方程式 `3x + 11 = 14` の解は `x = 1` です。"
          },
          "type": "text"
        }
      ],
      "created_at": 1707886169,
      "file_ids": [],
      "metadata": {},
      "object": "thread.message",
      "role": "assistant",
      "run_id": "run_MiG1SF2IBFrSZ2plJtER6XQz",
      "thread_id": "thread_6uwifReRlbkEJcBJxtJWWsib"
    },
    {
      "id": "msg_gNY7n2DdMB2Id3MMRhLbagQg",
      "assistant_id": null,
      "content": [
        {
          "text": {
            "annotations": [],
            "value": "方程式 `3x + 11 = 14` を解きたいです。助けてくれますか?"
          },
          "type": "text"
        }
      ],
      "created_at": 1707886162,
      "file_ids": [],
      "metadata": {},
      "object": "thread.message",
      "role": "user",
      "run_id": null,
      "thread_id": "thread_6uwifReRlbkEJcBJxtJWWsib"
    }
  ],
  "object": "list",
  "first_id": "msg_VWLczojSp5dADposhMrr0lle",
  "last_id": "msg_gNY7n2DdMB2Id3MMRhLbagQg",
  "has_more": false
}

2.8. 追加質問

コード

# 追加の質問を行う
message_1_2 = client.beta.threads.messages.create(
    thread_id=thread_1.id, # 既存のスレッドにさらにメッセージを追加
    role="user",
    content="この問題を解くために生成したコードを教えてください。"
)

# スレッドの実行
run_1_2 = client.beta.threads.runs.create(
  thread_id=thread_1.id,
  assistant_id=assistant_1.id,
)

# アシスタントが回答のメッセージを返すまで待つ
wait_for_assistant_response(thread_1.id, run_1_2.id)

コード

# スレッドのメッセージを確認する
print_thread_messages(thread_1.id)

出力例

{'role': 'assistant', 'message': "もちろんです。以下が問題 `3x + 11 = 14` を解くために使用したコードです:\n\n```python\nfrom sympy import symbols, Eq, solve\n\n# Create the symbol\nx = symbols('x')\n\n# Define the equation\nequation = Eq(3*x + 11, 14)\n\n# Solve the equation for x\nsolution = solve(equation, x)\n```\n\nこのコードでは、まず sympy ライブラリを用いて変数 `x` をシンボルとして定義しました。次に、与えられた方程式 `3x + 11 = 14` を `Eq` 関数を用いて定義しました。最後に、`solve` 関数で方程式を解き、その解を `solution` に格納しました。そして、その結果として `x = 1` を得ました。"}
{'role': 'user', 'message': 'この問題を解くために生成したコードを教えてください。'}
{'role': 'assistant', 'message': '方程式 `3x + 11 = 14` の解は `x = 1` です。'}
{'role': 'user', 'message': '方程式 `3x + 11 = 14` を解きたいです。助けてくれますか?'}

※ メッセージは新しいものから順に格納される

上記出力のコード部分だけを抽出

from sympy import symbols, Eq, solve

# Create the symbol
x = symbols('x')

# Define the equation
equation = Eq(3*x + 11, 14)

# Solve the equation for x
solution = solve(equation, x)

3. Function calling 使いのお天気アシスタント

ここからは、ツールとして Function calling を使うアシスタントを作成していきます。流れは以下のとおりです。5 までは Code interpreter を使う場合とほぼ同じ流れです。

  1. AOAI に接続するクライアントインスタンスを作成する (省略)
  2. どのようなアシスタントかを定義した Assistant インスタンスを作成する
  3. ユーザーとアシスタント間のメッセージを保持する Thread インスタンスを作成する
  4. ユーザーからの問いかけの Message インスタンスを作成して Thread に追加する
  5. Thread を実行して Run インスタンスを作成する
  6. Assistants API は Thread の文脈に応じてツール (今回は Function calling により与えられた外部 API のリスト) を利用すべきかどうかを判定したあと待ち状態のステータス (requires_action) になる
  7. アプリケーション側で Assistants API が選択した外部 API を実際に実行して結果を取得して Assistants API に渡すと、Assistants API は処理を続行して回答の Message インスタンスを作成して Thread に追加する
  8. Run のステータスを確認して完了したら Thread (結果) を確認する

3.1. AOAI クライアント作成

省略

3.2. Assistant 作成

コード

assistant_2 = client.beta.assistants.create(
    name="Otenki-assistant", # アシスタント名
    instructions="あなたはお天気アシスタントです。与えられた機能を使って質問に答えてください。", # 指示 (アシスタントの定義や目的など)
    model="<your-model-deployment-name>", # モデルのデプロイ名
    # アシスタントが使用できるツールのリスト (ここではFunction callingで1つの外部APIを指定)
    tools=[{
        "type": "function",
        "function": {
            "name": "getCurrentWeather",
            "description": "Get the current weather in location", # 指定した地点の現在の天気を取得する
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {"type": "string", "description": "The prefecture and city e.g. 東京都品川区"}, # 都道府県と町
                    "unit": {"type": "string", "enum": ["c", "f"]} # 単位 (摂氏 or 華氏)
                },
                "required": ["location"] # 必須フィールド
            }
        }
    }]
)

コード

# 確認
for k,v in dict(assistant_2).items():
    print(k + ": ", v)

出力例

id:  asst_2PfpqeMhIMyFNOXoE3BCyueY
created_at:  1707886191
description:  None
file_ids:  []
instructions:  あなたはお天気アシスタントです。与えられた機能を使って質問に答えてください。
metadata:  {}
model:  gpt-4-1106
name:  Otenki-assistant
object:  assistant
tools:  [ToolFunction(function=FunctionDefinition(name='getCurrentWeather', description='Get the current weather in location', parameters={'type': 'object', 'properties': {'location': {'type': 'string', 'description': 'The prefecture and city e.g. 東京都品川区'}, 'unit': {'type': 'string', 'enum': ['c', 'f']}}, 'required': ['location']}), type='function')]

3.3. Thread 作成

コード

# スレッドの作成
thread_2 = client.beta.threads.create()

3.4. Message 追加

コード

# ユーザーからのリクエストをスレッドに追加
message_2_1 = client.beta.threads.messages.create(
    thread_id=thread_2.id,
    role="user",
    content="品川の天気を教えて"
)

コード

# スレッドのメッセージを確認
print_thread_messages(thread_2.id)

出力例

{'role': 'user', 'message': '品川の天気を教えて'}

3.5. Thread 実行

コード

# スレッドの実行
run_2 = client.beta.threads.runs.create(
  thread_id=thread_2.id,
  assistant_id=assistant_2.id,
)

3.6. Run ステータス確認

コード

# 実行ステータスを確認する関数
def check_run_status(thread_id, run_id):
    r = client.beta.threads.runs.retrieve(
        thread_id=thread_id,
        run_id=run_id
    )
    status = r.status
    print(status)

# 実行ステータスの確認
check_run_status(thread_2.id, run_2.id)

出力例

requires_action

コード

# 実行の詳細を確認
print(run_2.model_dump_json(indent=2))

出力例

{
  "id": "run_I2Pail7I9T4xt1jGuBnS2e1r",
  "assistant_id": "asst_2PfpqeMhIMyFNOXoE3BCyueY",
  "cancelled_at": null,
  "completed_at": null,
  "created_at": 1707886791,
  "expires_at": 1707887391,
  "failed_at": null,
  "file_ids": [],
  "instructions": "あなたはお天気アシスタントです。与えられた機能を使って質問に答えてください。",
  "last_error": null,
  "metadata": {},
  "model": "gpt-4-1106",
  "object": "thread.run",
  "required_action": {
    "submit_tool_outputs": {
      "tool_calls": [
        {
          "id": "call_KCrKrVmGMZ9g0Cm1pJYi8j4z",
          "function": {
            "arguments": "{\"location\":\"東京都品川区\"}",
            "name": "getCurrentWeather"
          },
          "type": "function"
        }
      ]
    },
    "type": "submit_tool_outputs"
  },
  "started_at": 1707886792,
  "status": "requires_action",
  "thread_id": "thread_duYvDhzNS6y7SF6y8O0EDaDC",
  "tools": [
    {
      "function": {
        "name": "getCurrentWeather",
        "description": "Get the current weather in location",
        "parameters": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "The prefecture and city e.g. 東京都品川区"
            },
            "unit": {
              "type": "string",
              "enum": [
                "c",
                "f"
              ]
            }
          },
          "required": [
            "location"
          ]
        }
      },
      "type": "function"
    }
  ],
  "usage": null
}

参考

3.7. 外部 API 実行結果の送信

コード

# 外部APIのダミー
def getCurrentWeather(location, unit="c"):
    # 実際はここで外部APIを呼び出して結果を取得する
    current_weather = "晴17℃"
    return current_weather

# Assistants APIに送り返す結果格納用のリスト
tool_outputs = []

# tool_callsごとに指定された外部APIを実行して結果を作成していく(今回は1呼び出しのみ)
for tc in run_2.required_action.submit_tool_outputs.tool_calls:
    if tc.function.name == "getCurrentWeather":
        # JSON形式の引数情報を辞書に変換
        arg = json.loads(tc.function.arguments)
        # 必須引数を取得
        location = arg["location"]
        # 外部APIを実行
        weather = getCurrentWeather(location)
        # 結果をtool_callごとに作成
        output =  {
            "tool_call_id": tc.id,
            "output": weather,
        }
        tool_outputs.append(output)
    elif tc.function.name == "foo":
        # Function callingで複数の外部APIを候補として提示した場合はこのようにして実行していく
        pass
    elif tc.function.name == "bar":
        # Function callingで複数の外部APIを候補として提示した場合はこのようにして実行していく
        pass

print(tool_outputs)

出力例

[{'tool_call_id': 'call_KCrKrVmGMZ9g0Cm1pJYi8j4z', 'output': '晴17℃'}]

コード

# Assistants APIに外部APIの出力結果を送信する
run_2 = client.beta.threads.runs.submit_tool_outputs(
  thread_id=thread_2.id,
  run_id=run_2.id,
  tool_outputs=tool_outputs # 結果格納リスト
)

参考

3.8. 結果確認

コード

# アシスタントが回答のメッセージを返すまで待つ
wait_for_assistant_response(thread_2.id, run_2.id)

出力例

completed

コード

# スレッドのメッセージを確認
print_thread_messages(thread_2.id)
{'role': 'assistant', 'message': '現在、東京都品川区の天気は晴れで、気温は17℃です。'}
{'role': 'user', 'message': '品川の天気を教えて'}

※ メッセージは新しいものから順に格納される

4. [補足] ThreadAssistant の削除

4.1. Thread の ID を指定して削除

コード

# スレッドの削除
client.beta.threads.delete("<thread-id>")

4.2. Assistant のリストアップ

コード

# すべてのアシスタントのリスト
for a in client.beta.assistants.list():
    print(a.id, a.name)

出力例

asst_2PfpqeMhIMyFNOXoE3BCyueY Otenki-assistant
asst_7gZPjuHKgZJCBWW4tmNj5mhG Sugaku-no-sensei

※ クライアントが接続している AOAI リソース内のアシスタントがリストアップされる

4.3. Assistant の ID を指定して削除

コード

# アシスタントの削除
client.beta.assistants.delete("<assistant-id>")

4.4. すべての Assistant の削除

コード

# すべてのアシスタントの削除
for a in client.beta.assistants.list():
    client.beta.assistants.delete(a.id)

※ AOAI リソースを共有するすべてのユーザーに影響を及ぼすため実行時には注意する

5. [補足] Azure OpenAI Studio からの操作

Azure OpenAI Studio からでも Assistants API の操作を行うことができます。Studio の Assistants (Preview) タブからアクセスできます。

Studio では、各操作を行った際にどのようなリクエストが投げられてるかを画面右側の Logs から確認することができます。そのため、操作とリクエストの対応関係を直感的に理解しやすくなっています。

また、Studio からも新規アシスタントの作成を行ったり、既存のアシスタントを開いたりすることができます。

ただし、このアシスタントのリストは AOAI のリソース単位になっていますので、Studio や Python のいずれかで削除を行った場合は、他方からも利用できなくなります。

参考

おわりに

Assistants API はこれまで存在していた Chat Completions API とは異なりステートフルかつオブジェクト指向なため、はじめのうちはややとっつきにくく感じました。しかし、慣れてくると程よく抽象化されたシンプルで使いやすい API であることに気づきました。

本家 OpenAI のドキュメントの中でも "まだ β 版なので機能追加に取り組んでる、フィードバックをくれ!" といったことが書かれているとおり、今後より洗練されていく可能性はありますが、このコンセプトの延長で生成 AI 関連のアプリケーション開発が楽になっていってくれるとありがたいと思いました。

以上です。🍵

Microsoft (有志)

Discussion