Gradio.NET 支持 .NET 8 簡(jiǎn)化 Web 應(yīng)用開(kāi)發(fā)
Gradio.NET 是 Gradio 在 .NET 平臺(tái)上的移植版本。Gradio 是一個(gè)開(kāi)源的 Python 包,用于快速構(gòu)建機(jī)器學(xué)習(xí)模型、API 或任意 Python 函數(shù)的演示或 Web 應(yīng)用程序。
Gradio.NET 繼承了 Gradio 的核心理念,以.NET 開(kāi)發(fā)習(xí)慣和熟悉的方式進(jìn)行Web應(yīng)用開(kāi)發(fā),其主要特點(diǎn)包括:
-
易用性:只需幾行 .NET 代碼即可創(chuàng)建功能完善的用戶(hù)界面。
-
靈活性:支持多種類(lèi)型的輸入和輸出,包括文本、圖像、音頻等。
-
一鍵分享:輕松生成訪(fǎng)問(wèn)鏈接,方便進(jìn)行測(cè)試和使用。
-
集成支持:能夠無(wú)縫集成到主流的 .NET 框架和庫(kù)中,如 ASP.NET Core 和 Entity Framework,加速開(kāi)發(fā)和部署流程。
總而言之,Gradio.NET 是一個(gè)強(qiáng)大的工具,極大地簡(jiǎn)化了創(chuàng)建和分享界面的過(guò)程,使我們能夠?qū)W⒂跇I(yè)務(wù)邏輯而無(wú)需擔(dān)心復(fù)雜的前端開(kāi)發(fā)工作。

Gradio.NET
Gradio.NET 是一個(gè)基于 Gradio 的 .NET 實(shí)現(xiàn),我們無(wú)需掌握任何前端技術(shù)(如 JavaScript、CSS 或 HTML),僅用幾行 .NET 代碼就能快速構(gòu)建機(jī)器學(xué)習(xí)模型、API 或任意函數(shù)的演示或 Web 應(yīng)用程序。
通過(guò) Gradio.NET,可以輕松創(chuàng)建美觀的交互式 Web 界面,無(wú)需前端開(kāi)發(fā)經(jīng)驗(yàn)。

Gradio.NET 使用
1、創(chuàng)建項(xiàng)目
創(chuàng)建一個(gè)新的 .NET 8 WebAPI 標(biāo)準(zhǔn)項(xiàng)目,選擇啟用 OpenAPI 支持和使用控制器;
dotnet new webapi -n ManageCore.Api cd ManageCore.Api
2、安裝 Gradio.Net
安裝 NuGet 包 Gradio.Net.AspNetCore 這個(gè)包。

3、示例代碼
在 Program.cs 中輸入以下示例代碼:
App.Launch(await CreateBlocks()); ? async Task<Blocks> CreateBlocks() { using (var blocks = gr.Blocks()) { gr.Markdown("開(kāi)始在下面鍵入,然后點(diǎn)擊**運(yùn)行** 查看輸出結(jié)果."); Textbox input, output; using (gr.Row()) { input = gr.Textbox(placeholder: "你叫什么名字?"); output = gr.Textbox(); } var btn = gr.Button("運(yùn)行"); await btn.Click(fn: async (input) => gr.Output($"歡迎使用 Gradio.Net, {input.Data[0]}!"), inputs: new[] { input }, outputs: new[] { output }); ? return blocks; } }
運(yùn)行結(jié)果如下圖所示:

如果想在現(xiàn)有項(xiàng)目中使用 Gradio.NET
可以使用AddGradio和 UseGradio擴(kuò)展方法:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddGradio(); ? var app = builder.Build(); ? app.UseGradio(await CreateBlocks()); ? app.Run();
Gradio.NET 示例
1、Layout
Gradio.NET 常用的布局方式都包括:Row/Column、Tab、Group、Accordion等。
示例代碼
App.Launch(await CreateBlocks()); ? async Task<Blocks> CreateBlocks() { using (var blocks = gr.Blocks()) { gr.Markdown("# Layout Demo"); ? gr.Markdown("## Row/Column"); using (gr.Row()) { using (gr.Column(scale: 1)) { var text1 = gr.Textbox(); var text2 = gr.Textbox(); } ? using (gr.Column(scale: 4)) { var btn1 = gr.Button("Button 1"); var btn2 = gr.Button("Button 2"); } } ? gr.Markdown("## Tab"); using (gr.Tab("Lion")) { gr.Textbox("lion"); gr.Button("New Lion"); } using (gr.Tab("Tiger")) { gr.Textbox("tiger"); gr.Button("New Tiger"); } ? gr.Markdown("## Group"); using (gr.Group()) { gr.Textbox(label: "First"); gr.Textbox(label: "Last"); } ? gr.Markdown("## Accordion"); using (gr.Accordion("See Details")) { gr.Markdown("lorem ipsum"); } ? return blocks; } }
示例效果

2、Form
表單示例代碼,具體如下:
App.Launch(await CreateBlocks()); ? async Task<Blocks> CreateBlocks() { using (var blocks = gr.Blocks()) { using (gr.Column()) { var text1 = gr.Textbox(); var dropdown1 = gr.Dropdown(choices: new[] { "First Choice", "Second Choice", "Third Choice" }); var checkbox1 = gr.Checkbox(); var checkboxGroup1 = gr.CheckboxGroup(choices: new[] { "First Choice", "Second Choice", "Third Choice" }); var multimodalTextbox1 = gr.MultimodalTextbox(interactive:true); var number1 = gr.Number(); var radio1 = gr.Radio(choices: ["First Choice", "Second Choice", "Third Choice"]); var slider1 = gr.Slider(); ? var text_Result = gr.Textbox(label:"Form Value", interactive:false); var btn = gr.Button("Run"); await btn.Click(fn: async (input) => gr.Output($@" Textbox: {Textbox.Payload(input.Data[0])} Dropdown: {string.Join(", ",Dropdown.Payload(input.Data[1]))} Checkbox: {Checkbox.Payload(input.Data[2])} CheckboxGroup: {string.Join(", ", CheckboxGroup.Payload(input.Data[3]))} MultimodalTextbox: {MultimodalTextbox.Payload(input.Data[4]).Files.FirstOrDefault()?.OrigName} Number: {Number.Payload(input.Data[5])} Radio: {string.Join(", ", Radio.Payload(input.Data[6]))} Slider: {Slider.Payload(input.Data[7])} "), inputs: new Component[] { text1, dropdown1, checkbox1, checkboxGroup1, multimodalTextbox1, number1, radio1, slider1 }, outputs: new[] { text_Result }); } ? return blocks; } }
示例效果

3、Media
多媒體控件,具體參考代碼
App.Launch(await CreateBlocks()); ? async Task<Blocks> CreateBlocks() { using (var blocks = gr.Blocks()) { gr.Markdown("**Image Demo** upload a image and click button"); Gradio.Net.Image input, output; using (gr.Row()) { input = gr.Image(); output = gr.Image(); } var btn = gr.Button("Submit"); await btn.Click(fn: async (input) => gr.Output(DrawWaterMarkOnImage(Gradio.Net.Image.Payload(input.Data[0]))), inputs: new[] { input }, outputs: new[] { output }); ? return blocks; } } ? ? static string DrawWaterMarkOnImage(string inputImageFilePath) { using (var img = SixLabors.ImageSharp.Image.Load(inputImageFilePath)) { var outputFilePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".png"); Font font = SystemFonts.CreateFont("Arial", 10); // for scaling water mark size is largely ignored. ? using (var img2 = img.Clone(ctx => ApplyScalingWaterMarkSimple(ctx, font, "Gradio.Net", Color.HotPink, 5))) { img2.Save(outputFilePath); } return outputFilePath; } ? } static IImageProcessingContext ApplyScalingWaterMarkSimple(IImageProcessingContext processingContext, Font font, string text, Color color, float padding) { Size imgSize = processingContext.GetCurrentSize(); ? float targetWidth = imgSize.Width - (padding * 2); float targetHeight = imgSize.Height - (padding * 2); ? // Measure the text size FontRectangle size = TextMeasurer.MeasureSize(text, new TextOptions(font)); ? // Find out how much we need to scale the text to fill the space (up or down) float scalingFactor = Math.Min(targetWidth / size.Width, targetHeight / size.Height); ? // Create a new font Font scaledFont = new Font(font, scalingFactor * font.Size); ? var center = new PointF(imgSize.Width / 2, imgSize.Height / 2); var textOptions = new RichTextOptions(scaledFont) { Origin = center, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; return processingContext.DrawText(textOptions, text, color); }
示例效果

4、Chatbot
示例代碼
App.Launch(await CreateBlocks()); ? async Task<Blocks> CreateBlocks() { using (var blocks = gr.Blocks()) { gr.Markdown("# Chatbot Demo"); ? var chatbot = gr.Chatbot(); var msg = gr.Textbox(placeholder:"Enter to Submit"); ? await msg.Submit(streamingFn: (input) => Respond(Textbox.Payload(input.Data[0]), Chatbot.Payload(input.Data[1])), inputs: new Component[] { msg, chatbot }, outputs: new Component[] { msg, chatbot }); return blocks; } } ? static async IAsyncEnumerable<Output> Respond(string message, IList<ChatbotMessagePair> chatHistory) { chatHistory.Add(new ChatbotMessagePair(message, "You typed: ")); ? for (int i = 0; i < message.Length; i++) { await Task.Delay(500); chatHistory.Last().AiMessage.TextMessage += message[i]; ? yield return gr.Output("", chatHistory); } }
示例效果

5、Progress
根據(jù)自己的需求,調(diào)整進(jìn)度條代碼,參考代碼如下:
App.Launch(await CreateBlocks()); ? async Task<Blocks> CreateBlocks() { using (var blocks = gr.Blocks()) { gr.Markdown("# Progress Demo"); ? var load = gr.Button("Load"); var label = gr.Label(label: "Loader"); load.Click(LoadSet, outputs: new[] { label }); ? return blocks; } } static async Task<Output> LoadSet(Input input) { const int count = 24; input.Progress = gr.Progress(count); for (int i = 0; i < count; i++) { input.Progress.Report(i, desc: "Loading..."); await Task.Delay(100); } return gr.Output("Loaded"); }
示例效果

還有更多示例代碼,可以查看官方文檔進(jìn)行學(xué)習(xí)。
Gradio.NET 應(yīng)用
對(duì)于 AI 的愛(ài)好者來(lái)說(shuō),Gradio.NET 提供了一個(gè)絕佳的機(jī)會(huì),通過(guò)訪(fǎng)問(wèn) https://qwen.starworks.cc:88/,讓他們能夠與通義千問(wèn)開(kāi)源模型進(jìn)行互動(dòng)。
使用 Gradio.NET 打造你的 通義千問(wèn) AI 聊天機(jī)器人,具體如下圖所示:

這個(gè) Web 應(yīng)用不僅用戶(hù)體驗(yàn)流暢,還能夠記住會(huì)話(huà)歷史,輕松識(shí)別語(yǔ)義,這一切都得益于其背后的先進(jìn)技術(shù)。
該項(xiàng)目已開(kāi)源,源代碼地址:https://github.com/sdcb/Sdcb.DashScope
具體代碼講解,可以查看源碼。
項(xiàng)目地址
Github:https://github.com/feiyun0112/Gradio.Net
Demo:https://github.com/feiyun0112/Gradio.Net/blob/main/readme_files
AI聊天:https://github.com/sdcb/Sdcb.DashScope
總結(jié)
Gradio.NET 致力于成為 .NET 開(kāi)發(fā)者 構(gòu)建Web 應(yīng)用的首選框架。它的設(shè)計(jì)理念是簡(jiǎn)化開(kāi)發(fā)過(guò)程,讓每個(gè)人都能輕松參與到 Web 應(yīng)用的開(kāi)發(fā)中來(lái)。
如果你對(duì)創(chuàng)建聊天機(jī)器人感興趣,可以試試上面這個(gè)開(kāi)源項(xiàng)目,結(jié)合 Gradio.NET 開(kāi)發(fā)自己的AI聊天,有需要的朋友們可以參考學(xué)習(xí)。
如果你覺(jué)得這篇文章對(duì)你有幫助,不妨點(diǎn)個(gè)贊支持一下!你的支持是我繼續(xù)分享知識(shí)的動(dòng)力。如果有任何疑問(wèn)或需要進(jìn)一步的幫助,歡迎隨時(shí)留言。
也可以加入微信公眾號(hào)[DotNet技術(shù)匠] 社區(qū),與其他熱愛(ài)技術(shù)的同行一起交流心得,共同成長(zhǎng)!


浙公網(wǎng)安備 33010602011771號(hào)