📌

[アシスタントの仕組み編]OpenAI GPTsのAPI版、AssistantsAPIの仕様を読んでいく

2023/12/23に公開

はじめに

前回、概要について見ていったので、引き続き次の章を見ていきたいと思います。

https://platform.openai.com/docs/assistants/how-it-works

前回の記事はこちら
https://zenn.dev/kat/articles/ee0d8a7679963a

構成

アシスタントの仕組みのページは、5つの構成に分かれています。

  • オブジェクト
  • アシスタントの作成
  • スレッドとメッセージの管理
  • 実行と実行ステップ
  • 制限

アシスタントの仕組み

アシスタント API は、開発者がさまざまなタスクを実行できる強力な AI アシスタントを構築できるように設計されています。

  1. アシスタントは、OpenAI のモデル[1]を呼び出して、個性や能力を調整するための具体的な指示を与えることができます。
    ここでいう個性や機能とは、アシスタントの口調であったり、専門用語の使用有無など表現方法を変えたり、次項のツールの使用有無や特定の分野へ特化させることなどを指していると思います。
  2. アシスタントは複数のツールに並行してアクセスできます。
    ツールは、コードインタープリターや知識検索(Knowleadge retrieval)などの OpenAI が提供しているツールや、ユーザーが独自に構築したツールがあります。
  3. アシスタントは永続的なスレッドにアクセスできます。スレッドはメッセージ履歴を保存し、会話がモデルのコンテキストの長さに対して長すぎる場合に切り捨てることで、AI アプリケーション開発を簡素化します。一度スレッドを作成すると、ユーザーが返信するときにメッセージをそれに追加するだけです。
  4. アシスタントは、作成の一部として、またはアシスタントとユーザー間のスレッドの一部として、いくつかの形式でファイルにアクセスできます。ツールを使用する場合、アシスタントはファイル (画像、スプレッドシートなど) を作成し、作成するメッセージ内で参照するファイルを引用することもできます。

オブジェクト

アシスタントを構成するオブジェクトのアーキテクチャ図

オブジェクト 内容
アシスタント OpenAI のモデルを使用し、ツールを呼び出す専用 AI
スレッド アシスタントとユーザーの間の会話セッション。
スレッドはメッセージを保存し、コンテンツをモデルのコンテキストに適合させるために切り捨てを自動的に処理します。
メッセージ アシスタントまたはユーザーによって作成されたメッセージ。
メッセージにはテキスト、画像、その他のファイルを含めることができます。
メッセージはスレッド内にリストとして保存されます。
実行 スレッド上のアシスタントの呼び出し。
アシスタントは、その構成とスレッドのメッセージを使用して、モデルとツールを呼び出してタスクを実行します。
実行の一部として、アシスタントはメッセージをスレッドに追加します。
実行ステップ アシスタントが実行の一部として実行したステップの詳細なリスト。
アシスタントは、実行中にツールを呼び出したり、メッセージを作成したりできます。
実行ステップを調べると、アシスタントが最終結果にどのように到達するかを内省することができます。

先にここのイメージ図見ておくと全体の構成が分かりやすかったですね。
アシスタントAIの振る舞いや知識などはアシスタントオブジェクトが持ち、
ユーザとのやり取りはスレッドオブジェクトとして管理され、1回1回の会話はメッセージオブジェクトとしてスレッドの中にリストとして持ちます。
ユーザのメッセージに応じて、アシスタントがツールを用いて処理を実行し、得られた結果をメッセージとして返します。

アシスタントの作成

アシスタントの作成を開始するには、model使用する を指定するだけです。ただし、アシスタントの動作をさらにカスタマイズできます。

アシスタント作成時に指定できるパラメータの例

  1. instructions:アシスタントの性格をガイドし、その目標を定義します。手順は、Chat Completions API のシステム メッセージに似ています。
  2. tools:アシスタントが使用するツール。最大 128 個のツールへのアクセスを許可します。code_interpreterretrievalなどの OpenAI がホストするツールへのアクセスを許可したり、function呼び出しを通じてサードパーティツールを呼び出すことができます。
  3. file_idscode_interpreterretrievalなどのツールにファイルへのアクセスを許可します。

アシスタント作成のコマンド例

curl "https://api.openai.com/v1/assistants" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "OpenAI-Beta: assistants=v1" \
  -d '{
    "instructions": "You are a personal math tutor. When asked a question, write and run Python code to answer the question.",
    "name": "Math Tutor",
    "tools": [{"type": "code_interpreter"}],
    "model": "gpt-4",
    "file_ids": ["file-BK7bzQj3FfZFXr7DbL6xJwfo"]
  }'

file_idsで指定するファイルは、ファイルアップロード用のAPIを使用して事前にアップロードしておく必要があります。

たとえば、.csvファイルに基づいてデータ視覚化を作成できるアシスタントを作成するには、まずファイルをアップロードします。

curl https://api.openai.com/v1/files \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -F purpose="assistants" \
  -F file="@mydata.csv"

レスポンス

{
  "object": "file",
  "id": "file-EHaW1HlXihGdQfdVqSwAAQsj",
  "purpose": "assistants",
  "filename": "mydata.csv",
  "bytes": 1652,
  "created_at": 1702707182,
  "status": "processed",
  "status_details": null
}

※アシスタントAPIが参照するファイルをアップロードする際には、purposeassistantsに設定する必要があります。

次に、アップロードしたファイルを使用してアシスタントを作成します。

curl https://api.openai.com/v1/assistants \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'OpenAI-Beta: assistants=v1' \
  -d '{
    "name": "Data visualizer",
    "description": "You are great at creating beautiful data visualizations. You analyze data present in .csv files, understand trends, and come up with data visualizations relevant to those trends. You also share a brief text summary of the trends observed.",
    "model": "gpt-4-1106-preview",
    "tools": [{"type": "code_interpreter"}],
    "file_ids": ["{ファイルID}"]
  }'

※1つ注意なのは、OpenAIのサイトのコードでは、コマンドの$OPENAI_API_KEYの指定部分がシングルコーテーションのため、実行エラーが発生します。
上記のようにダブルコーテーションに書き換えて実行してあげましょう。

レスポンス

{
  "id": "asst_TUkrMHYAlwoGEWOAMTU1G2Ez",
  "object": "assistant",
  "created_at": 1702707542,
  "name": "Data visualizer",
  "description": "You are great at creating beautiful data visualizations. You analyze data present in .csv files, understand trends, and come up with data visualizations relevant to those trends. You also share a brief text summary of the trends observed.",
  "model": "gpt-4-1106-preview",
  "instructions": null,
  "tools": [
    {
      "type": "code_interpreter"
    }
  ],
  "file_ids": [
    "file-EHaW1HlXihGdQfdVqSwAAQsj"
  ],
  "metadata": {}
}
  • アシスタントごとに最大 20 個のファイルを添付可能
  • 各ファイルの最大サイズは 512 MB
  • 組織版のアカウントの場合は、組織内でアップロードするすべてのファイルのサイズは 100 GB
    このストレージ制限は、ヘルプセンター(英語のみ)[2]を使用して増やせるようです。
  • 各ファイルに含めることができるトークンは 2,000,000 個
    添付ファイルがトークン制限を超えると、アシスタントまたはメッセージの作成は失敗します。

アップロードしたファイルの確認

アップロードしたファイルは以下のようにブラウザからも確認できます。

https://platform.openai.com/files

スレッドとメッセージの管理

スレッドとメッセージは、アシスタントとユーザー間の会話セッションを表します。
スレッドに保存できるメッセージの数に制限はありません。
メッセージのサイズがモデルのコンテキストウィンドウを超えると、スレッドはコンテキストウィンドウに収まるできるだけ多くのメッセージを含めようとし、最も古いメッセージを削除します。

次のように、メッセージの初期リストを使用してスレッドを作成できます。

curl https://api.openai.com/v1/threads \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'OpenAI-Beta: assistants=v1' \
  -d '{
    "messages": [
      {
          "role": "user",
          "content": "Create 3 data visualizations based on the trends in this file.",
          "file_ids": ["file-wB6RM6wHdA49HfS2DJ9fEyrH"]
      }
    ]
  }'

レスポンス

{
  "id": "thread_iWH6FKkQjKQSzfMNCbNm0D52",
  "object": "thread",
  "created_at": 1702802104,
  "metadata": {}
}
  • メッセージにはテキスト、画像、またはファイルを含めることができます。
  • ユーザーが作成したメッセージに画像ファイルを含めることはできないようです。
    将来的には追加する予定とのこと。
  • メッセージには、アシスタントと同じファイルサイズとトークン制限もあります。
    (ファイルサイズ制限:512 MB、トークン制限:2,000,000)

コンテキストウィンドウの管理

コンテキストウィンドウとは、簡単に言えばAPIが入力を受け付け可能な文章量です。
文章量はトークンと呼ばれる単位で計算されます。
言語モデル毎にトークンの上限(コンテキストウィンドウ)は決まっています。

アシスタントAPIは、コンテキストウィンドウを自動的に管理します。
スレッド内のメッセージのサイズがモデルのコンテキストウィンドウを超えると、古いメッセージから削除されていくようです。

今後の機能として以下を検討しているようです。

  • 選択したモデルを超えて入出力トークン数を制御できる機能
  • 以前のメッセージの概要を自動的に生成してコンテキストとして渡す機能。

メッセージの注釈(annotations)

アシスタント側が作成したメッセージには、注釈が含まれる場合があります。

注釈には 2 つのタイプがあります。

  1. ファイル内の引用:アシスタントが応答を生成するために使用する特定のファイル内の特定の引用への参照。検索ツール使用時に設定されます。
  2. ファイルパス:コードインタープリターによって生成されたファイルへの参照が含まれます。

メッセージオブジェクトに注釈が存在する場合、テキスト内に判読できないモデル生成の部分文字列が表示されますが、これを注釈に置き換える必要があります。
これらの文字列は、【13†source】 または sandbox:/mnt/data/file.csv のようになります。

実行と実行ステップ

スレッド内のユーザーから必要なコンテキストをすべて取得したら、選択したアシスタントを使用してスレッドを実行できます。

curl https://api.openai.com/v1/threads/{スレッドID}/runs \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'OpenAI-Beta: assistants=v1' \
  -d '{
    "assistant_id": "{アシスタントID}"
  }'

レスポンス

{
  "id": "run_XSUosxpahqxc4NdjWT447cj7",
  "object": "thread.run",
  "created_at": 1702833730,
  "assistant_id": "asst_TUkrMHYAlwoGEWOAMTU1G2Ez",
  "thread_id": "thread_iWH6FKkQjKQSzfMNCbNm0D52",
  "status": "queued",
  "started_at": null,
  "expires_at": 1702834330,
  "cancelled_at": null,
  "failed_at": null,
  "completed_at": null,
  "last_error": null,
  "model": "gpt-4-1106-preview",
  "instructions": null,
  "tools": [
    {
      "type": "code_interpreter"
    }
  ],
  "file_ids": [
    "file-EHaW1HlXihGdQfdVqSwAAQsj"
  ],
  "metadata": {}
}

デフォルトでは、Run はAssistant オブジェクトに定義されているモデルや指示を用いますが、
Runのパラメータに指定することで、元の設定を差し替えて実行することができます。
これはGPTsでは出来ない機能ですね。
言語モデル、指示、ツールを差し替えきできるようです。
ファイルについては差し替え不可なので、アシスタントを変更するAPIで変更します。

モデルと指示、ツールを差し替えて実行する例

curl https://api.openai.com/v1/threads/{スレッドID}/runs \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'OpenAI-Beta: assistants=v1' \
  -d '{
    "assistant_id": "{アシスタントID}",
    "model": "gpt-3.5-turbo-1106",
    "instructions": "New instructions that override the Assistant instructions",
    "tools": [{"type": "code_interpreter"}, {"type": "retrieval"}]
  }'

レスポンス

{
  "id": "run_kaId9LdA2U8UDRcSP5WRmdSU",
  "object": "thread.run",
  "created_at": 1703058073,
  "assistant_id": "asst_TUkrMHYAlwoGEWOAMTU1G2Ez",
  "thread_id": "thread_iWH6FKkQjKQSzfMNCbNm0D52",
  "status": "queued",
  "started_at": null,
  "expires_at": 1703058673,
  "cancelled_at": null,
  "failed_at": null,
  "completed_at": null,
  "last_error": null,
  "model": "gpt-3.5-turbo-1106",
  "instructions": "New instructions that override the Assistant instructions",
  "tools": [
    {
      "type": "code_interpreter"
    },
    {
      "type": "retrieval"
    }
  ],
  "file_ids": [
    "file-EHaW1HlXihGdQfdVqSwAAQsj"
  ],
  "metadata": {}
}

ライフサイクルの実行

実行オブジェクトは複数のステータスを持つことができます。

実行ライフサイクル ステータスの状態遷移

状態 意味
queued Runを最初に実行したときか、required_actionを完了時のステータス。
すぐにin_progressに移行します。
in_progress 実行中。アシスタントがモデルとツールを使用して実行ステップを実行します。実行ステップを調べることで、実行の進行状況を確認できます。
completed 実行が完了した状態。アシスタントがスレッドに追加したすべてのメッセージと、実行されたすべての実行ステップを表示できるようになっています。
スレッドにさらにユーザーメッセージを追加し、別の実行を作成して会話を続けることもできます。
requires_action 関数呼び出しを使用する場合、モデルが呼び出す関数とその引数が決まると、この状態になります。
実行を続行する前に、これらの関数を実行し、出力を送信する必要があります。※ここはよくわからない。
作成から約 10 分経っても出力されない場合、実行は期限切れ(expired)ステータスに移行します。
expired 関数呼び出しの出力が期限切れの場合。
実行に時間がかかりすぎて、 expires_atの時間を超えた場合、システムは実行を期限切れにします。
cancelling 実行をキャンセルしている最中。実行中(in_progress)に、実行のキャンセルを試みることができます。
キャンセルの試行が成功すると、実行のステータスは cancelledに移行します。
キャンセルは試みられますが、保証はされません。
cancelled 実行が正常にキャンセルされた状態。
failed 実行が失敗した状態。実行オブジェクト内のlast_errorを確認すると、失敗の理由がわかります。
失敗のタイムスタンプはfailed_atに記録されます。

アップデートのポーリング

実行のステータスを最新の状態に保つには、定期的にAPIでRunオブジェクトの状況を取得する必要があります。
近い将来、これを簡単にするためにストリーミングのサポートを追加する予定とのこと。

スレッドロック

Run がin_progress状態ではない場合、スレッドはロックされます。
スレッドがロック状態の時、以下の制限があります。

  • スレッドに新しいメッセージを追加不可。
  • スレッドに新しい実行を作成不可。

実行ステップ

実行ステップのライフサイクル

実行ステップのステータスは、実行のステータスと同じ意味を持ちます。

実行ステップオブジェクトのフィールドで重要な情報はstep_detailsにあります。
ステップの詳細には次の 2 種類があります。

  1. message_creation: この実行ステップは、アシスタントがスレッド上にメッセージを作成するときに作成されます。
  2. tool_calls: この実行ステップは、アシスタントがツールを呼び出したときに作成されます。これに関する詳細については、ツールのガイド[3]で説明されています。

データアクセスのガイダンス

APIで作成したアシスタント、スレッド、メッセージ、およびファイルのアクセスは、組織の範囲内に限定されています。
そのため、組織のAPIキーアクセス権を持つユーザーは、組織内のアシスタント、スレッド、メッセージ、およびファイルの読み書きが可能です。

次のようなデータアクセス制御を強く推奨しています。

  • 認可
    アシスタント、スレッド、メッセージ、およびファイルに対して読み取りまたは書き込みを実行する前に、エンドユーザーが読み取りまたは書き込みを行う権限を持っていることを確認しましょう。たとえば、エンドユーザーがアクセスできるオブジェクトIDをデータベースに保存し、APIでオブジェクトIDを取得する前に権限を有しているかを確認します。
  • APIキーへのアクセス制限
    組織内の誰がAPIキーを所有すべきかを慎重に検討し、定期的にチェックしましょう。
    APIキーを使用すると、メッセージやファイルなどの機密情報の読み取りと変更を含む幅広い操作が可能になってしまいます。
  • アカウントを分ける
    複数のアプリケーション間でデータを分離するには、アプリケーションごとに個別のアカウント/組織を作成することを検討しましょう。

制限事項

※見出しと内容が合っていない気がしますが、日本語訳のせいかもしれません。
内容的には今後機能追加していく旨と追加されるであろう機能について記載されていると思われます。

アシスタントAPIはベータ版なので、今後数週間から数か月以内に対処する予定の既知の制限がいくつかあります。

  • ストリーミング出力のサポート (メッセージと実行ステップを含む)。
  • ポーリングを必要とせずにオブジェクトのステータス更新を共有するための通知のサポート。
  • ツールとしての DALL・E またはブラウジングのサポート。
  • 画像を使用したユーザーメッセージ作成のサポート。

まとめ

個人的には、アシスタントAPIのオブジェクト構成を示す図や状態遷移の図は内部構造がわかりやすくてよかったです。
アシスタントAPIにアップロードするファイル制限の情報や、実行時にアシスタントの定義を上書き出来ることなど、有益な情報がありました。
引用されたファイルの情報がアノテーションとして置き換えしないといけないというのは実際に使ってみないとイマイチ感覚が掴めないので、後日試した結果を更新したいと思います。

脚注
  1. OpenAPIで使用できるモデル
    https://platform.openai.com/docs/models ↩︎

  2. https://help.openai.com/en/ ↩︎

  3. https://platform.openai.com/docs/assistants/tools ↩︎

Discussion