ブルームテクノロジー

テクノロジー

【Assistants API】の実装方法について解説

【Assistants API】の実装方法について解説

Assistants APIとは

OpenAIでできるさまざまな機能を統合的に利用できるようにしたAPIです。

APIを使用して独自のアプリケーション内でAIアシスタントを構築できます。

OpenAIの類似サービスとの比較

※2024年1月時点の情報です

Chat Completions APIとの比較

Chat Completions API」 は 「Assistants API」が使えるようになる以前から存在していたAPIです。

Assistants API」は用意したファイルから事前知識を与えるKnowledge Retrievalという機能を使用することができますが、「Chat Completions API」ではできません。

また、「Chat Completions API」では連続した会話をするためにデータベース等に過去の会話の記録を残す必要がありましたが、「Assistants API」はスレッド形式で過去のやり取りを残せるため、その必要がなくなります。
ただし、スレッド内の全メッセージをプロンプトとして送信する仕様のため、プロンプトが膨大になり金額が膨れ上がってしまうことに注意してください。(毎回スレッドを作り直せばかかりません)

GPTsとの比較

※ GPTsはChatGPT Plusでのみ使用できるサービスです

GPTs」はファイルをアップロードできるという点では共通していますが、「GPTs」はOpenAIのWebサイトからのみ使用できます。
また、「Assistants API」とは異なり、「GPTs」はGPT Storeから販売することができます。

実装方法

※ Beta版のため、将来変更される可能性があります

Assistants、Threads、Messages、RUNs の4つのAPIを使ってAIアシスタントを実装し会話します。

ざっくり言えば、それぞれ

  • Assistants:カスタマイズしたチャットボット本体
  • Threads:やり取りする場所、LINEでいうところのトークルーム
  • Messages:メッセージの内容(テキストだけでなく画像ファイルなどを送ることもできる)
  • RUNs:Messageは作成しただけではチャットボットに送られないので実行(送信)する

の機能を持ちます。

環境構築・初期設定

Google Colaboratryでの実行を想定しております。

OpenAIのライブラリインストール

!pip install openai==1.8.0

インポートとOpenAIの初期設定

import os
import time

from openai import OpenAI

os.environ['OPENAI_API_KEY'] = 'OpenAIのAPIキー'
client = OpenAI()

ファイルアップロード

OpenAIにファイルをアップロードします。

Colab内(今回の場合は`/content/kotowaza.txt`)にファイルを配置しておいてください。

# ファイルアップロード
file = client.files.create(
  file=open("/content/kotowaza.txt", "rb"),
  purpose='assistants'
)

Assistant作成

# Assistant作成
assistant = client.beta.assistants.create(
  name="ことわざ大魔神",
  instructions="あなたは日本のことわざを知りつくしている人です。Knowledgeのファイルを使用して質問に答えます。",
  model="gpt-4-1106-preview",
  tools=[{"type": "retrieval"}],
  file_ids=[file.id]
)

各引数の解説

name: Assistantの名前

instructions: Assistantに行わせたい役割やルール

model: 元にするモデル

tools: 連携したいツール(以下参照)

file_ids: アップロードしたファイルのid

toolsで指定できるツール

code_interpreter

内部でpythonコードを作成し実行する
実際にPythonコードを試すので計算系の質問に強くなる
また、pythonで実行した結果(画像やグラフ)を返すことができるようになる
1セッションにつき$0.03(セッションは1時間で切れるため1時間内であれば1セッションとしてみなす)

retrieval

ファイルをアップロードすることでそのファイルの内容を読み取れる機能
ファイルの容量に比例して料金が発生し、1日あたり$0.2/GB

function

自作した関数と連携して人間の言葉でその関数を実行できるようになる
関数の中でGoogleなどの外部のAPIを呼び出せば外部のAPIと連携することも可能

ThreadとMessage作成

# Thread作成
thread = client.beta.threads.create()

# Thread内にMessageを作成し追加
message = client.beta.threads.messages.create(
  thread_id=thread.id,
  role="user",
  content="「お」から始まることわざを教えて下さい"
)

## Thread作成と同時にMessageを作成して追加することもできます
# thread = client.beta.threads.create(
#   messages=[
#     {
#       "role": "user",
#       "content": "「お」から始まることわざを教えて下さい"
#     }
#   ]
# )

実行

# スレッドを指定し実行
run = client.beta.threads.runs.create(
  thread_id=thread.id,
  assistant_id=assistant.id,
)

# 実行が完了するまで待つ
while True:
    # 実行状態の取得
    run = client.beta.threads.runs.retrieve(thread_id=thread.id, run_id=run.id)
    print("run.status:", run.status)

    # completedになればループを抜ける
    if run.status == 'completed':
        break

    time.sleep(5)

結果受け取り

# 結果受け取り
messages = client.beta.threads.messages.list(thread.id)
print(messages)

以下は出力結果を整形したものです。

SyncCursorPage[ThreadMessage](
    data=[
        ThreadMessage(
            id='msg_1JMGdLoDYpCOjpTtq8SrjA1o',
            assistant_id='asst_XOiL8dw2kd7Gc6dvkDHyq3eG',
            content=[
                MessageContentText(
                    text=Text(
                        annotations=[
                            TextAnnotationFileCitation(
                                end_index=272,
                                file_citation=TextAnnotationFileCitationFileCitation(
                                    file_id='file-oz8fUl9g19WR3EcnLIj5zAYy',
                                    quote='老いては子に従え\r\n負うた子に教えられて浅瀬を渡る\r\n鸚鵡よく言えども飛鳥を離れず\r\n大男総身に知恵が回りかね\r\n岡目八目\r\n落ち武者は薄の穂にも怖ず\r\n同じ穴の狢\r\n鬼に金棒\r\n鬼の居ぬ間の洗濯\r\n鬼の目にも涙\r\n帯に短く襷に長し\r\n溺れる者は藁をも掴む\r\n思い立ったが吉日\r\n親の意見と茄子の花は千に一つも無駄はない\r\n親の意見と冷や酒は後で効く\r\n親は無くとも子は育つ\r\n女は下げて育てよ\r\n女は乱の基\r\n陰陽師身の上知らず'
                                ),
                                start_index=262,
                                text='【9†source】',
                                type='file_citation'
                            )
                        ],
                        value='「お」から始まる日本のことわざには以下があります:\n\n- 老いては子に従え\n- 負うた子に教えられて浅瀬を渡る\n- 鸚鵡よく言えども飛鳥を離れず\n- 大男総身に知恵が回りかね\n- 岡目八目\n- 落ち武者は薄の穂にも怖ず\n- 同じ穴の狢\n- 鬼に金棒\n- 鬼の居ぬ間の洗濯\n- 鬼の目にも涙\n- 帯に短く襷に長し\n- 溺れる者は藁をも掴む\n- 思い立ったが吉日\n- 親の意見と茄子の花は千に一つも無駄はない\n- 親の意見と冷や酒は後で効く\n- 親は無くとも子は育つ\n- 女は下げて育てよ\n- 女は乱の基\n- 陰陽師身の上知らず【9†source】。'
                    ),
                    type='text'
                )
            ],
            created_at=1705655777,
            file_ids=[],
            metadata={},
            object='thread.message',
            role='assistant',
            run_id='run_0l6C7bFI6AN94WnAZCR0j18l',
            thread_id='thread_ASNMsHow7uoRpKfNK16QXLCN'
        ),
        ThreadMessage(
            id='msg_ZHC5Z2xfcOkuqHVMmKEBpfHZ',
            assistant_id=None,
            content=[
                MessageContentText(
                    text=Text(
                        annotations=[],
                        value='「お」から始まることわざを教えて下さい'
                    ),
                    type='text'
                )
            ],
            created_at=1705655766,
            file_ids=[],
            metadata={},
            object='thread.message',
            role='user',
            run_id=None,
            thread_id='thread_ASNMsHow7uoRpKfNK16QXLCN'
        )
    ],
    object='list',
    first_id='msg_1JMGdLoDYpCOjpTtq8SrjA1o',
    last_id='msg_ZHC5Z2xfcOkuqHVMmKEBpfHZ',
    has_more=False
)

チャットボットからの返信のテキストだけを取得したいときはmessages.data[0].content[0].text.valueで取得できます。

チャットボットからの返信が画像ファイルであったり、引用したファイルの情報を使用したい場合は別の処理が必要になってきますが、長くなってしまうため割愛させていただきます。

作成したものを削除

client.beta.threads.delete(thread.id)  # Thread削除
client.beta.assistants.delete(assistant.id)  # Assistant削除
client.files.delete(file.id)  # アップロードしたファイル削除

まとめ

今回はOpen AIのAssistants APIについて解説しました。
Chat Completions APIではできなかったファイルの読み込みや、画像・グラフの生成ができるようになり、便利になったなと感じます。

GPT関連はまだまだ進歩していくことが予想できますので、引き続き新しい技術を監視していきます。