.NET SK 如何给AI大模型添加搜索引擎功能?

普通的AI大模型的数据都是在一开始训练的时候决定的,所以大模型的数据来源都可能存在时效性。

下面我们会利用SK插件来给AI大模型添加联网功能。

准备工作

创建一个名称为5_SK_Plugin_Web的控制台项目
复制以下代码到5_SK_Plugin_Web项目文件中

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net8.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
        <PackageReference Include="Microsoft.SemanticKernel" Version="1.13.0" />
    </ItemGroup>

</Project>

创建OpenAIHttpClientHandler.cs


namespace ConsoleApp1;


public class OpenAIHttpClientHandler : HttpClientHandler
{
    private readonly string _uri;

    public OpenAIHttpClientHandler(string uri) => _uri = uri.TrimEnd('/');

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        UriBuilder uriBuilder;
        if (request.RequestUri?.LocalPath == "/v1/chat/completions")
        {
            uriBuilder = new UriBuilder(_uri + "/v1/chat/completions");
            request.RequestUri = uriBuilder.Uri;
        }
        else if (request.RequestUri?.LocalPath == "/v1/embeddings")
        {
            uriBuilder = new UriBuilder(_uri + "/v1/embeddings");
            request.RequestUri = uriBuilder.Uri;
        }

        return await base.SendAsync(request, cancellationToken);
    }
}

创建联网插件

HttpClientFunction.cs


public class HttpClientFunction(IHttpClientFactory httpClientFactory, IChatCompletionService completionService)
{
    private const string BingTemplate = "https://cn.bing.com/search?q={0}";

    private const string SystemTemplate =
        @"
## 角色:

你是一款专业的搜索引擎助手。你的主要任务是从Html根据标签生成md的内容,并专注于准确地总结段落的大意,而不包含任何其他多余的信息或解释。

## 能力:

- 解析html中标签生成对应的md。
- 将提取的信息准确地总结为一段简洁的文本。
- 不属于用户提问的数据则不用整理。

## 指南:

- 这是一个完整的html标签,您需要根据标签生成对应的md格式。
- 只包含关键信息,尽量减少非主要信息的出现。
- 完成总结后,立即向用户提供,不需要询问用户是否满意或是否需要进一步的修改和优化。
";

    /// <summary>
    /// 搜索用户提出的问题
    /// </summary>
    [KernelFunction, Description("搜索用户提出的问题")]
    public async Task<string> GetAsync(string value)
    {
        var http = httpClientFactory.CreateClient(nameof(HttpClientFunction));

        var html = await http.GetStringAsync(string.Format(BingTemplate, value)).ConfigureAwait(false);

        var scriptRegex = new Regex(@"<script[^>]*>[\s\S]*?</script>");
        var styleRegex = new Regex(@"<style[^>]*>[\s\S]*?</style>");
        var commentRegex = new Regex(@"<!--[\s\S]*?-->");
        var headRegex = new Regex(@"<head[^>]*>[\s\S]*?</head>");
        var tagAttributesRegex = new Regex(@"<(\w+)(?:\s+[^>]*)?>");
        var emptyTagsRegex = new Regex(@"<(\w+)(?:\s+[^>]*)?>\s*</\1>");

        html = scriptRegex.Replace(html, "");
        html = styleRegex.Replace(html, "");
        html = commentRegex.Replace(html, "");
        html = headRegex.Replace(html, "");
        html = tagAttributesRegex.Replace(html, "<$1>");
        html = emptyTagsRegex.Replace(html, "");

        var result = await completionService.GetChatMessageContentsAsync(new ChatHistory(SystemTemplate)
        {
            new(AuthorRole.User, html),
            new(AuthorRole.User, value)
        }, new OpenAIPromptExecutionSettings()
        {
            ModelId = "gpt-3.5-turbo-0125"
        });

        Console.WriteLine("搜索结果:" + result.FirstOrDefault()?.Content);

        return result.FirstOrDefault()?.Content ?? "抱歉,未找到相关信息。";
    }
}

我们使用HttpClientFunction类来实现一个搜索引擎插件,该插件可以根据用户提出的问题搜索相关信息。
利用了https://cn.bing.com/search?q={0}接口去获取我们需要的信息,然后返回Html,使用正则表达式将html中大部分不需要的内容去掉。

然后我们在将获取的Html使用以下提示词进行内容精简。

## 角色:

你是一款专业的搜索引擎助手。你的主要任务是从Html根据标签生成md的内容,并专注于准确地总结段落的大意,而不包含任何其他多余的信息或解释。

## 能力:

- 解析html中标签生成对应的md。
- 将提取的信息准确地总结为一段简洁的文本。
- 不属于用户提问的数据则不用整理。

## 指南:

- 这是一个完整的html标签,您需要根据标签生成对应的md格式。
- 只包含关键信息,尽量减少非主要信息的出现。
- 完成总结后,立即向用户提供,不需要询问用户是否满意或是否需要进一步的修改和优化。

然后我们实现我们的核心逻辑。

打开Program.cs文件


var kernelBuilder = Kernel.CreateBuilder()
    .AddOpenAIChatCompletion(
        modelId: "gpt-3.5-turbo-0125",
        apiKey: "这里填写在https://api.token-ai.cn/创建的令牌",
        httpClient: new HttpClient(new OpenAIHttpClientHandler("https://api.token-ai.cn/")));

kernelBuilder.Services.AddHttpClient();

var kernel = kernelBuilder.Build();

kernel.Plugins.AddFromType<HttpClientFunction>(serviceProvider: kernel.Services);

var chat = kernel.GetRequiredService<IChatCompletionService>();

var openAIPromptExecutionSettings = new OpenAIPromptExecutionSettings()
{
    ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions
};


while (true)
{
    Console.WriteLine("请输入您的问题:");
    var str = Console.ReadLine();

    if (str == "exit")
    {
        break;
    }

    var chatHistory = new ChatHistory();
    chatHistory.AddUserMessage(str);
    await foreach (var item in
                   chat.GetStreamingChatMessageContentsAsync(chatHistory, openAIPromptExecutionSettings, kernel))
    {
        Console.Write(item?.Content);
    }

    Console.WriteLine();
}

解析上面的代码,


var kernelBuilder = Kernel.CreateBuilder()
    .AddOpenAIChatCompletion(
        modelId: "gpt-3.5-turbo-0125",
        apiKey: "这里填写在https://api.token-ai.cn/创建的令牌",
        httpClient: new HttpClient(new OpenAIHttpClientHandler("https://api.token-ai.cn/")));

kernelBuilder.Services.AddHttpClient();

var kernel = kernelBuilder.Build();

在这里我们创建了一个kernelBuilder,然后我们添加了一个OpenAIChatCompletion插件,这个插件是用来调用OpenAI的API的,我们需要填写我们在https://api.token-ai.cn/创建的令牌,
然后我们在kernelBuilder中的Services注册了我们的HttpClient服务,以便插件的依赖注入的IHttpClientFactory能够正常工作。


kernel.Plugins.AddFromType<HttpClientFunction>(serviceProvider: kernel.Services);

这一行代码是将我们的HttpClientFunction插件添加到kernel中,这样我们就可以在kernel中使用我们的插件了。


var chat = kernel.GetRequiredService<IChatCompletionService>();

var openAIPromptExecutionSettings = new OpenAIPromptExecutionSettings()
{
    ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions
};

在这里我们通过kernel中的GetRequiredService方法获取了IChatCompletionService服务,这个服务是用来调用OpenAI的API的。
然后我们创建了一个OpenAIPromptExecutionSettings对象,这个对象是用来设置我们的插件的行为的,这里我们设置了ToolCallBehaviorAutoInvokeKernelFunctions,这样我们的插件就会自动调用kernel中的函数了。



while (true)
{
    Console.WriteLine("请输入您的问题:");
    var str = Console.ReadLine();

    if (str == "exit")
    {
        break;
    }

    var chatHistory = new ChatHistory();
    chatHistory.AddUserMessage(str);
    await foreach (var item in
                   chat.GetStreamingChatMessageContentsAsync(chatHistory, openAIPromptExecutionSettings, kernel))
    {
        Console.Write(item?.Content);
    }

    Console.WriteLine();
}

我们在这里创建了一个循环,然后我们在循环中获取用户输入的问题,然后我们创建了一个ChatHistory对象,这个对象是用来存储我们的对话历史的,然后我们调用chat.GetStreamingChatMessageContentsAsync方法。
对话的执行流程是:

  1. 用户输入问题
  2. 调用chat.GetStreamingChatMessageContentsAsync方法,然后传递kernel,让它自动调用插件,然后根据用户提问去判断调用哪个插件。
  3. 返回需要调用的插件。
  4. 调用插件HttpClientFunction.GetAsync方法,然后得到有用的信息。
  5. 整理信息,返回给用户。

运行

请输入您的问题:
庆余年最新一集?
搜索结果:**庆余年最新一集**是庆余年第二季的剧情:在悬空寺上,庆帝遭遇三连刺杀,范闲出手相救却导致武功全废。危机四伏,压力陡增,范闲别无选择,他必须以这样的身体下江南,挑战庞大的势力与既定的游戏规则,以求彻底夺回内库。
庆余年第二季的最新一集剧情是:在悬空寺上,庆帝遭遇三连刺杀,范闲出手相救却导致武功全废。危机四伏,压力陡增,范闲别无选择,他必须以这样的身体下江南,挑战庞大的势力与既定的游戏规则,以求彻底夺回内库。
请输入您的问题

总结

我们通过上面的代码实现了一个搜索引擎插件,这个插件可以根据用户提出的问题搜索相关信息,然后返回给用户。

SK入门学习社区

qq群:961090189

微信:wk28u9123456789

文档站点:https://docs.token-ai.cn/guide/5_sk_plugin_web

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

taskENTER_CRITICAL()分析

1. 临界段代码 //任务级的临界段代码保护 taskENTER_CRITICAL() taskEXIT_CRITICAL()//中断级的临界段代码保护 taskENTER_CRITICAL_FROM_ISR() taskEXIT_CRITICAL_FROM_ISR()2. 以STM32为例 &#xff08;1&#xff09;STM32有0~15&#xff0c;共16级中断&#xff0c;可嵌套…

数据结构算法 数组的实现与练习(C语言实现,Java实现)

文章目录 数据结构数组(顺序表)特点使用Java实现更高级的数组C语言实现总结优点缺点 例题[26. 删除有序数组中的重复项](https://leetcode.cn/problems/remove-duplicates-from-sorted-array/)[1. 两数之和](https://leetcode.cn/problems/two-sum/)[27. 移除元素](https://lee…

教育数字展馆助力全球教育传播,科技引领数字化教育潮流

一、教育数字展馆助力教育传播 1、提高教育资源的可及性 教育数字展馆通过VR和WEB3D技术&#xff0c;将丰富的教育资源呈现在用户面前。不论是名校的经典课程&#xff0c;还是专家的精彩讲座&#xff0c;均可通过教育数字展馆实现线上展示。用户只需登录平台&#xff0c;即可…

【解决】Tree prefab at index 8 is missing.

开发平台&#xff1a;Unity 2020 版本以上   问题描述 翻译&#xff1a;树预制体集合中第8位预制体丢失。   解决方法&#xff1a;修复丢失树资产 关联 Unity Terrier 组件使用&#xff0c;前往 树绘制工作区&#xff0c;检查 “树资产” 引用是否丢失&#xff1f;删除或重…

Mysql基础教程(10):LIMIT

MySQL LIMIT 用法与实例 在 MySQL 中&#xff0c;我们使用 LIMIT 子句来限定 SELECT 语句返回的行的数量。 MySQL LIMIT语法 该 LIMIT 子句可用于限制 SELECT 语句返回的行数。 LIMIT 接受一个或两个非负数正数作为参数。 LIMIT 子句的语法如下&#xff1a; LIMIT [offset,…

CDH6.3.2集成Flink1.12.2

一、Linux下载httpd服务并开启 yum install y httpd systemctl start httpd systemctl enable httpd 二、获取已制作好的安装包 flink-1.12.2-bin-scala_2.11.tar ​ FLINK_ON_YARN-1.12.2.jar ​ flink-shaded-hadoop-2-uber-3.0.0-cdh6.3.2-10.0.jar 三、集成CM 1.上传编…

K210视觉识别模块学习笔记2:固件的下载升级_官方数字识别例程导入方法

今日开始学习K210视觉识别模块:固件的下载升级_官方数字识别例程导入方法 主要学习如何升级固件库&#xff0c;在哪下载固件库&#xff0c;以及如何在TF卡正确导入官方例程&#xff1a; 亚博智能的K210视觉识别模块...... 本次最终目的是正确导入官方的数字识别例程&#xff0…

[GESP202306 四级] 幸运数

按照题目做就OK了&#xff08;本蒟蒻写得太烂了&#xff09; #include<bits/stdc.h> using namespace std; long long w(long long n) {if(n1||n0){return n*7;}n*7;long long tsgn,s0;while(true){s0;while(tsg!0){stsg%10;tsg/10;}if(s<9){return s;}tsgs;} } bool…

可编程晶体振荡器应用于车载倒车雷达

倒车雷达&#xff0c;即“倒车防撞雷达”&#xff0c;又称“"停车辅助装置”&#xff0c;是汽车停车或倒车时的安全辅助装置。它主要由超声波传感器、控制器和显示器等组成&#xff0c;可以通过声音或更直观的显示告知驾驶员周围的障碍物&#xff0c;解除驾驶员在停车、倒…

【软件测试】软件测试概念 | 测试用例 | BUG | 开发模型 | 测试模型 | 生命周期

文章目录 一、什么是软件测试1.什么是软件测试2.软件测试和调试的区别测试人员需要的素养 二、软件测试概念1.需求1.需求的定义2.测试人员眼中的需求 2.测试用例1.测试用例概念 3.BUG 软件错误4、开发模型和测试模型1.软件的生命周期2.开发模型1.瀑布模型2.螺旋模型3.增量、迭代…

2024年人工智能与机械自动化技术国际会议( ICAIMAT 2024)

2024年人工智能与机械自动化技术国际会议( ICAIMAT 2024) 会议简介 随着科技的飞速发展&#xff0c;人工智能和机械化自动化技术已成为全球产业升级和经济发展的重要动力。为了进一步促进国际交流与合作&#xff0c;推动人工智能和机械化自动化技术的创新与应用&#xff0c;我…

2024年艺术鉴赏与科学教育国际会议(ICAASE 2024)

2024年艺术鉴赏与科学教育国际会议 2024 International Conference on Art Appreciation and Science Education 【1】会议简介 2024年艺术鉴赏与科学教育国际会议是一场集艺术、科学和教育于一体的国际性学术盛会。本次会议旨在推动艺术鉴赏与科学教育领域的深入交流与合作&am…

电脑提示缺少vcruntime140_1.dll的解决方法,总结7种有效方法

vcruntime140_1.dll是Microsoft Visual C 2015运行时库的一部分&#xff0c;它为使用Visual Studio 2015开发的应用程序提供了必要的运行时组件。该文件支持C程序的执行&#xff0c;包括内存管理、输入输出操作以及多线程功能等。缺失或损坏此文件可能导致应用程序无法启动或运…

Redis实战篇3:优惠券秒杀

说明 该实战篇基于某马的Redis课程中的《某马点评项目》。非常适合有相关经验、缺少企业级解决方案&#xff0c;或者想要复习的人观看&#xff0c;全篇都会一步一步的推导其为什么要这么做&#xff0c;分析其优缺点&#xff0c;达到能够应用的地步。 本实战篇中心思想就是把项目…

谷歌Material Design设计标准指南

Material Design是谷歌的Android设计规范。虽然这种优秀的设计语言应用于Android&#xff0c;但它的本质被许多设计师借鉴&#xff0c;并用于自己的设计。它是一个广泛的UX、UI设计师必须学习优秀的设计规范。 现在&#xff0c;Material Design设计规范已正式内置为即时设计&a…

MySQL -- SQL笔试题相关

1.银行代缴花费bank_bill 字段名描述serno流水号date交易日期accno账号name姓名amount金额brno缴费网点 serno: 一个 BIGINT UNSIGNED 类型的列&#xff0c;作为主键&#xff0c;且不为空。该列是自动增量的&#xff0c;每次插入新行时&#xff0c;都会自动递增生成一个唯一的…

【AIGC】大型语言模型在人工智能规划领域模型生成中的探索

大型语言模型在人工智能规划领域模型生成中的新应用 一、引言二、LLM在规划领域模型生成中的潜力三、实证分析&#xff1a;LLM在规划领域模型生成中的表现四、代码实例&#xff1a;LLM在规划领域模型生成中的应用五、结论与展望 一、引言 随着人工智能技术的迅猛发展&#xff0…

String类详解

前言&#xff1a;String类是表示字符串的类&#xff0c;String类的内部也提供了非常多的方法来供程序员使用。 String类还有一大特性&#xff0c;就是不可变性。只要使用string创建了字符串&#xff0c;就不可以修改。为string类提供了一层安全性。&#xff08;对于" &qu…

Android 11.0 系统设置语言和输入法菜单Launage语言列表增加支持多种英语语言功能

1.前言 在11.0的系统ROM产品定制化开发中,在系统中的语言和输入法菜单中,在添加语言的默认列表中对于同一类型的语言就可以会出现一中语言,比如多种英语类型 就显示的不全,所以要求显示所有的英语类型,这样就需要了解语言列表的加载流程然后加载所有的英语类型,接下来具…

Qt 5桌面APP开发实战

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 第一节&#xff1a;Qt 5桌面APP开发实战入门 Qt 5的跨平台特性 Qt 5的界面设计工具 Qt 5的…