Udostępnij za pośrednictwem


Wprowadzenie do asystentów usługi Azure OpenAI (wersja zapoznawcza)

Asystenci usługi Azure OpenAI (wersja zapoznawcza) umożliwiają tworzenie opartych na sztucznej inteligencji asystentów dostosowanych do potrzeb za pomocą niestandardowych instrukcji i wspomaganych przez zaawansowane narzędzia, takie jak interpreter kodu i funkcje niestandardowe. W tym artykule przedstawiono szczegółowy przewodnik po rozpoczęciu pracy z interfejsem API Asystentów.

Uwaga

  • Wyszukiwanie plików może pozyskiwać maksymalnie 10 000 plików na asystenta — 500 razy więcej niż wcześniej. Jest szybkie, obsługuje zapytania równoległe za pośrednictwem wyszukiwania wielowątkowego i oferuje ulepszone ponowne klasyfikowanie praz ponowne zapisywanie zapytań.
    • Magazyn wektorów to nowy obiekt w interfejsie API. Po dodaniu pliku do magazynu wektorów jest on automatycznie analizowany, fragmentowany i osadzany oraz przygotowywany do wyszukiwania. Magazyny wektorów mogą być używane między asystentami i wątkami, upraszczając zarządzanie plikami i rozliczenia.
  • Dodaliśmy obsługę parametru tool_choice , który może służyć do wymuszenia użycia określonego narzędzia (takiego jak wyszukiwanie plików, interpreter kodu lub funkcja) w określonym uruchomieniu.

Pomoc techniczna asystentów

Obsługa regionów i modeli

Interpreter kodu jest dostępny we wszystkich regionach obsługiwanych przez asystentów usługi Azure OpenAI. Strona modeli zawiera najbardziej aktualne informacje dotyczące regionów/modeli, w których asystentzy są obecnie obsługiwane.

Wersje interfejsu API

  • 2024-02-15-preview
  • 2024-05-01-preview

Typy obsługiwanych plików

File format Typ MIME Interpreter kodów
c. tekst/x-c
.Cpp text/x-c++
.csv aplikacja/csv
.docx application/vnd.openxmlformats-officedocument.wordprocessingml.document
.html, text/html
.java text/x-java
.json application/json
.md tekst/znaczniki 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 tekst/x-ruby
.Tex text/x-tex
txt text/plain
.Css tekst/css
.jpeg image/jpeg
.jpg image/jpeg
js text/javascript
.gif obraz/gif
.png image/png
.smoła aplikacja/x-tar
.Ts application/typescript
.xlsx application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
xml application/xml lub "text/xml"
.zip aplikacja/zip

Narzędzia

Napiwek

Dodaliśmy obsługę parametru tool_choice , który może służyć do wymuszenia użycia określonego narzędzia (na przykład file_search, code_interpreterlub ) functionw konkretnym uruchomieniu.

Indywidualny asystent może uzyskać dostęp do maksymalnie 128 narzędzi, w tym interpretera kodu i wyszukiwania plików, ale można również zdefiniować własne narzędzia niestandardowe za pomocą funkcji.

Pliki

Pliki można przekazywać za pośrednictwem programu Studio lub programowo. Parametr jest wymagany do udzielenia file_ids narzędzi, takich jak code_interpreter dostęp do plików. W przypadku korzystania z punktu końcowego przekazywania plików musisz mieć purpose ustawiony zestaw asystentów do użycia z interfejsem API Asystentów.

Asystentów plac zabaw

W naszym przewodniku Szybki start udostępnimy przewodnik po placu zabaw Dla asystentów. Zapewnia to środowisko bez kodu do testowania możliwości asystentów.

Składniki asystentów

Składnik Opis
Asystent Niestandardowa sztuczna inteligencja korzystająca z modeli usługi Azure OpenAI w połączeniu z narzędziami.
Nitka Sesja konwersacji między asystentem a użytkownikiem. Wątki przechowują komunikaty i automatycznie obsługują obcinanie w celu dopasowania zawartości do kontekstu modelu.
Wiadomość Komunikat utworzony przez Asystenta lub użytkownika. Wiadomości mogą zawierać tekst, obrazy i inne pliki. Komunikaty są przechowywane jako lista w wątku.
Run Aktywacja asystenta w celu rozpoczęcia działania na podstawie zawartości wątku. Asystent używa konfiguracji i komunikatów wątku do wykonywania zadań przez wywoływanie modeli i narzędzi. W ramach przebiegu Asystent dołącza komunikaty do wątku.
Krok uruchamiania Szczegółowa lista kroków, które asystent wziął w ramach przebiegu. Asystent może wywoływać narzędzia lub tworzyć komunikaty podczas jego uruchamiania. Badanie kroków uruchamiania pozwala zrozumieć, jak asystent uzyskuje wyniki końcowe.

Konfigurowanie pierwszego asystenta

Tworzenie asystenta

W tym przykładzie utworzymy asystenta, który zapisuje kod w celu generowania wizualizacji przy użyciu możliwości code_interpreter narzędzia. Poniższe przykłady mają być uruchamiane sekwencyjnie w środowisku, na przykład Jupyter Notebooks.

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.
)

W powyższej konfiguracji należy zwrócić uwagę na kilka szczegółów:

  • Włączymy tego asystenta, aby uzyskać dostęp do interpretera kodu przy użyciu wiersza tools=[{"type": "code_interpreter"}],. Daje to modelowi dostęp do środowiska python z piaskiem, aby uruchamiać i wykonywać kod, aby ułatwić formułowanie odpowiedzi na pytanie użytkownika.
  • W instrukcjach przypominamy modelowi, że może on wykonywać kod. Czasami model potrzebuje pomocy w kierowaniu go do odpowiedniego narzędzia w celu rozwiązania danego zapytania. Jeśli wiesz, że chcesz użyć określonej biblioteki, aby wygenerować określoną odpowiedź, którą znasz, jest częścią interpretera kodu, może pomóc w zapewnieniu wskazówek, mówiąc coś takiego jak "Użyj biblioteki Matplotlib do wykonania x".
  • Ponieważ jest to azure OpenAI, wartość wprowadzona musi model= być zgodna z nazwą wdrożenia.

Następnie wyświetlimy zawartość asystenta, który właśnie utworzyliśmy, aby potwierdzić, że tworzenie zakończyło się pomyślnie:

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"
    }
  ]
}

Tworzenie wątku

Teraz utwórzmy wątek.

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

Wątek jest zasadniczo rekordem sesji konwersacji między asystentem a użytkownikiem. Jest on podobny do tablicy/listy komunikatów w typowym wywołaniu interfejsu API uzupełniania czatu. Jedną z kluczowych różnic jest w przeciwieństwie do tablicy komunikatów uzupełniania czatów, nie trzeba śledzić tokenów przy każdym wywołaniu, aby upewnić się, że pozostajesz poniżej długości kontekstu modelu. Wątki wyodrębniają te szczegóły zarządzania i będą kompresować historię wątków zgodnie z potrzebami, aby umożliwić kontynuowanie konwersacji. Możliwość wykonania tego zadania za pomocą większych konwersacji jest rozszerzona w przypadku korzystania z najnowszych modeli, które mają większe długości kontekstu i obsługę najnowszych funkcji.

Następnie utwórz pierwsze pytanie użytkownika, aby dodać do wątku.

# 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"
)

Wyświetlanie listy komunikatów wątków

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
}

Uruchom wątek

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
)

Możemy również przekazać instructions parametr tutaj, ale spowoduje to zastąpienie istniejących instrukcji, które zostały już podane dla asystenta.

Pobieranie stanu wątku

# 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

W zależności od złożoności uruchamianego zapytania wątek może trwać dłużej. W takim przypadku możesz utworzyć pętlę, aby monitorować stan uruchomienia wątku przy użyciu kodu, takiego jak w poniższym przykładzie:

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))

Gdy element Run jest in_progress lub w innych stanach nieterminalnych, wątek jest zablokowany. Nie można dodać nowych komunikatów, gdy nie można dodać wątku i nie można utworzyć nowych przebiegów.

Wyświetlanie listy komunikatów wątku po uruchomieniu

Gdy stan uruchomienia wskazuje pomyślne ukończenie, możesz ponownie wyświetlić zawartość wątku, aby pobrać odpowiedź modelu i wszystkich narzędzi:

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
}

Pobieranie identyfikatora pliku

Zażądaliśmy, aby model wygenerował obraz sinusoidy. Aby pobrać obraz, najpierw musimy pobrać identyfikator pliku images.

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

Pobieranie obrazu

content = client.files.content(image_file_id)

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

Otwórz obraz lokalnie po pobraniu:

from PIL import Image

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

Zrzut ekranu przedstawiający wygenerowaną sinusoidę interpretera kodu.

Zadaj pytanie dotyczące kontynuacji wątku

Ponieważ asystent nie postępował zgodnie z naszymi instrukcjami i uwzględnił kod, który został uruchomiony w części tekstowej odpowiedzi, umożliwia jawne zapytanie o te informacje.

# 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"
)

Ponownie musimy uruchomić i pobrać stan wątku:

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

Po osiągnięciu stanu uruchomienia ponownie wyświetlimy komunikaty w wątku, które powinny teraz zawierać odpowiedź na nasze najnowsze pytanie.

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
}

Aby wyodrębnić tylko odpowiedź na nasze najnowsze pytanie:

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

Z pewnością oto kod, który został użyty do wygenerowania wizualizacji sinusoidy:

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()

Tryb ciemny

Dodajmy ostatnie pytanie do wątku, aby sprawdzić, czy interpreter kodu może zamienić wykres na tryb ciemny.

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

Wyodrębnij nowy identyfikator pliku obrazu i pobierz i wyświetl obraz:

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()

Zrzut ekranu przedstawiający wygenerowaną sinusoidę interpretera kodu w trybie ciemnym.

Dodatkowa dokumentacja

Definicje stanu uruchamiania

Stan Definicja
queued Po pierwszym utworzeniu lub zakończeniu required_action zostaną one przeniesione do stanu w kolejce. Powinni niemal natychmiast przejść do in_progress.
in_progress Podczas in_progress Asystent używa modelu i narzędzi do wykonywania kroków. Postęp wykonywania można wyświetlić, sprawdzając kroki uruchamiania.
completed Przebieg został ukończony pomyślnie. Teraz możesz wyświetlić wszystkie komunikaty dodane przez Asystenta do wątku i wszystkie kroki, które wykonał przebieg. Możesz również kontynuować konwersację, dodając więcej wiadomości użytkownika do wątku i tworząc kolejny przebieg.
requires_action W przypadku korzystania z narzędzia wywołującego funkcję uruchomienie zostanie przeniesione do stanu required_action, gdy model określi nazwy i argumenty funkcji do wywołania. Następnie należy uruchomić te funkcje i przesłać dane wyjściowe przed kontynuowaniem przebiegu. Jeśli dane wyjściowe nie zostaną podane przed przejściem znacznika czasu expires_at (mniej więcej 10 minut po utworzeniu), przebieg zostanie przeniesiony do wygasłego stanu.
expired Dzieje się tak, gdy funkcja wywołująca dane wyjściowe nie została przesłana przed expires_at i przebieg wygaśnie. Ponadto jeśli wykonanie przebiegów trwa zbyt długo i wykracza poza czas określony w expires_at, nasze systemy wygasną.
cancelling Możesz spróbować anulować uruchomienie in_progress przy użyciu punktu końcowego Anuluj przebieg. Po pomyślnym anulowaniu próby stan uruchomienia zostanie przeniesiony do anulowania. Próba anulowania jest podejmowana, ale nie jest gwarantowana.
cancelled Przebieg został pomyślnie anulowany.
failed Przyczynę błędu można wyświetlić, przeglądając last_error obiekt w przebiegu. Sygnatura czasowa niepowodzenia zostanie zarejestrowana w failed_at.

Adnotacje komunikatów

Adnotacje komunikatów asystenta różnią się od adnotacji filtrowania zawartości, które są obecne w odpowiedziach interfejsu API uzupełniania i uzupełniania czatu. Adnotacje asystenta mogą wystąpić w tablicy zawartości obiektu. Adnotacje zawierają informacje dotyczące dodawania adnotacji do tekstu w odpowiedziach na użytkownika.

Gdy adnotacje znajdują się w tablicy zawartości Komunikat, w tekście, które należy zastąpić poprawnymi adnotacjami, zobaczysz nieczytelne podciągy wygenerowane przez model. Te ciągi mogą wyglądać mniej więcej tak, jak 【13†source】 lub sandbox:/mnt/data/file.csv. Oto fragment kodu języka Python z interfejsu OpenAI, który zastępuje te ciągi informacjami obecnymi w adnotacjach.


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)

Adnotacja komunikatu opis
file_citation Cytaty plików są tworzone przez narzędzie do pobierania i definiują odwołania do określonego cudzysłowu w określonym pliku przekazanym i używanym przez Asystenta do wygenerowania odpowiedzi.
file_path Adnotacje ścieżki pliku są tworzone przez narzędzie code_interpreter i zawierają odwołania do plików generowanych przez narzędzie.

Zobacz też