Semantic Kernel 的一个核心能力就是实现“目标导向”的AI应用。
目标导向
“目标导向”听起来是一个比较高大的词,但是却是实际生活中我们处理问题的基本方法和原则。
顾名思义,这种方法的核心就是先确定目标,然后再寻找实现目标的方法和步骤。这对于人来说的是很自然的事情,但是对于机器则不然。一大堆的指令和控制逻辑其实都是在完成另外一种产出导向的结果。所有的流程和过程都需要提前预定义好,然后期待一个结果的产出。
如今,借助 LLM AI 的力量,我们可以轻松的实现目标导向的过程。
在 Semantic Kernel中,Planner就用于这项工作。
我们可以提前准备好所需的Skill,根据设定好的最终目标,通过Planner,可以将目标分解为需要执行的任务列表,并且可以指定好对应的参数传递,然后逐个任务执行,从而实现最终目标。
做好技能准备
为了让LLM AI更好的理解我们所提供的技能,需要明确地配置好每个技能本身的描述和参数描述。
对于的Semantic Function来说,可以在config.json中配置。以下是一个Translate的配置。
需要注意的就是 description
和 input
参数,最终会成为的LLM是否选择使用的判断标准。而这一切都是基于语义化的理解。
{ | |
"schema": 1, | |
"type": "completion", | |
"description": "Translate the input into the specified language", | |
"completion": { | |
"max_tokens": 1024, | |
"temperature": 0.0, | |
"top_p": 0.9, | |
"presence_penalty": 0.0, | |
"frequency_penalty": 0.0 | |
}, | |
"input": { | |
"parameters": [ | |
{ | |
"name": "input", | |
"description": "input text", | |
"defaultValue": "" | |
}, | |
{ | |
"name":"language", | |
"description":"the specified language", | |
"defaultValue":"English" | |
} | |
] | |
} | |
} |
对于Native Function ,可以使用特性进行声明,其实 SKFunction
中用于添加Function的描述, SKFunctionContextParameter
用于添加参数的说明。
public class EmailSKill { | |
[SKFunction("Send email conten to receiver")] | |
[SKFunctionContextParameter(Name ="content", Description = "email content")] | |
[SKFunctionContextParameter(Name ="receiver", Description = "the email address of receiver")] | |
public void SendTo(SKContext context){ | |
var email = context["content"]; | |
var receiver = context["receiver"]; | |
Console.WriteLine( | |
$""" | |
mail to: {receiver} | |
{email} | |
"""); | |
} | |
} |
准备好技能之后,就可以将这些技能导入到Kernel中,等待后续使用。
作为示例,这里导入了三个功能:
MySkill.WriteText
: 文案写作MySkill.Translate
:文本翻译email.SendTo
: 邮件发送
使用Planner
然后我们就可以开始使用 Planner了。
0.13之前版本
Planner作为一个核心组件,在0.13版本之后从Skill中提升了出来,目前(0.13版本)使用了独立的SequentialPlanner,直接创建即可使用。
var planner = new SequentialPlanner(kernel); |
指定好任务目标。
var goal = "The PowerBlog is about to release a new product, please write a chinese press release about the new product and send it to mail@example.com"; |
0.13之前版本
然后就可以直接使用 SequentialPlanner 创建一个Plan了。
var plan = await planner.CreatePlanAsync(goal); |
此时可以使用plan.ToJson(),查看任务编排的情况。
plan.ToJson().Dump("Create Plan"); |
0.13之前版本
0.13 版本之后,任务执行方法更加简单。
由于Plan本身就是一组 ISKFunction,所以可以直接使用 Kernel.RunAsync执行
var result = await kernel.RunAsync(plan); |
和通常的Skill执行一样,查看result.Result即可得到结果。
result.Result.Dump("RESULT"); |
如果需要逐步执行查看结果,或者进行干预的话,也可以手动的调用执行过程。执行的状态都由Plan本身来维护,使用 HasNextStep
可以查看当前所有任务是否执行完成,可以使用Plan 的 InvokeNextStepAsync
来执行下一步,也可以使用Kernel的StepAsync
逐步执行。
async Task<Plan> ExecutePlanAsync(IKernel kernel, Plan plan,string input = "") | |
{ | |
while(plan.HasNextStep){ | |
if(string.IsNullOrWhiteSpace(input)){ | |
await kernel.StepAsync(plan); | |
}else { | |
await kernel.StepAsync(input,plan); | |
} | |
plan.State.Dump(); | |
if(!plan.HasNextStep){ | |
break; | |
} | |
} | |
return plan; | |
} | |
await ExecutePlanAsync(kernel,plan); |
Plan执行完成的结果,可以直接使用Plan.State.ToString()
获取。
plan.State.ToString().Dump("RESULT"); | |
// output | |
/* | |
PowerBlog很高兴地宣布即将推出我们的最新产品,这将彻底改变人们生活的方式。我们一直在不懈努力地开发一款产品,它将对我们的客户生活产生重大影响,我们相信我们已经做到了这一点。 | |
我们的新产品旨在成为一款改变游戏规则的产品,为用户提供独特的体验,增强他们的日常生活。我们相信,这款产品将成为任何想要提高生产力、效率和整体生活质量的人必备的产品。 | |
我们知道人们总是在寻找简化生活的方法,而这正是我们的新产品的目的。它将帮助用户更好地管理时间,保持组织,更有效地实现他们的目标。 | |
我们很高兴能够向我们的客户提供这款产品,我们迫不及待地想看到它对他们生活的积极影响。请继续关注我们最新产品的发布,准备体验一种新的生活方式。 | |
*/ |
至此,我们就掌握了Semantic Kernel 当前所有的核心概念和基本使用方法。
TIPS: 由于模型的能力问题,目前推荐使用GPT4模型执行以上操作。
参考资料:
- Planner in Semantic Kernel | Microsoft Learn
- semantic-kernel/05-using-the-planner.ipynb at main · microsoft/semantic-kernel · GitHub
- What is Semantic Kernel? | Microsoft Learn
- kernel-syntax-examples/Example12_Planning