Semantic Kernel 入门系列:🔥Kernel 内核和🧂Plugin 插件
理解了LLM的作用之后,如何才能构造出与LLM相结合的应用程序呢?
首先我们需要把LLM AI的能力和原生代码的能力区分开来,在Semantic Kernel(以下简称SK),LLM的能力称为 semantic function ,代码的能力称为 native function,两者平等的称之为function(功能),一组功能构成一个插件(Plugin)。 SK的基本能力均是由Plugin构成。
有了一堆Plugin之后并不能直接执行,需要有一个配置和管理的单元,就像是MVC 需要ASP.NET框架一样,Plugins也需要有一个Kernel进行组织管理。
Kernel 除了组织管理Plugins,还兼顾了基础服务的配置,例如OpenAI/Azure OpenAI的授权信息,默认的LLM模型选择等等。另外当涉及到上下文的管理,插件参数的传递时,Kernel也能发挥重要的作用。
接下来我们就以开始着手上手SK应用开发的学习。
准备阶段
- 首先准备一个应用环境,Console 可以,ASP.NET 也可以,Notebooks 也可以。使用Notebooks的话推荐参考官方的Notebooks合集和Semantic Kernel CookBook。
- 应用环境准备好之后,和所有的.Net 库一样,接下来就是安装SK的nuget 包。由于是一个较新的包,所以更新变化会比较快。
dotnet add package Microsoft.SemanticKernel
- 接下来进行应用内的准备工作,首先创建一个
kernel
;
using Microsoft.SemanticKernel;
var builder = Kernel.CreateBuilder();
-
然后配置基础模型,基础模型目前有两个:
- TextCompletion,最常用的GPT-3的模型,常用于文本生成
- ChatCompletion,GPT3.5、GPT4模型,基于聊天模式的文本生成
还有一些预览的模型:
- EmbeddingGeneration,嵌入模型,这个将用于Memory的生成和搜索,在后期能力扩展时将会有极大的用途
- TextToImage,图形模型,也就是DALL-E模型,用于图片的生成
- TextToAudio,文本转语音模型,用于语音合成
- ImageToText, 从图片中提取文本
由于Azure OpenAI提供了和Open AI相同的能力,所以以上的模型配置可以选择OpenAI的接口,也可以选择Azure OpenAI的接口,根据自己有哪个选哪个的原则使用。
当然以上模型也提供了基本的接口定义,如果有自己的LLM AI接口的话,也可以自行实现相关接口,然后使用。
这里以Azure OpenAI的接口为例,继续进行学习。
// 使用任意的Completion,这里以ChatCompletion为例
// 使用AzureOpenAIChatCompletion的话需要指定 deployment、endpoint、apikey
// 完成配置之后,构建出kernel
builder.AddAzureOpenAIChatCompletion("gpt-35-turbo",
Environment.GetEnvironmentVariable("AZURE_OPEN_AI_ENDPOINT"),
Environment.GetEnvironmentVariable("AZURE_OPEN_AI_APIKEY"));
var kernel = builder.Build();
Semantic Function
- 注册一个Semantic Function
// ⚠️ Semantic Function的核心就是prompt⚠️
// 这里偷懒,使用Semantic Kernel官方样例库里面的的Summary Plugin
var prompt =
"""
[SUMMARIZATION RULES]
DONT WASTE WORDS
USE SHORT, CLEAR, COMPLETE SENTENCES.
DO NOT USE BULLET POINTS OR DASHES.
USE ACTIVE VOICE.
MAXIMIZE DETAIL, MEANING
FOCUS ON THE CONTENT
[BANNED PHRASES]
This article
This document
This page
This material
[END LIST]
Summarize:
Hello how are you?
+++++
Hello
Summarize this
{{$input}}
+++++
""";
// 使用扩展方法在Kernel上注册一个SemanticFunction
// prompt 是Semantic Function的核心,如何设计一个好的prompt是成功构建Semantic Function的关键所在,也是未来LLM AI 应用中的重要内容
// PromptExecutionSettings 用于配置prompt 模板的相关参数
// functionName 是自定义的功能名称[可选]
var summaryFunction = kernel.CreateFunctionFromPrompt(prompt,new PromptExecutionSettings());
可以注意到的是在prompt中,有一个变量参数 {{$input}}
,这是SK的默认输入参数,用于注入需要处理的用户输入,这样的格式用于预防Prompt Injection,这就是另外一个话题了。
- 执行Function
// 定义需要处理的输入
var input = "Multi-modal interfaces are becoming increasingly popular for app developers. These interfaces allow users to interact with apps in a variety of ways by combining different modes of input and output, such as voice, touch, and visuals, to create a more interactive and engaging user experience. In this blog we will overview how you can use Semantic Kernel with a multi-modal example. ";
// 通过 Kernel 运行 function
var resultContext = await kernel.InvokeAsync(summaryFunction, new () {["input"] = input });
// 输出结果
resultContext.GetValue<string>().Dump();
// output
// Multi-modal interfaces are growing in popularity among app developers. They enable users to interact with apps using various input and output methods, including voice, touch, and visuals. These interfaces enhance user experience by making it more interactive and engaging. In this blog, we will discuss how Semantic Kernel can be used with a multi-modal example.
以上就完成了一个简单的Semantic Function的使用。
好的,我们继续。
Native Function
- 声明一个Native Plugin
// 这里偷懒,使用Semantic Kernel CorePlugins中的 TextPlugin
public class TextPlugin {
[KernelFunction]
[Description("Convert a string to uppercase.")]
public string Uppercase(string text)
{
return text.ToUpper(System.Globalization.CultureInfo.CurrentCulture);
}
}
这里只需要对方法添加一个KernelFunction的注释,就可以转变为一个SK的Native Function。
- 注册Native Plugin
// 可以通过类型注入
var textPlugin = kernel.ImportPluginFromType<TextPlugin>(nameof(TextPlugin));
// or 使用实例注入
// PluginInstance 就是Native Plugin的实例
// PluginName 自定义的插件名称 [可选]
var textPlugin = kernel.ImportPluginFromObject(new TextPlugin(),nameof(TextPlugin));
这里使用到的是一个Import,意味着导入了PluginType/PluginInstance中所有的定义KernelFunction。而Semantic Plugin 也有一个对应的Import方法ImportPluginFromPromptDirectory,可以从一个文件夹中导入所有插件。
- 执行Function
// 注册Native Function 如何没有指定 KernelFunctionName的话,都会是用方法声明的名称,使用nameof这种偷懒方法可以方便得从Plugin集合中获取对应的Function
var uppercaseFunction = textPlugin[nameof(TextPlugin.Uppercase)];
// 通过 Kernel 运行 function
var nativeResultContext = await kernel.InvokeAsync(uppercaseFunction,new () {["text"] = input });
// 输出结果
nativeResultContext.GetValue<string>().Dump();
// output:
// MULTI-MODAL INTERFACES ARE BECOMING INCREASINGLY POPULAR FOR APP DEVELOPERS. THESE INTERFACES ALLOW USERS TO INTERACT WITH APPS IN A VARIETY OF WAYS BY COMBINING DIFFERENT MODES OF INPUT AND OUTPUT, SUCH AS VOICE, TOUCH, AND VISUALS, TO CREATE A MORE INTERACTIVE AND ENGAGING USER EXPERIENCE. IN THIS BLOG WE WILL OVERVIEW HOW YOU CAN USE SEMANTIC KERNEL WITH A MULTI-MODAL EXAMPLE.
以上就完成了一个简单的Native Function的使用。
至此,一个简单的结合了LLM AI能力和原生代码能力的应用就构建成功了。
参考资料: