经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 大数据/云/AI » 人工智能基础 » 查看文章
动手学Avalonia:基于SemanticKernel与硅基流动构建AI聊天与翻译工具
来源:cnblogs  作者:mingupupup  时间:2024/7/3 14:35:26  对本文有异议

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类:

  1. public class OpenAIHttpClientHandler : HttpClientHandler
  2. {
  3. protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
  4. {
  5. UriBuilder uriBuilder;
  6. switch (request.RequestUri?.LocalPath)
  7. {
  8. case "/v1/chat/completions":
  9. uriBuilder = new UriBuilder(request.RequestUri)
  10. {
  11. // 这里是你要修改的 URL
  12. Scheme = "https",
  13. Host = "api.siliconflow.cn",
  14. Path = "v1/chat/completions",
  15. };
  16. request.RequestUri = uriBuilder.Uri;
  17. break;
  18. }
  19. HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
  20. return response;
  21. }
  22. }

kernel通过这种方式构建:

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

_kernel为全局私有变量:

  1. private Kernel _kernel;

构建页面

axaml如下所示:

  1. <Window xmlns="https://github.com/avaloniaui"
  2. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  3. xmlns:vm="using:AvaloniaChat.ViewModels"
  4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6. xmlns:views="clr-namespace:AvaloniaChat.Views"
  7. mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
  8. x:Class="AvaloniaChat.Views.MainWindow"
  9. Icon="/Assets/avalonia-logo.ico"
  10. Title="AvaloniaChat">
  11. <Design.DataContext>
  12. <!-- This only sets the DataContext for the previewer in an IDE,
  13. to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
  14. <vm:MainViewModel />
  15. </Design.DataContext>
  16. <StackPanel>
  17. <Grid>
  18. <Grid.ColumnDefinitions>
  19. <ColumnDefinition Width="*" />
  20. <ColumnDefinition Width="*" />
  21. </Grid.ColumnDefinitions>
  22. <Grid Grid.Column="0">
  23. <StackPanel>
  24. <StackPanel Orientation="Horizontal">
  25. <Button Content="问AI" Margin="10"
  26. Command="{Binding AskCommand}"></Button>
  27. <!--<Button Content="翻译为:"></Button>-->
  28. <Label Content="翻译为:"
  29. HorizontalAlignment="Center"
  30. VerticalAlignment="Center"></Label>
  31. <ComboBox ItemsSource="{Binding Languages}"
  32. SelectedItem="{Binding SelectedLanguage}"
  33. HorizontalAlignment="Center"
  34. VerticalAlignment="Center"></ComboBox>
  35. <Button Content="翻译" Margin="10"
  36. Command="{Binding TranslateCommand}"></Button>
  37. </StackPanel>
  38. <TextBox Height="300" Margin="10"
  39. Text="{Binding AskText}"
  40. TextWrapping="Wrap"
  41. AcceptsReturn="True"></TextBox>
  42. </StackPanel>
  43. </Grid>
  44. <Grid Grid.Column="1">
  45. <StackPanel>
  46. <Button Content="AI回答" Margin="10"></Button>
  47. <TextBox Height="300"
  48. Margin="10"
  49. Text="{Binding ResponseText}"
  50. TextWrapping="Wrap"></TextBox>
  51. </StackPanel>
  52. </Grid>
  53. </Grid>
  54. </StackPanel>
  55. </Window>

界面效果如下所示:

image-20240703134726518

构建ViewModel

ViewModel如下所示:

  1. public partial class MainViewModel : ViewModelBase
  2. {
  3. private Kernel _kernel;
  4. [ObservableProperty]
  5. private string askText;
  6. [ObservableProperty]
  7. private string responseText;
  8. [ObservableProperty]
  9. private string selectedLanguage;
  10. public string[] Languages { get; set; }
  11. public MainViewModel()
  12. {
  13. var handler = new OpenAIHttpClientHandler();
  14. var builder = Kernel.CreateBuilder()
  15. .AddOpenAIChatCompletion(
  16. modelId: "Qwen/Qwen1.5-7B-Chat",
  17. apiKey: "你的apikey",
  18. httpClient: new HttpClient(handler));
  19. _kernel = builder.Build();
  20. AskText = " ";
  21. ResponseText = " ";
  22. SelectedLanguage = " ";
  23. Languages = new string[] { "中文","英文"};
  24. }
  25. [RelayCommand]
  26. private async Task Ask()
  27. {
  28. if(ResponseText != "")
  29. {
  30. ResponseText = "";
  31. }
  32. await foreach (var update in _kernel.InvokePromptStreamingAsync(AskText))
  33. {
  34. ResponseText += update.ToString();
  35. }
  36. }
  37. [RelayCommand]
  38. private async Task Translate()
  39. {
  40. string skPrompt = """
  41. {{$input}}
  42. 将上面的输入翻译成{{$language}},无需任何其他内容
  43. """;
  44. if (ResponseText != "")
  45. {
  46. ResponseText = "";
  47. }
  48. await foreach (var update in _kernel.InvokePromptStreamingAsync(skPrompt, new() { ["input"] = AskText,["language"] = SelectedLanguage }))
  49. {
  50. ResponseText += update.ToString();
  51. }
  52. }
  53. }

使用流式返回

  1. [RelayCommand]
  2. private async Task Ask()
  3. {
  4. if(ResponseText != "")
  5. {
  6. ResponseText = "";
  7. }
  8. await foreach (var update in _kernel.InvokePromptStreamingAsync(AskText))
  9. {
  10. ResponseText += update.ToString();
  11. }
  12. }

实现效果如下:

写提示

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

  1. string skPrompt = """
  2. {{$input}}
  3. 将上面的输入翻译成{{$language}},无需任何其他内容
  4. """;

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

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

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

原文链接:https://www.cnblogs.com/mingupupu/p/18281546

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号