使用 .NET 开发 AI 应用(5): 创建第一个 AI 聊天机器人应用

目录

前端页面设计

后端逻辑实现

结论


 

文末附全部源代码

(1):踏上旅程

(2):引入 Semantic Kernel 框架

(3): 创建第一个 AI 应用

(4):提示模板

在前面的章节中,我们探索了构建一个基础的问答系统。然而,在当今的人工智能领域,更为流行的是类似于ChatGPT这样的聊天机器人。本章将指导你如何使用.NET技术开发一个类似的聊天机器人应用程序。

前端页面设计

Gradio.Net提供了一个内置的Chatbot聊天机器人组件,为了增强用户体验,我们还将添加一个文本框,使用户能够输入他们的问题或命令:

var chatbot = gr.Chatbot();
var txt = gr.Textbox(placeholder:"请输入您的问题后按回车键");

通过简洁的两行代码,我们就能够轻松创建一个直观的聊天界面。

后端逻辑实现

一旦界面部分准备就绪,我们接下来需要处理文本框的回车事件Submit

txt.Submit(streamingFn:  (input) => GenerateResponse(input, kernel), inputs: new Gradio.Net.Component[] { txt, chatbot }, outputs: new Gradio.Net.Component[] { txt, chatbot });

值得注意的是,我们采用streamingFn参数来处理Submit事件,这样可以启动组件的流式输出模式,从而实现类似ChatGPT的连续打字效果。

接着,我们定义一个生成响应的函数:

static async IAsyncEnumerable<Output> GenerateResponse(Input input, Kernel kernel)
{
    var userPrompt = Textbox.Payload(input.Data[0]);
    var chatHistory = Chatbot.Payload(input.Data[1]);

    chatHistory.Add(new ChatbotMessagePair(new ChatMessage { TextMessage = userPrompt }, new ChatMessage { TextMessage = "" }));

    await foreach (var responseMessage in kernel.InvokePromptStreamingAsync<string>(userPrompt))
    {
        if (!string.IsNullOrEmpty(responseMessage))
        {
            chatHistory.Last().AiMessage.TextMessage += responseMessage;
            yield return gr.Output("", chatHistory);
        }
        await Task.Delay(50);
    }
}

由于我们采用了流式输出,因此方法返回值必须是IAsyncEnumerable<>类型。

在这里,userPormpt代表用户的输入,而chatHistory则是Chatbot组件内部保存的对话历史。由于对话通常是成对出现的,使用两个ChatMessage来分别代表本次对话中用户和AI的发言。由于AI尚未回复,因此其TextMessage字段为空。

我们使用SK提供的InvokePromptStreamingAsync方法来支持流式输出,通过简单的foreach循环,我们可以连续获取AI返回的文本。

最终,我们通过yield return语句及时输出AI的最新回复作为对话历史返回给Chatbot组件。

接下来,让我们看看实际运行的效果:

图片

结论

在本章中,我们探讨了如何利用.NET技术构建一个功能齐全的聊天机器人。

通过Gradio.Net的组件,我们能够快速搭建起聊天界面,并且通过流式输出模式,实现了类似ChatGPT的动态交互效果。

在实现过程中,我们注意到了细节的重要性,比如如何处理文本框的回车事件,以及如何优雅地管理对话历史。这些细节不仅影响着程序的性能,也直接关系到用户的满意度。


Gradio.NET(https://github.com/feiyun0112/Gradio.Net/)的目标是成为用于开发 Web 应用的 .NET 开发者的首选框架。它的设计理念是让开发变得更加简单,让每个人都能够参与到Web应用的创造中来。

添加微信GradioDotNet,通过加入技术讨论群,开发者们可以分享经验,解决问题,并共同推动.NET的发展。

图片


完整源代码:

using Gradio.Net;
using Microsoft.SemanticKernel;

string endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT");
string deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_GPT_NAME");
string apiKey = Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY");

var kernel = Kernel.CreateBuilder()
    .AddAzureOpenAIChatCompletion(
        deploymentName: deploymentName,
        endpoint: endpoint,
        apiKey: apiKey)
    .Build();

App.Launch(await CreateBlocks(kernel));

static async Task<Blocks> CreateBlocks(Kernel kernel)
{
    using (var blocks = gr.Blocks())
    {
        var chatbot = gr.Chatbot();

        var txt = gr.Textbox(showLabel: false,
                placeholder: "输入文本并按回车键"
            );

        txt.Submit(streamingFn: (input) => GenerateResponse(input, kernel), inputs: new Gradio.Net.Component[] { txt, chatbot }, outputs: new Gradio.Net.Component[] { txt, chatbot });
        return blocks;
    }
}
static async IAsyncEnumerable<Output> GenerateResponse(Input input, Kernel kernel)
{
    var userPrompt = Textbox.Payload(input.Data[0]);
    var chatHistory = Chatbot.Payload(input.Data[1]);

    chatHistory.Add(new ChatbotMessagePair(new ChatMessage { TextMessage = userPrompt }, new ChatMessage { TextMessage = "" }));

    await foreach (var responseMessage in kernel.InvokePromptStreamingAsync<string>(userPrompt))
    {
        if (!string.IsNullOrEmpty(responseMessage))
        {
            chatHistory.Last().AiMessage.TextMessage += responseMessage;
            
            yield return gr.Output("", chatHistory);
        }
        await Task.Delay(50);
    }
}

引入地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值