次の方法で共有


方法: 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

重要

Visual Studio で NuGet パッケージを管理する場合は、 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>

さらに、Grimms-The-King-of-the-Golden-Mountain.txtからGrimms-The-Water-of-Life.txtGrimms-The-White-Snake.txt、およびLearnResourcesパブリック ドメインのコンテンツをコピーします。 これらのファイルをプロジェクト フォルダーに追加し、出力ディレクトリにコピーするように構成します。

  <ItemGroup>
    <None Include="Grimms-The-King-of-the-Golden-Mountain.txt">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
    <None Include="Grimms-The-Water-of-Life.txt">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
    <None Include="Grimms-The-White-Snake.txt">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
  </ItemGroup>

まず、スクリプト (.py ファイル) とサンプル リソースを保持するフォルダーを作成します。 .py ファイルの先頭に次のインポートを含めます。

import asyncio
import os

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

さらに、Grimms-The-King-of-the-Golden-Mountain.txtからGrimms-The-Water-of-Life.txtGrimms-The-White-Snake.txt、およびLearnResourcesパブリック ドメインのコンテンツをコピーします。 これらのファイルをプロジェクト フォルダーに追加します。

機能は現在 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" "https://lightspeed-team-shared-openai-eastus.openai.azure.com/"
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 ファイルを作成することです。

Azure OpenAI または OpenAI の .env ファイルで次の設定を構成します。

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 Assistants には、少なくとも 2024-05-01-preview の API バージョンが必要です。 新機能が導入されると、それに応じて API バージョンが更新されます。 この執筆時点では、最新バージョンは 2025-01-01-preview です。 最新のバージョン管理の詳細については、Azure OpenAI API プレビュー ライフサイクルを参照してください。

構成が完了すると、それぞれの AI サービス クラスが必要な変数を取得し、インスタンス化中にそれらを使用します。

機能は現在 Java では使用できません。

コーディング

このサンプルのコーディング プロセスには、次のものが含まれます。

  1. セットアップ - 設定とプラグインの初期化。
  2. エージェント定義 - テンプレート化された命令とプラグインを使用して_Chat_CompletionAgentを作成します。
  3. Chat ループ - ユーザー/エージェントの対話を促進するループを記述します。

完全なコード例については、「 Final 」セクションを参照してください。 完全な実装については、そのセクションを参照してください。

セットアップ

OpenAIAssistantAgentを作成する前に、構成設定が使用可能であることを確認し、ファイル リソースを準備します。

前の Settings セクションで参照されている クラスをインスタンス化します。 設定を使用して、ファイルのアップロードおよびAzureOpenAIClientに使用するVectorStoreを作成します。

Settings settings = new();

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

Assistant エージェントの静的メソッド create_client() は、必要な構成に基づいてクライアントを作成し、返すことを処理します。 Pydantic 設定は、環境変数から、または .env ファイルから最初に環境変数を読み込むのに使用されます。 api_keyapi_versiondeployment_name、または endpointを渡すことができます。これは、構成された環境変数よりも優先されます。

# Create the client using Azure OpenAI resources and configuration
client = AzureAssistantAgent.create_client()

機能は現在 Java では使用できません。

次に、 File Search ツールで使用する空の_Vector ストアを作成します。

AzureOpenAIClientを使用してVectorStoreClientにアクセスし、VectorStoreを作成します。

Console.WriteLine("Creating store...");
VectorStoreClient storeClient = client.GetVectorStoreClient();
CreateVectorStoreOperation operation = await storeClient.CreateVectorStoreAsync(waitUntilCompleted: true);
string storeId = operation.VectorStoreId;
# Upload the files to the client
file_ids: list[str] = []
for path in [get_filepath_for_filename(filename) for filename in filenames]:
    with open(path, "rb") as file:
        file = await client.files.create(file=file, purpose="assistants")
        file_ids.append(file.id)

vector_store = await client.vector_stores.create(
    name="assistant_search",
    file_ids=file_ids,
)

# Get the file search tool and resources
file_search_tools, file_search_tool_resources = AzureAssistantAgent.configure_file_search_tool(
    vector_store_ids=vector_store.id
)

機能は現在 Java では使用できません。

前の Configuration セクションで説明した 3 つのコンテンツ ファイルを宣言しましょう。

private static readonly string[] _fileNames =
    [
        "Grimms-The-King-of-the-Golden-Mountain.txt",
        "Grimms-The-Water-of-Life.txt",
        "Grimms-The-White-Snake.txt",
    ];
filenames = [
    "Grimms-The-King-of-the-Golden-Mountain.txt",
    "Grimms-The-Water-of-Life.txt",
    "Grimms-The-White-Snake.txt",
]

機能は現在 Java では使用できません。

次に、これらのファイルをアップロードし、Vector Store に追加します以前に作成したVectorStoreClient クライアントを使用して各ファイルをOpenAIFileClientと共にアップロードし結果の File References を保持して、Vector Store に追加します。

Dictionary<string, OpenAIFile> fileReferences = [];

Console.WriteLine("Uploading files...");
OpenAIFileClient fileClient = client.GetOpenAIFileClient();
foreach (string fileName in _fileNames)
{
    OpenAIFile fileInfo = await fileClient.UploadFileAsync(fileName, FileUploadPurpose.Assistants);
    await storeClient.AddFileToVectorStoreAsync(storeId, fileInfo.Id, waitUntilCompleted: true);
    fileReferences.Add(fileInfo.Id, fileInfo);
}

機能は現在 Java では使用できません。

エージェント定義

これで、OpenAIAssistantAgentをインスタンス化する準備ができました。 エージェントは、ターゲット モデル、 Instructions、および File Search ツールを有効にして構成されます。 さらに、 Vector StoreFile Search ツールに明示的に関連付けます。

AzureOpenAIClientの作成の一環として、OpenAIAssistantAgentをもう一度利用します。

Console.WriteLine("Defining assistant...");
Assistant assistant =
    await assistantClient.CreateAssistantAsync(
        settings.AzureOpenAI.ChatModelDeployment,
        name: "SampleAssistantAgent",
        instructions:
                """
                The document store contains the text of fictional stories.
                Always analyze the document store to provide an answer to the user's question.
                Never rely on your knowledge of stories not included in the document store.
                Always format response using markdown.
                """,
        enableFileSearch: true,
        vectorStoreId: storeId);

// Create agent
OpenAIAssistantAgent agent = new(assistant, assistantClient);
# Create the assistant definition
definition = await client.beta.assistants.create(
    model=AzureOpenAISettings().chat_deployment_name,
    instructions="""
        The document store contains the text of fictional stories.
        Always analyze the document store to provide an answer to the user's question.
        Never rely on your knowledge of stories not included in the document store.
        Always format response using markdown.
        """,
    name="SampleAssistantAgent",
    tools=file_search_tools,
    tool_resources=file_search_tool_resources,
)

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

機能は現在 Java では使用できません。

Chat ループ

最後に、ユーザーと Agentの間の相互作用を調整できます。 まず、会話状態を維持するための AgentThread を作成し、空のループを作成します。

また、不要な料金を最小限に抑えるために、実行の終了時にリソースが削除されるようにしましょう。

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

Console.WriteLine("Ready!");

try
{
    bool isComplete = false;
    do
    {
        // Processing occurs here
    } while (!isComplete);
}
finally
{
    Console.WriteLine();
    Console.WriteLine("Cleaning-up...");
    await Task.WhenAll(
        [
            agentThread.DeleteAsync();
            assistantClient.DeleteAssistantAsync(assistant.Id),
            storeClient.DeleteVectorStoreAsync(storeId),
            ..fileReferences.Select(fileReference => fileClient.DeleteFileAsync(fileReference.Key))
        ]);
}
# If no thread is provided, a new thread will be
# created and returned with the initial response
thread: AssistantAgentThread = None

try:
    is_complete: bool = False
    while not is_complete:
        # Processing occurs here

finally:
    print("\nCleaning up resources...")
    [await client.files.delete(file_id) for file_id in file_ids]
    await client.vector_stores.delete(vector_store.id)
    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 応答を呼び出す前に、Unicode 注釈角かっこを ANSI 角かっこに再フォーマットするヘルパー メソッドを追加しましょう。

private static string ReplaceUnicodeBrackets(this string content) =>
    content?.Replace('【', '[').Replace('】', ']');
# No special handling required.

機能は現在 Java では使用できません。

ユーザー入力に対する Agent 応答を生成するには、メッセージとエージェント スレッドを指定してエージェントを呼び出します。 この例では、ストリーム応答を選択し、応答サイクルの最後に表示するために、関連付けられている 引用注釈 をキャプチャします。 ストリーミングされた各チャンクは、前のヘルパー メソッドを使用して再フォーマットされていることに注意してください。

List<StreamingAnnotationContent> footnotes = [];
await foreach (StreamingChatMessageContent chunk in agent.InvokeStreamingAsync(message, agentThread))
{
    // Capture annotations for footnotes
    footnotes.AddRange(chunk.Items.OfType<StreamingAnnotationContent>());

    // Render chunk with replacements for unicode brackets.
    Console.Write(chunk.Content.ReplaceUnicodeBrackets());
}

Console.WriteLine();

// Render footnotes for captured annotations.
if (footnotes.Count > 0)
{
    Console.WriteLine();
    foreach (StreamingAnnotationContent footnote in footnotes)
    {
        Console.WriteLine($"#{footnote.Quote.ReplaceUnicodeBrackets()} - {fileReferences[footnote.FileId!].Filename} (Index: {footnote.StartIndex} - {footnote.EndIndex})");
    }
}
footnotes: list[StreamingAnnotationContent] = []
async for response in agent.invoke_stream(messages=user_input, thread=thread):
    thread = response.thread
    footnotes.extend([item for item in response.items if isinstance(item, StreamingAnnotationContent)])

    print(f"{response.content}", end="", flush=True)

print()

if len(footnotes) > 0:
    for footnote in footnotes:
        print(
            f"\n`{footnote.quote}` => {footnote.file_id} "
            f"(Index: {footnote.start_index} - {footnote.end_index})"
        )

機能は現在 Java では使用できません。

最終

すべての手順をまとめて、この例の最後のコードを作成します。 完全な実装を以下に示します。

次の推奨される入力を使用してみてください。

  1. 各ストーリーの段落数は何ですか?
  2. ストーリーごとに主人公とアンタゴニストを識別するテーブルを作成します。
  3. 白いヘビの道徳は何ですか?
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;
using Microsoft.SemanticKernel.Agents.OpenAI;
using Microsoft.SemanticKernel.ChatCompletion;
using OpenAI.Assistants;
using OpenAI.Files;
using OpenAI.VectorStores;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace AgentsSample;

public static class Program
{
    private static readonly string[] _fileNames =
        [
            "Grimms-The-King-of-the-Golden-Mountain.txt",
            "Grimms-The-Water-of-Life.txt",
            "Grimms-The-White-Snake.txt",
        ];

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
    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();
        VectorStoreClient storeClient = client.GetVectorStoreClient();

        // Create the vector store
        Console.WriteLine("Creating store...");
        CreateVectorStoreOperation operation = await storeClient.CreateVectorStoreAsync(waitUntilCompleted: true);
        string storeId = operation.VectorStoreId;

        // Upload files and retain file references.
        Console.WriteLine("Uploading files...");
        Dictionary<string, OpenAIFile> fileReferences = [];
        foreach (string fileName in _fileNames)
        {
            OpenAIFile fileInfo = await fileClient.UploadFileAsync(fileName, FileUploadPurpose.Assistants);
            await storeClient.AddFileToVectorStoreAsync(storeId, fileInfo.Id, waitUntilCompleted: true);
            fileReferences.Add(fileInfo.Id, fileInfo);
        }

        // Define assistant
        Console.WriteLine("Defining assistant...");
        Assistant assistant =
            await assistantClient.CreateAssistantAsync(
                settings.AzureOpenAI.ChatModelDeployment,
                name: "SampleAssistantAgent",
                instructions:
                        """
                        The document store contains the text of fictional stories.
                        Always analyze the document store to provide an answer to the user's question.
                        Never rely on your knowledge of stories not included in the document store.
                        Always format response using markdown.
                        """,
                enableFileSearch: true,
                vectorStoreId: storeId);

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

                List<StreamingAnnotationContent> footnotes = [];
                await foreach (StreamingChatMessageContent chunk in agent.InvokeStreamingAsync(message, agentThread))
                {
                    // Capture annotations for footnotes
                    footnotes.AddRange(chunk.Items.OfType<StreamingAnnotationContent>());

                    // Render chunk with replacements for unicode brackets.
                    Console.Write(chunk.Content.ReplaceUnicodeBrackets());
                }

                Console.WriteLine();

                // Render footnotes for captured annotations.
                if (footnotes.Count > 0)
                {
                    Console.WriteLine();
                    foreach (StreamingAnnotationContent footnote in footnotes)
                    {
                        Console.WriteLine($"#{footnote.Quote.ReplaceUnicodeBrackets()} - {fileReferences[footnote.FileId!].Filename} (Index: {footnote.StartIndex} - {footnote.EndIndex})");
                    }
                }
            } while (!isComplete);
        }
        finally
        {
            Console.WriteLine();
            Console.WriteLine("Cleaning-up...");
            await Task.WhenAll(
                [
                    agentThread.DeleteAsync(),
                    assistantClient.DeleteAssistantAsync(assistant.Id),
                    storeClient.DeleteVectorStoreAsync(storeId),
                    ..fileReferences.Select(fileReference => fileClient.DeleteFileAsync(fileReference.Key))
                ]);
        }
    }

    private static string ReplaceUnicodeBrackets(this string content) =>
        content?.Replace('【', '[').Replace('】', ']');
}
# Copyright (c) Microsoft. All rights reserved.

import asyncio
import os

from semantic_kernel.agents import AssistantAgentThread, AzureAssistantAgent
from semantic_kernel.connectors.ai.open_ai import AzureOpenAISettings
from semantic_kernel.contents import StreamingAnnotationContent

"""
The following sample demonstrates how to create a simple,
OpenAI assistant agent that utilizes the vector store
to answer questions based on the uploaded documents.

This is the full code sample for the Semantic Kernel Learn Site: How-To: Open AI Assistant Agent File Search

https://learn.microsoft.com/semantic-kernel/frameworks/agent/examples/example-assistant-search?pivots=programming-language-python
"""


def get_filepath_for_filename(filename: str) -> str:
    base_directory = os.path.join(
        os.path.dirname(os.path.dirname(os.path.realpath(__file__))),
        "resources",
    )
    return os.path.join(base_directory, filename)


filenames = [
    "Grimms-The-King-of-the-Golden-Mountain.txt",
    "Grimms-The-Water-of-Life.txt",
    "Grimms-The-White-Snake.txt",
]


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

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

    vector_store = await client.vector_stores.create(
        name="assistant_search",
        file_ids=file_ids,
    )

    # Get the file search tool and resources
    file_search_tools, file_search_tool_resources = AzureAssistantAgent.configure_file_search_tool(
        vector_store_ids=vector_store.id
    )

    # Create the assistant definition
    definition = await client.beta.assistants.create(
        model=AzureOpenAISettings().chat_deployment_name,
        instructions="""
            The document store contains the text of fictional stories.
            Always analyze the document store to provide an answer to the user's question.
            Never rely on your knowledge of stories not included in the document store.
            Always format response using markdown.
            """,
        name="SampleAssistantAgent",
        tools=file_search_tools,
        tool_resources=file_search_tool_resources,
    )

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

    thread: AssistantAgentThread | None = None

    try:
        is_complete: bool = False
        while not is_complete:
            user_input = input("User:> ")
            if not user_input:
                continue

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

            footnotes: list[StreamingAnnotationContent] = []
            async for response in agent.invoke_stream(messages=user_input, thread=thread):
                footnotes.extend([item for item in response.items if isinstance(item, StreamingAnnotationContent)])

                print(f"{response.content}", end="", flush=True)
                thread = response.thread

            print()

            if len(footnotes) > 0:
                for footnote in footnotes:
                    print(
                        f"\n`{footnote.quote}` => {footnote.file_id} "
                        f"(Index: {footnote.start_index} - {footnote.end_index})"
                    )

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


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

上記のように、完全な コードがリポジトリにあります。

機能は現在 Java では使用できません。

次のステップ