Gradio.NET 支援 .NET 8 簡化 Web 應用開發

小码编匠發表於2024-08-26

前言

Gradio.NET 是 Gradio 在 .NET 平臺上的移植版本。Gradio 是一個開源的 Python 包,用於快速構建機器學習模型、API 或任意 Python 函式的演示或 Web 應用程式。

Gradio.NET 繼承了 Gradio 的核心理念,以.NET 開發習慣和熟悉的方式進行Web應用開發,其主要特點包括:

  • 易用性:只需幾行 .NET 程式碼即可建立功能完善的使用者介面。

  • 靈活性:支援多種型別的輸入和輸出,包括文字、影像、音訊等。

  • 一鍵分享:輕鬆生成訪問連結,方便進行測試和使用。

  • 整合支援:能夠無縫整合到主流的 .NET 框架和庫中,如 ASP.NET Core 和 Entity Framework,加速開發和部署流程。

總而言之,Gradio.NET 是一個強大的工具,極大地簡化了建立和分享介面的過程,使我們能夠專注於業務邏輯而無需擔心複雜的前端開發工作。

Gradio.NET 支援 .NET 8 簡化 Web 應用開發

Gradio.NET

Gradio.NET 是一個基於 Gradio 的 .NET 實現,我們無需掌握任何前端技術(如 JavaScript、CSS 或 HTML),僅用幾行 .NET 程式碼就能快速構建機器學習模型、API 或任意函式的演示或 Web 應用程式。

透過 Gradio.NET,可以輕鬆建立美觀的互動式 Web 介面,無需前端開發經驗。

Gradio.NET 支援 .NET 8 簡化 Web 應用開發

Gradio.NET 使用

1、建立專案

建立一個新的 .NET 8 WebAPI 標準專案,選擇啟用 OpenAPI 支援和使用控制器;

dotnet new webapi -n ManageCore.Api
cd ManageCore.Api

2、安裝 Gradio.Net

安裝 NuGet 包 Gradio.Net.AspNetCore 這個包。

Gradio.NET 支援 .NET 8 簡化 Web 應用開發

3、示例程式碼

在 Program.cs 中輸入以下示例程式碼:

App.Launch(await CreateBlocks());
​
async Task<Blocks> CreateBlocks()
{
    using (var blocks = gr.Blocks())
    {
        gr.Markdown("開始在下面鍵入,然後點選**執行** 檢視輸出結果.");
        Textbox input, output;
        using (gr.Row())
        {
            input = gr.Textbox(placeholder: "你叫什麼名字?");
            output = gr.Textbox();
        }
        var btn = gr.Button("執行");
        await btn.Click(fn: async (input) => gr.Output($"歡迎使用 Gradio.Net, {input.Data[0]}!"), inputs: new[] { input }, outputs: new[] { output });
​
        return blocks;
    }
}

執行結果如下圖所示:

Gradio.NET 支援 .NET 8 簡化 Web 應用開發

如果想在現有專案中使用 Gradio.NET

可以使用AddGradioUseGradio擴充套件方法:

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;
    }
}

示例效果

Gradio.NET 支援 .NET 8 簡化 Web 應用開發

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;
    }
}

示例效果

Gradio.NET 支援 .NET 8 簡化 Web 應用開發

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);
}

示例效果

Gradio.NET 支援 .NET 8 簡化 Web 應用開發

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);
    }
}

示例效果

Gradio.NET 支援 .NET 8 簡化 Web 應用開發

5、Progress

根據自己的需求,調整進度條程式碼,參考程式碼如下:

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");
 }

示例效果

Gradio.NET 支援 .NET 8 簡化 Web 應用開發

還有更多示例程式碼,可以檢視官方文件進行學習。

Gradio.NET 應用

對於 AI 的愛好者來說,Gradio.NET 提供了一個絕佳的機會,透過訪問 https://qwen.starworks.cc:88/,讓他們能夠與通義千問開源模型進行互動。

使用 Gradio.NET 打造你的 通義千問 AI 聊天機器人,具體如下圖所示:

Gradio.NET 支援 .NET 8 簡化 Web 應用開發

這個 Web 應用不僅使用者體驗流暢,還能夠記住會話歷史,輕鬆識別語義,這一切都得益於其背後的先進技術。

該專案已開源,原始碼地址:https://github.com/sdcb/Sdcb.DashScope

具體程式碼講解,可以檢視原始碼。

專案地址

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

總結

Gradio.NET 致力於成為 .NET 開發者 構建Web 應用的首選框架。它的設計理念是簡化開發過程,讓每個人都能輕鬆參與到 Web 應用的開發中來。

如果你對建立聊天機器人感興趣,可以試試上面這個開源專案,結合 Gradio.NET 開發自己的AI聊天,有需要的朋友們可以參考學習。

最後

如果你覺得這篇文章對你有幫助,不妨點個贊支援一下!你的支援是我繼續分享知識的動力。如果有任何疑問或需要進一步的幫助,歡迎隨時留言。

也可以加入微信公眾號[DotNet技術匠] 社群,與其他熱愛技術的同行一起交流心得,共同成長!

相關文章