Поделиться через


Руководство: Интерпретатор кода OpenAIAssistantAgent

Важный

Эта функция находится на стадии релиз-кандидата. Функции на этом этапе почти завершены и обычно стабильны, хотя они могут пройти незначительные уточнения или оптимизации, прежде чем достичь полной общедоступной доступности.

Обзор

В этом примере мы рассмотрим, как использовать инструмент интерпретатора кода OpenAIAssistantAgent для выполнения задач анализа данных. Этот подход будет разбит по шагам, чтобы выделить ключевые части процесса программирования. В рамках задачи агент создаст как изображения, так и текстовые ответы. Это продемонстрирует универсальность этого инструмента при выполнении количественного анализа.

Для передачи ответов агента будет использоваться потоковая технология. Это обеспечит обновления в режиме реального времени по мере выполнения задачи.

Начало работы

Прежде чем приступить к программированию функций, убедитесь, что среда разработки полностью подготовлена и настроена.

Начните с создания проекта консоли. Затем включите следующие ссылки на пакеты, чтобы убедиться, что доступны все необходимые зависимости.

Чтобы добавить зависимости пакета из командной строки, используйте dotnet команду:

dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.Binder
dotnet add package Microsoft.Extensions.Configuration.UserSecrets
dotnet add package Microsoft.Extensions.Configuration.EnvironmentVariables
dotnet add package Microsoft.SemanticKernel
dotnet add package Microsoft.SemanticKernel.Agents.OpenAI --prerelease

Важный

При управлении пакетами NuGet в Visual Studio убедитесь, что Include prerelease установлен.

Файл проекта (.csproj) должен содержать следующие PackageReference определения:

  <ItemGroup>
    <PackageReference Include="Azure.Identity" Version="<stable>" />
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="<stable>" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="<stable>" />
    <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="<stable>" />
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="<stable>" />
    <PackageReference Include="Microsoft.SemanticKernel" Version="<latest>" />
    <PackageReference Include="Microsoft.SemanticKernel.Agents.OpenAI" Version="<latest>" />
  </ItemGroup>

Agent Framework является экспериментальным и требует подавления предупреждений. Это может быть решено как свойство в файле проекта (.csproj):

  <PropertyGroup>
    <NoWarn>$(NoWarn);CA2007;IDE1006;SKEXP0001;SKEXP0110;OPENAI001</NoWarn>
  </PropertyGroup>

Кроме того, скопируйте файлы PopulationByAdmin1.csv и файлы данных PopulationByCountry.csv из проекта Semantic KernelLearnResources. Добавьте эти файлы в папку проекта и настройте их копирование в выходной каталог:

  <ItemGroup>
    <None Include="PopulationByAdmin1.csv">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
    <None Include="PopulationByCountry.csv">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
  </ItemGroup>

Начните с создания папки, в которую будут храниться скрипт (.py файл) и примеры ресурсов. Включите следующие импорты в верхней части .py файла:

import asyncio
import os

from semantic_kernel.agents import AssistantAgentThread, AzureAssistantAgent
from semantic_kernel.contents import StreamingFileReferenceContent

Кроме того, скопируйте файлы данных PopulationByAdmin1.csv и PopulationByCountry.csv из каталога семантического ядраlearn_resources/resources. Добавьте эти файлы в рабочий каталог.

Функция в настоящее время недоступна в Java.

Настройка

Этот пример требует настройки для подключения к удаленным службам. Вам потребуется определить параметры для OpenAI или Azure OpenAI.

# OpenAI
dotnet user-secrets set "OpenAISettings:ApiKey" "<api-key>"
dotnet user-secrets set "OpenAISettings:ChatModel" "gpt-4o"

# Azure OpenAI
dotnet user-secrets set "AzureOpenAISettings:ApiKey" "<api-key>" # Not required if using token-credential
dotnet user-secrets set "AzureOpenAISettings:Endpoint" "<model-endpoint>"
dotnet user-secrets set "AzureOpenAISettings:ChatModelDeployment" "gpt-4o"

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

using System.Reflection;
using Microsoft.Extensions.Configuration;

namespace AgentsSample;

public class Settings
{
    private readonly IConfigurationRoot configRoot;

    private AzureOpenAISettings azureOpenAI;
    private OpenAISettings openAI;

    public AzureOpenAISettings AzureOpenAI => this.azureOpenAI ??= this.GetSettings<Settings.AzureOpenAISettings>();
    public OpenAISettings OpenAI => this.openAI ??= this.GetSettings<Settings.OpenAISettings>();

    public class OpenAISettings
    {
        public string ChatModel { get; set; } = string.Empty;
        public string ApiKey { get; set; } = string.Empty;
    }

    public class AzureOpenAISettings
    {
        public string ChatModelDeployment { get; set; } = string.Empty;
        public string Endpoint { get; set; } = string.Empty;
        public string ApiKey { get; set; } = string.Empty;
    }

    public TSettings GetSettings<TSettings>() =>
        this.configRoot.GetRequiredSection(typeof(TSettings).Name).Get<TSettings>()!;

    public Settings()
    {
        this.configRoot =
            new ConfigurationBuilder()
                .AddEnvironmentVariables()
                .AddUserSecrets(Assembly.GetExecutingAssembly(), optional: true)
                .Build();
    }
}

Самый быстрый способ начать работу с правильной конфигурацией для запуска примера кода — создать .env файл в корне проекта (где выполняется скрипт).

Настройте следующие параметры в .env файле для Azure OpenAI или OpenAI:

AZURE_OPENAI_API_KEY="..."
AZURE_OPENAI_ENDPOINT="https://<resource-name>.openai.azure.com/"
AZURE_OPENAI_CHAT_DEPLOYMENT_NAME="..."
AZURE_OPENAI_API_VERSION="..."

OPENAI_API_KEY="sk-..."
OPENAI_ORG_ID=""
OPENAI_CHAT_MODEL_ID=""

Совет

Для помощников Azure требуется версия API по крайней мере 2024-05-01-preview. По мере создания новых функций версии API обновляются соответствующим образом. По состоянию на этот момент последняя версия — 2025-01-01-preview. Актуальные сведения о версионности см. в разделе жизненный цикл предварительного просмотра API Azure OpenAI.

После настройки соответствующие классы служб ИИ будут собирать необходимые переменные и использовать их во время инициализации объекта.

Функция в настоящее время недоступна в Java.

Написание кода

Процесс написания кода для этого примера включает в себя:

  1. Настройка — инициализация параметров и плагина.
  2. определение агента. Создайте _OpenAI_AssistantAgent с шаблонизированными инструкциями и плагином.
  3. цикл чата — запись цикла, который управляет взаимодействием пользователя или агента.

Полный пример кода представлен в заключительном разделе. См. этот раздел для полной реализации.

Настройка

Перед созданием OpenAIAssistantAgentубедитесь, что параметры конфигурации доступны и подготовьте ресурсы файлов.

Создайте экземпляр Settingsкласса, на который ссылается предыдущий раздел Конфигурация. Используйте параметры, чтобы также создать AzureOpenAIClient элемент, который будет применяться для определения агента, а также для загрузки файлов.

Settings settings = new();

AzureOpenAIClient client = OpenAIAssistantAgent.CreateAzureOpenAIClient(new AzureCliCredential(), new Uri(settings.AzureOpenAI.Endpoint));

Функция в настоящее время недоступна в Java.

Используйте AzureOpenAIClient, чтобы получить доступ к OpenAIFileClient и загрузить два файла данных, описанных в предыдущем разделе конфигурации, сохраняя упоминание файла для окончательной очистки.

Console.WriteLine("Uploading files...");
OpenAIFileClient fileClient = client.GetOpenAIFileClient();
OpenAIFile fileDataCountryDetail = await fileClient.UploadFileAsync("PopulationByAdmin1.csv", FileUploadPurpose.Assistants);
OpenAIFile fileDataCountryList = await fileClient.UploadFileAsync("PopulationByCountry.csv", FileUploadPurpose.Assistants);

Перед созданием AzureAssistantAgent или OpenAIAssistantAgentубедитесь, что параметры конфигурации доступны и подготовьте ресурсы файлов.

Совет

Возможно, потребуется настроить пути к файлам в зависимости от расположения файлов.

# Let's form the file paths that we will use as part of file upload
csv_file_path_1 = os.path.join(
    os.path.dirname(os.path.dirname(os.path.realpath(__file__))),
    "resources",
    "PopulationByAdmin1.csv",
)

csv_file_path_2 = os.path.join(
    os.path.dirname(os.path.dirname(os.path.realpath(__file__))),
    "resources",
    "PopulationByCountry.csv",
)
# Create the client using Azure OpenAI resources and configuration
client, model = AzureAssistantAgent.setup_resources()

# Upload the files to the client
file_ids: list[str] = []
for path in [csv_file_path_1, csv_file_path_2]:
    with open(path, "rb") as file:
        file = await client.files.create(file=file, purpose="assistants")
        file_ids.append(file.id)

# Get the code interpreter tool and resources
code_interpreter_tools, code_interpreter_tool_resources = AzureAssistantAgent.configure_code_interpreter_tool(
    file_ids=file_ids
)

# Create the assistant definition
definition = await client.beta.assistants.create(
    model=model,
    instructions="""
        Analyze the available data to provide an answer to the user's question.
        Always format response using markdown.
        Always include a numerical index that starts at 1 for any lists or tables.
        Always sort lists in ascending order.
        """,
    name="SampleAssistantAgent",
    tools=code_interpreter_tools,
    tool_resources=code_interpreter_tool_resources,
)

Сначала мы настраиваем ресурсы Azure OpenAI для получения клиента и модели. Затем мы отправим CSV-файлы из указанных путей с помощью API файлов клиента. Затем мы настраиваем code_interpreter_tool, используя переданные идентификаторы файлов, которые при создании привязываются к помощнику, вместе с моделью, инструкциями и именем.

Функция в настоящее время недоступна в Java.

Определение агента

Теперь мы готовы создать экземпляр OpenAIAssistantAgent, сначала создав определение ассистента. Помощник настроен с помощью целевой модели инструкциии средства интерпретатора кода. Кроме того, мы явно ассоциируем два файла данных с инструментом Интерпретатор кода.

Console.WriteLine("Defining agent...");
AssistantClient assistantClient = client.GetAssistantClient();
        Assistant assistant =
            await assistantClient.CreateAssistantAsync(
                settings.AzureOpenAI.ChatModelDeployment,
                name: "SampleAssistantAgent",
                instructions:
                        """
                        Analyze the available data to provide an answer to the user's question.
                        Always format response using markdown.
                        Always include a numerical index that starts at 1 for any lists or tables.
                        Always sort lists in ascending order.
                        """,
                enableCodeInterpreter: true,
                codeInterpreterFileIds: [fileDataCountryList.Id, fileDataCountryDetail.Id]);

// Create agent
OpenAIAssistantAgent agent = new(assistant, assistantClient);

Теперь мы готовы создать экземпляр AzureAssistantAgent. Агент настраивается с помощью клиента и определения помощника.

# Create the agent using the client and the assistant definition
agent = AzureAssistantAgent(
    client=client,
    definition=definition,
)

Функция в настоящее время недоступна в Java.

Цикл чата

Наконец-то, мы можем координировать взаимодействие между пользователем и Agent. Сначала создайте AgentThread для поддержания состояния беседы, а также создайте пустой цикл.

Давайте также убедимся, что ресурсы удаляются в конце выполнения, чтобы свести к минимуму ненужные расходы.

Console.WriteLine("Creating thread...");
AssistantAgentThread agentThread = new();

Console.WriteLine("Ready!");

try
{
    bool isComplete = false;
    List<string> fileIds = [];
    do
    {

    } while (!isComplete);
}
finally
{
    Console.WriteLine();
    Console.WriteLine("Cleaning-up...");
    await Task.WhenAll(
        [
            agentThread.DeleteAsync(),
            assistantClient.DeleteAssistantAsync(assistant.Id),
            fileClient.DeleteFileAsync(fileDataCountryList.Id),
            fileClient.DeleteFileAsync(fileDataCountryDetail.Id),
        ]);
}
thread: AssistantAgentThread = None

try:
    is_complete: bool = False
    file_ids: list[str] = []
    while not is_complete:
        # agent interaction logic here
finally:
    print("\nCleaning up resources...")
    [await client.files.delete(file_id) for file_id in file_ids]
    await thread.delete() if thread else None
    await client.beta.assistants.delete(agent.id)

Функция в настоящее время недоступна в Java.

Теперь давайте зафиксируем входные данные пользователя в предыдущем цикле. В этом случае пустые входные данные будут игнорироваться, и термин EXIT будет сигнализировать о завершении беседы.

Console.WriteLine();
Console.Write("> ");
string input = Console.ReadLine();
if (string.IsNullOrWhiteSpace(input))
{
    continue;
}
if (input.Trim().Equals("EXIT", StringComparison.OrdinalIgnoreCase))
{
    isComplete = true;
    break;
}

var message = new ChatMessageContent(AuthorRole.User, input);

Console.WriteLine();
user_input = input("User:> ")
if not user_input:
    continue

if user_input.lower() == "exit":
    is_complete = True
    break

Функция в настоящее время недоступна в Java.

Перед вызовом ответа Agent давайте добавим некоторые вспомогательные функции для скачивания всех файлов, которые могут быть созданы Agent.

Здесь мы поместим содержимое файла в системно определённую временную директорию, а затем запускаем системное приложение средства просмотра.

private static async Task DownloadResponseImageAsync(OpenAIFileClient client, ICollection<string> fileIds)
{
    if (fileIds.Count > 0)
    {
        Console.WriteLine();
        foreach (string fileId in fileIds)
        {
            await DownloadFileContentAsync(client, fileId, launchViewer: true);
        }
    }
}

private static async Task DownloadFileContentAsync(OpenAIFileClient client, string fileId, bool launchViewer = false)
{
    OpenAIFile fileInfo = client.GetFile(fileId);
    if (fileInfo.Purpose == FilePurpose.AssistantsOutput)
    {
        string filePath =
            Path.Combine(
                Path.GetTempPath(),
                Path.GetFileName(Path.ChangeExtension(fileInfo.Filename, ".png")));

        BinaryData content = await client.DownloadFileAsync(fileId);
        await using FileStream fileStream = new(filePath, FileMode.CreateNew);
        await content.ToStream().CopyToAsync(fileStream);
        Console.WriteLine($"File saved to: {filePath}.");

        if (launchViewer)
        {
            Process.Start(
                new ProcessStartInfo
                {
                    FileName = "cmd.exe",
                    Arguments = $"/C start {filePath}"
                });
        }
    }
}
import os

async def download_file_content(agent, file_id: str):
    try:
        # Fetch the content of the file using the provided method
        response_content = await agent.client.files.content(file_id)

        # Get the current working directory of the file
        current_directory = os.path.dirname(os.path.abspath(__file__))

        # Define the path to save the image in the current directory
        file_path = os.path.join(
            current_directory,  # Use the current directory of the file
            f"{file_id}.png"  # You can modify this to use the actual filename with proper extension
        )

        # Save content to a file asynchronously
        with open(file_path, "wb") as file:
            file.write(response_content.content)

        print(f"File saved to: {file_path}")
    except Exception as e:
        print(f"An error occurred while downloading file {file_id}: {str(e)}")

async def download_response_image(agent, file_ids: list[str]):
    if file_ids:
        # Iterate over file_ids and download each one
        for file_id in file_ids:
            await download_file_content(agent, file_id)

Функция в настоящее время недоступна в Java.

Чтобы создать ответ Agent на входные данные пользователя, вызовите агента, предоставив сообщение AgentThread. В этом примере мы выбираем потоковый ответ и фиксируем все созданные ссылки на файлы для скачивания и проверки в конце цикла отклика. Важно отметить, что созданный код определяется наличием ключа метаданных в ответном сообщении, отличая его от ответа.

bool isCode = false;
await foreach (StreamingChatMessageContent response in agent.InvokeStreamingAsync(message, agentThread))
{
    if (isCode != (response.Metadata?.ContainsKey(OpenAIAssistantAgent.CodeInterpreterMetadataKey) ?? false))
    {
        Console.WriteLine();
        isCode = !isCode;
    }

    // Display response.
    Console.Write($"{response.Content}");

    // Capture file IDs for downloading.
    fileIds.AddRange(response.Items.OfType<StreamingFileReferenceContent>().Select(item => item.FileId));
}
Console.WriteLine();

// Download any files referenced in the response.
await DownloadResponseImageAsync(fileClient, fileIds);
fileIds.Clear();
is_code = False
last_role = None
async for response in agent.invoke_stream(messages=user_input, thread=thread):
    current_is_code = response.metadata.get("code", False)

    if current_is_code:
        if not is_code:
            print("\n\n```python")
            is_code = True
        print(response.content, end="", flush=True)
    else:
        if is_code:
            print("\n```")
            is_code = False
            last_role = None
        if hasattr(response, "role") and response.role is not None and last_role != response.role:
            print(f"\n# {response.role}: ", end="", flush=True)
            last_role = response.role
        print(response.content, end="", flush=True)
    file_ids.extend([
        item.file_id for item in response.items if isinstance(item, StreamingFileReferenceContent)
    ])
    thread = response.thread
if is_code:
    print("```\n")
print()

await download_response_image(agent, file_ids)
file_ids.clear()

Функция в настоящее время недоступна в Java.

финал

Объединяя все шаги, мы получаем окончательный код для этого примера. Полная реализация представлена ниже.

Попробуйте использовать эти предлагаемые входные данные:

  1. Сравните файлы, чтобы определить количество стран, у которых не указан штат или провинция, по сравнению с общим числом стран.
  2. Создайте таблицу для стран с определенным государством или провинцией. Включите количество штатов или провинций и общее население
  3. Предоставьте линейчатую диаграмму для стран, имена которых начинаются с одной буквы и отсортируют ось x по максимальному количеству до наименьшего (включая все страны).
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents.OpenAI;
using Microsoft.SemanticKernel.ChatCompletion;
using OpenAI.Assistants;
using OpenAI.Files;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace AgentsSample;

public static class Program
{
    public static async Task Main()
    {
        // Load configuration from environment variables or user secrets.
        Settings settings = new();

        // Initialize the clients
        AzureOpenAIClient client = OpenAIAssistantAgent.CreateAzureOpenAIClient(new AzureCliCredential(), new Uri(settings.AzureOpenAI.Endpoint));
        //OpenAIClient client = OpenAIAssistantAgent.CreateOpenAIClient(new ApiKeyCredential(settings.OpenAI.ApiKey)));
        AssistantClient assistantClient = client.GetAssistantClient();
        OpenAIFileClient fileClient = client.GetOpenAIFileClient();

        // Upload files
        Console.WriteLine("Uploading files...");
        OpenAIFile fileDataCountryDetail = await fileClient.UploadFileAsync("PopulationByAdmin1.csv", FileUploadPurpose.Assistants);
        OpenAIFile fileDataCountryList = await fileClient.UploadFileAsync("PopulationByCountry.csv", FileUploadPurpose.Assistants);

        // Define assistant
        Console.WriteLine("Defining assistant...");
        Assistant assistant =
            await assistantClient.CreateAssistantAsync(
                settings.AzureOpenAI.ChatModelDeployment,
                name: "SampleAssistantAgent",
                instructions:
                        """
                        Analyze the available data to provide an answer to the user's question.
                        Always format response using markdown.
                        Always include a numerical index that starts at 1 for any lists or tables.
                        Always sort lists in ascending order.
                        """,
                enableCodeInterpreter: true,
                codeInterpreterFileIds: [fileDataCountryList.Id, fileDataCountryDetail.Id]);

        // Create agent
        OpenAIAssistantAgent agent = new(assistant, assistantClient);

        // Create the conversation thread
        Console.WriteLine("Creating thread...");
        AssistantAgentThread agentThread = new();

        Console.WriteLine("Ready!");

        try
        {
            bool isComplete = false;
            List<string> fileIds = [];
            do
            {
                Console.WriteLine();
                Console.Write("> ");
                string input = Console.ReadLine();
                if (string.IsNullOrWhiteSpace(input))
                {
                    continue;
                }
                if (input.Trim().Equals("EXIT", StringComparison.OrdinalIgnoreCase))
                {
                    isComplete = true;
                    break;
                }

                var message = new ChatMessageContent(AuthorRole.User, input);

                Console.WriteLine();

                bool isCode = false;
                await foreach (StreamingChatMessageContent response in agent.InvokeStreamingAsync(message, agentThread))
                {
                    if (isCode != (response.Metadata?.ContainsKey(OpenAIAssistantAgent.CodeInterpreterMetadataKey) ?? false))
                    {
                        Console.WriteLine();
                        isCode = !isCode;
                    }

                    // Display response.
                    Console.Write($"{response.Content}");

                    // Capture file IDs for downloading.
                    fileIds.AddRange(response.Items.OfType<StreamingFileReferenceContent>().Select(item => item.FileId));
                }
                Console.WriteLine();

                // Download any files referenced in the response.
                await DownloadResponseImageAsync(fileClient, fileIds);
                fileIds.Clear();

            } while (!isComplete);
        }
        finally
        {
            Console.WriteLine();
            Console.WriteLine("Cleaning-up...");
            await Task.WhenAll(
                [
                    agentThread.DeleteAsync(),
                    assistantClient.DeleteAssistantAsync(assistant.Id),
                    fileClient.DeleteFileAsync(fileDataCountryList.Id),
                    fileClient.DeleteFileAsync(fileDataCountryDetail.Id),
                ]);
        }
    }

    private static async Task DownloadResponseImageAsync(OpenAIFileClient client, ICollection<string> fileIds)
    {
        if (fileIds.Count > 0)
        {
            Console.WriteLine();
            foreach (string fileId in fileIds)
            {
                await DownloadFileContentAsync(client, fileId, launchViewer: true);
            }
        }
    }

    private static async Task DownloadFileContentAsync(OpenAIFileClient client, string fileId, bool launchViewer = false)
    {
        OpenAIFile fileInfo = client.GetFile(fileId);
        if (fileInfo.Purpose == FilePurpose.AssistantsOutput)
        {
            string filePath =
                Path.Combine(
                    Path.GetTempPath(),
                    Path.GetFileName(Path.ChangeExtension(fileInfo.Filename, ".png")));

            BinaryData content = await client.DownloadFileAsync(fileId);
            await using FileStream fileStream = new(filePath, FileMode.CreateNew);
            await content.ToStream().CopyToAsync(fileStream);
            Console.WriteLine($"File saved to: {filePath}.");

            if (launchViewer)
            {
                Process.Start(
                    new ProcessStartInfo
                    {
                        FileName = "cmd.exe",
                        Arguments = $"/C start {filePath}"
                    });
            }
        }
    }
}
import asyncio
import logging
import os

from semantic_kernel.agents import AssistantAgentThread, AzureAssistantAgent
from semantic_kernel.contents import StreamingFileReferenceContent

logging.basicConfig(level=logging.ERROR)

"""
The following sample demonstrates how to create a simple,
OpenAI assistant agent that utilizes the code interpreter
to analyze uploaded files.
"""

# Let's form the file paths that we will later pass to the assistant
csv_file_path_1 = os.path.join(
    os.path.dirname(os.path.dirname(os.path.realpath(__file__))),
    "resources",
    "PopulationByAdmin1.csv",
)

csv_file_path_2 = os.path.join(
    os.path.dirname(os.path.dirname(os.path.realpath(__file__))),
    "resources",
    "PopulationByCountry.csv",
)


async def download_file_content(agent: AzureAssistantAgent, file_id: str):
    try:
        # Fetch the content of the file using the provided method
        response_content = await agent.client.files.content(file_id)

        # Get the current working directory of the file
        current_directory = os.path.dirname(os.path.abspath(__file__))

        # Define the path to save the image in the current directory
        file_path = os.path.join(
            current_directory,  # Use the current directory of the file
            f"{file_id}.png",  # You can modify this to use the actual filename with proper extension
        )

        # Save content to a file asynchronously
        with open(file_path, "wb") as file:
            file.write(response_content.content)

        print(f"File saved to: {file_path}")
    except Exception as e:
        print(f"An error occurred while downloading file {file_id}: {str(e)}")


async def download_response_image(agent: AzureAssistantAgent, file_ids: list[str]):
    if file_ids:
        # Iterate over file_ids and download each one
        for file_id in file_ids:
            await download_file_content(agent, file_id)


async def main():
    # Create the client using Azure OpenAI resources and configuration
    client, model = AzureAssistantAgent.setup_resources()

    # Upload the files to the client
    file_ids: list[str] = []
    for path in [csv_file_path_1, csv_file_path_2]:
        with open(path, "rb") as file:
            file = await client.files.create(file=file, purpose="assistants")
            file_ids.append(file.id)

    # Get the code interpreter tool and resources
    code_interpreter_tools, code_interpreter_tool_resources = AzureAssistantAgent.configure_code_interpreter_tool(
        file_ids=file_ids
    )

    # Create the assistant definition
    definition = await client.beta.assistants.create(
        model=model,
        instructions="""
            Analyze the available data to provide an answer to the user's question.
            Always format response using markdown.
            Always include a numerical index that starts at 1 for any lists or tables.
            Always sort lists in ascending order.
            """,
        name="SampleAssistantAgent",
        tools=code_interpreter_tools,
        tool_resources=code_interpreter_tool_resources,
    )

    # Create the agent using the client and the assistant definition
    agent = AzureAssistantAgent(
        client=client,
        definition=definition,
    )

    thread: AssistantAgentThread = None

    try:
        is_complete: bool = False
        file_ids: list[str] = []
        while not is_complete:
            user_input = input("User:> ")
            if not user_input:
                continue

            if user_input.lower() == "exit":
                is_complete = True
                break

            is_code = False
            last_role = None
            async for response in agent.invoke_stream(messages=user_input, thread=thread):
                current_is_code = response.metadata.get("code", False)

                if current_is_code:
                    if not is_code:
                        print("\n\n```python")
                        is_code = True
                    print(response.content, end="", flush=True)
                else:
                    if is_code:
                        print("\n```")
                        is_code = False
                        last_role = None
                    if hasattr(response, "role") and response.role is not None and last_role != response.role:
                        print(f"\n# {response.role}: ", end="", flush=True)
                        last_role = response.role
                    print(response.content, end="", flush=True)
                file_ids.extend([
                    item.file_id for item in response.items if isinstance(item, StreamingFileReferenceContent)
                ])
                thread = response.thread
            if is_code:
                print("```\n")
            print()

            await download_response_image(agent, file_ids)
            file_ids.clear()

    finally:
        print("\nCleaning up resources...")
        [await client.files.delete(file_id) for file_id in file_ids]
        await thread.delete() if thread else None
        await client.beta.assistants.delete(agent.id)


if __name__ == "__main__":
    asyncio.run(main())

Вы можете найти полный код, как показано выше, в нашем репозитории.

Функция в настоящее время недоступна в Java.

Дальнейшие шаги