目录
在本章中,我们将探索如何使用 .NET 开发我们的第一个人工智能应用程序。
在之前的章节里,我们主要通过控制台界面与用户进行交互,但在实际应用中,一个清晰且美观的图形用户界面(GUI)对于提升用户体验至关重要。
图形用户界面(GUI)通过图形元素如图标、按钮和菜单,提供了一种直观的交互方式。在GUI中,视觉对象不仅传达信息,还指示用户可以执行的操作。
一般情况下,AI 应用采用 Web 页面提供GUI,这通常需要前端开发知识,如HTML、JavaScript和CSS,以及对Vue等专业前端框架的理解。
为了降低这些技术门槛,我们选择使用Gradio.Net来开发AI应用。Gradio.Net是一个开源的.NET库,它简化了为机器学习模型创建定制用户界面的过程。开发者可以利用它快速构建和部署基于Web的交互式界面,让用户能够与模型互动并实时查看结果。
Gradio.Net抽象了Web开发的复杂性,使得无需任何前端开发经验的开发者也能专注于模型及其功能的开发。
第一个 AI 应用
现在,让我们使用Gradio.Net来为我们之前的代码实现一个用户界面。
首先,通过Visual Studio 2022创建一个新的ASP.NET Core Web API应用程序,并使用NuGet包管理器添加Gradio.Net.AspNetCore库。
接着,编写以下代码来启动应用程序并创建页面配置:
App.Launch(await CreateBlocks(kernel));
static async Task<Blocks> CreateBlocks(Kernel kernel)
{
using (var blocks = gr.Blocks())
{
Textbox inputTextbox, outputTextbox;
using (gr.Row())
{
inputTextbox = gr.Textbox(label: "提问", placeholder: "你的问题?");
outputTextbox = gr.Textbox(label: "回答");
}
var btn = gr.Button("提交");
await btn.Click(fn: async (input) => gr.Output(await AskAi(input, kernel)), inputs: new[] { inputTextbox }, outputs: new[] { outputTextbox });
return blocks;
}
}
在这段代码中,App.Launch
是Gradio.Net应用的入口点,而CreateBlocks
方法则负责创建页面布局和组件。
我们使用gr.Blocks
来定义根组件,由它来控制其他组件放置的位置,以及定义用于交互式用户体验的事件处理程序。
有几点需要注意:
-
定义 Gradio Blocks 需要使用 “using” 子句。
-
using 子句中的组件才会添加到应用中。
-
组件将按照定义的顺序垂直呈现。
如果想改变组件的呈现方式,可以在内部继续使用 “using” 子句定义其他布局组件。比如gr.Row
, using 子句中的组件将在同一行呈现。布局组件的详细介绍请查看 https://github.com/feiyun0112/Gradio.Net/blob/main/readme_files/layout_demo.md。
此外,我们还创建了一个按钮,并为其定义了点击事件,Click
方法包含 3 个参数:fn
事件处理、inputs
输入组件数组、outputs
输出组件数组。
当按钮被点击时,输入组件对应的值将作为参数传递给fn
,而fn
的返回值将传递给输出组件。
static async Task<string> AskAi(Input input, Kernel kernel)
{
var result = await kernel.InvokePromptAsync(Textbox.Payload(input.Data[0]));
return result.ToString();
}
最终运行效果如图:
结论
通过实际的代码示例,我们展示了如何使用Gradio.Net构建一个简单的问答系统。即使是没有前端开发经验的开发者也能够创建直观、交互式的GUI,从而使得AI应用程序更加用户友好。
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())
{
Textbox inputTextbox, outputTextbox;
using (gr.Row())
{
inputTextbox = gr.Textbox(label: "提问", placeholder: "你的问题?");
outputTextbox = gr.Textbox(label: "回答");
}
var btn = gr.Button("提交");
await btn.Click(fn: async (input) => gr.Output(await AskAi(input, kernel)), inputs: new[] { inputTextbox }, outputs: new[] { outputTextbox });
return blocks;
}
}
static async Task<string> AskAi(Input input, Kernel kernel)
{
var result = await kernel.InvokePromptAsync(Textbox.Payload(input.Data[0]));
return result.ToString();
}