共用方式為


開始使用 Azure OpenAI 助理 (預覽版)

Azure OpenAI Assistants (預覽版) 可讓您使用自訂指示以根據您的需求量身打造 AI 助理,並透過程式碼解釋器和自訂函式等進階工具進行擴增。 在本文中,我們會提供開始使用助理 API 的深入逐步解說。

注意

  • 檔案搜尋可以內嵌每個助理最多 10,000 個檔案 - 比之前多 500 倍。 其速度很快,可透過多對話搜尋支援平行查詢,以及增強重新排名和查詢重寫的功能。
    • 向量存放區是 API 中的新物件。 一旦檔案新增至向量存放區,它就會自動進行剖析、區塊化和內嵌,並準備好提供搜尋。 向量存放區可以跨助理和對話使用,簡化檔案管理和計費。
  • 我們已新增 tool_choice 參數的支援,可用來強制在特定執行中使用特定工具 (例如檔案搜尋、程式碼解譯器或函式)。

助理支援

區域和模型支援

程式碼解譯器可在 Azure OpenAI Assistants 支援的所有區域中使用。 模型頁面包含目前支援助理所在區域/模型的最新資訊。

API 版本

  • 2024-02-15-preview
  • 2024-05-01-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 應用程式/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

工具

提示

我們已新增 tool_choice 參數的支援,可用來強制在特定執行中使用特定工具(例如 file_searchcode_interpreterfunction)。

個別助理最多可以存取 128 個工具,包括程式碼解譯器檔案搜尋,但您也可以透過函式來定義自己的自訂工具。

檔案

檔案可以透過 Studio 或以程式設計方式上傳。 需要 file_ids 參數,才能讓 code_interpreter 之類的工具存取檔案。 使用檔案上傳端點時,您必須將 purpose 設定為要與助理 API 搭配使用的助理。

助理遊樂場

我們在快速入門指南中提供助理遊樂場的逐步解說。 這提供無程式碼環境來測試助理的功能。

助理元件

元件 說明
小幫手 搭配工具使用 Azure OpenAI 模型的自訂 AI。
Thread 助理與使用者之間的交談工作階段。 對話會儲存訊息,並自動處理截斷,以將內容放入模型的內容中。
訊息 助理或使用者所建立的訊息。 訊息可以包含文字、影像和其他檔案。 訊息會儲存為對話上的清單。
執行 啟用助理,以根據對話的內容開始執行。 助理會使用其設定和對話的訊息,藉由呼叫模型和工具來執行工作。 在執行過程中,助理會將訊息附加至對話。
執行步驟 助理參與執行的詳細步驟清單。 助理可以在其執行期間呼叫工具或建立訊息。 檢查執行步驟可讓您了解助理如何取得其最終結果。

設定您的第一個助理

建立助理

在此範例中,我們將建立助理,以使用 code_interpreter 工具的功能撰寫程式碼來產生視覺效果。 下列範例旨在依序在 Jupyter Notebook 等環境中執行。

import os
import json
from openai import AzureOpenAI
    
client = AzureOpenAI(
    api_key=os.getenv("AZURE_OPENAI_API_KEY"),  
    api_version="2024-05-01-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 呼叫中的訊息陣列/清單。 其中一個主要差異是與聊天完成訊息陣列不同,您不需要追蹤每個呼叫的權杖,即可確保您仍然低於模型的內容長度。 對話會抽象化此管理詳細資料,並視需要壓縮對話歷程記錄,以允許交談繼續。 當使用具有較大內容長度且支援最新功能的最新模型時,對話完成此具有較大交談作業的能力會增強。

接下來,建立要新增至對話的第一個使用者問題。

# 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
}

擷取檔案識別碼

我們已要求模型產生正弦波的影像。 為了下載影像,我們必須先擷取影像檔案識別碼。

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
}

擷取新的影像檔案識別碼並下載並顯示影像:

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 使用函式呼叫工具時,一旦模型決定要呼叫的函式名稱和引數,執行就會移至 required_action 狀態。 然後,您必須執行這些函式,並在執行繼續進行之前提交輸出。 如果在 expires_at 時間戳記經過 (大約建立後 10 分鐘) 之前未提供輸出,則執行會移至過期狀態。
expired 當呼叫輸出的函式在 expires_at 之前未提交,且執行過期時,就會發生這種情況。 此外,如果執行時間過長而無法執行,且超出 expires_at 中所述的時間,我們的系統將會使執行過期。
cancelling 您可以使用 [取消執行] 端點,以嘗試取消 in_progress 執行。 嘗試取消成功之後,[執行] 的狀態會移至 [已取消]。 已嘗試取消,但不保證。
cancelled 已成功取消執行。
failed 您可以藉由查看執行中的 last_error 物件來檢視失敗的原因。 失敗的時間戳記將會記錄在 failed_at 底下。

訊息註解

助理訊息註釋與完成和聊天完成 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-05-01-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 工具所建立,且包含工具所產生檔案的參考。

另請參閱