前言
上一章節我們瞭解了一下Semantic Kernnel
中Plugins
外掛的概念以及學習了的 Semantic Kernel
模板外掛的建立,本章節我們來學習 Native Plugins
原生函式外掛使用。
透過函式定義外掛
在之前的章節中我們介紹過在在 Semantic Kernel 中應用 Function Calling,在文中講解了Functioncalling
的概念,以及在SK
中的應用。
在Semantic Kernel
中定義Native Plugins
函式外掛,和 gpt-3.5-turbo
在 6 月 13 日 釋出的 Function Calling
特別的像,這是透過增加外部函式,透過呼叫來增強 OpenAI 模型的能力。
在 Semantic Kernel 中定義函式外掛
在Semantic Kernerl
中提供了很多定義Native Plugins
的擴充套件方法來建立外掛下面介紹最常用的幾種:
根據型別建立外掛
SK
原始碼
public static KernelPlugin ImportPluginFromType<T>(this Kernel kernel, string? pluginName = null)
{
KernelPlugin plugin = CreatePluginFromType<T>(kernel, pluginName);
kernel.Plugins.Add(plugin);
return plugin;
}
- 定義
Native Plugins
在 Semantic Kernel
中定義函式外掛,需要用到兩個特性KernelFunction
和Description
KernelFunction
特性把函式標記為一個SK
的Native function
;Description
給函式和引數以及返回值加描述,方便LLMs
能夠更好的理解。
具體使用如下
public class WeatherPlugin
{
public static string GetWeather => "WeatherSearch";
[KernelFunction, Description("根據城市查詢天氣")]
public string WeatherSearch([Description("城市名")] string city)
{
return $"{city}, 25℃,天氣晴朗。";
}
}
Kernel
新增外掛
kernel.ImportPluginFromType<WeatherPlugin>();
這就是剛才說的根據型別來建立SK
外掛
- 呼叫
var getWeatherFunc = kernel.Plugins.GetFunction(nameof(WeatherPlugin), WeatherPlugin.GetWeather);
var weatherContent = await getWeatherFunc.InvokeAsync(kernel, new() { ["city"] = "北京" });
Console.WriteLine(weatherContent.ToString());
- 輸出
北京, 25℃,天氣晴朗。
這是手動呼叫的方式當然也可以
IChatCompletionService
會話模式自動呼叫。
根據物件建立
主要用到了ImportPluginFromObject
這個擴充套件方法
public static KernelPlugin ImportPluginFromObject(this Kernel kernel, object target, string? pluginName = null)
{
KernelPlugin plugin = CreatePluginFromObject(kernel, target, pluginName);
kernel.Plugins.Add(plugin);
return plugin;
}
- 定義根據城市名獲取美食的外掛
public class FinefoodPlugin
{
[KernelFunction, Description("根據城市獲取美食推薦")]
public string GetFinefoodList([Description("城市名")] string city)
{
return "烤鴨,滷煮,老北京炸醬麵,炒肝等";
}
}
和上一個使用 Type 註冊外掛是一樣的操作
- 註冊並呼叫
FinefoodPlugin finefoodPlugin = new();
kernel.ImportPluginFromObject(finefoodPlugin);
var getWeatherFunc = kernel.Plugins.GetFunction(nameof(FinefoodPlugin), "GetFinefoodList");
var weatherContent = await getWeatherFunc.InvokeAsync(kernel, new() { ["city"] = "北京" });
Console.WriteLine(weatherContent.ToString());
- 輸出:
烤鴨,滷煮,老北京炸醬麵,炒肝等
- 擴充套件
既然Kernel
物件提供了根據物件例項建立外掛的方案,那麼就可以我們最喜歡的依賴注入獲取的服務做外掛的例項,這一點非常的重要,在以後專案實戰中很實用。
依賴注入舉例
IServiceCollection services = new ServiceCollection();
services.AddSingleton<FinefoodPlugin>();
var rootProvider = services.BuildServiceProvider();
FinefoodPlugin finefoodPlugin = rootProvider.GetRequiredService<FinefoodPlugin>();
kernel.ImportPluginFromObject(finefoodPlugin);
根據 Kernelfunction 建立物件的例項
SK
提供了幾個根據 Kernelfunction
來建立Plugins
的方案,這就用到Kernel
物件建立 kernel functions
的擴充套件方法。
關於Kernel Function
的建立有兩種常用的形式第一種是根據Prompts
來建立Semantic function
也可以叫Prompts function
,第二種是根據 C#的Delegate
來建立Kernel Function
。
第一種方案之前的文章中有講過,有興趣可以瀏覽一下深入學習 Semantic Kernel:建立和配置 prompts functions,這裡不過多介紹。
第二種在這裡我們重點講一下,根據委託來建立Kernel Function
- 原始碼一覽
public static KernelFunction CreateFunctionFromMethod(
this Kernel kernel,
Delegate method,
string? functionName = null,
string? description = null,
IEnumerable<KernelParameterMetadata>? parameters = null,
KernelReturnParameterMetadata? returnParameter = null)
{
Verify.NotNull(kernel);
Verify.NotNull(method);
return KernelFunctionFactory.CreateFromMethod(method.Method, method.Target, functionName, description, parameters, returnParameter, kernel.LoggerFactory);
}
在之前的文章介紹過,所有建立Kernelfunction
基本上都是利用KernelFunctionFactory
的function
工廠建立的,其實外掛的建立也是一樣透過KernelPluginFactory
外掛plugin
工廠建立的。
建立一個根據城市名獲取遊玩地點的外掛
- 建立 Kernel Function
var kernelfunction = kernel.CreateFunctionFromMethod((string city) => { return $"{city} 好玩的地方有八達嶺長城,故宮,恭王府等"; },
functionName: "GetTourismClassic", description: "獲取城市的經典",
[
new KernelParameterMetadata(name:"city") {
Description="城市名"
}]);
- 註冊外掛並呼叫
kernel.ImportPluginFromFunctions("TourismClassicPlugin", [kernelfunction]);
var getTourismClassic = kernel.Plugins.GetFunction("TourismClassicPlugin", "GetTourismClassic");
var weatherContent = await getTourismClassic.InvokeAsync(kernel, new() { ["city"] = "北京" });
Console.WriteLine(weatherContent.ToString());
- 輸出
北京 好玩的地方有八達嶺長城,故宮,恭王府等
擴充套件
上面介紹的都是在Sk
中建立Native Plugins
常用的方法,還有一些用法,比如
ImportPluginFromApiManifestAsync
OpenAPI 功能相關
ImportPluginFromOpenAIAsync
透過 OpenAI 的 ChatGPT 格式為 OpenAI 外掛建立一個外掛CreatePluginFromOpenApiAsync
從 OpenAPI v3 端點建立外掛ImportPluginFromGrpcFile
從 gRPC 文件匯入- 其他
最後
本章我們學習了在 Semantic Kernel
中使用 Native Plugins
原生函式外掛的方法,包括透過函式定義外掛和根據物件建立外掛的步驟。我們探討了不同的建立外掛的方式,以及如何註冊外掛並進行呼叫。透過這些方法,我們可以擴充套件 Semantic Kernel
的功能,增強模型的能力。
參考文獻
- 開啟大模型的技能之門 - Plugins
示例程式碼
本文原始碼