理解了LLM的作用之后,如何才能构造出与LLM相结合的应用程序呢?

首先我们需要把LLM AI的能力和原生代码的能力区分开来,在Semantic Kernel(以下简称SK),LLM的能力称为 semantic function ,代码的能力称为 native function,两者平等的称之为function(功能),一组功能构成一个技能(skill)。 SK的基本能力均是由skill构成。

有了一堆skill之后并不能直接执行,需要有一个配置和管理的单元,就像是MVC 需要ASP.NET框架一样,Skill也需要有一个Kernel进行组织管理。

Kernel 除了组织管理Skill,还兼顾了基础服务的配置,例如OpenAI/Azure OpenAI的授权信息,默认的LLM模型选择等等。另外当涉及到上下文的管理,技能参数的传递时,Kernel也能发挥重要的作用。

接下来我们就以开始着手上手SK应用开发的学习。

准备阶段

  1. 首先准备一个应用环境,Console 可以,ASP.NET 也可以,Notebooks 也可以。使用Notebooks的话推荐参考官方的Notebooks合集Uncle John's Semantic Kernel Recipes
  2. 应用环境准备好之后,和所有的.Net 库一样,接下来就是安装SK的nuget 包。由于是一个较新的包,所以更新变化会比较快。
dotnet add package Microsoft.SemanticKernel --prerelease
  1. 接下来进行应用内的准备工作,首先创建一个 kernel;
using Microsoft.SemanticKernel;
var kernel = Kernel.Builder.Build();
  1. 然后配置基础模型,基础模型目前有四个:

    • TextCompletion,最常用的GPT-3的模型,常用于文本生成
    • ChatCompetion,GPT3.5模型,也就是所谓的ChatGPT的模型,基本就用于聊天功能
    • EmbeddingGeneration,嵌入模型,这个将用于Memory的生成和搜索,在后期能力扩展时将会有极大的用途
    • ImageGeneration,图形模型,也就是DALL-E模型,用于图片的生成

    由于Azure OpenAI提供了和Open AI相同的能力,所以以上的模型配置可以选择OpenAI的接口,也可以选择Azure OpenAI的接口,根据自己有哪个选哪个的原则使用。

    当然以上模型也提供了基本的接口定义,如果有自己的LLM AI接口的话,也可以自行实现相关接口,然后使用。

    这里以OpenAI的接口为例,继续进行学习。

// 简单的技能任务使用TextCompletion即可
// 1. ServiceId 用于指定当前模型的配置,相同的模型不能有重复的ServiceId配置
// 2. modelId 指定TextCompetion所使用的LLM 模型,目前基本为 text-davinci-003
// 3. apikey OpenAI 接口调用需要使用的APIkey
kernel.Config.AddOpenAITextCompletionService("ServiceId","text-davinci-003",Environment.GetEnvironmentVariable("OPENAI_API_KEY"));

Semantic Function

  1. 注册一个Semantic Function
using Microsoft.SemanticKernel.SemanticFunctions;

// ️ Semantic Function的核心就是prompt️
// 这里偷懒,使用Semantic Kernel官方样例库里面的的Summary Skill
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 应用中的重要内容
// PromptTemplateConfig 用于配置prompt 模板的相关参数
// functionName 是自定义的功能名称[可选]
// skillName 是自定义的技能名称[可选]
var summaryFunction = kernel.CreateSemanticFunction(prompt,new PromptTemplateConfig());

可以注意到的是在prompt中,有一个变量参数 {{$input}},这是SK的默认输入参数,用于注入需要处理的用户输入,这样的格式用于预防Prompt Injection,这就是另外一个话题了。

  1. 执行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.RunAsync(input,summaryFunction);
// 输出结果
resultContext.Result.Dump();
// output
// Multi-modal interfaces are becoming increasingly popular for app developers, combining different modes of input and output such as voice, touch, and visuals to create a more interactive and engaging user experience. Semantic Kernel can be used to create a multi-modal example.

以上就完成了一个简单的Semantic Function的使用。

好的,我们继续。

Native Function

  1. 声明一个Native Skill
using Microsoft.SemanticKernel.SkillDefinition;
// 这里偷懒,使用Semantic Kernel CoreSkills中的 TextSkill
public class TextSkill {
[SKFunction("Convert a string to uppercase.")]
public string Uppercase(string text)
{
return text.ToUpper(System.Globalization.CultureInfo.CurrentCulture);
}
}

这里只需要对方法添加一个SKFunction的注释,就可以转变为一个SK的Native Function。

  1. 注册Native Skill
// skillInstance 就是Native Skill的实例
// skillName 自定义的技能名称 [可选]
var textSkill = kernel.ImportSkill(new TextSkill(),nameof(TextSkill));

这里使用到的是一个Import,意味着导入了SkillInstance中所有的定义SKFunction。而Semantic Skill 也有一个对应的Import方法ImportSemanticSkillFromDirectory,可以从一个文件夹中导入所有技能。

  1. 执行Function
// 注册Native Function 如何没有指定 SKFunctionName的话,都会是用方法声明的名称,使用nameof这种偷懒方法可以方便得从Skill集合中获取对应的Function
var uppercaseFunction = textSkill[nameof(TextSkill.Uppercase)];
// 通过 Kernel 运行 function
var nativeResultContext = await kernel.RunAsync(input,uppercaseFunction);
// 输出结果
nativeResultContext.Result.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的使用。

链式调用

当完成了以上Skill和Function的准备之后,就可以想办法将多个Skill串联起来使用了,就像是命令行中的管道,函数式编程中的管道一样。

// kernel.RunAsync 本身就支持多个Function参数,并按照顺序依次执行
var upperSummeryContext = await kernel.RunAsync(input, summaryFunction,uppercaseFunction);
// 输出结果
upperSummeryContext.Result.Dump(); // output:
// MULTI-MODAL INTERFACES ARE BECOMING INCREASINGLY POPULAR FOR APP DEVELOPERS, COMBINING DIFFERENT MODES OF INPUT AND OUTPUT SUCH AS VOICE, TOUCH, AND VISUALS TO CREATE A MORE INTERACTIVE AND ENGAGING USER EXPERIENCE. SEMANTIC KERNEL CAN BE USED TO CREATE A MULTI-MODAL EXAMPLE.

至此,一个简单的结合了LLM AI能力和原生代码能力的应用就构建成功了。


参考资料:

  1. Concepts Overview for Semantic Kernel | Microsoft Learn
  2. Kernel in Semantic Kernel | Microsoft Learn
  3. Skills in Semantic Kernel | Microsoft Learn
  4. How to write semantic skills in Semantic Kernel | Microsoft Learn
  5. How to write native skills in Semantic Kernel | Microsoft Learn
  6. SK-Recipes

Semantic Kernel 入门系列:🔥Kernel 内核和🧂Skills 技能的更多相关文章

  1. [中英对照]Linux kernel coding style | Linux内核编码风格

    Linux kernel coding style | Linux内核编码风格 This is a short document describing the preferred coding sty ...

  2. Linux kernel pwn notes(内核漏洞利用学习)

    前言 对这段时间学习的 linux 内核中的一些简单的利用技术做一个记录,如有差错,请见谅. 相关的文件 https://gitee.com/hac425/kernel_ctf 相关引用已在文中进行了 ...

  3. Linux Kernel - Debug Guide (Linux内核调试指南 )

    http://blog.csdn.net/blizmax6/article/details/6747601 linux内核调试指南 一些前言 作者前言 知识从哪里来 为什么撰写本文档 为什么需要汇编级 ...

  4. Docker入门系列(一):目标和安排

    Docker入门系列(一) 这个系列的教程来源于docker的官方文档,此文档的目的在于一步一步学习docker的使用方法. 这一系列的教程有如下几篇文档: docker安装启动 构建第一个docke ...

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

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

  6. 快速入门系列--WebAPI--03框架你值得拥有

    接下来进入的是俺在ASP.NET学习中最重要的WebAPI部分,在现在流行的互联网场景下,WebAPI可以和HTML5.单页应用程序SPA等技术和理念很好的结合在一起.所谓ASP.NET WebAPI ...

  7. 数据挖掘入门系列教程(九)之基于sklearn的SVM使用

    目录 介绍 基于SVM对MINIST数据集进行分类 使用SVM SVM分析垃圾邮件 加载数据集 分词 构建词云 构建数据集 进行训练 交叉验证 炼丹术 总结 参考 介绍 在上一篇博客:数据挖掘入门系列 ...

  8. 数据挖掘入门系列教程(十一)之keras入门使用以及构建DNN网络识别MNIST

    简介 在上一篇博客:数据挖掘入门系列教程(十点五)之DNN介绍及公式推导中,详细的介绍了DNN,并对其进行了公式推导.本来这篇博客是准备直接介绍CNN的,但是想了一下,觉得还是使用keras构建一个D ...

  9. linux入门系列2--CentOs图形界面操作及目录结构

    上一篇文章"linux入门系列1--环境准备及linux安装"直观演示了虚拟机软件VMware和Centos操作系统的安装,按照文章一步一步操作,一定都可以安装成功.装好系统之后, ...

  10. linux入门系列5--新手必会的linux命令

    上一篇文章"linux入门系列4--vi/vim编辑器"我们讨论了在linux下如何快速高效对文本文件进行编辑和管理,本文将进一步学习必须掌握的linux命令,掌握这些命令才能让计 ...

随机推荐

  1. PLC入门笔记9

    梯形图电路之电机控制 电机直接启动控制电路 电机正反停控制电路 我的图.. 但愿最后说的不要发生吧 例如下错了程序 导致... 最好外部电路互锁一下.. 电机故障判断电路 我的图.. 电机故障转换电路 ...

  2. Alibaba Cloud Linux 3.2104 64位安装php7.2.12

    1 安装php所需要的扩展 yum -y install libxml2 libxml2-devel openssl openssl-devel bzip2 bzip2-devel curl curl ...

  3. 学习Java的第一个代码

    HelloWorld 新建一个文件夹 新建一个Java 文件后缀为java hello.java 编写代码 public class hello{ public static void main(St ...

  4. qt webassembly emscripten build 编译 环境搭建 JS调用C++传参

    环境搭建 本文主要是针对ubuntu/mac编译环境搭建和调试环境 可以直接参考下面的dockerfile qt wasm build docker pull colorlength/qt-webas ...

  5. JAVA 学习打卡 day1

    2022-04-21 21:03:26 1.java程序的注释 (1)单行注释,就是在注释内容前面加双斜线(//) (2)多行注释,就是在注释内容前面以单斜线加一个星形标记(/*)开头,并在注释内容末 ...

  6. 加热算法,加热温度控制加热功率,加热功率控制加热速度(PWM)

    uint8_t user_heating_algorithmPID(void) { uint32_t temp_1; uint16_t Adcn; nrfx_err_t err_code; HEATI ...

  7. [Unity移动端]真机调试

    一.Android Studio 1.log打印 打开AS,新建一个工程,点击左下角的Logcat,如下图,1是设备(支持模拟器,如果是真机的话,需要usb连接电脑,真机要是usb调试模式),2是包名 ...

  8. python - 命令行下一键更新所有包

    Python3.8以下这样一键更新所有包:from pip._internal.utils.misc import get_installed_distributionsfrom subprocess ...

  9. git提交的时候,报错yarn run v1.21.1 ,SyntaxError: Cannot use import statement outside a module 解决

    原因是 lint-staged这个依赖中,需要的node的版本是, 而我使用的node版本是12.13.1 ,切换成14.17.0就可以了

  10. Repeater 绑定数据如何根据数据列的内容排序

    可指定Repeater的数据源 从数据库查询时直接排序,而后绑定数据这样