How to apply streaming in azure openai dotnet web application?

题意:"如何在 Azure OpenAI 的 .NET Web 应用程序中应用流式处理?"

问题背景:

I want to create a web api backend that stream openai completion responses.

"我想创建一个 Web API 后端,用于流式传输 OpenAI 的完成响应。"

How can I apply the following solution to a web api action in controller?

"如何将以下解决方案应用到控制器中的 Web API 操作?"

cs 复制代码
var client = new OpenAIClient(nonAzureOpenAIApiKey, new OpenAIClientOptions());
var chatCompletionsOptions = new ChatCompletionsOptions()
{
    DeploymentName = "gpt-3.5-turbo", // Use DeploymentName for "model" with non-Azure clients
    Messages =
    {
        new ChatRequestSystemMessage("You are a helpful assistant. You will talk like a pirate."),
        new ChatRequestUserMessage("Can you help me?"),
        new ChatRequestAssistantMessage("Arrrr! Of course, me hearty! What can I do for ye?"),
        new ChatRequestUserMessage("What's the best way to train a parrot?"),
    }
};

await foreach (StreamingChatCompletionsUpdate chatUpdate in client.GetChatCompletionsStreaming(chatCompletionsOptions))
{
    if (chatUpdate.Role.HasValue)
    {
        Console.Write($"{chatUpdate.Role.Value.ToString().ToUpperInvariant()}: ");
    }
    if (!string.IsNullOrEmpty(chatUpdate.ContentUpdate))
    {
        Console.Write(chatUpdate.ContentUpdate);
    }
}

问题解决:

You can simply wrap your code inside the controller

"您可以简单地将代码包裹在控制器内。"

cs 复制代码
using Microsoft.AspNetCore.Mvc;
using OpenAI;
using OpenAI.Chat;
using System.Collections.Generic;
using System.Threading.Tasks;

[ApiController]
[Route("[controller]")]
public class ChatController : ControllerBase
{
    [HttpGet]
    public async Task<ActionResult<List<string>>> GetChatCompletions()
    {
        var client = new OpenAIClient(nonAzureOpenAIApiKey, new OpenAIClientOptions());
        var chatCompletionsOptions = new ChatCompletionsOptions()
        {
            DeploymentName = "gpt-3.5-turbo",
            Messages =
            {
                new ChatRequestSystemMessage("You are a helpful assistant. You will talk like a pirate."),
                new ChatRequestUserMessage("Can you help me?"),
                new ChatRequestAssistantMessage("Arrrr! Of course, me hearty! What can I do for ye?"),
                new ChatRequestUserMessage("What's the best way to train a parrot?"),
            }
        };

        var responses = new List<string>();

        await foreach (StreamingChatCompletionsUpdate chatUpdate in client.GetChatCompletionsStreaming(chatCompletionsOptions))
        {
            if (chatUpdate.Role.HasValue)
            {
                responses.Add($"{chatUpdate.Role.Value.ToString().ToUpperInvariant()}: ");
            }
            if (!string.IsNullOrEmpty(chatUpdate.ContentUpdate))
            {
                responses.Add(chatUpdate.ContentUpdate);
            }
        }

        return Ok(responses);
    }
}

If you don't want to hardcode the message and pass that as a body then you can do something like this

"如果您不想将消息硬编码并作为主体传递,那么您可以这样做"

cs 复制代码
using Microsoft.AspNetCore.Mvc;
using OpenAI;
using OpenAI.Chat;
using System.Collections.Generic;
using System.Threading.Tasks;

[ApiController]
[Route("[controller]")]
public class ChatController : ControllerBase
{
    public class ChatRequest
    {
        public List<string> Messages { get; set; }
    }

    [HttpPost]
    public async Task<ActionResult<List<string>>> PostChatCompletions([FromBody] ChatRequest request)
    {
        var client = new OpenAIClient(nonAzureOpenAIApiKey, new OpenAIClientOptions());
        var chatCompletionsOptions = new ChatCompletionsOptions()
        {
            DeploymentName = "gpt-3.5-turbo",
            Messages = new List<ChatRequestMessage>()
        };

        foreach (var message in request.Messages)
        {
            chatCompletionsOptions.Messages.Add(new ChatRequestUserMessage(message));
        }

        var responses = new List<string>();

        await foreach (StreamingChatCompletionsUpdate chatUpdate in client.GetChatCompletionsStreaming(chatCompletionsOptions))
        {
            if (chatUpdate.Role.HasValue)
            {
                responses.Add($"{chatUpdate.Role.Value.ToString().ToUpperInvariant()}: ");
            }
            if (!string.IsNullOrEmpty(chatUpdate.ContentUpdate))
            {
                responses.Add(chatUpdate.ContentUpdate);
            }
        }

        return Ok(responses);
    }
}

Remember the above implementation of the API does not support streaming responses. It waits for all the chat completions to be received from the OpenAI API, then sends them all at once to the client.

"请记住,上述 API 实现不支持流式响应。它会等待从 OpenAI API 接收到所有聊天完成后,再将它们一次性发送给客户端。"

Streaming responses to the client as they are received from the OpenAI API would require a different approach. This could be achieved using Server-Sent Events (SSE) or a similar technology, but it's important to note that not all clients and network environments support these technologies.

"将从 OpenAI API 接收到的响应流式传输给客户端需要采用不同的方法。这可以通过使用服务器发送事件 (SSE) 或类似技术来实现,但需要注意的是,并非所有客户端和网络环境都支持这些技术。"

Here's a simplified example of how you could implement this using Server-Sent Events in ASP.NET Core:

"以下是一个使用服务器发送事件 (SSE) 在 ASP.NET Core 中实现此功能的简化示例:"

cs 复制代码
[HttpPost]
public async Task PostChatCompletions([FromBody] ChatRequest request)
{
    var client = new OpenAIClient(nonAzureOpenAIApiKey, new OpenAIClientOptions());
    var chatCompletionsOptions = new ChatCompletionsOptions()
    {
        DeploymentName = "gpt-3.5-turbo",
        Messages = new List<ChatRequestMessage>()
    };

    foreach (var message in request.Messages)
    {
        chatCompletionsOptions.Messages.Add(new ChatRequestUserMessage(message));
    }

    Response.Headers.Add("Content-Type", "text/event-stream");

    await foreach (StreamingChatCompletionsUpdate chatUpdate in client.GetChatCompletionsStreaming(chatCompletionsOptions))
    {
        if (chatUpdate.Role.HasValue)
        {
            await Response.WriteAsync($"data: {chatUpdate.Role.Value.ToString().ToUpperInvariant()}: \n\n");
        }
        if (!string.IsNullOrEmpty(chatUpdate.ContentUpdate))
        {
            await Response.WriteAsync($"data: {chatUpdate.ContentUpdate}\n\n");
        }
    }
}
相关推荐
玫瑰互动GEO6 小时前
GEM优化广告六要素: 从命名一致到落地页双对齐的工程化落地
人工智能·ai·chatgpt·gem优化
Luhui Dev6 小时前
几何画板工程持久化与版本管理方案:变更监听、自动保存与版本恢复
人工智能·数学·ai·agent·luhuidev
强哥聊算力7 小时前
《算力江湖·Intel帝国往事》第三集:安迪·格鲁夫的铁血时代:Intel为什么能把对手逼到墙角?
运维·人工智能·科技·算法·ai·gpu算力
海宇数据8 小时前
零信任架构实战:基于海宇双人婚姻评估查询构建自动化配偶签约一致性审查网关
人工智能·ai·工具分享
胖纸不争8 小时前
EnergyStarZ:让 Windows 后台进程给前台让路的能效管理器(v1.2 发布)
windows·性能优化·c#·win32·ef core
我才是银古8 小时前
把 666 个会话摊开看:一份 DSH 使用经验与教训的复盘
ai·deepseek·dsh
空堂与归9 小时前
国产开源登顶全球第一,1.3B OXR 登顶三榜:RSI 闭环重塑文档解析
人工智能·ai·agent
曹牧9 小时前
C#:The operation has timed out
开发语言·c#
He BianGu9 小时前
【WPF-Control教程】IOC 依赖注入
c#·wpf·wpf-control
He BianGu10 小时前
【WPF-Control教程】H.Extensions.Behvaiors 开发文档
c#·wpf·wpf-control