Semantic Kernel 入门系列:💾Native Function
语义的归语义,语法的归语法。
基础定义
最基本的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";
}
}
这里针对 AsdfgAsync
的KernelFunction
特性添加了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
通过安装 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 的基础能力就学习得差不多了。
参考资料: