Начало работы с Azure Ассистентами OpenAI (предварительный просмотр) (классическая версия)

Применяется только к:Портал Foundry (классический). Эта статья недоступна для нового портала Foundry. Дополнительные сведения о новом портале.

Примечание

Ссылки в этой статье могут открывать содержимое в новой документации Microsoft Foundry вместо документации Foundry (классической), которую вы просматриваете сейчас.

Примечание

API Assistants устарел и будет выведен из эксплуатации 26 августа 2026 года. Воспользуйтесь общедоступной услугой Microsoft Foundry Agents. Следуйте руководству по миграции, чтобы обновить ваши нагрузки. Дополнительные сведения.

Azure Помощники OpenAI (предварительная версия) позволяют создавать помощники по ИИ, адаптированные к вашим потребностям, с помощью пользовательских инструкций и дополненных расширенными инструментами, такими как интерпретатор кода и пользовательские функции. В этой статье мы предоставляем подробное пошаговое руководство по началу работы с API Помощников.

Поддержка помощников

Поддержка регионов, моделей и API

Страница моделей содержит самые up-to-date сведения о регионах и моделях, где помощники в настоящее время поддерживаются. Помощники можно использовать в версии 2024-02-15-preview и более поздних версиях API прогноза Azure OpenAI preview API. Полный список предыдущих версий API можно найти в GitHub.

Поддерживаемые типы файлов

Формат файла Тип 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

Инструменты

Совет

Мы добавили поддержку параметра tool_choice, который можно использовать для принудительного использования определенного средства (например, file_search, code_interpreter или function) в определенном запуске.

Отдельный помощник может получить доступ до 128 инструментов, включая интерпретатор кода и поиск файлов, но также можно определить собственные пользовательские инструменты с помощью функций.

Файлы

Файлы можно отправлять через Студию или программным способом. Этот file_ids параметр необходим для предоставления таких средств, как code_interpreter доступ к файлам. При использовании точки загрузки файла необходимо, чтобы purpose был установлен как assistants для использования с API помощников.

Компоненты помощников

Компонент Описание
Помощник Настраиваемый ИИ, использующий модели OpenAI Azure в сочетании с инструментами.
Поток Сеанс беседы между помощником и пользователем. Потоки хранят сообщения и автоматически выполняют усечение, чтобы вписать их в контекст модели.
Сообщение Сообщение, созданное помощником или пользователем. Сообщения могут включать текст, изображения и другие файлы. Сообщения хранятся в виде списка в потоке.
Запустить Активация помощника для начала работы на основе содержимого потока данных. Помощник использует свою конфигурацию и сообщения потока для выполнения задач путем вызова моделей и инструментов. В рамках выполнения ассистент добавляет сообщения в поток.
Шаг выполнения Подробный список шагов, которые выполняет помощник в ходе процесса. Помощник может вызывать средства или создавать сообщения во время выполнения. Изучение этапов выполнения позволяет понять, как Ассистент добивается своих окончательных результатов.

Настройка первого помощника

Создание помощника

В этом примере мы создадим помощник, который записывает код для создания визуализаций с помощью возможностей 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-08-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 При первом создании запусков или при завершении требуемого действия они перемещаются в статус ожидания. Они должны почти сразу перейти к 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. Ниже приведен фрагмент кода Python из OpenAI, который заменяет эти строки сведениями, представленными в заметках.


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 и содержат ссылки на файлы, созданные средством.

См. также