• 探索Native Plugins:开启大模型的技能之门


    前言

    上一章节我们了解了一下Semantic KernnelPlugins插件的概念以及学习了的 Semantic Kernel 模板插件的创建,本章节我们来学习 Native Plugins 原生函数插件使用。

    通过函数定义插件

    在之前的章节中我们介绍过在在 Semantic Kernel 中应用 Function Calling,在文中讲解了Functioncalling的概念,以及在SK中的应用。
    Semantic Kernel中定义Native Plugins 函数插件,和 gpt-3.5-turbo 在 6 月 13 日 发布的 Function Calling特别的像,这是通过增加外部函数,通过调用来增强 OpenAI 模型的能力。

    在 Semantic Kernel 中定义函数插件

    Semantic Kernerl 中提供了很多定义Native Plugins的扩展方法来创建插件下面介绍最常用的几种:

    根据类型创建插件

    • SK源码
        public static KernelPlugin ImportPluginFromType(this Kernel kernel, string? pluginName = null)
        {
            KernelPlugin plugin = CreatePluginFromType(kernel, pluginName);
            kernel.Plugins.Add(plugin);
            return plugin;
        }
    
    • 定义Native Plugins

    Semantic Kernel 中定义函数插件,需要用到两个特性KernelFunctionDescription
    KernelFunction特性把函数标记为一个SKNative functionDescription给函数和参数以及返回值加描述,方便LLMs能够更好的理解。

    具体使用如下

    public class WeatherPlugin
    {
        public static string GetWeather => "WeatherSearch";
    
        [KernelFunction, Description("根据城市查询天气")]
        public string WeatherSearch([Description("城市名")] string city)
        {
            return $"{city}, 25℃,天气晴朗。";
        }
    }
    
    • Kernel添加插件
    kernel.ImportPluginFromType();
    

    这就是刚才说的根据类型来创建SK插件

    • 调用
    var getWeatherFunc = kernel.Plugins.GetFunction(nameof(WeatherPlugin), WeatherPlugin.GetWeather);
    var weatherContent = await getWeatherFunc.InvokeAsync(kernel, new() { ["city"] = "北京" });
    Console.WriteLine(weatherContent.ToString());
    
    • 输出
    北京, 25℃,天气晴朗。
    

    这是手动调用的方式当然也可以IChatCompletionService会话模式自动调用。

    根据对象创建

    主要用到了ImportPluginFromObject这个扩展方法

        public static KernelPlugin ImportPluginFromObject(this Kernel kernel, object target, string? pluginName = null)
        {
            KernelPlugin plugin = CreatePluginFromObject(kernel, target, pluginName);
            kernel.Plugins.Add(plugin);
            return plugin;
        }
    
    • 定义根据城市名获取美食的插件
    public class FinefoodPlugin
    {
        [KernelFunction, Description("根据城市获取美食推荐")]
        public string GetFinefoodList([Description("城市名")] string city)
        {
            return "烤鸭,卤煮,老北京炸酱面,炒肝等";
        }
    }
    

    和上一个使用 Type 注册插件是一样的操作

    • 注册并调用
        FinefoodPlugin finefoodPlugin = new();
        kernel.ImportPluginFromObject(finefoodPlugin);
        var getWeatherFunc = kernel.Plugins.GetFunction(nameof(FinefoodPlugin), "GetFinefoodList");
        var weatherContent = await getWeatherFunc.InvokeAsync(kernel, new() { ["city"] = "北京" });
        Console.WriteLine(weatherContent.ToString());
    
    • 输出:
    烤鸭,卤煮,老北京炸酱面,炒肝等
    
    • 扩展
      既然 Kernel 对象提供了根据对象实例创建插件的方案,那么就可以我们最喜欢的依赖注入获取的服务做插件的实例,这一点非常的重要,在以后项目实战中很实用。

    依赖注入举例

        IServiceCollection services = new ServiceCollection();
        services.AddSingleton();
        var rootProvider = services.BuildServiceProvider();
        FinefoodPlugin finefoodPlugin = rootProvider.GetRequiredService();
        kernel.ImportPluginFromObject(finefoodPlugin);
    

    根据 Kernelfunction 创建对象的实例

    SK 提供了几个根据 Kernelfunction 来创建Plugins的方案,这就用到Kernel对象创建 kernel functions的扩展方法。

    关于Kernel Function的创建有两种常用的形式第一种是根据Prompts来创建Semantic function也可以叫Prompts function,第二种是根据 C#的Delegate来创建Kernel Function

    第一种方案之前的文章中有讲过,有兴趣可以浏览一下深入学习 Semantic Kernel:创建和配置 prompts functions,这里不过多介绍。

    第二种在这里我们重点讲一下,根据委托来创建Kernel Function

    • 源码一览
        public static KernelFunction CreateFunctionFromMethod(
            this Kernel kernel,
            Delegate method,
            string? functionName = null,
            string? description = null,
            IEnumerable? parameters = null,
            KernelReturnParameterMetadata? returnParameter = null)
        {
            Verify.NotNull(kernel);
            Verify.NotNull(method);
    
            return KernelFunctionFactory.CreateFromMethod(method.Method, method.Target, functionName, description, parameters, returnParameter, kernel.LoggerFactory);
        }
    

    在之前的文章介绍过,所有创建Kernelfunction基本上都是利用KernelFunctionFactoryfunction工厂创建的,其实插件的创建也是一样通过KernelPluginFactory插件plugin工厂创建的。

    创建一个根据城市名获取游玩地点的插件

    • 创建 Kernel Function
        var kernelfunction = kernel.CreateFunctionFromMethod((string city) => { return $"{city} 好玩的地方有八达岭长城,故宫,恭王府等"; },
            functionName: "GetTourismClassic", description: "获取城市的经典",
             [
                new KernelParameterMetadata(name:"city") {
                 Description="城市名"
        }]);
    
    • 注册插件并调用
        kernel.ImportPluginFromFunctions("TourismClassicPlugin", [kernelfunction]);
        var getTourismClassic = kernel.Plugins.GetFunction("TourismClassicPlugin", "GetTourismClassic");
        var weatherContent = await getTourismClassic.InvokeAsync(kernel, new() { ["city"] = "北京" });
        Console.WriteLine(weatherContent.ToString());
    
    • 输出
    北京 好玩的地方有八达岭长城,故宫,恭王府等
    

    扩展

    上面介绍的都是在Sk中创建Native Plugins常用的方法,还有一些用法,比如

    • ImportPluginFromApiManifestAsync OpenAPI 功能相关
    • ImportPluginFromOpenAIAsync 通过 OpenAI 的 ChatGPT 格式为 OpenAI 插件创建一个插件
    • CreatePluginFromOpenApiAsync 从 OpenAPI v3 端点创建插件
    • ImportPluginFromGrpcFile 从 gRPC 文档导入
    • 其他

    最后

    本章我们学习了在 Semantic Kernel 中使用 Native Plugins 原生函数插件的方法,包括通过函数定义插件和根据对象创建插件的步骤。我们探讨了不同的创建插件的方式,以及如何注册插件并进行调用。通过这些方法,我们可以扩展 Semantic Kernel 的功能,增强模型的能力。

    参考文献

    示例代码

    本文源代码

  • 相关阅读:
    Codeforces Round #816 (Div. 2) B - Beautiful Array
    openGauss学习笔记-100 openGauss 数据库管理-管理数据库安全-客户端接入之用SSL进行安全的TCP/IP连接
    QT QToolBox控件使用详解
    ChatGPT - 高效编写Prompt
    使用python自动监控程序运行过程数据
    代码随想录第四十三天|343. 整数拆分 ● 96.不同的二叉搜索树
    【PowerQuery】PowerBI的增量刷新设置
    阿里云服务中断事件:原因、影响与解决方案
    C#源码 LIS实验室(检验科)信息系统源码 SaaS模式的Client/Server架构
    torch.nn.functional.grid_sample(F.grid_sample)函数的说明 & 3D空间中的点向图像投影的易错点
  • 原文地址:https://www.cnblogs.com/ruipeng/p/18234840