💌

Azure OpenAI Service の Assistants API を理解する

に公開
2024/03/13

はじめに

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 でいうずころの Agent や Semanic 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 Central、East US 2、Australia 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. [補足] Thread や Assistant の削陀

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