Semantic Kernel 深度解析:微软的 Agent 开发框架
Semantic Kernel 深度解析:微软的 Agent 开发框架摘要/引言开门见山(Hook)你有没有想过,像《钢铁侠》里贾维斯那样的通用智能助手,会不会在202X年就不再是科幻电影的专属?当我们打开手机的Siri、电脑的Cortana或者ChatGPT网页版,它们确实能回答问题、写邮件、甚至生成简单的代码片段,但它们真的能自主帮我们完成从“订一张明天去上海虹桥的最早高铁二等座,同时给同事发会议改期提醒,还要帮我查明天虹桥附近最近的全家便利店开门时间”这样的多步骤、跨工具、需要上下文感知的复杂任务吗?答案是:用通用的单模型Prompt很难稳定做到,但用微软最新开源的、专门为大语言模型(LLM)应用构建的Agent开发框架——Semantic Kernel(以下简称SK),你可以在短短几小时甚至几十分钟内,原型化一个这样的“小贾维斯”雏形!问题陈述(Problem Statement)随着GPT-4、Claude 3、文心一言、通义千问等大语言模型的爆发式发展,基于LLM的应用已经从“Demo秀场”阶段进入到“落地实用”阶段。但在构建真正生产级、自主、可靠、可扩展的LLM Agent(智能体)时,我们会遇到一系列棘手的共性问题:多模态/多工具能力的整合复杂度高:传统的LLM只能处理文本或文本化的其他模态数据(比如把图片转成base64编码丢进去),要让它调用浏览器API查天气、调用支付API订酒店、调用PDF解析工具读取合同、调用数据库查询订单信息,需要开发者手动编写大量的“胶水代码”(Glue Code),而且不同工具的参数格式、返回值解析逻辑千差万别,维护成本极高。上下文窗口(Context Window)的限制难以突破:当前主流的LLM上下文窗口大小在4K-128K tokens之间(虽然Claude 3 Opus达到了200K,但价格昂贵,且不是永久免费),如果我们要把用户的所有历史对话、所有工具的调用日志、所有读取到的外部数据都塞到上下文中,不仅会大幅增加成本(按token计费),还会导致LLM的响应速度变慢、甚至因为上下文溢出而失效。Prompt Engineering(提示工程)的“脆弱性”和“可维护性差”:单靠给LLM写一大段“超级Prompt”(Super Prompt)来引导它完成复杂任务,不仅容易因为LLM版本更新、用户输入风格变化而失效(脆弱性),而且超级Prompt本身就是一堆杂乱无章的文字,很难进行版本控制、模块化管理和团队协作(可维护性差)。任务规划(Planning)和推理链(Reasoning Chain)的不可控性:LLM虽然有一定的“思维链”(Chain of Thought, CoT)能力,但它的推理过程往往是“黑盒”的,开发者很难预测它下一步会做什么、会调用哪些工具,也很难在它出错的时候及时干预和修正。安全性和合规性的要求难以满足:在生产级应用中,我们需要对用户的输入进行过滤(避免恶意Prompt注入)、对工具的调用进行权限控制(比如普通用户不能调用支付API、管理员可以调用)、对敏感数据进行脱敏处理(比如不能把用户的身份证号、银行卡号直接丢给LLM),但这些功能在传统的LLM应用开发中都需要开发者从零开始实现,工作量巨大。核心价值(Value Proposition)Semantic Kernel的出现,就是为了系统性地解决上述所有LLM Agent开发中的共性问题。它是微软开源的、基于.NET、Python、Java三种主流编程语言的、生产级、开源免费、跨平台的Agent开发框架,核心价值在于:提供了一套标准化的工具整合机制:SK将所有工具统一封装成“插件”(Plugin),开发者只需要按照SK的规范编写插件的元数据(Metadata)和实现代码,SK就会自动帮LLM识别插件的功能、生成调用参数、解析返回值,极大地减少了胶水代码的编写量。提供了一套可扩展的记忆(Memory)系统:SK的记忆系统支持向量数据库(Vector DB)存储,可以将用户的历史对话、工具的调用日志、外部文档等数据转换成向量(Embedding)存入向量数据库,当LLM需要相关信息时,SK会自动从向量数据库中检索出最相关的Top-K条数据,塞到上下文中,既突破了上下文窗口的限制,又降低了成本。提供了一套模块化的Prompt管理机制:SK将Prompt模块化、语义化,封装成“语义函数”(Semantic Function),开发者可以将不同的语义函数组合成“管道”(Pipeline)或者“工作流”(Workflow),进行版本控制、模块化管理和团队协作,大大提高了Prompt Engineering的可维护性和稳定性。提供了一套可定制的任务规划机制:SK内置了多种任务规划器(Planner),比如Basic Planner、Action Planner、Sequential Planner、Stepwise Planner等,开发者可以根据自己的需求选择合适的规划器,或者自定义规划器,让LLM的推理过程变得“白盒化”,可以预测、可以干预、可以修正。提供了一套完善的安全性和合规性机制:SK内置了Prompt过滤器(Prompt Filter)、工具调用权限控制(Function Authorization)、敏感数据脱敏(Sensitive Data Redaction)等功能,开发者只需要简单的配置,就可以满足生产级应用的安全性和合规性要求。文章概述(Roadmap)本文将对Semantic Kernel进行全方位、深度、系统性的解析,主要涵盖以下内容:Semantic Kernel的核心概念与架构:详细介绍SK的核心概念(包括内核、插件、函数、记忆、规划器等)、整体架构(包括前端层、中间层、后端层)以及各个核心要素之间的关系(使用Markdown表格、ER图、交互关系图进行可视化展示)。Semantic Kernel的数学模型与核心算法:简要介绍SK背后用到的数学模型(包括向量嵌入、余弦相似度、Top-K检索等)和核心算法(包括Prompt模板填充算法、规划器生成算法、工具调用验证算法等),并使用LaTeX公式和Mermaid流程图进行可视化展示。Semantic Kernel的快速入门与环境搭建:分别介绍基于.NET、Python、Java三种主流编程语言的SK环境搭建方法,并提供一个简单的“Hello World”示例和一个稍微复杂一点的“查天气+写邮件”示例,让读者能够快速上手。Semantic Kernel的核心功能详解:深入解析SK的核心功能,包括插件开发与管理、语义函数开发与管理、记忆系统的使用、规划器的使用与定制、安全性和合规性机制的使用等,并提供大量的Python源代码示例。Semantic Kernel的实际场景应用与项目实战:以一个“智能旅行助手”(Travel Assistant)为项目实战案例,详细介绍项目背景、环境安装、系统功能设计、系统架构设计、系统接口设计、系统核心实现源代码等,让读者能够将所学知识应用到实际项目中。Semantic Kernel的最佳实践与行业发展趋势:分享SK的最佳实践Tips(包括插件设计最佳实践、语义函数设计最佳实践、记忆系统使用最佳实践、规划器选择最佳实践等),并通过Markdown表格梳理LLM Agent开发框架的问题演变发展历史,展望SK和整个LLM Agent开发领域的未来发展趋势。结论与展望:简要回顾本文的主要内容,再次强调SK的核心价值,鼓励读者尝试使用SK构建自己的LLM Agent,并提出一些开放性问题以引发讨论。正文一、 Semantic Kernel的核心概念与架构1.1 核心概念在深入了解Semantic Kernel的架构之前,我们首先需要掌握SK的几个核心概念,这些概念是SK的“骨架”,理解了它们,就相当于掌握了SK的基本使用方法。1.1.1 内核(Kernel)核心概念:内核(Kernel)是Semantic Kernel的核心执行引擎,它负责协调所有其他核心组件(包括插件、函数、记忆、规划器等)的工作,是开发者与LLM、外部工具、外部数据交互的“桥梁”。核心属性:服务集合(Services):内核中注册了所有需要使用的服务,包括大语言模型服务(LLM Service)、文本嵌入服务(Text Embedding Service)、向量数据库服务(Vector DB Service)、日志服务(Logging Service)、配置服务(Configuration Service)等。插件集合(Plugins):内核中注册了所有需要使用的插件,插件是函数的集合。记忆集合(Memories):内核中注册了所有需要使用的记忆,记忆是外部数据的“语义化存储容器”。规划器集合(Planners):虽然规划器不是直接注册在内核中的,但内核是规划器的“执行环境”,规划器需要依赖内核来调用函数、检索记忆、与LLM交互。类比理解:我们可以把内核想象成一台智能机器人的“大脑中枢”——大脑中枢里连接了各种“器官”(服务)、“工具箱”(插件)、“记忆库”(记忆),当机器人接到一个任务时,大脑中枢会调用“规划器”(比如大脑的前额叶皮层)来分析任务、制定计划,然后根据计划调用“工具箱”里的工具、检索“记忆库”里的信息、使用“器官”与外部世界交互,最终完成任务。1.1.2 插件(Plugin)核心概念:插件(Plugin)是一组相关函数的集合,它是SK用来组织和管理函数的“容器”。插件可以是“语义插件”(Semantic Plugin)——只包含语义函数,也可以是“原生插件”(Native Plugin)——只包含原生函数,还可以是“混合插件”(Hybrid Plugin)——同时包含语义函数和原生函数。核心属性:插件名称(Plugin Name):插件的唯一标识符,由字母、数字、下划线组成,不能包含空格或特殊字符。插件描述(Plugin Description):插件的功能描述,用于告诉LLM这个插件是用来做什么的,非常重要,因为LLM主要通过插件描述来选择合适的插件。函数集合(Functions):插件中包含的所有函数,每个函数都有自己的名称、描述、参数、返回值等元数据。类比理解:我们可以把插件想象成一套专门的工具箱——比如“厨房工具箱”(包含切菜、炒菜、洗碗等工具)、“办公工具箱”(包含写邮件、查日历、打印文件等工具)、“旅行工具箱”(包含查天气、订机票、订酒店、查地图等工具)。当我们需要完成某个任务时,我们会先选择合适的工具箱,然后再从工具箱里选择合适的工具。1.1.3 函数(Function)核心概念:函数(Function)是SK中最小的可执行单元,它可以完成一个具体的任务,比如“生成一段欢迎词”、“查北京明天的天气”、“把一段中文翻译成英文”、“把一篇长文档总结成100字的摘要”等。函数分为两种类型:语义函数(Semantic Function)和原生函数(Native Function)。1.1.3.1 语义函数(Semantic Function)核心概念:语义函数是基于Prompt模板和LLM构建的函数,它不需要开发者编写复杂的业务逻辑代码,只需要编写一个语义化的Prompt模板,然后将用户的输入或其他参数填充到Prompt模板中,最后调用LLM生成输出即可。核心属性:函数名称(Function Name):函数的唯一标识符,在同一个插件内不能重复。函数描述(Function Description):函数的功能描述,用于告诉LLM这个函数是用来做什么的,非常重要,因为LLM主要通过函数描述来选择合适的函数。Prompt模板(Prompt Template):语义函数的核心,它是一个包含占位符(Placeholder)的文本,占位符通常用{ {$变量名}}表示,比如{ {$input}}、{ {$language}}等。Prompt模板配置(Prompt Template Configuration):用于配置Prompt模板的执行参数,比如LLM的选择、温度(Temperature)、Top-P、最大生成Token数、停止词等。类比理解:我们可以把语义函数想象成一个专业的“翻译官”或“文案策划师”——翻译官不需要自己发明语言,只需要按照用户的要求(Prompt模板)把一种语言翻译成另一种语言;文案策划师不需要自己发明文字,只需要按照用户的要求(Prompt模板)生成一段合适的文案。1.1.3.2 原生函数(Native Function)核心概念:原生函数是基于编程语言(比如.NET、Python、Java)的原生代码构建的函数,它主要用来完成语义函数无法完成或难以稳定完成的任务,比如调用外部API、操作数据库、读写文件、解析JSON/XML等结构化数据、执行复杂的数学计算等。核心属性:函数名称(Function Name):函数的唯一标识符,在同一个插件内不能重复。函数描述(Function Description):函数的功能描述,用于告诉LLM这个函数是用来做什么的,非常重要。参数列表(Parameters):函数的输入参数,每个参数都有自己的名称、描述、类型、是否必填等元数据,SK使用自定义的特性(Attribute)来标注这些元数据,比如Python中的@sk_function、@sk_function_context_parameter、@sk_function_input_parameter等。返回值(Return Value):函数的输出结果,通常是一个字符串,也可以是其他类型的数据,但SK会自动将其转换成字符串传给LLM。类比理解:我们可以把原生函数想象成一个专业的“工程师”或“程序员”——工程师需要操作各种机器(外部API、数据库、文件系统等)来完成任务;程序员需要编写复杂的代码来执行复杂的数学计算、解析结构化数据等。1.1.4 记忆(Memory)核心概念:记忆(Memory)是SK中用来存储和检索语义化外部数据的系统,它可以帮助LLM突破上下文窗口的限制,获取到需要的“长期记忆”或“外部知识”。记忆系统分为两种类型:短期记忆(Short-Term Memory)和长期记忆(Long-Term Memory)。1.1.4.1 短期记忆(Short-Term Memory)核心概念:短期记忆是存储在内存中的记忆,它主要用来存储当前对话的上下文信息、工具的调用日志等临时数据,不需要持久化存储,对话结束后就会被清空。类比理解:我们可以把短期记忆想象成我们大脑的“工作记忆”——比如我们在做数学题时,会暂时记住中间的计算结果,但做完题后就会很快忘记。1.1.4.2 长期记忆(Long-Term Memory)核心概念:长期记忆是存储在持久化存储介质(比如向量数据库、关系型数据库、文件系统等)中的记忆,它主要用来存储用户的历史对话记录、外部文档(比如PDF、Word、TXT等)、知识库等长期数据,可以随时检索和更新。核心属性:记忆存储(Memory Store):长期记忆的“存储容器”,SK内置了多种记忆存储的实现,比如VolatileMemoryStore(存储在内存中的临时实现,用于测试)、AzureCognitiveSearchMemoryStore(基于Azure Cognitive Search的实现)、QdrantMemoryStore(基于Qdrant向量数据库的实现)、PineconeMemoryStore(基于Pinecone向量数据库的实现)等,开发者也可以自定义记忆存储的实现。文本嵌入生成器(Text Embedding Generator):用于将文本数据转换成向量(Embedding),SK内置了多种文本嵌入生成器的实现,比如AzureTextEmbeddingGenerationService(基于Azure OpenAI的实现)、OpenAITextEmbeddingGenerationService(基于OpenAI的实现)、HuggingFaceTextEmbeddingGenerationService(基于Hugging Face的实现)等,开发者也可以自定义文本嵌入生成器的实现。记忆集合(Memory Collection):记忆存储中的“子容器”,用于组织和管理不同类型的记忆数据,比如“用户历史对话”、“产品说明书”、“公司规章制度”等。类比理解:我们可以把长期记忆想象成我们大脑的“海马体”或“大脑皮层”——海马体负责将短期记忆转化为长期记忆,大脑皮层负责存储长期记忆;我们也可以把长期记忆想象成一个图书馆——记忆存储是图书馆的大楼,记忆集合是图书馆的不同书架(比如“历史书书架”、“科技书书架”、“文学书书架”),文本嵌入生成器是图书馆的“索引员”,负责给每本书编一个“语义索引”(向量),当我们需要找一本书时,我们不需要一本一本地翻,只需要告诉索引员我们的需求,索引员就会根据语义索引帮我们找到最相关的几本书。1.1.5 规划器(Planner)核心概念:规划器(Planner)是SK中用来分析用户的复杂任务、制定执行计划、协调函数调用的组件,它是SK实现“自主”Agent的关键。SK内置了多种规划器,每种规划器都有自己的优缺点和适用场景,开发者也可以自定义规划器。核心属性:规划器类型(Planner Type):SK内置的规划器类型包括Basic Planner、Action Planner、Sequential Planner、Stepwise Planner、Handlebars Planner等。规划器配置(Planner Configuration):用于配置规划器的执行参数,比如LLM的选择、可调用的函数列表、最大计划步骤数、是否允许重试等。类比理解:我们可以把规划器想象成一个专业的“项目经理”或“导演”——项目经理负责分析项目需求、制定项目计划、分配任务给不同的团队成员(函数)、监督项目进度、处理项目中的问题;导演负责分析剧本(用户需求)、制定拍摄计划、分配角色给不同的演员(函数)、监督拍摄进度、处理拍摄中的问题。1.2 概念之间的关系为了更直观地理解SK的核心概念之间的关系,我们将使用Markdown表格(核心属性维度对比)、ER实体关系图(Mermaid)、**交互关系图(Mermaid)**三种方式进行可视化展示。1.2.1 核心属性维度对比(Markdown表格)我们首先对比一下SK的五个核心概念(内核、插件、语义函数、原生函数、记忆、规划器)的核心属性、主要功能、实现方式、依赖关系等维度:核心概念核心属性主要功能实现方式依赖关系内核(Kernel)服务集合、插件集合、记忆集合、配置信息协调所有核心组件的工作,是开发者与外部世界交互的桥梁编程语言原生类(.NET的Kernel、Python的Kernel、Java的Kernel)无(是其他核心组件的依赖)插件(Plugin)插件名称、插件描述、函数集合组织和管理相关的函数目录结构(语义插件)、编程语言原生类(原生插件/混合插件)内核(需要注册到内核中)语义函数(Semantic Function)函数名称、函数描述、Prompt模板、Prompt模板配置基于Prompt模板和LLM完成文本生成、文本理解、文本翻译等任务Prompt模板文件(.txt/.md/.skprompt)+ 配置文件(.json)、编程语言原生代码内核、LLM服务、插件(需要注册到插件中,插件需要注册到内核中)原生函数(Native Function)函数名称、函数描述、参数列表、返回值调用外部API、操作数据库、读写文件、解析结构化数据、执行复杂计算等任务编程语言原生代码(.NET的类方法、Python的函数/类方法、Java的类方法)内核、插件(需要注册到插件中,插件需要注册到内核中)记忆(Memory)记忆存储、文本嵌入生成器、记忆集合存储和检索语义化的外部数据,帮助LLM突破上下文窗口的限制记忆存储实现类 + 文本嵌入生成器实现类内核、文本嵌入生成器服务、记忆存储服务(需要注册到内核中)规划器(Planner)规划器类型、规划器配置分析用户的复杂任务、制定执行计划、协调函数调用编程语言原生类(.NET的BasicPlanner、Python的BasicPlanner等)内核、LLM服务、已注册的插件和函数(需要依赖内核来调用)1.2.2 ER实体关系图(Mermaid)接下来,我们使用ER实体关系图来展示SK的核心概念之间的“一对多”、“多对多”等实体关系:注册注册注册使用包含包含包含包含生成调用调用依赖可能调用可能操作可能读写依赖依赖
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2500940.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!