语义的归语义,语法的归语法。
基础定义
最基本的Native Function定义只需要在方法上添加 SKFunction
的特性即可。
using Microsoft.SemanticKernel.SkillDefinition; using Microsoft.SemanticKernel.Orchestration; namespace MySkillsDirectory; public class MyCSharpSkill { [SKFunction("Return the first row of a qwerty keyboard")] public string Qwerty(string input) { return "qwertyuiop"; } [SKFunction("Return a string that's duplicated")] public string DupDup(string text) { return text + text; } }
默认情况下只需要传递一个string 参数就行,如果需要多个参数的话,和Semantic Function一样,也是使用Context,不过这里传进去是 SKContext
。在方法上使用 SKFunctionContextParameter
声明一下参数,可以提供一定的说明,同时的有需要的话,可以设置参数的默认值。
using Microsoft.SemanticKernel.SkillDefinition; using Microsoft.SemanticKernel.Orchestration; namespace MySkillsDirectory; public class MyCSharpSkill { [SKFunction("Return a string that's duplicated")] public string DupDup(string text) { return text + text; } [SKFunction("Joins a first and last name together")] [SKFunctionContextParameter(Name = "firstname", Description = "Informal name you use")] [SKFunctionContextParameter(Name = "lastname", Description = "More formal name you use")] public string FullNamer(SKContext context) { return context["firstname"] + " " + context["lastname"]; } }
调用的时候,一样使用 ContextVariables
.
using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Orchestration; using MySkillsDirectory; // ... instantiate a kernel as myKernel var myContext = new ContextVariables(); myContext.Set("firstname","Sam"); myContext.Set("lastname","Appdev"); var myCshSkill = myKernel.ImportSkill ( new MyCSharpSkill(), "MyCSharpSkill"); var myOutput = await myKernel.RunAsync(myContext,myCshSkill["FullNamer"]); Console.WriteLine(myOutput);
当然异步的方法也是支持的。这样的话,就可以处理一些像是网络请求,数据库访问、文件读写等操作了。
using Microsoft.SemanticKernel.SkillDefinition; using Microsoft.SemanticKernel.Orchestration; public class MyCSharpSkill { [SKFunction("Return the first row of a qwerty keyboard")] public string Qwerty(string input) { return "qwertyuiop"; } [SKFunction("Return the second row of a qwerty keyboard")] [SKFunctionName("Asdfg")] public async Task<string> AsdfgAsync(string input) { await ...do something asynchronous... return "asdfghjkl"; }
这里针对 AsdfgAsync
添加了一个 SKFunctionName
的特性,主要是为了使Function name 好看一些,避免 MyCSharpSkill.AsdfgAsync
这样。
混合调用
和 Semantic Function中能够调用 Native Function一样,在 Native Function也可以调用Semantic Function,其中主要使用的还是 SKContext
.
using Microsoft.SemanticKernel.SkillDefinition; using Microsoft.SemanticKernel.Orchestration; namespace MySkillsDirectory; public class MyCSharpSkill { [SKFunction("Tell me a joke in one line of text")] [SKFunctionName("TellAJokeInOneLine")] public async Task<string> TellAJokeInOneLineAsync(SKContext context) { // Fetch a semantic function previously loaded into the kernel ISKFunction joker1 = context.Func("funSkill", "joker"); // OR Fetch a semantic function previously loaded into the kernel ISKFunction joker2 = context.Skills.GetSemanticFunction("funSkill", "joker"); var joke = await joker1.InvokeAsync(); return joke.Result.ReplaceLineEndings(" "); } }
这里并没有限制是 Semantic Function 还是Native Function,所以甚至可以完全使用Native Function编排技能调用,除了参数的定义和提取有些费劲以外,其他的几乎没什么问题,毕竟返回值都是string,这也就贯彻了Text is the universal wire protocol,即便是代码也得将就一下。
一些核心技能
Semantic Kernel 中大部分的能力都是有技能提供的,例如Semantic Kernel的一个核心组件Planner,其实就是一个Semantic Skill,另外官方提供了一些Core SKill,基本是日常比较常用的。具体可以参考https://github.com/microsoft/semantic-kernel/tree/main/dotnet/src/SemanticKernel/CoreSkills
和自行定义的Native Function一样的,只需要使用ImportSkill就行了
using Microsoft.SemanticKernel.CoreSkills; // ( You want to instantiate a kernel and configure it first ) myKernel.ImportSkill(new TimeSkill(), "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 = myKernel.CreateSemanticFunction(ThePromptTemplate, maxTokens: 150); var myOutput = await myKindOfDay.InvokeAsync(); Console.WriteLine(myOutput);
至此,Semantic Kernel 的基础能力就学习得差不多了。
参考资料: