Semantic Kernel 的一個核心能力就是實現(xiàn)“目標導(dǎo)向”的AI應(yīng)用。
目標導(dǎo)向
“目標導(dǎo)向”聽起來是一個比較高大的詞,但是卻是實際生活中我們處理問題的基本方法和原則。
顧名思義,這種方法的核心就是先確定目標,然后再尋找實現(xiàn)目標的方法和步驟。這對于人來說的是很自然的事情,但是對于機器則不然。一大堆的指令和控制邏輯其實都是在完成另外一種產(chǎn)出導(dǎo)向的結(jié)果。所有的流程和過程都需要提前預(yù)定義好,然后期待一個結(jié)果的產(chǎn)出。
如今,借助 LLM AI 的力量,我們可以輕松的實現(xiàn)目標導(dǎo)向的過程。
在 Semantic Kernel中,Planner就用于這項工作。
我們可以提前準備好所需的Skill,根據(jù)設(shè)定好的最終目標,通過Planner,可以將目標分解為需要執(zhí)行的任務(wù)列表,并且可以指定好對應(yīng)的參數(shù)傳遞,然后逐個任務(wù)執(zhí)行,從而實現(xiàn)最終目標。
做好技能準備
為了讓LLM AI更好的理解我們所提供的技能,需要明確地配置好每個技能本身的描述和參數(shù)描述。
對于的Semantic Function來說,可以在config.json中配置。以下是一個Translate的配置。
需要注意的就是 description
和 input
參數(shù),最終會成為的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
用于添加參數(shù)的說明。
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}
""");
}
}
準備好技能之后,就可以將這些技能導(dǎo)入到Kernel中,等待后續(xù)使用。
作為示例,這里導(dǎo)入了三個功能:
-
MySkill.WriteText
: 文案寫作 -
MySkill.Translate
:文本翻譯 -
email.SendTo
: 郵件發(fā)送
使用Planner
然后我們就可以開始使用 Planner了。
0.13之前版本
Planner本身也是 Semantic Kernel中的一個Skill,融合了Semantic Function 和 Native Function。和通常的Skill一樣,導(dǎo)入 PlannerSkill 后即可使用。
var planner = kernel.ImportSkill(new PlannerSkill(kernel),"plan");
Planner作為一個核心組件,在0.13版本之后從Skill中提升了出來,目前(0.13版本)使用了獨立的SequentialPlanner,直接創(chuàng)建即可使用。
var planner = new SequentialPlanner(kernel);
指定好任務(wù)目標。
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之前版本
然后就可以執(zhí)行 `CreatePlan` 創(chuàng)建一個Plan。var plan = await kernel.RunAsync(goal,planner["CreatePlan"]);
此時可以使用Plan.PathString查看當(dāng)前的任務(wù)編排。
Plan所有狀態(tài)的結(jié)果都會保存在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>
*/
然后就可以直接使用 SequentialPlanner 創(chuàng)建一個Plan了。
var plan = await planner.CreatePlanAsync(goal);
此時可以使用plan.ToJson(),查看任務(wù)編排的情況。
plan.ToJson().Dump("Create Plan");
0.13之前版本
創(chuàng)建好了 Plan 就可以使用 ExecutePlan
執(zhí)行了。
由于每次只能執(zhí)行一個Function,所以我們需要通過循環(huán)來執(zhí)行所有Function。
同時根據(jù)Plan的狀態(tài),判斷是否執(zhí)行成功,是否執(zhí)行完成。
Plan 有兩種狀態(tài),一種是 IsSuccessful
,表示當(dāng)前的Plan是否執(zhí)行成功。
另一個是 IsComplete
,表示整個Plan是否執(zhí)行完成。
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——專為企業(yè)和企業(yè)家設(shè)計的終極博客平臺。我們的新產(chǎn)品旨在幫助您輕松創(chuàng)建、管理和優(yōu)化博客內(nèi)容。
PowerBlog是為想要創(chuàng)建與競爭對手不同的專業(yè)博客的企業(yè)和企業(yè)家完美的解決方案。通過我們的直觀用戶界面,您可以快速創(chuàng)建和管理博客文章,優(yōu)化SEO內(nèi)容,并跟蹤博客的性能。
我們的新產(chǎn)品還包括強大的功能,如自動內(nèi)容策劃、社交媒體整合和分析工具。通過這些功能,您可以輕松監(jiān)控博客的性能,并就內(nèi)容策略做出明智的決定。
PowerBlog是為想要創(chuàng)建與競爭對手不同的專業(yè)博客的企業(yè)和企業(yè)家完美的解決方案。通過我們的直觀用戶界面,您可以快速創(chuàng)建和管理博客文章,優(yōu)化SEO內(nèi)容,并跟蹤博客的性能。
我們很高興向客戶提供這款新產(chǎn)品,期待幫助您創(chuàng)建一個成功的博客。今天就注冊,開始創(chuàng)建與競爭對手不同的內(nèi)容吧。
*/
最后根據(jù)狀態(tài)判斷Plan最后執(zhí)行是否成功,并從plan.Result
中獲取最后的輸出結(jié)果。
if(!result.Variables.ToPlan().IsSuccessful) {
result.Variables.ToPlan().Result.Dump("Complete!");
}else {
result.Variables.ToPlan().Result.Dump("Error");
}
/*
:Complete!:
介紹PowerBlog——專為企業(yè)和企業(yè)家設(shè)計的終極博客平臺。我們的新產(chǎn)品旨在幫助您輕松創(chuàng)建、管理和優(yōu)化博客內(nèi)容。
PowerBlog是為想要創(chuàng)建與競爭對手不同的專業(yè)博客的企業(yè)和企業(yè)家完美的解決方案。通過我們的直觀用戶界面,您可以快速創(chuàng)建和管理博客文章,優(yōu)化SEO內(nèi)容,并跟蹤博客的性能。
我們的新產(chǎn)品還包括強大的功能,如自動內(nèi)容策劃、社交媒體整合和分析工具。通過這些功能,您可以輕松監(jiān)控博客的性能,并就內(nèi)容策略做出明智的決定。
PowerBlog是為想要創(chuàng)建與競爭對手不同的專業(yè)博客的企業(yè)和企業(yè)家完美的解決方案。通過我們的直觀用戶界面,您可以快速創(chuàng)建和管理博客文章,優(yōu)化SEO內(nèi)容,并跟蹤博客的性能。
我們很高興向客戶提供這款新產(chǎn)品,期待幫助您創(chuàng)建一個成功的博客。今天就注冊,開始創(chuàng)建與競爭對手不同的內(nèi)容吧。
*/
0.13 版本之后,任務(wù)執(zhí)行方法更加簡單。
由于Plan本身就是一組 ISKFunction,所以可以直接使用 Kernel.RunAsync執(zhí)行
var result = await kernel.RunAsync(plan);
和通常的Skill執(zhí)行一樣,查看result.Result即可得到結(jié)果。
result.Result.Dump("RESULT");
如果需要逐步執(zhí)行查看結(jié)果,或者進行干預(yù)的話,也可以手動的調(diào)用執(zhí)行過程。執(zhí)行的狀態(tài)都由Plan本身來維護,使用 HasNextStep
可以查看當(dāng)前所有任務(wù)是否執(zhí)行完成,可以使用Plan 的 InvokeNextStepAsync
來執(zhí)行下一步,也可以使用Kernel的StepAsync
逐步執(zhí)行。
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執(zhí)行完成的結(jié)果,可以直接使用Plan.State.ToString()
獲取。
plan.State.ToString().Dump("RESULT");
// output
/*
PowerBlog很高興地宣布即將推出我們的最新產(chǎn)品,這將徹底改變?nèi)藗兩畹姆绞?。我們一直在不懈努力地開發(fā)一款產(chǎn)品,它將對我們的客戶生活產(chǎn)生重大影響,我們相信我們已經(jīng)做到了這一點。
我們的新產(chǎn)品旨在成為一款改變游戲規(guī)則的產(chǎn)品,為用戶提供獨特的體驗,增強他們的日常生活。我們相信,這款產(chǎn)品將成為任何想要提高生產(chǎn)力、效率和整體生活質(zhì)量的人必備的產(chǎn)品。
我們知道人們總是在尋找簡化生活的方法,而這正是我們的新產(chǎn)品的目的。它將幫助用戶更好地管理時間,保持組織,更有效地實現(xiàn)他們的目標。
我們很高興能夠向我們的客戶提供這款產(chǎn)品,我們迫不及待地想看到它對他們生活的積極影響。請繼續(xù)關(guān)注我們最新產(chǎn)品的發(fā)布,準備體驗一種新的生活方式。
*/
至此,我們就掌握了Semantic Kernel 當(dāng)前所有的核心概念和基本使用方法。
TIPS: 由于模型的能力問題,目前推薦使用GPT4模型執(zhí)行以上操作。文章來源:http://www.zghlxwxcb.cn/news/detail-415608.html
參考資料:文章來源地址http://www.zghlxwxcb.cn/news/detail-415608.html
- 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
到了這里,關(guān)于Semantic Kernel 入門系列:? Planner 計劃管理的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!