首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

使用Aspire优雅的进行全栈开发——WinUI使用Semantic Kernel调用智普清言LLM总结Asp.Net Core通过Playwright解析的网页内容

编程知识
2024年08月04日 15:25

前言

这算是一篇学习记录博客了,主要是学习语义内核(Semantic Kernel)的实践,以及Aspire进行全栈开发的上手体验,我是采用Aspire同时启动API服务,Blazor前端服务以及WinUI的桌面端项目,同时进行三个项目的代码修改,整体感觉很方便,如果代码都修改了只需要启动Aspire项目,不用每个项目单独起一遍了,而且速度很快,即使是有用容器服务的情况下。

技术方案

1. 框架选型

  • WebApi使用Asp.Net Core WebApi实现。
  • Bing搜索结果获取,以及网页解析内容提取使用的是PlayWright库。
  • 网页内容总结使用的是WinUI编写的客户端,结合语义内核(Semantic Kernel)调用国产智普清言LLM。
  • 后台管理页面使用的Blazor,不过只是一个demo页面。

img

2. 为什么这样选

作为一个.Net开发,肯定优先使用.Net相关的技术了,也为了能实践最新的技术,就进行了一些新技术的选择。

主要说明一下选择这几个技术框架的原因:

  • Playwright 原因是通过测试发现它的表现最好,其他类型的库也有测试,比如Selenium,HtmlAgilityPack,HtmlAgilityPack对静态网页解析比较好,但是如果遇到js渲染的数据很多的页面就不好了,Selenium比Playwright提取的内容差了一些,Playwright是通过模拟用户操作启动浏览器,然后获取内容,感觉如果一次性处理很多的页面应该也会负载很大。

  • Aspire 这个是因为这是微软最新的专门给开发人员开发的工具,那既然是给开发人员做的,那肯定要体验一把了,体验完感觉是真的不错,能够节省很多的步骤。

  • 语义内核(Semantic Kernel)选择它是因为这算是.Net社区对接大语言模型最流行的框架了,提供了很多的开箱即用的功能,对于开发智能APP帮助很大,而且社区热度也很高。

  • 智普清言LLM 选择它是多方面考虑的结果,第一是它兼容OpenAI的接口,这样语义内核就可以通过配置就能使用它,第二是它是支持Function Call的,也就是说它可以作为OpenAI的国内平替,用它开发一些智能APP是很好的。

  • WinUI 选择它是个人对客户端开发主要使用的是WinUI,而且用它对接大语言模型不把对接放到后端也是为了后面对接离线大语言模型做基础,比如微软的Phi3之类的。

代码讲解

本博客涉及的代码链接如下:

https://github.com/GreenShadeZhang/BingSearchSummary

1. 搜索结果获取

示例代码如下:

先创建Playwright实例,然后进行用户操作模拟。

   var playwright = await Playwright.CreateAsync();
   var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions { Headless = true });
   var page = await browser.NewPageAsync();

   // 设置 User-Agent 和视口大小
   var js = @"Object.defineProperties(navigator, {webdriver:{get:()=>false}});";
   await page.AddInitScriptAsync(js);

   await page.GotoAsync("https://www.bing.com");

   // 模拟用户输入搜索关键词
   await page.FillAsync("input[name=q]", keyword);
   await page.Keyboard.PressAsync("Enter");

   // 等待搜索结果加载
   await page.WaitForLoadStateAsync(LoadState.NetworkIdle);

   // 获取搜索结果内容
   var content = await page.ContentAsync();
   var dataList = BingSearchHelper.ParseHtmlToJson(content);
   var result = new List<BingSearchItem>();
   

将搜索结果解析成json数据如下:

这一步是因为我没有bing搜索的订阅,所以只能解析页面,如果有bing搜索的订阅这一步可以省略。

using BingSearchSummary.ApiService.Models;
using HtmlAgilityPack;

namespace BingSearchSummary.ApiService;

public class BingSearchHelper
{
    public static List<BingSearchItem> ParseHtmlToJson(string htmlContent)
    {
        var htmlDocument = new HtmlDocument();
        htmlDocument.LoadHtml(htmlContent);

        var results = new List<BingSearchItem>();

        foreach (var node in htmlDocument.DocumentNode.SelectNodes("//li[@class='b_algo']"))
        {
            var titleNode = node.SelectSingleNode(".//h2/a");
            var snippetNode = node.SelectSingleNode(".//p");
            var urlNode = node.SelectSingleNode(".//cite");

            var title = titleNode?.InnerText.Trim();
            var snippet = snippetNode?.InnerText.Trim();
            var url = urlNode?.InnerText.Trim();

            if (string.IsNullOrEmpty(title))
            {
                continue;
            }

            var searchItem = new BingSearchItem
            {
                Title = title,
                Snippet = snippet ?? "",
                Url = url ?? ""
            };

            results.Add(searchItem);
        }

        return results;
    }
}

通过上面的代码操作,关键词搜索的网页URL就已经拿到了,然后就可以继续进行页面内容的解析了。

2. 网页内容解析

客户端通过调用接口,然后获取关键词的前三条的搜索结果和网页内容。

    // 获取搜索结果内容
    var content = await page.ContentAsync();
    var dataList = BingSearchHelper.ParseHtmlToJson(content);
    var result = new List<BingSearchItem>();

    foreach (var data in dataList)
    {
        if (result.Count >= 3)
        {
            break;
        }//只处理三条数据
        await page.GotoAsync(data.Url);

        var divContent = await page.QuerySelectorAsync(".content");

        divContent ??= await page.QuerySelectorAsync("body");

        if (divContent != null)
        {
            var pageContent = await divContent.InnerTextAsync();

            result.Add(new BingSearchItem
            {
                Title = data.Title,
                Url = data.Url,
                Snippet = data.Snippet,
                PageContent = pageContent
            });
        }

swagger结果展示如下:

img

3. 网页结果总结

这部分代码在WinUI项目中实现,WinUI调用接口获取到结果,并通过Microsoft.SemanticKernel.PromptTemplates.Liquid库进行消息模板动态生成消息,调用语义内核(Semantic Kernel)进行内容总结。

语义内核(Semantic Kernel)注入代码如下:

            //测试token被删除 已经无效 请换成自己的智普token
            builder.AddOpenAIChatCompletion(modelId: "GLM-4-Air", apiKey: "4827638425a6b9d48bea3b0599246ff2.pFjhEKShPOZE8OFd", httpClient: GetProxyClient("https://open.bigmodel.cn/api/paas/v4/chat/completions"));

            builder.Plugins.AddFromType<TimeInformationPlugin>();

            services.AddSingleton(builder.Build());

#pragma warning disable SKEXP0040 // 类型仅用于评估,在将来的更新中可能会被更改或删除。取消此诊断以继续。
            services.AddSingleton<IPromptTemplateFactory, LiquidPromptTemplateFactory>();
#pragma warning restore SKEXP0040 // 类型仅用于评估,在将来的更新中可能会被更改或删除。取消此诊断以继续。

内容总结代码如下:

  [RelayCommand]
  private async Task SummaryAndUploadAsync(BingSearchItem item)
  {
      _chatHistory.Clear();

      SummaryProcessRingStatus = true;
      try
      {
          var arguments = new KernelArguments
          {
              ["startTime"] = DateTimeOffset.Now.ToString("hh:mm:ss tt zz", CultureInfo.CurrentCulture),

              ["userMessage"] = item.PageContent
          };

          var systemMessage = await _promptTemplateFactory.Create(new PromptTemplateConfig(_systemPromptTemplate)
          {
              TemplateFormat = "liquid",
          }).RenderAsync(_kernel, arguments);

          var userMessage = await _promptTemplateFactory.Create(new PromptTemplateConfig(_userPromptTemplate)
          {
              TemplateFormat = "liquid",
          }).RenderAsync(_kernel, arguments);

          _chatHistory.AddSystemMessage(systemMessage);

          _chatHistory.AddUserMessage(userMessage);


          var chatResult = await _chatCompletionService.GetChatMessageContentAsync(_chatHistory, _openAIPromptExecutionSettings, _kernel);

          SummaryResult = chatResult.ToString();

          await _apiClient.PostContentsAsync(new BingSearchSummaryItem
          {
              Title = item.Title,
              Summary = chatResult.ToString(),
              Url = item.Url
          });

      }
      catch (Exception ex)
      {
          System.Diagnostics.Debug.WriteLine(ex.Message);
          SummaryProcessRingStatus = false;
      }

      SummaryProcessRingStatus = false;
  }

效果如下:

img

到此总结就已经完成了,大家可以去看看代码,看看有没有帮助。

个人心得体会

在进行一段时间的学习之后,对大语言模型有了一些全面的认识,意识到大语言模型并不是万能的,但是它能够很轻松的做到我们之前要很复杂才能做到的事情。轻松做到的前提就是要给出很好的提示词。

如果把大语言模型比作战斗机,那提示词就可以比作是驾驶员了,提示词的好坏直接决定大语言模型输出的准确度。

作为软件开发人员,对于提示词的编写一定要多学习,多总结才行了。

参考推荐文档项目如下:

From:https://www.cnblogs.com/GreenShade/p/18341903
本文地址: http://shuzixingkong.net/article/771
0评论
提交 加载更多评论
其他文章 位段 -- 内存布局详解C语言
目录位段的介绍位段使用示例:位段的内存分配Example内存分配解析: ## 位段 位段的介绍 位段(二进制位):就是按位存储 位段(bit-field)是C语言中的一种特殊数据类型,它允许将一个字节分成几个部分,并为每个部分指定特定的位数,以便在内存中存储和访问这些部分。 其中位段相较于结构体有两
位段 -- 内存布局详解C语言
HTML 编辑器
使用像Notepad(在Windows上)或TextEdit(在MacOS上)这样的基本文本编辑器来学习HTML是一个非常棒的开始。这些工具虽然简单,但足以让你编写并查看基本的HTML代码,帮助你理解HTML的结构和语法。下面我将详细解释每一步,确保你能成功创建并查看你的第一张HTML网页。 步骤一
ComfyUI插件:ComfyUI layer style 节点(四)
前言: 学习ComfyUI是一场持久战,而ComfyUI layer style 是一组专为图片设计制作且集成了Photoshop功能的强大节点。该节点几乎将PhotoShop的全部功能迁移到ComfyUI,诸如提供仿照Adobe Photoshop的图层样式、提供调整颜色功能(亮度、饱和度、对比度
ComfyUI插件:ComfyUI layer style 节点(四) ComfyUI插件:ComfyUI layer style 节点(四) ComfyUI插件:ComfyUI layer style 节点(四)
推荐3款免费且实用的数据库管理工具
前言 数据库在日常工作中确实扮演着至关重要的角色,无论是数据管理、分析还是应用开发,都离不开它的支持。今天大姚给大家分享3款免费且实用的数据库管理工具,希望可以帮助到有需要的同学。 DBeaver DBeaver是一款免费的跨平台数据库工具,适用于开发人员、数据库管理员、分析师和所有数据处理人员。它
推荐3款免费且实用的数据库管理工具 推荐3款免费且实用的数据库管理工具 推荐3款免费且实用的数据库管理工具
使用 C# 和 ONNX 來玩转Phi-3 SLM
LLM 席卷世界刷新 AI 的认知之后,由于 LLM 需要的硬件要求实在太高,很难在普通设备上运行,因此 SLM 逐漸受到重視,Phi-3 SLM 是由 Microsoft 所开发的模型,可以在你的电脑、手机等设备来运行,小型语言模型 (SLM) 和 ONNX 的结合改变了 AI 互操作性的游戏规则
使用 C# 和 ONNX 來玩转Phi-3 SLM 使用 C# 和 ONNX 來玩转Phi-3 SLM
使用python对Excel表格某个区域保存为图片
实际工作中,我们经常会把表格某个区域(如:A1:F5)或某个图形保存为图片,如何用python自动做到这一点?不知屏幕前的小伙伴有没有遇到过类似的需求,此刻脑海里有木有一丢丢思路。 python操作excel的第三方库有很多,个个都有各自的绝招和擅长的应用场景,简单罗列一下: pyexcel:pye
使用python对Excel表格某个区域保存为图片 使用python对Excel表格某个区域保存为图片
三.mysql问答合集
目录三.MySQL3.1 关系型和非关系型数据库的区别关系型数据库非关系型数据库3.2 登录数据库的方式,如何远程登录3.3 MySQL的服务结构,当客户端发起请求后,处理过程3.4 如何设置或者重置MySQL密码3.5 DDL,DML,DQL,DCL等SQL语句的写法DDL数据定义语句DCL数据控
三.mysql问答合集 三.mysql问答合集 三.mysql问答合集
Jenkins API用户认证方式
1、概述 Jenkins的API可以通过用户名+密码或者用户名+Token的方式来进行认证,这篇文章以具体示例来说明具体的使用方式。 2、Jenkins环境 本文示例基于Jenkins 2.452.3版本进行演示,详细的环境构建可参考《Centos7下安装配置最新版本Jenkins(2.452.3)
Jenkins API用户认证方式 Jenkins API用户认证方式 Jenkins API用户认证方式