OpenAI API の Assistant API のしくみ
以下の記事が面白かったので、かるくまとめました。
前回
1. Assistant API
「OpenAI API」の「Assistant API」は、さまざまなタスクを実行できる強力な「AIアシスタント」を作成するためのAPIです。
(1) アシスタントは、OpenAIのモデルを呼び出し、個性や能力を調整するための具体的な指示を与えることができる。
(2) アシスタントは複数のツールに並行してアクセスできる。「Code interpreter」「Knowledge retrieval」などOpenAIが提供するツールに加えて、「Function calling」を介してユーザーが提供するツールを利用できる。
(3) アシスタントは永続的なスレッドにアクセスできる。スレッドはメッセージ履歴を保存し、会話長がモデルのコンテキスト長より長すぎる場合に切り捨てることで、AIアプリケーション開発を簡素化。
(4) アシスタントは、いくつかの形式でファイルにアクセスできる。ツールを使用する場合、アシスタントはファイル (画像、スプレッドシートなど) を作成し、作成するメッセージ内で参照するファイルを引用することもできる。
2. オブジェクト
「Assistant API」を構成するオブジェクトは、次のとおりです。

2-1. Assistant
OpenAIの「モデル」を使用し「ツール」を呼び出す専用AIです。
2-2. Thread
アシスタントとユーザー間の会話セッションです。メッセージを保存し、会話長をモデルのコンテキスト長に適合させるため、自動的に切り捨て処理を実行します。
2-3. Message
アシスタントまたはユーザーによって作成されるメッセージです。「テキスト」「画像」「その他のファイル」を含めることができます。
2-4. Run
スレッド上でのアシスタントの呼び出しのことです。 アシスタントは、「アシスタント自身の設定」と「スレッドのメッセージ」を使用して、「モデル」と「ツール」を呼び出して、タスクを実行します。実行の処理の1つとして、アシスタントはスレッドにメッセージを追加します。
2-5. Run Step
アシスタントが実行したステップの詳細リストのことです。アシスタントは、実行中に「ツール」を呼び出したり、「メッセージ」を作成したりできます。「Run Step」を調べると、アシスタントが最終結果にどのように到達するかを内省することができます。
3. アシスタントの作成
アシスタントの作成に必須のパラメータは「model」のみです。他のオプションで、アシスタントをカスタマイズすることもできます。
・model : 使用するモデル
・instructions : アシスタントの性格と目標を定義
「Chat Completions API」のシステムメッセージに似ています
・tools : 最大128 個のツールへのアクセスを許可
・file_ids : ツールにファイルへのアクセス権を与える
ファイルは「File upload」エンドポイントでアップロードし、「purpose」に「assistants」が設定する必要があります
「.csv」をもとにデータを可視化するアシスタントを作成するには、はじめにファイルをアップロードします。
file = client.files.create(
file=open("speech.py", "rb"),
purpose='assistants'
)次に、アップロードしたファイルを使用してアシスタントを作成します。
assistant = client.beta.assistants.create(
name="Data visualizer",
description="あなたはデータを可視化するのが得意です。.csvファイルに存在するデータを分析し、傾向を理解し、それらの傾向に関連するデータの可視化を行います。また、観察された傾向の短いテキストの概要も共有します。",
model="gpt-4-1106-preview",
tools=[{"type": "code_interpreter"}],
file_ids=[file.id]
)アシスタントごとに最大20個のファイルを添付でき、各ファイルの最大サイズは 512MBです。 さらに、組織がアップロードする全ファイルの限界サイズは100GB です。ヘルプセンターで、この制限の増加をリクエストできます。
「AssistantFile」で、「Assistant」と「File」の間の関連付けを作成、削除、表示することができます。「AssistantFile」を削除しても、元のファイルは削除されず、「File」と「Assistant」の間の関連付けが削除されるだけです。ファイルを削除するには、「File delete」エンドポイントを使用します。
4. スレッドとメッセージの管理
4-1. スレッドとメッセージ
スレッドとメッセージは、アシスタントとユーザー間の会話セッションを表します。スレッドに保存できるメッセージの数に制限はありません。 会話長がモデルのコンテキストウィンドウ長を超えると、スレッドはメッセージを適切に切り詰めて適合させます。
次のように、メッセージの初期リストを使用して、スレッドを作成できます。
thread = client.beta.threads.create(
messages=[
{
"role": "user",
"content": "Create 3 data visualizations based on the trends in this file.",
"file_ids": [file.id]
}
]
)メッセージには「テキスト」「画像」「その他のファイル」を含めることができます。 現時点では、ユーザーが作成したメッセージに画像ファイルを含めることはできませんが、将来的にサポートを追加する予定です。
4-2. メッセージの注釈
アシスタントによって作成されたメッセージには、オブジェクトのコンテンツ (content) に注釈 (annotations) が含まれる場合があります。
注釈には、次の2つのタイプがあります。
・file_quote : ファイルの引用は、Retrievalによって作成される。回答を生成するために使用した特定のファイル内の特定の引用への参照が含まれる。
・file_path : ファイルパスの注釈は、Code Interpreterによって作成される。ツールによって生成されたファイルへの参照が含まれる。
メッセージに注釈が存在する場合、テキスト内に判読できないモデル生成の部分文字列 (【13†source】、Sandbox:/mnt/data/file.csv など) が表示されるため、これを注釈に置き換える必要があります。
これらの文字列を注釈に置き換えるPythonコードの例を次に示します。
# メッセージの取得
message = client.beta.threads.messages.retrieve(
thread_id="...",
message_id="..."
)
# メッセージのannotationsの抽出
message_content = message.content[0].text
annotations = message_content.annotations
citations = []
# 注釈の追加
for index, annotation in enumerate(annotations):
message_content.value = message_content.value.replace(annotation.text, f' [{index}]')
if (file_citation := getattr(annotation, 'file_citation', None)):
cited_file = client.files.retrieve(file_citation.file_id)
citations.append(f'[{index}] {file_citation.quote} from {cited_file.filename}')
elif (file_path := getattr(annotation, 'file_path', None)):
cited_file = client.files.retrieve(file_path.file_id)
citations.append(f'[{index}] Click <here> to download {cited_file.filename}')
# 注: 簡潔にするため、ファイルのダウンロードは上記では実装していません
# ユーザーに表示する前にメッセージの末尾に脚注を追加
message_content.value += '\n' + '\n'.join(citations)5. RunとRun Step
5-1. Run
スレッドのメッセージリストをもとに、選択したアシスタントに応答をリクエストできます。
run = client.beta.threads.runs.create(
thread_id=thread.id,
assistant_id=assistant.id
)デフォルトでは、「Run」は「Assistant」で指定されたモデルとツール構成を使用しますが、「Run」作成時にこれらをオーバーライドすることもできます。
run = client.beta.threads.runs.create(
thread_id=thread.id,
assistant_id=assistant.id,
model="gpt-4-1106-preview",
instructions="additional instructions",
tools=[{"type": "code_interpreter"}, {"type": "retrieval"}]
)「file_id」はオーバーライドできません。これを行うには、「modify Assistant」エンドポイントを使用する必要があります。
5-2. Run のステータス
「Run」のステータスは、次のとおりです。

・queued : Run作成時、またはrequired_actionの完了時に queue に移行。多くの場合すぐに in_progress に移行。
・in_progress : 進行中。アシスタントはモデルとツールでステップを実行中。「Run step」で進行状況を確認できる。
・completed : 完了。アシスタントがスレッドに追加した全メッセージと、実行された全ステップを確認できる。さらにスレッドにユーザー メッセージを追加し、別の「Run」を作成して会話を続けることもできる。
・requires_action : 「Function Calling」を使用時に、モデルによって呼び出す関数の名前と引数が決定された時、required_action 移行。次に「Run」を続行する前に、これらの関数を実行し、出力を送信する必要がある。 expires_atが経過する (作成から約 10 分) 前に出力が提供されない場合、expired に移行。
・expired : 「Run」または「Function Calling」がexpires_at前に送信されず、期限切れになった場合に expired に移行。
・cancelling : キャンセル中。「Cancel Run」エンドポイントで、進行中の「Run」のキャンセルを試みた時、 cancelling に移行。キャンセル成功すると、cancelled に移行。
・cancelled : キャンセル完了。
・failed : 失敗。失敗の原因は last_error 、タイムスタンプは failed_at で確認できる。
5-3. 最新ステータスのポーリング
「Run」の最新ステータスを保つには、定期的に「Run」を取得する必要があります。オブジェクトを取得するたびに「Run」のステータスを確認して、アプリケーションが次に何を行うべきかを判断できます。近い将来、これを簡単にするためにストリーミングのサポートを追加する予定です。
5-4. スレッドのロック
「Run」が進行中で、終了状態ではない場合、スレッドはロックされます。具体的には、 新しいメッセージをスレッドに追加することができず、スレッド上に新しい「Run」を作成することもできません。
5-5. Run Step のステータス

「Run Step」のステータスは、「Run」のステータスと同じ意味を持ちます。
「Run Step」の興味深い詳細のほとんどは、「step_details」にあります。 「step_details」には次の2 種類があります。
・message_creation : この「Run Step」は、アシスタントがスレッド上にメッセージを作成するときに作成される。
・tool_calls : この「Run Step」は、アシスタントがツールを呼び出すときに作成される。
6. 制限事項
「Assistant API」のBeta版では、今後数週間から数か月以内に対処する予定の既知の制限がいくつかあります。変更の際には、このページに変更ログを公開されます。
・ストリーミング出力のサポート (「Message」「Run step」を含む)。
・ポーリングなしにオブジェクトのステータス更新を共有するための通知のサポート。
・ツールとしての「DALL・E」のサポート。
・画像を使用したユーザーメッセージ作成のサポート。
