使用 .NET 创建最小的 AI 助手

在本快速入门中,你将了解如何使用 OpenAI 或 Azure OpenAI SDK 库创建最少的 AI 助手。 AI 助手提供代理功能,帮助用户使用 AI 工具和模型完成任务。 在前面的部分中,你将了解以下内容:

  • AI 助手的核心组件和概念
  • 如何使用 Azure OpenAI SDK 创建助手
  • 如何增强和自定义助手的功能

先决条件

AI 助手的核心组件

AI 助手是围绕与用户的对话线程构建的。 用户向会话线程上的助手发送提示,该提示指示助手使用其可用的工具完成任务。 助手可以处理和分析数据、做出决策以及与用户或其他系统交互以实现特定目标。 大多数助手包括以下组件:

组件 说明
助手 使用 Azure OpenAI 模型、管理聊天线程以及利用已配置工具的核心 AI 客户端和逻辑。
线程 助理和用户之间的对话会话。 线程存储消息并自动处理截断,以便将内容放入模型的上下文中。
消息 由助理或用户创建的消息。 消息可以包括文本、图像和其他文件。 消息作为列表存储在线程上。
运行 激活助手以根据线程的内容开始运行。 助手使用其配置和线程的消息通过调用模型和工具来执行任务。 作为运行的一部分,助手会将消息追加到线程。
运行步骤 助手在运行期间所采取的步骤的详细列表。 助手可以在运行期间调用工具或创建消息。 通过检查运行步骤,可以了解助手如何获取其最终结果。

还可以将助手配置为并行使用多个工具来完成任务,包括:

  • 代码解释器工具:在沙盒执行环境中编写和运行代码。
  • 调用的函数:运行在代码中定义的本地自定义函数。
  • 文件搜索功能:使用模型外部的知识来增强助手能力。

通过了解这些核心组件及其交互方式,可以构建和自定义功能强大的 AI 助手以满足你的特定需求。

创建 .NET 应用

完成以下步骤以创建 .NET 控制台应用并添加使用助手所需的包:

  1. 在终端窗口中,导航到设备上的空目录,并使用 dotnet new 命令创建新应用:

    dotnet new console -o AIAssistant
    
  2. OpenAI 包添加到应用:

    dotnet add package OpenAI --prerelease
    
  3. 在所选编辑器中打开新应用,例如 Visual Studio Code。

    code .
    
  1. 在终端窗口中,导航到设备上的空目录,并使用 dotnet new 命令创建新应用:

    dotnet new console -o AIAssistant
    
  2. Azure.AI.OpenAI 包添加到应用:

    dotnet add package Azure.AI.OpenAI --prerelease
    
  3. 在所选编辑器中打开新应用,例如 Visual Studio Code。

    code .
    

创建 AI 助手客户端

  1. Program.cs打开该文件,将文件的内容替换为以下代码以创建所需的客户端:

    using OpenAI;
    using OpenAI.Assistants;
    using OpenAI.Files;
    using Azure.AI.OpenAI;
    using Azure.Identity;
    
    // Create the OpenAI client
    OpenAIClient openAIClient = new("your-apy-key");
    
    // For Azure OpenAI, use the following client instead:
    AzureOpenAIClient azureAIClient = new(
            new Uri("your-azure-openai-endpoint"),
            new DefaultAzureCredential());
    
    #pragma warning disable OPENAI001
    AssistantClient assistantClient = openAIClient.GetAssistantClient();
    OpenAIFileClient fileClient = openAIClient.GetOpenAIFileClient();
    
  2. 创建内存中示例文档并将其上传到 OpenAIFileClient

    // Create an in-memory document to upload to the file client
    using Stream document = BinaryData.FromBytes("""
        {
            "description": "This document contains the sale history data for Contoso products.",
            "sales": [
                {
                    "month": "January",
                    "by_product": {
                        "113043": 15,
                        "113045": 12,
                        "113049": 2
                    }
                },
                {
                    "month": "February",
                    "by_product": {
                        "113045": 22
                    }
                },
                {
                    "month": "March",
                    "by_product": {
                        "113045": 16,
                        "113055": 5
                    }
                }
            ]
        }
        """u8.ToArray()).ToStream();
    
    // Upload the document to the file client
    OpenAIFile salesFile = fileClient.UploadFile(
        document,
        "monthly_sales.json",
        FileUploadPurpose.Assistants);
    
  3. 通过 AssistantCreationOptions启用文件搜索和代码解释器工具功能:

    // Configure the assistant options
    AssistantCreationOptions assistantOptions = new()
    {
        Name = "Example: Contoso sales RAG",
        Instructions =
            "You are an assistant that looks up sales data and helps visualize the information based"
            + " on user queries. When asked to generate a graph, chart, or other visualization, use"
            + " the code interpreter tool to do so.",
        Tools =
        {
            new FileSearchToolDefinition(), // Enable the assistant to search and access files
            new CodeInterpreterToolDefinition(), // Enable the assistant to run code for data analysis
        },
        ToolResources = new()
        {
            FileSearch = new()
            {
                NewVectorStores =
                {
                    new VectorStoreCreationHelper([salesFile.Id]),
                }
            }
        },
    };
    
  4. 创建 Assistant 和线程来管理用户与助手之间的交互:

    // Create the assistant
    Assistant assistant = assistantClient.CreateAssistant("gpt-4o", assistantOptions);
    
    // Configure and create the conversation thread
    ThreadCreationOptions threadOptions = new()
    {
        InitialMessages = { "How well did product 113045 sell in February? Graph its trend over time." }
    };
    
    ThreadRun threadRun = assistantClient.CreateThreadAndRun(assistant.Id, threadOptions);
    
    // Sent the prompt and monitor progress until the thread run is complete
    do
    {
        Thread.Sleep(TimeSpan.FromSeconds(1));
        threadRun = assistantClient.GetRun(threadRun.ThreadId, threadRun.Id);
    }
    while (!threadRun.Status.IsTerminal);
    
    // Get the messages from the thread run
    var messages = assistantClient.GetMessagesAsync(
        threadRun.ThreadId,
        new MessageCollectionOptions()
        {
            Order = MessageCollectionOrder.Ascending
        });
    
  5. 打印消息,并从与助手的对话中保存生成的图像:

    // Process the messages from the assistant
    await foreach (ThreadMessage message in messages)
    {
        // Print out the messages from the assistant
        Console.Write($"[{message.Role.ToString().ToUpper()}]: ");
        foreach (MessageContent contentItem in message.Content)
        {
            if (!string.IsNullOrEmpty(contentItem.Text))
            {
                Console.WriteLine($"{contentItem.Text}");
    
                if (contentItem.TextAnnotations.Count > 0)
                {
                    Console.WriteLine();
                }
    
                // Include annotations, if any
                foreach (TextAnnotation annotation in contentItem.TextAnnotations)
                {
                    if (!string.IsNullOrEmpty(annotation.InputFileId))
                    {
                        Console.WriteLine($"* File citation, file ID: {annotation.InputFileId}");
                    }
                    if (!string.IsNullOrEmpty(annotation.OutputFileId))
                    {
                        Console.WriteLine($"* File output, new file ID: {annotation.OutputFileId}");
                    }
                }
            }
            // Save the generated image file
            if (!string.IsNullOrEmpty(contentItem.ImageFileId))
            {
                OpenAIFile imageInfo = fileClient.GetFile(contentItem.ImageFileId);
                BinaryData imageBytes = fileClient.DownloadFile(contentItem.ImageFileId);
                using FileStream stream = File.OpenWrite($"{imageInfo.Filename}.png");
                imageBytes.ToStream().CopyTo(stream);
    
                Console.WriteLine($"<image: {imageInfo.Filename}.png>");
            }
        }
        Console.WriteLine();
    }
    

    在应用 bin 目录中找到并打开保存的图像,应如下所示:

    显示 AI 模型生成的可视化效果的图形。

后续步骤