Gradio.NET支持 .NET 8 简化 Web 应用开发

news2024/11/13 23:41:53

目录

前言

Gradio.NET

Gradio.NET 使用

1、创建项目

2、安装 Gradio.Net

3、示例代码

Gradio.NET 示例

1、Layout

2、Form

3、Media

4、Chatbot

5、Progress

Gradio.NET 应用

项目地址

总结

最后


前言

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

Gradio.NET 是一个基于 Gradio 的 .NET 实现,我们无需掌握任何前端技术(如 JavaScript、CSS 或 HTML),仅用几行 .NET 代码就能快速构建机器学习模型、API 或任意函数的演示或 Web 应用程序。

通过 Gradio.NET,可以轻松创建美观的交互式 Web 界面,无需前端开发经验。

Gradio.NET 使用

1、创建项目

创建一个新的 .NET 8 WebAPI 标准项目,选择启用 OpenAPI 支持和使用控制器;

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

2、安装 Gradio.Net

安装 NuGet 包 Gradio.Net.AspNetCore 这个包。

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

可以使用AddGradio和 UseGradio扩展方法:

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

根据自己的需求,调整进度条代码,参考代码如下:

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 应用

对于 AI 的爱好者来说,Gradio.NET 提供了一个绝佳的机会,通过访问 Gradio.Net,让他们能够与通义千问开源模型进行互动。

使用 Gradio.NET 打造你的 通义千问 AI 聊天机器人,具体如下图所示:

这个 Web 应用不仅用户体验流畅,还能够记住会话历史,轻松识别语义,这一切都得益于其背后的先进技术。

该项目已开源,源代码地址:GitHub - sdcb/Sdcb.DashScope: 为阿里云灵积模型服务DashScope开发的非官方.NET SDK

具体代码讲解,可以查看源码。

项目地址

Github:GitHub - feiyun0112/Gradio.Net: ⭐Gradio for .NET – a port of Gradio, an open-source Python package that allows you to quickly build a demo or web application for your machine learning model, API, or any arbitrary Python function. Gradio for .NET – 基于 Gradio 的 .NET 移植,Gradio 是一个开源 Python 包,允许你为机器学习模型、API 或任何任意 Python 函数快速构建演示或 Web 应用程序。

Demo:Gradio.Net/readme_files at main · feiyun0112/Gradio.Net · GitHub

AI聊天:GitHub - sdcb/Sdcb.DashScope: 为阿里云灵积模型服务DashScope开发的非官方.NET SDK

总结

Gradio.NET 致力于成为 .NET 开发者 构建Web 应用的首选框架。它的设计理念是简化开发过程,让每个人都能轻松参与到 Web 应用的开发中来。

如果你对创建聊天机器人感兴趣,可以试试上面这个开源项目,结合 Gradio.NET 开发自己的AI聊天,有需要的朋友们可以参考学习。

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。

也可以加入微信公众号[DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2069719.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

内容为王:数字化营销的致胜法宝

​在当今数字化时代&#xff0c;营销环境发生了巨大变化。消费者被海量信息包围&#xff0c;注意力成为必争资源。在这种情况下&#xff0c;“内容为王” 的理念愈发凸显其重要性&#xff0c;成为数字化营销的致胜法宝。 1. 吸引用户注意力 高质量、有价值的内容能够在众多信息…

推荐好古文《马说》

韩愈 世有伯乐&#xff0c;然后有千里马。千里马常有&#xff0c;而伯乐不常有。故虽有名马&#xff0c;只辱于奴隶人之手&#xff0c;骈死于槽枥之间&#xff0c;不以千里称也。 马之千里者&#xff0c;一食或尽粟一石。食马者不知其能千里而食也。是马也&#xff0c;虽有千…

【Python最全系统学习路线】:千万不要盲目自学Python,顺序真的很重要!

如果你一直想学Python&#xff0c;但是不知道如何入手&#xff0c;那就别犹豫了。这篇文章就是为你写的。 根据我自己的经验来说&#xff0c;想从零开始学Python&#xff0c;以后也确实想找相关的工作&#xff0c;基本是下边这三种方式&#xff1a; 继续上学。报个这方面的专业…

WiFi的IP和电脑IP一样吗?怎么更改wifi的ip地址

在数字化时代&#xff0c;网络连接已成为我们日常生活和工作中不可或缺的一部分。无论是通过手机、电脑还是其他智能设备接入互联网&#xff0c;IP地址作为网络设备的唯一标识&#xff0c;扮演着至关重要的角色。然而&#xff0c;很多用户对于WiFi的IP地址与电脑&#xff08;或…

Linux权限维持实战

目录 介绍步骤 介绍 攻击者在获取服务器权限后&#xff0c;会通过一些技巧来隐藏自己的踪迹和后门文件 查看/tmp目录下的flag文件 查看/root目录下具有特殊文件属性的文件 操作机中共有几个SUID文件 操作机中共有几个SGID文件 查看操作机中ssh公私钥免密登陆 查看strace后门 …

机器视觉学习笔记和过程记录:下载安装OpenCv

下载安装opencv 1、本机已经安装了anaconda&#xff0c;打开对应的环境下的命令行窗口&#xff0c;输入python后回车&#xff0c;会显示python版本&#xff0c;本机是3.8.3&#xff1a; 2、打开链接&#xff1a;Links for opencv-python &#xff0c;在网页中查找与python版本…

【计算机组成原理】三、存储系统:5.页式存储、虚拟存储

9.页式存储器 文章目录 9.页式存储器9.1页表9.2地址变换过程9.3快表TLB 10.虚拟存储器10.1页式虚拟存储器10.2段式虚拟存储器10.3段页式虚拟存储器 详见 操作系统 3.内存管理 存储器管理 分页存储管理 因为实际连续存放一段程序是不现实的&#xff0c;那样会使得利用率极低。所…

探索人工智能领域:从探索到战略整合

我们正站在商业和技术新时代的风口浪尖。人工智能已经成为一股变革力量&#xff0c;有望彻底改变行业并重新定义我们的工作方式。然而&#xff0c;从最初的人工智能探索到全面整合&#xff0c;这条路并不平坦。 全球各地的组织都在努力解决如何充分利用人工智能潜力的复杂问题&…

TXT文件转换pdf格式的java方法

<dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13.2</version> </dependency>接下来&#xff0c;编写一个方法来执行文件转换&#xff1a; import com.itextpdf.text.Document…

文心快码 Baidu Comate 前端工程师观点分享:以文心快码 Baidu Comate为例,智能代码助手需要什么(四)⓵

本系列视频来自百度工程效能部的前端研发经理杨经纬&#xff0c;她在由开源中国主办的“AI编程革新研发效能”OSC源创会杭州站105期线下沙龙活动上&#xff0c;从一款文心快码&#xff08;Baidu Comate&#xff09;前端工程师的角度&#xff0c;分享了关于智能研发工具本身的研…

一文彻底搞懂CNN - 模型架构(Model Architecture)

CNN Model Architecture CNN&#xff08;卷积神经网络&#xff09;的模型架构由输入层、卷积层、池化层以及全连接层组成&#xff0c;通过卷积操作提取图像特征&#xff0c;并通过池化减少参数数量&#xff0c;最终通过全连接层进行分类或回归。 输入层&#xff1a;接收原始图…

​14:00面试,14:06就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到5月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…

BoosterX:Windows 游戏玩家都爱的电脑优化工具箱

《黑神话&#xff1a;悟空》、《艾尔登法环&#xff1a;黄金树幽影》、暴雪「全家桶」回归……今年&#xff0c;我们将迎来一场豪华的游戏大餐&#xff01; 想要畅玩游戏&#xff0c;除了要准备好给力的硬件设备&#xff0c;系统优化当然也不能落下&#xff01;BoosterX 正是一…

IO进程(8)

目录 1.信号灯集 1.1概念 1.2操作步骤 1.3函数接口 1.3.1创建信号灯集 1.3.2初始化或删除信号灯集 ​​​​​​​​​​​​​​1.3.3pv操作 ​​​​​​​​​​​​​​1.4操作命令 2.消息队列 2.1特点 ​​​​​​​​​​​​​​2.2步骤 ​​​​​​​2.3函数接口 2.3…

如何选择适合自己的开放式耳机?五款实力出众爆款安利!

开放式耳机以其不侵入耳道的设计&#xff0c;为耳朵提供了更轻的负担&#xff0c;同时保护了耳道健康&#xff0c;这与传统的头戴式或入耳式耳机相比&#xff0c;在长时间佩戴时更能减少不适感。市场上的开放式耳机种类繁多&#xff0c;要找到一款真正满意的产品可能有些困难。…

使用kubeadm快速部署一套K8S集群

一、Kubernetes概述 1.1 Kubernetes是什么 Kubernetes是Google在2014年开源的一个容器集群管理系统&#xff0c;Kubernetes简称K8S。 K8S用于容器化应用程序的部署&#xff0c;扩展和管理。 K8S提供了容器编排&#xff0c;资源调度&#xff0c;弹性伸缩&#xff0c;部署管理…

Meta被曝取消了自己的“Vision Pro计划”内部代号La Jolla

据媒体周五报道&#xff0c;美国科技巨头Meta已经取消了原定于2027年推出高端混合现实头显的计划&#xff0c;Meta原本计划利用这款设备与苹果的Vision Pro一较高下。据Meta的两名员工声称&#xff0c;在本周的一次产品审查会议后&#xff0c;公司管理层突然要求Reality Labs部…

【数据结构】动态顺序表的实现

1.什么是数据结构 数据结构就是把数据元素按照一定的关系组织起来的集合&#xff0c;用来组织和存储数据。通过数据结构&#xff0c;能够有效的将数据组织和管理在一起&#xff0c;按照我们的方式任意对数据进行增删查改等操作。 2.数据结构的分类 数据结构大概可分为逻辑结构…

拆分因子+减枝

前言&#xff1a;一开始看到数据量这么大&#xff0c;我怎么拆分出因子&#xff0c;看了题解才发现要大减枝&#xff0c;但是如何拆分因数我还是要好好学一下 1 0 18 10^{18} 1018 的拆分因子有 1 0 5 10^5 105 的复杂度&#xff0c;再乘以 1 0 3 10^3 103 的数量&#xff0c…

光伏电站设备设施巡视卡之转变二维码登记卡

光伏电站作为重要的能源供应设施&#xff0c;其稳定运行和高效维护至关重要&#xff0c;光伏电站巡回检查制度是保障电站设备正常运行和安全性的重要手段,制定好的制度可以提高电站的经济效益和安全性。 传统的纸质光伏电站巡视卡容易出现巡检记录作假、信息统计不及时、汇总困…