对微软SemanticKernel的一篇调研笔记
随着LLM的持续火爆,各行业都在探索如何用LLM重构自己的产品。但需要看到,目前我们对LLM的使用方式,还处于非常表层的阶段,没有脱离最原生的Chat模式,还不涉及更高级的能力,比如如何跟已有知识库打通做「检索增强生成」、如何跟已有的API能力打通让AI干点更实际的事情、如何对LLM的回复做安全审查以及对输出质量做评判等。什么是下一代的LLM开发范式?企业内部的开发者怎么能更容易用LLM开发?LLM开发能在哪些场景给产品带来增益?带着这些问题,我对微软的Semantic Kernel做了调研。文章写于2023年8月份
01
一、对LLM编排,就像K8S之于Docker
回看当年Docker横空出世的时候,也是相当火爆,Docker颠覆性地解决了高昂的虚拟化成本,更轻量级的资源隔离、「镜像」封装能力更好地满足了云计算对弹性的需求。但现在生产环境普遍使用的模式,不是直接用Docker的API操作Docker,反而用的是Google开源的K8S,容器编排引擎,从此Docker被锁死在只能提供容器相关的能力上,成为K8S的一个组件。WHY?因为在生产环境中使用容器技术,不光是容器,还有流量路由、服务注册与发现、资源管理等,K8S是Google Borg的开源版本,在集群调度上领先业内同类公司数年,故很快K8S统一了容器编排市场,成为了事实标准。
回到LLM这个领域,不管是OpenAI还是Meta,不管是GPT4还是llama2,开源闭源的LLM即使再进化、再多的参数、再智能,也只是「通用」大语言模型,基于公开的数据做训练。由于没有细分行业和企业内部的数据,通用型LLM无法准确回答企业内部的问题;没有跟企业内部的服务、小模型打通,通用型LLM也无法很好地解决企业面临的实际问题。
如果要让通用型LLM更有用,成为用户的Copilot,在架构层面一定有一个「LLM流程编排层」,连接LLM和企业内部知识和能力。在LLM时代开发copilot,一定跟传统的软件开发模式不同,2023年5月,微软CTO兼AI副总裁Kevin Scott在微软2023开发者大会上发表演讲,「the era of the AI Copilot」,推荐看一下,很有启发。另外,看这个图是否让你想到了经典的IAAS-PAAS-SAAS图?如出一辙
02
选型:LangChain还是Semantic Kernel
在LLM编排这个领域,比较活跃的有LangChain和Semantic Kernel,对比如下表,
综合来看,SK整齐的文档、清晰的抽象,尤其是微软在Copilot方面的成功实践,都让我更倾向于选择Semantic Kernel
03
Semantic Kernel的简要介绍
1、什么是Semantic Kernel
根据官方介绍,Semantic Kernel(简称SK)是一个开源的 SDK,允许您轻松地将 AI 服务(如 OpenAI、Azure OpenAI 和 Hugging Face)与常规编程语言(如 C# 和 Python)结合使用。通过这样做,您可以创建结合了两者优势的 AI 应用程序。简而言之,SK的目标是帮助你创建一个完全自主的Agent,最起码也得是一个副驾驶Copilot,替你在本地完成一些工作
2、SK的核心模型
3、Plugin
一组Function的集合。Plugin除了作为function的集合/目录之外,也可以有自己的Description,但目前还没有看到plugin description具体的作用;plugin起初在SK中是叫skill,这从现有的一些方法名称上还能看得到,但后来为了降低开发者的认知成本,统一改成了plugin,并跟OpenAI的plugin概念保持一致了
4、Function
prompt和代码在SK中被统一抽象为function,按照类型分为Semantic function和native function,通过kernel做统一的调用。
不管是Semantic Function还是Native Function,要想使用都必须注册到kernel里边,才能被SK调用或者编排。
5、Kernel
之所以这里才介绍kernel,是因为对于开发者而言,我们直接感知的是function和plugin;但function的执行是依赖于kernel的,kernel封装了对上下文的透传、对function的调用入口,以及一些开箱即用的function。通过kernel去调度/执行function需要有以下几步,
Step1、Kernel集成Plugin
Step2、通过Kernel获取function
在SK中,所有的function执行都是要通过kernel的,包括语义函数和原生函数,参数也是需要通过kernel传入。尤其对于原生函数,跟普通的代码比较像,但仍然不能直接调用传参,而是通过kernel.run_async传参。
Step3、通过Kernel执行function
Step4、将Semantic function和Native function串起来
将两种Function串起来可以有两种模式,
- 在prompt中调用native function来传入变量。用提示词模板来 {“ }plugin.function $param}}” }
- 识别用户意图,并执行对应动作。SK里边允许写编排器Orchestrator,主要起到了「意图识别」和「路由转发」的功能,其中,意图识别,根据用户的输入input,将意图分类,或提取用户输入中的参数,这里一般都是Semantic function,再根据意图分类,来调用不同的native function,如果有参数的话将必要的参数传入
6、Context
SK借鉴了Unix中的“管道”设计理念,通过在内核上下文中的特殊变量input,在多个function之间传递信息
也就是在Joke, Poem, Menu中都可以通过input获取上一个function的输出,最后也是通过input获取最终的结果。
7、Planner
因为用户的输入是千奇百怪的,判断用户的真实意图最好留给LLM来做,SK提供了Planner自动制定Plan去达成目标,核心依赖的是注册到kernel中的函数描述。而Planner在本质上也是传给LLM的一段prompt,比如basic_planner.py确
最大的坑在于,LLM太玄学了。比如我就没跑通官方示例,ask = “If my investment of 2130.23 dollars increased by 23%, how much would I have after I spent $5 on a latte?”,答案应该是2130.23*1.23-5 = 2615.1829但我执行了几遍官方示例,除了提示报错之外就是执行的结果不正确,基本没办法用。
这么尴尬的结果,SK团队是知道的,因为在接下来的Evaluate your plugins with Prompt flow文档中写到
If you began testing your planner with additional inputs, however, you may have noticed that it doesn’t always produce the desired results.
现阶段让LLM生成复杂的、准确的流程,还是有点困难的。
04
如何在国内使用Semantic Kernel?
由于SK是需要使用OpenAI的API,但OpenAI的账号、API受限于🪜比较难单独访问到,尤其是API需要有国外的信用卡。很多同学可能不知道,微软的Azure是有OpenAI的官方服务的,可以通过Azure购买和部署GPT的模型;并且Azure是有第一年$200的优惠券,只需要绑定国内信用卡即可。
推荐先通读一遍Semantic Kernel的手册,可以不求甚解,有个大概感觉;再手动执行一下Semantic Kernel的Python notebook案例,来帮助理解。
05
总结
本文对SemanticKernel做了初步调研,SK的很多设计思路都值得我们借鉴和学习,比如对于语义函数SemanticFunction和本地函数NativeFunction的抽象、两种Function的相互调用过程、Planner中通过结构化的Prompt模板和变量占位符来代替LangChain里边的Chain、用Kernel来简化LLM的调用和集成等。
当然,不管是SK还是LangChain,在生产环境中还不能直接拿来就用,在落地过程中必须结合着企业内部的研发流程与生态,避免水土不服。