Semantic Kernel 入门系列:💾Native Function

image
语义的归语义,语法的归语法。

基础定义

最基本的Native Function定义只需要在方法上添加 KernelFunction 的特性即可。


namespace MyPluginsDirectory;

public class MyCSharpPlugin
{
    [KernelFunction]
    [Description("Return the first row of a qwerty keyboard")]
    public string Qwerty(string input)
    {
        return "qwertyuiop";
    }

    [KernelFunction]
    [Description("Return a string that's duplicated")]
    public string DupDup(string text)
    {
        return text + text;
    }
}

参数的传递来自于Kernel调用时的KernelArguments,其中的参数名和参数类型需要匹配,多个参数的话也是类似的。



namespace MyPluginsDirectory;

public class MyCSharpPlugin
{
    [KernelFunction]
    [Description("Return a string that's duplicated")]
    public string DupDup(string text)
    {
        return text + text;
    }

    [KernelFunction]
    [Description("Joins a first and last name together")]
    public string FullNamer(string firstname, string lastname)
    {
        return $"{firstname} {lastname}";
	}
}

调用的时候,传递KernelArguments即可。



using MyPluginsDirectory;

// ... instantiate a kernel as myKernel
var arguments = new KernelArguments();
arguments.Add("FirstName", "Sam");
arguments.Add("LastName", "ve");

var Plugin = kernel.ImportPluginFromObject ( new MyCSharpPlugin(), "MyCSharpPlugin");

var result = await kernel.InvokeAsync(Plugin[nameof(MyCSharpPlugin.FullNamer)],arguments);

Console.WriteLine(result);

当然异步的方法也是支持的。这样的话,就可以处理一些像是网络请求,数据库访问、文件读写等操作了。

using Microsoft.SemanticKernel.PluginDefinition;
using Microsoft.SemanticKernel.Orchestration;

public class MyCSharpPlugin
{
    [KernelFunction]
    [Description("Return the first row of a qwerty keyboard")]
    public string Qwerty(string input)
    {
        return "qwertyuiop";
    }

    [KernelFunction("JustDoIt")]
    [Description("Return the second row of a qwerty keyboard")]
    public async Task<string> AsdfgAsync(string input)
    {
        await ...do something asynchronous...

        return "asdfghjkl";
    }
}

这里针对 AsdfgAsyncKernelFunction 特性添加了name参数,可以为方法指定一个特定的名称。默认情况下同步方法将直接使用方法名,异步方法也将使用方法名(移除Async后缀)。

混合调用

和 Semantic Function中能够调用 Native Function一样,在 Native Function也可以调用Semantic Function,其中主要使用的还是 Kernel.

namespace MyPluginsDirectory;

public class MyCSharpPlugin
{
    [KernelFunction()]
    [Description("Tell me a joke in one line of text")]
    public async Task<string> TellAJokeInOneLineAsync(Kernel kernel)
    {
        // Fetch a semantic function previously loaded into the kernel
        KernelFunction joker1 = kernel.Plugins.GetFunction("funPlugin", "joker");

        // OR Try Fetch a semantic function previously loaded into the kernel
        kernel.Plugins.TryGetFunction("funPlugin", "joker",out var joker2);

        var joke = await joker1.InvokeAsync(kernel);

        return joke.GetValue<string>().ReplaceLineEndings(" ");
    }
}

这里并没有限制是 Semantic Function 还是Native Function,所以甚至可以完全使用Native Function编排插件调用。

一些核心插件

Semantic Kernel 中大部分的能力都是有插件提供的,例如Semantic Kernel的一个核心组件Planner,其实就是一组Semantic Plugin,另外官方提供了一些Core Plugin,基本是日常比较常用的。具体可以参考Plugins.Core
img

通过安装 Nuget package Microsoft.SemanticKernel.Plugins.Core 即可,和自行定义的Native Function一样的,只需要使用ImportPlugin就行了

using Microsoft.SemanticKernel.Plugins.Core;
// ( You want to instantiate a kernel and configure it first )

kernel.ImportPluginFromType<TimePlugin>("time");

const string ThePromptTemplate = @"
Today is: {{time.Date}}
Current time is: {{time.Time}}

Answer to the following questions using JSON syntax, including the data used.
Is it morning, afternoon, evening, or night (morning/afternoon/evening/night)?
Is it weekend time (weekend/not weekend)?";

var myKindOfDay = kernel.CreateFunctionFromPrompt(ThePromptTemplate);

var myOutput = await myKindOfDay.InvokeAsync(kernel);
Console.WriteLine(myOutput.GetValue<string>());

至此,Semantic Kernel 的基础能力就学习得差不多了。


参考资料:

  1. Creating native functions for AI to call
  2. Use the out-of-the-box plugins in the kernel
  3. Plugins.Core
posted @ 2023-04-11 21:59  宵伯特  阅读(1213)  评论(2编辑  收藏  举报