在今天的技术博文中,我们将详细介绍利用Semantic Kernel框架中的Plugins.Core来增强我们.Net智能化应用的功能。Semantic Kernel的插件体系是一个强大的特性,它允许我们通过插件来扩展Kernel的功能。接下来,我们将逐一探讨其中一些较为重要的系统内置插件。
ConversationSummaryPlugin
首先,当我们聊天时,历史记录会随着对话的发展而逐步累积。随着对话轮数的增加,消息数量的增长可能会导致token使用量的上升,这时ConversationSummaryPlugin
插件就显得尤其重要。通过这个插件我们可以对聊天记录进行摘要总结,有效减少token的使用量,并提高聊天上下文的处理效率。插件内部使用了TextChunker来分割文本,并通过特定的提示词来生成对话的摘要。
举个例子,插件内部可能通过下面的方式来生成摘要:
PromptExecutionSettings settings = new PromptExecutionSettings {
ExtensionData = new Dictionary<string, object> {
{ "Temperature", 0.1 },
{ "TopP", 0.5 },
{ "MaxTokens", MaxTokens }
}
};
KernelFunction summarizeConversationFunction = KernelFunctionFactory.CreateFromPrompt(
PromptFunctionConstants.SummarizeConversationDefinition,
"给定一段对话记录,概述对话的内容。",
settings);
private static async Task<string> ProcessAsync(KernelFunction func, string input, Kernel kernel)
{
List<string> lines = TextChunker.SplitPlainTextLines(input, MaxTokens);
List<string> paragraphs = TextChunker.SplitPlainTextParagraphs(lines, MaxTokens);
string[] results = new string[paragraphs.Count];
for (int i = 0; i < results.Length; i++)
{
// The first parameter is the input text.
results[i] = (await func.InvokeAsync(kernel, new() { ["input"] = paragraphs[i] }).ConfigureAwait(false))
.GetValue<string>() ?? string.Empty;
}
return string.Join("\n", results);
}
这个设计思路让我们可以更高效地处理对话内容,尤其是在聊天中需要传递历史信息作为上下文时更显得至关重要。
FileIOPlugin
接下来是FileIOPlugin
,一个简单却十分实用的文件处理插件。它提供了基本的文件读写功能,可以通过以下方式读取和写入文件:
public async Task<string> ReadAsync(string path) {
// 异步读取文件内容
}
public async Task WriteAsync(string path, string content) {
// 异步写入内容到文件
}
通过这个插件,我们的应用可以轻松地完成对文件的基本操作。
HttpPlugin
继续我们的探索,HttpPlugin
为我们提供了基础的HTTP功能,包括Post、Get、Put、Delete和SendRequest等方法。有了这个插件,执行HTTP请求变得非常直接和便捷。
MathPlugin
而MathPlugin
扩展了基本的数学操作,比如加法和减法。虽然它的功能可能相对较为基础,但它向我们展示了为Semantic Kernel添加新功能的一个例子。
TextPlugin
另外,TextPlugin
提供了多项文本处理功能,包括去除空白字符、大小写转换、获取字符串长度和字符串拼接等。这些基本操作虽然在大模型中也能实现,但作为插件来说,它们的存在无疑提供了一定便利。
TimePlugin
TimePlugin
非常有用,因为大家知道,大模型通常不具备获取实时日期和时间的能力。因此,当我们要处理相对时间概念时(如“昨天”、“前天”、“上周”、“上个月”等),TimePlugin变得尤为重要。借助于这个插件,我们可以将时间函数传递给Prompt,使得模型能够在处理时间描述时参照当前日期进行推理。
今天的日期是:{{TimePlugin.Now}}
为我推荐本次旅行适合的交通方式:
我的请求是:{{$input}}
这个插件提供了一系列方法来处理时间和日期,例如Date、Today、Now、UtcNow、Time等,但它似乎缺少了自定义日期格式化的方法,这是它的一个小遗憾。
WaitPlugin
另有WaitPlugin
插件,提供了一个基本的SecondsAsync功能,允许代码执行在指定的秒数后继续。
以上这些就是Semantic Kernel 提供的核心插件功能,在我们的应用中可以直接使用。比如,如果想要在Kernel中导入ConversationSummaryPlugin
插件,我们可以使用以下的代码:
KernelPlugin conversationSummaryPlugin = kernel.ImportPluginFromType<ConversationSummaryPlugin>();
在深入探讨SemanticKernel Plugins.Core 系统内置插件的强大功能之外,值得一提的是,SemanticKernel的扩展性同样令人兴奋。框架不仅提供了一套丰富的预定义插件,而且还允许开发者根据自己的特定需求来扩展和创建自定义的插件。这些自定义插件主要分为两类:PromptPlugin
和NativePlugin
。
自定义PromptPlugin
PromptPlugin
是建立在对话提示(Prompt)之上的插件。这种插件允许开发者为大模型定义特定的提示,从而实现特定的功能。例如,我们可以设计一个专门处理特定业务逻辑的PromptPlugin,它通过提供特定的提示来指导模型的回答方向。
你可以像这样创建一个PromptPlugin:
public BusinessLogicPlugin()
{
this._handleBusinessQueryFunction = KernelFunctionFactory.CreateFromPrompt(
PromptFunctionConstants.HandleBusinessQueryDefinition,
description: "处理特定业务相关的查询。",
executionSettings: 自定义设置);
}
在这里,我定义了一个处理业务查询的功能,它会告诉模型如何理解和回答这些查询。
自定义NativePlugin
另一方面,NativePlugin
是直接运行在.NET环境中的插件,能够执行非大模型的.NET代码。开发者可以运用这一插件类型来执行与现有.NET生态内库和服务的交互,比如数据库操作、文件系统操作等。
以下是创建一个简单的NativePlugin的示例:
[KernelFunction, Description("Query database")]
public async Task<string> QueryDatabaseAsync([Description("Database query string")] string query)
{
// 实现数据库查询逻辑
}
在上述示例中,DatabasePlugin
提供了一个基础的数据库查询功能,允许我们通过内核插件直接与数据库交互。
这种插件架构不仅增加了.Net应用的功能,同时也极大地提高了其适应性。通过定制PromptPlugin和NativePlugin,我们可以灵活地根据业务需求制作出专属的插件,从而在Semantic Kernel框架下构建出更加专业和高效的.Net应用。