动手学Avalonia:基于SemanticKernel与硅基流动构建AI聊天与翻译工具

avalonia,semantickernel,ai · 浏览次数 : 0

小编点评

Avalonia是一个跨平台的UI框架,专为.NET开发打造,提供灵活的样式系统,支持Windows、macOS、Linux、iOS、Android及WebAssembly等多种平台。它已成熟并适合生产环境,被Schneider Electric、Unity、JetBrains和GitHub等公司采用。许多人认为Avalonia是WPF的继任者,它为XAML开发人员提供了一种熟悉且现代的跨平台应用开发体验。 SemanticKernel是一个SDK,它可以将大型语言模型(如OpenAI、Azure OpenAI和Hugging Face)与常规编程语言(如C#、Python和Java)整合。特殊之处在于,Semantic Kernel通过允许定义和链式调用插件,能够自动调度并组合这些AI模型。其功能是,用户可以向LLM提出个性化目标,由Semantic Kernel的规划器生成实现目标的计划,然后由系统自动执行这份计划。 硅基流动是一个一站式云服务平台,旨在打造大模型时代的AI基础设施。它通过算法、系统和硬件的协同创新,跨数量级降低大模型应用成本和开发门槛,加速AGI普惠人类。SiliconCloud作为集合主流开源大模型的一站式云服务平台,为开发者提供更快、更便宜、更全面、体验更丝滑的模型API。目前,SiliconCloud已上架包括DeepSeek-Coder-V2、Stable Diffusion 3 Medium、Qwen2、GLM-4-9B-Chat、DeepSeek V2、SDXL、InstantID在内的多种开源大语言模型、图片生成模型,支持用户自由切换符合不同应用场景的模型。同时,SiliconCloud提供开箱即用的大模型推理加速服务,为生成式AI应用带来更高效的用户体验。 在国内使用OpenAI不太方便且成本较高,而现在已经有许多开源的大模型。然而,对于个人开发者而言,部署这些大模型的一大难点是硬件资源。硅基流动宣布,其平台的Qwen2(7B)、GLM4(9B)、Yi1.5(9B)等顶尖开源大模型免费使用。这意味着个人开发者现在也可以使用这些强大的AI工具,而无需担心硬件资源的问题。 在这个背景下,学习Avalonia并动手制作一个实现自己需求的小工具是一个很好的开始。同时,对SemanticKernel也感兴趣的个人开发者可以从最基本的制作一个基于大模型的聊天应用开始。

正文

Avalonia是什么?

Avalonia是一个跨平台的UI框架,专为.NET开发打造,提供灵活的样式系统,支持Windows、macOS、Linux、iOS、Android及WebAssembly等多种平台。它已成熟并适合生产环境,被Schneider Electric、Unity、JetBrains和GitHub等公司采用。

许多人认为Avalonia是WPF的继任者,它为XAML开发人员提供了一种熟悉且现代的跨平台应用开发体验。尽管与WPF相似,但Avalonia并非完全复制,而包含了许多改进。

image-20240703120741584

SemanticKernel是什么?

Semantic Kernel是一个SDK,它可以将大型语言模型(如OpenAI、Azure OpenAI和Hugging Face)与常规编程语言(如C#、Python和Java)整合。特殊之处在于,Semantic Kernel通过允许定义和链式调用插件,能够自动调度并组合这些AI模型。其功能是,用户可以向LLM提出个性化目标,由Semantic Kernel的规划器生成实现目标的计划,然后由系统自动执行这份计划。

image-20240703121053734

硅基流动介绍

硅基流动致力于打造大模型时代的AI基础设施,通过算法、系统和硬件的协同创新,跨数量级降低大模型应用成本和开发门槛,加速AGI普惠人类。

SiliconCloud是集合主流开源大模型的一站式云服务平台,为开发者提供更快、更便宜、更全面、体验更丝滑的模型API。

目前,SiliconCloud已上架包括DeepSeek-Coder-V2、Stable Diffusion 3 Medium、Qwen2、GLM-4-9B-Chat、DeepSeek V2、SDXL、InstantID在内的多种开源大语言模型、图片生成模型,支持用户自由切换符合不同应用场景的模型。同时,SiliconCloud提供开箱即用的大模型推理加速服务,为生成式AI应用带来更高效的用户体验。

我们知道在国内使用OpenAI不太方便同时成本也比较高。现在已经有很多开源的大模型了,但是对于个人开发者而言,部署它们的一大难点是硬件资源。没有显卡,也能部署一些参数少一些的开源大模型,但是推理速度肯定是很慢的,这里选择硅基流动的原因是第一,之前注册送了42元的额度,该额度不会过期,可以一直使用,第二,试了一下推理速度真的很快,第三(也是最重要的一点)(白嫖),硅基流动宣布:SiliconCloud平台的Qwen2(7B)、GLM4(9B)、Yi1.5(9B)等顶尖开源大模型免费使用。

构建什么样的工具

最近在学习Avalonia,动手做一个小工具实现自己的需求是一个很好的开始。同时对SemanticKernel也比较感兴趣,所以选择从最基本的制作一个基于大模型的聊天应用开始。个人对大模型的一大需求就是翻译,在查看英文网站时,遇到不太理解的地方,总喜欢问大模型,将某某某翻译为中文。因此选择构建解决自己这个需求的Avalonia练手小工具。该工具的效果如下所示:

聊天

英译中

中译英

开始实践

在SemanticKernel中使用SiliconCloud提供的API服务

要解决的第一个问题就是如何在SemanticKernel中使用SiliconCloud提供的服务。

SemanticKernel中并没有告诉我们如何连接其他的大模型,但由于SiliconCloud提供的接口是与OpenAI兼容的,因此可以通过在发送请求时,改变发送请求的地址来实现。

添加OpenAIHttpClientHandler类:

public class OpenAIHttpClientHandler : HttpClientHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        UriBuilder uriBuilder;
        switch (request.RequestUri?.LocalPath)
        {
            case "/v1/chat/completions":
                uriBuilder = new UriBuilder(request.RequestUri)
                {
                    // 这里是你要修改的 URL
                    Scheme = "https",
                    Host = "api.siliconflow.cn",
                    Path = "v1/chat/completions",
                };
                request.RequestUri = uriBuilder.Uri;
                break;
        }
    
        HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
      
        return response;
    }
}

kernel通过这种方式构建:

var handler = new OpenAIHttpClientHandler();
var builder = Kernel.CreateBuilder()
.AddOpenAIChatCompletion(
   modelId: "Qwen/Qwen1.5-7B-Chat",
   apiKey: "你的apikey",
   httpClient: new HttpClient(handler));
_kernel = builder.Build();

_kernel为全局私有变量:

private Kernel _kernel;

构建页面

axaml如下所示:

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="using:AvaloniaChat.ViewModels"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:views="clr-namespace:AvaloniaChat.Views"
        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
        x:Class="AvaloniaChat.Views.MainWindow"
        Icon="/Assets/avalonia-logo.ico"
        Title="AvaloniaChat">
	<Design.DataContext>
		<!-- This only sets the DataContext for the previewer in an IDE,
         to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
		<vm:MainViewModel />
	</Design.DataContext>
	<StackPanel>
		<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <Grid Grid.Column="0">
		<StackPanel>
			<StackPanel Orientation="Horizontal">
				 <Button Content="问AI" Margin="10"
					     Command="{Binding AskCommand}"></Button>
				 <!--<Button Content="翻译为:"></Button>-->
				 <Label Content="翻译为:"
						HorizontalAlignment="Center"
						VerticalAlignment="Center"></Label>
				 <ComboBox ItemsSource="{Binding Languages}"
						   SelectedItem="{Binding SelectedLanguage}"
						   HorizontalAlignment="Center"
						   VerticalAlignment="Center"></ComboBox>
			     <Button Content="翻译" Margin="10"
					Command="{Binding TranslateCommand}"></Button>
			</StackPanel>	   
	        <TextBox Height="300" Margin="10"
					 Text="{Binding AskText}"
				     TextWrapping="Wrap"
					 AcceptsReturn="True"></TextBox>
		</StackPanel>    
    </Grid>

    <Grid Grid.Column="1">
       <StackPanel>
		    <Button Content="AI回答" Margin="10"></Button>
	        <TextBox Height="300" 					 
					 Margin="10"
					 Text="{Binding ResponseText}"
	                 TextWrapping="Wrap"></TextBox>
		</StackPanel>    
    </Grid>
</Grid>		
	</StackPanel>
</Window>

界面效果如下所示:

image-20240703134726518

构建ViewModel

ViewModel如下所示:

public partial class MainViewModel : ViewModelBase
{  
    private Kernel _kernel;

    [ObservableProperty]
    private string askText;

    [ObservableProperty]
    private string responseText;

    [ObservableProperty]
    private string selectedLanguage;

    public string[] Languages { get; set; }

    public MainViewModel()
    {
        var handler = new OpenAIHttpClientHandler();
        var builder = Kernel.CreateBuilder()
        .AddOpenAIChatCompletion(
           modelId: "Qwen/Qwen1.5-7B-Chat",
           apiKey: "你的apikey",
           httpClient: new HttpClient(handler));
        _kernel = builder.Build();
        AskText = " ";
        ResponseText = " ";
        SelectedLanguage = " ";
        Languages = new string[] { "中文","英文"};
    }

    [RelayCommand]
    private async Task Ask()
    {   
        if(ResponseText != "")
        {
            ResponseText = "";
        }
        await foreach (var update in _kernel.InvokePromptStreamingAsync(AskText))
        {
            ResponseText += update.ToString();         
        }     
    }

    [RelayCommand]
    private async Task Translate()
    {
        string skPrompt =   """
                            {{$input}}

                            将上面的输入翻译成{{$language}},无需任何其他内容
                            """;
    
        if (ResponseText != "")
        {
            ResponseText = "";
        }
        await foreach (var update in _kernel.InvokePromptStreamingAsync(skPrompt, new() { ["input"] = AskText,["language"] = SelectedLanguage }))
        {
            ResponseText += update.ToString();
        }
    }
}

使用流式返回

[RelayCommand]
private async Task Ask()
{   
    if(ResponseText != "")
    {
        ResponseText = "";
    }
    await foreach (var update in _kernel.InvokePromptStreamingAsync(AskText))
    {
        ResponseText += update.ToString();         
    }     
}

实现效果如下:

写提示

当我们需要翻译功能的时候,只需要翻译文本,其他的内容都不要,简易的模板如下:

 string skPrompt =   """
                     {{$input}}

                     将上面的输入翻译成{{$language}},无需任何其他内容
                     """;

{{$input}}{{$language}}是模板里的参数,使用时会被替换,如下所示:

 await foreach (var update in _kernel.InvokePromptStreamingAsync(skPrompt, new() { ["input"] = AskText,["language"] = SelectedLanguage }))
 {
     ResponseText += update.ToString();
 }

通过以上这几个步骤,我们就使用Avalonia制作完成一个简易的小工具了。

与动手学Avalonia:基于SemanticKernel与硅基流动构建AI聊天与翻译工具相似的内容:

动手学Avalonia:基于SemanticKernel与硅基流动构建AI聊天与翻译工具

Avalonia是什么? Avalonia是一个跨平台的UI框架,专为.NET开发打造,提供灵活的样式系统,支持Windows、macOS、Linux、iOS、Android及WebAssembly等多种平台。它已成熟并适合生产环境,被Schneider Electric、Unity、JetBrai

自己动手2小时学会配置游戏辅助

在工作、生活和娱乐中,我们经常遇到一些重复性的鼠标点击操作,我们可能会首先想到使用按键精灵类软件来解放双手,但是它们的使用门槛比较高,还要专门学一门脚本语言。本文介绍的软件完全不需要编程和脚本开发经验,看完就能配置出自己想要的辅助类脚本

[转帖]我偷偷学了这 5 个命令,打印 Linux 环境变量那叫一个“丝滑”!

https://xie.infoq.cn/article/2acfef8d543517619c9202e4e 一、概述 在基于 Linux 和 Unix 的系统中,环境变量是一组动态命名值,存储在系统中,供在 shell 或子 shell 中启动的应用程序使用。简单来说,环境变量是具有名称和关联值的

App复杂动画实现——Rive保姆级教程

在App开发过程中,如果想实现动画效果,可以粗略分为两种方式。一种是直接用代码编写,像平移、旋转等简单的动画效果,都可以这么干,如果稍微复杂点,就会对开发工程师的数学功底、图形图像学功底有很高的要求。

策略梯度玩 cartpole 游戏,强化学习代替PID算法控制平衡杆

cartpole游戏,车上顶着一个自由摆动的杆子,实现杆子的平衡,杆子每次倒向一端车就开始移动让杆子保持动态直立的状态,策略函数使用一个两层的简单神经网络,输入状态有4个,车位置,车速度,杆角度,杆速度,输出action为左移动或右移动,输入状态发现至少要给3个才能稳定一会儿,给2个完全学不明白,给

[WPF]用HtmlTextBlock实现消息对话框的内容高亮和跳转

动手写一个简单的消息对话框一文介绍了如何实现满足常见应用场景的消息对话框。但是内容区域的文字仅仅起到信息展示作用,对于需要部分关键字高亮,或者部分内容有交互性的场景(例如下图提示信息中的“what's the risk?”需要跳转)则无能为力了。本文将介绍如何在WPF中灵活的实现消息对话框中局部文字

动手造轮子自己实现人工智能神经网络(ANN),解决鸢尾花分类问题Golang1.18实现

人工智能神经网络( Artificial Neural Network,又称为ANN)是一种由人工神经元组成的网络结构,神经网络结构是所有机器学习的基本结构,换句话说,无论是深度学习还是强化学习都是基于神经网络结构进行构建。关于人工神经元,请参见:人工智能机器学习底层原理剖析,人造神经元,您一定能看

带你动手做AI版的垃圾分类

摘要:本案例将使用YOLOX模型,实现一个简单的垃圾分类应用。 本文分享自华为云社区《ModelBox社区案例 - 使用YOLOX做垃圾分类》,作者:HWCloudAI。 1 ModelBox社区案例 - 使用YOLOX做垃圾分类 本案例将使用YOLOX模型,实现一个简单的垃圾分类应用,最终效果如下

动手实践丨使用华为云IoT边缘体验“边云协同”

摘要:“边云协同”,即云端与边缘的协同。通过边云通道,部署在边缘节点上,并实现在云端远程管理应用,保障部署在边缘的应用能够正常运行,并通过与云端的连线,将业务执行结果在云端呈现。 本文分享自华为云社区《使用华为云IoT平台的IoT边缘体验“边云协同”【我的IoT端边云体验】》,作者:Jan-tao

动手实践丨基于ModelAtrs使用A2C算法制作登月器着陆小游戏

摘要:在本案例中,我们将展示如何基于A2C算法,训练一个LunarLander小游戏。 本文分享自华为云社区《使用A2C算法控制登月器着陆》,作者:HWCloudAI 。 LunarLander是一款控制类的小游戏,也是强化学习中常用的例子。游戏任务为控制登月器着陆,玩家通过操作登月器的主引擎和副引