Semantic Kernel 的一个核心能力就是实现“目标导向”的AI应用。

目标导向

“目标导向”听起来是一个比较高大的词,但是却是实际生活中我们处理问题的基本方法和原则。

顾名思义,这种方法的核心就是先确定目标,然后在寻找实现目标的方法和步骤。这对于人来说的是很自然的事情,但是对于机器则不然。一大堆的指令和控制逻辑其实都是在完成另外一种产出导向的结果。所有的流程和过程都需要提前预定义好,然后期待一个结果的产出。

如今,借助 LLM AI 的力量,我们可以轻松的实现目标导向的过程。

在 Semantic Kernel中,Planner就用于这项工作。

我们可以提前准备好所需的Skill,根据设定好的最终目标,通过Planner,可以将目标分解为需要执行的任务列表,并且可以指定好对应的参数传递,然后逐个任务执行,从而实现最终目标。

做好技能准备

为了让LLM AI更好的理解我们所提供的技能,需要明确地配置好每个技能本身的描述和参数描述。

对于的Semantic Function来说,可以在config.json中配置。以下是一个Translate的配置。

需要注意的就是 descriptioninput 参数,最终会成为的LLM是否选择使用的判断标准。而这一切都是基于语义化的理解。

{
"schema": 1,
"type": "completion",
"description": "Translate the input into the specified language",
"completion": {
"max_tokens": 256,
"temperature": 0.0,
"top_p": 0.0,
"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中,准备后续时候。

作为示例,这里导入了三个功能:

  1. MySkill.WriteText : 文案写作
  2. MySkill.Translate :文本翻译
  3. email.SendTo : 邮件发送

使用Planner

然后我们就可以开始使用 Planner了。

Planner本身也是 Semantic Kernel中的一个Skill,融合了Semantic Function 和 Native Function。

和通常的Skill一样,导入 PlannerSkill 后即可使用。

var planner = kernel.ImportSkill(new PlannerSkill(kernel),"plan");

指定好任务目标。

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";

然后就可以执行 CreatePlan 创建一个Plan。

var plan = await kernel.RunAsync(goal,planner["CreatePlan"]);

此时可以使用Plan.PathString查看当前的任务编排。

Plan所有状态的结果都会保存在Context中,所以可以通过 context.Variables.ToPlan() 方法获取Plan对象。

plan.Variables.ToPlan().PlanString.Dump("Create Plan");
/*
<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
</goal>
<plan>
<function.MySkill.WriteText input="The PowerBlog is about to release a new product" setContextVariable="PRESS_RELEASE"/>
<function.MySkill.Translate input="$PRESS_RELEASE" language="Chinese" setContextVariable="TRANSLATED_PRESS_RELEASE"/>
<function.email.SendTo content="$TRANSLATED_PRESS_RELEASE" receiver="mail@example.com"/>
</plan>
*/

创建好了 Plan 就可以使用 ExecutePlan 执行了。

由于每次只能执行一个Function,所以我们需要通过循环来执行所有Function。

同时根据Plan的状态,判断是否执行成功,是否执行完成。

Plan 有两种状态,一种是 IsSuccessful ,表示当前的Plan是否执行成功。

另一个是 IsComplete,表示整个Plan是否执行完成。

async Task<SKContext> ExecutePlanAsync(IKernel kernel, SKContext plan)
{
var executionResults = plan;
while (!executionResults.Variables.ToPlan().IsComplete)
{
var result = await kernel.RunAsync(executionResults.Variables, planner["ExecutePlan"]);
var planResult = result.Variables.ToPlan();
if (planResult.IsSuccessful)
{
if (planResult.IsComplete)
{
break;
}
}
else
{
break;
}
executionResults = result;
}
return executionResults;
} var result = await ExecutePlanAsync(kernel,plan);
// output:
/*
mail to: mail@example.com 介绍PowerBlog——专为企业和企业家设计的终极博客平台。我们的新产品旨在帮助您轻松创建、管理和优化博客内容。 PowerBlog是为想要创建与竞争对手不同的专业博客的企业和企业家完美的解决方案。通过我们的直观用户界面,您可以快速创建和管理博客文章,优化SEO内容,并跟踪博客的性能。 我们的新产品还包括强大的功能,如自动内容策划、社交媒体整合和分析工具。通过这些功能,您可以轻松监控博客的性能,并就内容策略做出明智的决定。 PowerBlog是为想要创建与竞争对手不同的专业博客的企业和企业家完美的解决方案。通过我们的直观用户界面,您可以快速创建和管理博客文章,优化SEO内容,并跟踪博客的性能。 我们很高兴向客户提供这款新产品,期待帮助您创建一个成功的博客。今天就注册,开始创建与竞争对手不同的内容吧。
*/

最后根据状态判断Plan最后执行是否成功,并从plan.Result 中获取最后的输出结果。

if(!result.Variables.ToPlan().IsSuccessful) {
result.Variables.ToPlan().Result.Dump("Complete!");
}else {
result.Variables.ToPlan().Result.Dump("Error");
}
/*
:Complete!: 介绍PowerBlog——专为企业和企业家设计的终极博客平台。我们的新产品旨在帮助您轻松创建、管理和优化博客内容。 PowerBlog是为想要创建与竞争对手不同的专业博客的企业和企业家完美的解决方案。通过我们的直观用户界面,您可以快速创建和管理博客文章,优化SEO内容,并跟踪博客的性能。 我们的新产品还包括强大的功能,如自动内容策划、社交媒体整合和分析工具。通过这些功能,您可以轻松监控博客的性能,并就内容策略做出明智的决定。 PowerBlog是为想要创建与竞争对手不同的专业博客的企业和企业家完美的解决方案。通过我们的直观用户界面,您可以快速创建和管理博客文章,优化SEO内容,并跟踪博客的性能。 我们很高兴向客户提供这款新产品,期待帮助您创建一个成功的博客。今天就注册,开始创建与竞争对手不同的内容吧。
*/

至此,我们就掌握了Semantic Kernel 当前所有的核心概念和基本使用方法。


参考资料:

  1. Planner in Semantic Kernel | Microsoft Learn
  2. semantic-kernel/05-using-the-planner.ipynb at main · microsoft/semantic-kernel · GitHub
  3. What is Semantic Kernel? | Microsoft Learn

Semantic Kernel 入门系列:📅 Planner 计划管理的更多相关文章

  1. linux入门系列13--磁盘管理之RAID、LVM技术

    前一篇文章学习了磁盘分区.格式化.挂载等相关知识,本文将讲解RAID和LVM技术. 磁盘管理操作主要是运维人员用的较多,如果只是单纯的开发人员,可以先略过本文.但是在很多小公司里往往都是一人多用,运维 ...

  2. linux入门系列12--磁盘管理之分区、格式化与挂载

    前面系列文章讲解了VI编辑器.常用命令.防火墙及网络服务管理,本篇将讲解磁盘管理相关知识. 本文将会介绍大量的Linux命令,其中有一部分在"linux入门系列5--新手必会的linux命令 ...

  3. linux入门系列6--软件管理之rpm和yum仓库

    前面系列文章中,我们对vi编辑器和46个基本命令进行了介绍,本文将演示在centos7下使用RPM和YUM安装和管理软件. 一.RPM软件包管理器 1.1 RPM背景介绍 ​ RPM(RedHat P ...

  4. linux入门系列9--用户管理及文件权限控制

    ​ 前面文章分享了Linux下常用命令以及Shell编程相关知识,本节继续学习Linux用户管理及文件权限控制. ​ Linux是多用户多任务操作系统,具有很好的稳定性和安全性.既然是多用户,那就意味 ...

  5. linux入门系列10--firewalld防火墙管理

    上一篇文章学习了用户及文件相关权限,本篇继续学习防火墙技术. 防火墙作为公网与内网之间的保护屏障,对系统至关重要.防火墙又分为硬件防火墙和软件防火墙,主要功能都是依据设置的策略对穿越防火墙的流量进行过 ...

  6. linux入门系列14--ssh服务及主机远程管理

    通过前面十余篇文章的介绍,相信已经初步入门Linux本地管理的基本方法了,后续的文章将介绍Linux中常用的服务部署以及如何为外部提供相应的服务. 系列文章第三篇"linux入门系列3--l ...

  7. linux入门系列18--Web服务之Apache服务2

    接上一篇文章,在了解Apache基本配置以及SELinux相关知识后,继续演示Apache提供的虚拟主机功能以及访问控制方式. 如果还没看上一篇的建议先查看后再来,上篇文章"linux入门系 ...

  8. ABP入门系列(9)——权限管理

    ABP入门系列目录--学习Abp框架之实操演练 源码路径:Github-LearningMpaAbp 完成了简单的增删改查和分页功能,是不是觉得少了点什么? 是的,少了权限管理.既然涉及到了权限,那我 ...

  9. HBase编程 API入门系列之create(管理端而言)(8)

    大家,若是看过我前期的这篇博客的话,则 HBase编程 API入门系列之put(客户端而言)(1) 就知道,在这篇博文里,我是在HBase Shell里创建HBase表的. 这里,我带领大家,学习更高 ...

  10. Linux入门到放弃之八《任务计划管理》

    任务计划管理 1.每周一下午5:50将/data目录下的所有目录和文件归档并压缩为:backup.tar.gz 放在/home/backup目录下. 先新建/data目录,并在目录中随意生成几个文件 ...

随机推荐

  1. C# DevExpress gridview 字符串尾部带数字如何排序

    我们经常遇到这样的问题,字符串尾部带数字,如何正确排序; 首先设置GridView ,Columns 的相关列,设置属性中,SortMode为Custom 解决思路,把字符串尾缀数字,分离出来.先比较 ...

  2. 快速排序(Java分治法)

    快速排序(Java分治法) 文章目录 快速排序(Java分治法) 0. 分治策略 1.思路步骤 2.代码 3.复杂度分析 3.1 最好情况 3.2 最坏情况 3.3 平均情况 3.4 性能影响因素 4 ...

  3. JavaScript数组常用的方法总结

    数组常用方法 concat() 方法 concat() 方法用于连接两个或多个数组. 该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本. var arr = new Array(3) arr ...

  4. vue打包记录

    这里的确是css以及js文件的路径问题,但解决时并不需要手动改路径或者加一段判断去修改,最方便的办法时在项目打包前的vue.config.js里面将publicPath属性添加或者修改为 public ...

  5. 重构SeleniumeDownloader底层浏览器驱动

    一.解决bug:Selenium with PhantomJS,重构SeleniumeDownloader底层浏览器驱动 0.小背景: 想爬取外网steam的数据,但是steam官网在海外,加上ste ...

  6. 关于Android开发工具的下载之ADT篇

    ADT的下载 首先可以选择下面推荐的两个网站去下载相应的安装包,网址如下: http://tools.android-studio.org/index.php/adt-bundle-plugin 或者 ...

  7. 验证码案例的实现---MyBatis+Session+Cookie

    展示验证码(jsp页面) 首先,我们需要自己利用BufferedImage类去生成一张可以变换的验证码图片: 之后,我们就可以利用这样一串代码去将验证码里面的内容获取到: 这是一串测试代码: Outp ...

  8. Feign调用报错The bean 'XXX.FeignClientSpecification', defined in null, could not be registered....的解决办法

    问题描述: 创建了两个远程调用类,一个是调用退款的,一个是调用折扣的 但是两个调用类是调用的同一个微服务 都叫@FeignClient(value = "xxx-shop") 如何 ...

  9. Android 音视频采集那些事

    音视频采集 在整个音视频处理的过程中,位于发送端的音视频采集工作无疑是整个音视频链路的开始.在 Android 或者 IOS 上都有相关的硬件设备--Camera 和麦克风作为输入源.本章我们来分析如 ...

  10. 同步协程的必备工具: WaitGroup

    1. 简介 本文将介绍 Go 语言中的 WaitGroup 并发原语,包括 WaitGroup 的基本使用方法.实现原理.使用注意事项以及常见的使用方式.能够更好地理解和应用 WaitGroup 来协 ...