Azure OpenAI Assistants (プレビュー) の概要

Azure OpenAI Assistants (プレビュー) を使うと、カスタム命令でニーズに合うように調整され、コード インタープリターやカスタム関数などの高度なツールによって強化された AI アシスタントを作成できます。 この記事では、アシスタント API の使用を開始するための詳細なチュートリアルが用意されています。

Note

Azure OpenAI では、Assistants V2 はまだサポートされていません。 V2 サポートが利用可能になるまで、OpenAI Python ライブラリの v1.20.0 リリースを使用してください。

アシスタントのサポート

リージョンとモデルのサポート

モデルのページには、アシスタントが現在サポートされているリージョンとモデルに関する最新情報が含まれています。

API バージョン

  • 2024-02-15-preview

サポートされているファイルの種類

ファイル形式 MIME の種類 コード インタープリター
c. text/x-c
.cpp text/x-c++
.csv application/csv
.docx application/vnd.openxmlformats-officedocument.wordprocessingml.document
.html text/html
.java text/x-java
.json application/json
.md text/markdown
.pdf application/pdf
.php text/x-php
.pptx application/vnd.openxmlformats-officedocument.presentationml.presentation
.py text/x-python
.py text/x-script.python
.rb text/x-ruby
.tex text/x-tex
.txt text/plain
.css text/css
.jpeg image/jpeg
.jpg image/jpeg
.js text/javascript
.gif image/gif
.png image/png
.tar application/x-tar
.ts application/typescript
.xlsx application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
.xml application/xml または "text/xml"
.zip application/zip

ツール

個々のアシスタントは、code interpreter を含む最大 128 個のツールにアクセスできますが、関数を使って独自のカスタム ツールを定義することもできます。

Files

ファイルは、Studio 経由で、またはプログラムを使ってアップロードできます。 file_ids パラメーターは、code_interpreter などのツールにファイルへのアクセスを許可するために必要です。 ファイル アップロード エンドポイントを使う場合、アシスタント API で使うには、purpose をアシスタントに設定する必要があります。

アシスタントのプレイグラウンド

アシスタント プレイグラウンドの詳細については、クイックスタート ガイドに関する記事で説明します。 これにより、アシスタントの機能をテストするためのコードなしの環境が提供されます。

アシスタントのコンポーネント

コンポーネント 説明
アシスタント Azure OpenAI モデルをツールと組み合わせて使うカスタム AI。
スレッド アシスタントとユーザーの間の会話セッション。 スレッドはメッセージを格納し、コンテンツをモデルのコンテキストに合わせるために切り捨てを自動的に処理します。
メッセージ アシスタントまたはユーザーによって作成されたメッセージ。 メッセージにはテキスト、画像、その他のファイルを含めることができます。 メッセージはスレッド上にリストとして格納されます。
実行 スレッドの内容に基づいて実行を開始するアシスタントのアクティブ化。 アシスタントは、その構成とスレッドのメッセージを使って、モデルとツールを呼び出してタスクを実行します。 実行の一部として、アシスタントはスレッドにメッセージを追加します。
実行ステップ アシスタントが実行の一部として実行したステップの詳細なリスト。 アシスタントは、実行中にツールを呼び出したり、メッセージを作成したりできます。 実行ステップを調べると、アシスタントが最終結果にどのように到達するかを理解できます。

最初のアシスタントを設定する

アシスタントを作成する

この例では、code_interpreter ツールの機能を使って視覚化を生成するコードを記述するアシスタントを作成します。 次の例は、Jupyter Notebooks のような環境で順番に実行することを目的としています。

import os
import json
from openai import AzureOpenAI
    
client = AzureOpenAI(
    api_key=os.getenv("AZURE_OPENAI_API_KEY"),  
    api_version="2024-02-15-preview",
    azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
    )

# Create an assistant
assistant = client.beta.assistants.create(
    name="Data Visualization",
    instructions=f"You are a helpful AI assistant who makes interesting visualizations based on data." 
    f"You have access to a sandboxed environment for writing and testing code."
    f"When you are asked to create a visualization you should follow these steps:"
    f"1. Write the code."
    f"2. Anytime you write new code display a preview of the code to show your work."
    f"3. Run the code to confirm that it runs."
    f"4. If the code is successful display the visualization."
    f"5. If the code is unsuccessful display the error message and try to revise the code and rerun going through the steps from above again.",
    tools=[{"type": "code_interpreter"}],
    model="gpt-4-1106-preview" #You must replace this value with the deployment name for your model.
)

上記の構成には、注意する必要のある詳細がいくつかあります。

  • tools=[{"type": "code_interpreter"}], で、このアシスタントがコード インタープリターにアクセスできるようにしています。 これにより、モデルはサンドボックス化された python 環境にアクセスして実行し、ユーザーの質問に対する応答の作成に役立つコードを実行できるようになります。
  • この手順では、モデルがコードを実行できることを再認識させられます。 場合によっては、特定のクエリを解決するためにモデルを適切なツールに導くための支援が必要になります。 特定のライブラリを使って、コード インタープリターの一部である特定の応答を生成する必要があることがわかっている場合は、"Matplotlib を使って x を実行する" などと言うことで、ガイダンスを提供するのに役立ちます。
  • これは Azure OpenAI であるため、model= に入力する値はデプロイ名と一致する必要があります。 慣例により、このドキュメントでは、特定の例をテストするときにどのモデルが使われたかを示すため、偶然モデル名と一致するデプロイ名を使うことがありますが、環境によってはデプロイ名が異なる場合があり、それはコードに入力する必要がある名前です。

次に、作成したばかりのアシスタントの内容を出力して、作成が成功したことを確認します。

print(assistant.model_dump_json(indent=2))
{
  "id": "asst_7AZSrv5I3XzjUqWS40X5UgRr",
  "created_at": 1705972454,
  "description": null,
  "file_ids": [],
  "instructions": "You are a helpful AI assistant who makes interesting visualizations based on data.You have access to a sandboxed environment for writing and testing code.When you are asked to create a visualization you should follow these steps:1. Write the code.2. Anytime you write new code display a preview of the code to show your work.3. Run the code to confirm that it runs.4. If the code is successful display the visualization.5. If the code is unsuccessful display the error message and try to revise the code and rerun going through the steps from above again.",
  "metadata": {},
  "model": "gpt-4-1106-preview",
  "name": "Data Visualization",
  "object": "assistant",
  "tools": [
    {
      "type": "code_interpreter"
    }
  ]
}

スレッドを作成する

ここで、スレッドを作成してみます。

# Create a thread
thread = client.beta.threads.create()
print(thread)
Thread(id='thread_6bunpoBRZwNhovwzYo7fhNVd', created_at=1705972465, metadata={}, object='thread')

スレッドは基本的に、アシスタントとユーザーの間の会話セッションの記録です。 これは、一般的なチャット入力候補 API 呼び出しのメッセージ配列/リストに似ています。 主な違いの 1 つは、チャット入力候補メッセージの配列とは異なり、モデルのコンテキスト長を下回っていることを確認するために各呼び出しでトークンを追跡する必要がないことです。 スレッドはこの管理の詳細を要約し、会話を継続できるようにするために必要に応じてスレッド履歴を圧縮します。 最新のモデルを使うと、スレッドの機能が強化されて、より大きな会話でこれが達成されます。そこでは、コンテキストの長さが長くなり、最新の機能もサポートされています。

次に、スレッドに追加する最初のユーザーの質問を作成します。

# Add a user question to the thread
message = client.beta.threads.messages.create(
    thread_id=thread.id,
    role="user",
    content="Create a visualization of a sinewave"
)

スレッド メッセージを一覧表示する

thread_messages = client.beta.threads.messages.list(thread.id)
print(thread_messages.model_dump_json(indent=2))
{
  "data": [
    {
      "id": "msg_JnkmWPo805Ft8NQ0gZF6vA2W",
      "assistant_id": null,
      "content": [
        {
          "text": {
            "annotations": [],
            "value": "Create a visualization of a sinewave"
          },
          "type": "text"
        }
      ],
      "created_at": 1705972476,
      "file_ids": [],
      "metadata": {},
      "object": "thread.message",
      "role": "user",
      "run_id": null,
      "thread_id": "thread_6bunpoBRZwNhovwzYo7fhNVd"
    }
  ],
  "object": "list",
  "first_id": "msg_JnkmWPo805Ft8NQ0gZF6vA2W",
  "last_id": "msg_JnkmWPo805Ft8NQ0gZF6vA2W",
  "has_more": false
}

スレッドを実行する

run = client.beta.threads.runs.create(
  thread_id=thread.id,
  assistant_id=assistant.id,
  #instructions="New instructions" #You can optionally provide new instructions but these will override the default instructions
)

ここで instructions パラメーターを渡すこともできますが、これによりアシスタントに既に指定されている既存の指示がオーバーライドされます。

スレッド状態を取得する

# Retrieve the status of the run
run = client.beta.threads.runs.retrieve(
  thread_id=thread.id,
  run_id=run.id
)

status = run.status
print(status)
completed

実行するクエリの複雑さによっては、スレッドの実行に時間がかかる場合があります。 その場合、次の例のようなコードを使って、スレッドの実行状態を監視するループを作成できます。

import time
from IPython.display import clear_output

start_time = time.time()

status = run.status

while status not in ["completed", "cancelled", "expired", "failed"]:
    time.sleep(5)
    run = client.beta.threads.runs.retrieve(thread_id=thread.id,run_id=run.id)
    print("Elapsed time: {} minutes {} seconds".format(int((time.time() - start_time) // 60), int((time.time() - start_time) % 60)))
    status = run.status
    print(f'Status: {status}')
    clear_output(wait=True)

messages = client.beta.threads.messages.list(
  thread_id=thread.id
) 

print(f'Status: {status}')
print("Elapsed time: {} minutes {} seconds".format(int((time.time() - start_time) // 60), int((time.time() - start_time) % 60)))
print(messages.model_dump_json(indent=2))

実行が in_progress、またはその他の非終了状態の場合、スレッドはロックされます。 スレッドがロックされている場合、新しいメッセージを追加できず、新しい実行を作成できません。

実行後のスレッド メッセージを一覧表示する

実行状態が正常に完了したことを示したら、スレッドの内容を再度一覧表示して、モデルおよびツールの応答を取得できます。

messages = client.beta.threads.messages.list(
  thread_id=thread.id
)

print(messages.model_dump_json(indent=2))
{
  "data": [
    {
      "id": "msg_M5pz73YFsJPNBbWvtVs5ZY3U",
      "assistant_id": "asst_eHwhP4Xnad0bZdJrjHO2hfB4",
      "content": [
        {
          "text": {
            "annotations": [],
            "value": "Is there anything else you would like to visualize or any additional features you'd like to add to the sine wave plot?"
          },
          "type": "text"
        }
      ],
      "created_at": 1705967782,
      "file_ids": [],
      "metadata": {},
      "object": "thread.message",
      "role": "assistant",
      "run_id": "run_AGQHJrrfV3eM0eI9T3arKgYY",
      "thread_id": "thread_ow1Yv29ptyVtv7ixbiKZRrHd"
    },
    {
      "id": "msg_oJbUanImBRpRran5HSa4Duy4",
      "assistant_id": "asst_eHwhP4Xnad0bZdJrjHO2hfB4",
      "content": [
        {
          "image_file": {
            "file_id": "assistant-1YGVTvNzc2JXajI5JU9F0HMD"
          },
          "type": "image_file"
        },
        {
          "text": {
            "annotations": [],
            "value": "Here is the visualization of a sine wave: \n\nThe wave is plotted using values from 0 to \\( 4\\pi \\) on the x-axis, and the corresponding sine values on the y-axis. I've also added grid lines for easier reading of the plot."
          },
          "type": "text"
        }
      ],
      "created_at": 1705967044,
      "file_ids": [],
      "metadata": {},
      "object": "thread.message",
      "role": "assistant",
      "run_id": "run_8PsweDFn6gftUd91H87K0Yts",
      "thread_id": "thread_ow1Yv29ptyVtv7ixbiKZRrHd"
    },
    {
      "id": "msg_Pu3eHjM10XIBkwqh7IhnKKdG",
      "assistant_id": null,
      "content": [
        {
          "text": {
            "annotations": [],
            "value": "Create a visualization of a sinewave"
          },
          "type": "text"
        }
      ],
      "created_at": 1705966634,
      "file_ids": [],
      "metadata": {},
      "object": "thread.message",
      "role": "user",
      "run_id": null,
      "thread_id": "thread_ow1Yv29ptyVtv7ixbiKZRrHd"
    }
  ],
  "object": "list",
  "first_id": "msg_M5pz73YFsJPNBbWvtVs5ZY3U",
  "last_id": "msg_Pu3eHjM10XIBkwqh7IhnKKdG",
  "has_more": false
}

ファイル ID を取得する

モデルに正弦波の画像を生成させるように要求しました。 画像をダウンロードするには、まず画像ファイル ID を取得する必要があります。

data = json.loads(messages.model_dump_json(indent=2))  # Load JSON data into a Python object
image_file_id = data['data'][0]['content'][0]['image_file']['file_id']

print(image_file_id)  # Outputs: assistant-1YGVTvNzc2JXajI5JU9F0HMD

イメージをダウンロードする

content = client.files.content(image_file_id)

image= content.write_to_file("sinewave.png")

ダウンロードしたら、画像をローカルで開きます。

from PIL import Image

# Display the image in the default image viewer
image = Image.open("sinewave.png")
image.show()

コード インタープリターによって生成された正弦波のスクリーンショット。

スレッドでフォローアップの質問をする

アシスタントがこちらの指示に完全には従わず、応答のテキスト部分に実行されたコードが含まれていなかったため、明示的にその情報を要求してみます。

# Add a new user question to the thread
message = client.beta.threads.messages.create(
    thread_id=thread.id,
    role="user",
    content="Show me the code you used to generate the sinewave"
)

もう一度実行して、スレッドの状態を取得する必要があります。

run = client.beta.threads.runs.create(
  thread_id=thread.id,
  assistant_id=assistant.id,
  #instructions="New instructions" #You can optionally provide new instructions  but these will override the default instructions
)

# Retrieve the status of the run
run = client.beta.threads.runs.retrieve(
  thread_id=thread.id,
  run_id=run.id
)

status = run.status
print(status)

completed

実行状態が完了に達したら、スレッド内のメッセージを再度一覧表示します。これには、最新の質問への応答が含まれているはずです。

messages = client.beta.threads.messages.list(
  thread_id=thread.id
)

print(messages.model_dump_json(indent=2))
{
  "data": [
    {
      "id": "msg_oaF1PUeozAvj3KrNnbKSy4LQ",
      "assistant_id": "asst_eHwhP4Xnad0bZdJrjHO2hfB4",
      "content": [
        {
          "text": {
            "annotations": [],
            "value": "Certainly, here is the code I used to generate the sine wave visualization:\n\n```python\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# Generating data for the sinewave\nx = np.linspace(0, 4 * np.pi, 1000)  # Generate values from 0 to 4*pi\ny = np.sin(x)  # Compute the sine of these values\n\n# Plotting the sine wave\nplt.plot(x, y)\nplt.title('Sine Wave')\nplt.xlabel('x')\nplt.ylabel('sin(x)')\nplt.grid(True)\nplt.show()\n```\n\nThis code snippet uses `numpy` to generate an array of x values and then computes the sine for each x value. It then uses `matplotlib` to plot these values and display the resulting graph."
          },
          "type": "text"
        }
      ],
      "created_at": 1705969710,
      "file_ids": [],
      "metadata": {},
      "object": "thread.message",
      "role": "assistant",
      "run_id": "run_oDS3fH7NorCUVwROTZejKcZN",
      "thread_id": "thread_ow1Yv29ptyVtv7ixbiKZRrHd"
    },
    {
      "id": "msg_moYE3aNwFYuRq2aXpxpt2Wb0",
      "assistant_id": null,
      "content": [
        {
          "text": {
            "annotations": [],
            "value": "Show me the code you used to generate the sinewave"
          },
          "type": "text"
        }
      ],
      "created_at": 1705969678,
      "file_ids": [],
      "metadata": {},
      "object": "thread.message",
      "role": "user",
      "run_id": null,
      "thread_id": "thread_ow1Yv29ptyVtv7ixbiKZRrHd"
    },
    {
      "id": "msg_M5pz73YFsJPNBbWvtVs5ZY3U",
      "assistant_id": "asst_eHwhP4Xnad0bZdJrjHO2hfB4",
      "content": [
        {
          "text": {
            "annotations": [],
            "value": "Is there anything else you would like to visualize or any additional features you'd like to add to the sine wave plot?"
          },
          "type": "text"
        }
      ],
      "created_at": 1705967782,
      "file_ids": [],
      "metadata": {},
      "object": "thread.message",
      "role": "assistant",
      "run_id": "run_AGQHJrrfV3eM0eI9T3arKgYY",
      "thread_id": "thread_ow1Yv29ptyVtv7ixbiKZRrHd"
    },
    {
      "id": "msg_oJbUanImBRpRran5HSa4Duy4",
      "assistant_id": "asst_eHwhP4Xnad0bZdJrjHO2hfB4",
      "content": [
        {
          "image_file": {
            "file_id": "assistant-1YGVTvNzc2JXajI5JU9F0HMD"
          },
          "type": "image_file"
        },
        {
          "text": {
            "annotations": [],
            "value": "Here is the visualization of a sine wave: \n\nThe wave is plotted using values from 0 to \\( 4\\pi \\) on the x-axis, and the corresponding sine values on the y-axis. I've also added grid lines for easier reading of the plot."
          },
          "type": "text"
        }
      ],
      "created_at": 1705967044,
      "file_ids": [],
      "metadata": {},
      "object": "thread.message",
      "role": "assistant",
      "run_id": "run_8PsweDFn6gftUd91H87K0Yts",
      "thread_id": "thread_ow1Yv29ptyVtv7ixbiKZRrHd"
    },
    {
      "id": "msg_Pu3eHjM10XIBkwqh7IhnKKdG",
      "assistant_id": null,
      "content": [
        {
          "text": {
            "annotations": [],
            "value": "Create a visualization of a sinewave"
          },
          "type": "text"
        }
      ],
      "created_at": 1705966634,
      "file_ids": [],
      "metadata": {},
      "object": "thread.message",
      "role": "user",
      "run_id": null,
      "thread_id": "thread_ow1Yv29ptyVtv7ixbiKZRrHd"
    }
  ],
  "object": "list",
  "first_id": "msg_oaF1PUeozAvj3KrNnbKSy4LQ",
  "last_id": "msg_Pu3eHjM10XIBkwqh7IhnKKdG",
  "has_more": false
}

最新の質問に対する応答のみを抽出するには、以下を行います。

data = json.loads(messages.model_dump_json(indent=2))
code = data['data'][0]['content'][0]['text']['value']
print(code)

"はい。これが正弦波の視覚化を生成するために使ったコードです。"

import numpy as np
import matplotlib.pyplot as plt

# Generating data for the sinewave
x = np.linspace(0, 4 * np.pi, 1000)  # Generate values from 0 to 4*pi
y = np.sin(x)  # Compute the sine of these values

# Plotting the sine wave
plt.plot(x, y)
plt.title('Sine Wave')
plt.xlabel('x')
plt.ylabel('sin(x)')
plt.grid(True)
plt.show()

ダーク モード

最後の質問をスレッドに追加して、コード インタープリターがグラフをダーク モードに切り替えられるかどうかを確認してみましょう。

# Add a user question to the thread
message = client.beta.threads.messages.create(
    thread_id=thread.id,
    role="user",
    content="I prefer visualizations in darkmode can you change the colors to make a darkmode version of this visualization."
)

# Run the thread
run = client.beta.threads.runs.create(
  thread_id=thread.id,
  assistant_id=assistant.id,
)

# Retrieve the status of the run
run = client.beta.threads.runs.retrieve(
  thread_id=thread.id,
  run_id=run.id
)

status = run.status
print(status)
completed
messages = client.beta.threads.messages.list(
  thread_id=thread.id
)

print(messages.model_dump_json(indent=2))
{
  "data": [
    {
      "id": "msg_KKzOHCArWGvGpuPo0pVZTHgV",
      "assistant_id": "asst_eHwhP4Xnad0bZdJrjHO2hfB4",
      "content": [
        {
          "text": {
            "annotations": [],
            "value": "You're viewing the dark mode version of the sine wave visualization in the image above. The plot is set against a dark background with a cyan colored sine wave for better contrast and visibility. If there's anything else you'd like to adjust or any other assistance you need, feel free to let me know!"
          },
          "type": "text"
        }
      ],
      "created_at": 1705971199,
      "file_ids": [],
      "metadata": {},
      "object": "thread.message",
      "role": "assistant",
      "run_id": "run_izZFyTVB1AlFM1VVMItggRn4",
      "thread_id": "thread_ow1Yv29ptyVtv7ixbiKZRrHd"
    },
    {
      "id": "msg_30pXFVYNgP38qNEMS4Zbozfk",
      "assistant_id": null,
      "content": [
        {
          "text": {
            "annotations": [],
            "value": "I prefer visualizations in darkmode can you change the colors to make a darkmode version of this visualization."
          },
          "type": "text"
        }
      ],
      "created_at": 1705971194,
      "file_ids": [],
      "metadata": {},
      "object": "thread.message",
      "role": "user",
      "run_id": null,
      "thread_id": "thread_ow1Yv29ptyVtv7ixbiKZRrHd"
    },
    {
      "id": "msg_3j31M0PaJLqO612HLKVsRhlw",
      "assistant_id": "asst_eHwhP4Xnad0bZdJrjHO2hfB4",
      "content": [
        {
          "image_file": {
            "file_id": "assistant-kfqzMAKN1KivQXaEJuU0u9YS"
          },
          "type": "image_file"
        },
        {
          "text": {
            "annotations": [],
            "value": "Here is the dark mode version of the sine wave visualization. I've used the 'dark_background' style in Matplotlib and chosen a cyan color for the plot line to ensure it stands out against the dark background."
          },
          "type": "text"
        }
      ],
      "created_at": 1705971123,
      "file_ids": [],
      "metadata": {},
      "object": "thread.message",
      "role": "assistant",
      "run_id": "run_B91erEPWro4bZIfryQeIDDlx",
      "thread_id": "thread_ow1Yv29ptyVtv7ixbiKZRrHd"
    },
    {
      "id": "msg_FgDZhBvvM1CLTTFXwgeJLdua",
      "assistant_id": null,
      "content": [
        {
          "text": {
            "annotations": [],
            "value": "I prefer visualizations in darkmode can you change the colors to make a darkmode version of this visualization."
          },
          "type": "text"
        }
      ],
      "created_at": 1705971052,
      "file_ids": [],
      "metadata": {},
      "object": "thread.message",
      "role": "user",
      "run_id": null,
      "thread_id": "thread_ow1Yv29ptyVtv7ixbiKZRrHd"
    },
    {
      "id": "msg_oaF1PUeozAvj3KrNnbKSy4LQ",
      "assistant_id": "asst_eHwhP4Xnad0bZdJrjHO2hfB4",
      "content": [
        {
          "text": {
            "annotations": [],
            "value": "Certainly, here is the code I used to generate the sine wave visualization:\n\n```python\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# Generating data for the sinewave\nx = np.linspace(0, 4 * np.pi, 1000)  # Generate values from 0 to 4*pi\ny = np.sin(x)  # Compute the sine of these values\n\n# Plotting the sine wave\nplt.plot(x, y)\nplt.title('Sine Wave')\nplt.xlabel('x')\nplt.ylabel('sin(x)')\nplt.grid(True)\nplt.show()\n```\n\nThis code snippet uses `numpy` to generate an array of x values and then computes the sine for each x value. It then uses `matplotlib` to plot these values and display the resulting graph."
          },
          "type": "text"
        }
      ],
      "created_at": 1705969710,
      "file_ids": [],
      "metadata": {},
      "object": "thread.message",
      "role": "assistant",
      "run_id": "run_oDS3fH7NorCUVwROTZejKcZN",
      "thread_id": "thread_ow1Yv29ptyVtv7ixbiKZRrHd"
    },
    {
      "id": "msg_moYE3aNwFYuRq2aXpxpt2Wb0",
      "assistant_id": null,
      "content": [
        {
          "text": {
            "annotations": [],
            "value": "Show me the code you used to generate the sinewave"
          },
          "type": "text"
        }
      ],
      "created_at": 1705969678,
      "file_ids": [],
      "metadata": {},
      "object": "thread.message",
      "role": "user",
      "run_id": null,
      "thread_id": "thread_ow1Yv29ptyVtv7ixbiKZRrHd"
    },
    {
      "id": "msg_M5pz73YFsJPNBbWvtVs5ZY3U",
      "assistant_id": "asst_eHwhP4Xnad0bZdJrjHO2hfB4",
      "content": [
        {
          "text": {
            "annotations": [],
            "value": "Is there anything else you would like to visualize or any additional features you'd like to add to the sine wave plot?"
          },
          "type": "text"
        }
      ],
      "created_at": 1705967782,
      "file_ids": [],
      "metadata": {},
      "object": "thread.message",
      "role": "assistant",
      "run_id": "run_AGQHJrrfV3eM0eI9T3arKgYY",
      "thread_id": "thread_ow1Yv29ptyVtv7ixbiKZRrHd"
    },
    {
      "id": "msg_oJbUanImBRpRran5HSa4Duy4",
      "assistant_id": "asst_eHwhP4Xnad0bZdJrjHO2hfB4",
      "content": [
        {
          "image_file": {
            "file_id": "assistant-1YGVTvNzc2JXajI5JU9F0HMD"
          },
          "type": "image_file"
        },
        {
          "text": {
            "annotations": [],
            "value": "Here is the visualization of a sine wave: \n\nThe wave is plotted using values from 0 to \\( 4\\pi \\) on the x-axis, and the corresponding sine values on the y-axis. I've also added grid lines for easier reading of the plot."
          },
          "type": "text"
        }
      ],
      "created_at": 1705967044,
      "file_ids": [],
      "metadata": {},
      "object": "thread.message",
      "role": "assistant",
      "run_id": "run_8PsweDFn6gftUd91H87K0Yts",
      "thread_id": "thread_ow1Yv29ptyVtv7ixbiKZRrHd"
    },
    {
      "id": "msg_Pu3eHjM10XIBkwqh7IhnKKdG",
      "assistant_id": null,
      "content": [
        {
          "text": {
            "annotations": [],
            "value": "Create a visualization of a sinewave"
          },
          "type": "text"
        }
      ],
      "created_at": 1705966634,
      "file_ids": [],
      "metadata": {},
      "object": "thread.message",
      "role": "user",
      "run_id": null,
      "thread_id": "thread_ow1Yv29ptyVtv7ixbiKZRrHd"
    }
  ],
  "object": "list",
  "first_id": "msg_KKzOHCArWGvGpuPo0pVZTHgV",
  "last_id": "msg_Pu3eHjM10XIBkwqh7IhnKKdG",
  "has_more": false
}

新しい画像ファイル ID を抽出し、画像をダウンロードして表示します。

data = json.loads(messages.model_dump_json(indent=2))  # Load JSON data into a Python object
image_file_id = data['data'][0]['content'][0]['image_file']['file_id'] # index numbers can vary if you have had a different conversation over the course of the thread.

print(image_file_id)

content = client.files.content(image_file_id)
image= content.write_to_file("dark_sine.png")

# Display the image in the default image viewer
image = Image.open("dark_sine.png")
image.show()

ダーク モードでコード インタープリターによって生成された正弦波のスクリーンショット。

その他の参照情報

実行状態の定義

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

メッセージの注釈

アシスタント メッセージの注釈は、入力候補 API 応答やチャット入力候補 API 応答に存在するコンテンツ フィルター処理の注釈とは異なります。 アシスタントの注釈は、オブジェクトのコンテンツ配列内に出現する場合があります。 注釈は、ユーザーへの応答内のテキストに注釈を付ける方法に関する情報を提供します。

注釈がメッセージ コンテンツ配列に存在する場合、テキスト内に判読できないモデル生成の部分文字列があることがわかります。これを正しい注釈に置き換える必要があります。 これらの文字列は、【13†source】 または sandbox:/mnt/data/file.csv のようになります。 以下は、これらの文字列を注釈に存在する情報に置き換える OpenAI の Python コード スニペットです。


from openai import AzureOpenAI
    
client = AzureOpenAI(
    api_key=os.getenv("AZURE_OPENAI_API_KEY"),  
    api_version="2024-02-15-preview",
    azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
    )

# Retrieve the message object
message = client.beta.threads.messages.retrieve(
  thread_id="...",
  message_id="..."
)

# Extract the message content
message_content = message.content[0].text
annotations = message_content.annotations
citations = []

# Iterate over the annotations and add footnotes
for index, annotation in enumerate(annotations):
    # Replace the text with a footnote
    message_content.value = message_content.value.replace(annotation.text, f' [{index}]')

    # Gather citations based on annotation attributes
    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}')
        # Note: File download functionality not implemented above for brevity

# Add footnotes to the end of the message before displaying to user
message_content.value += '\n' + '\n'.join(citations)

メッセージの注釈 説明
file_citation ファイル引用は取得ツールによって作成され、アップロードされ、アシスタントが応答を生成するために使った特定のファイル内の特定の引用への参照を定義します。
file_path ファイル パスの注釈は code_interpreter ツールによって作成され、ツールによって生成されたファイルへの参照が含まれます。

関連項目