動態

詳情 返回 返回

探索Native Plugins:開啓大模型的技能之門 - 動態 詳情

前言

上一章節我們瞭解了一下Semantic KernnelPlugins插件的概念以及學習了的 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 中定義函數插件,需要用到兩個特性KernelFunctionDescription
KernelFunction特性把函數標記為一個SKNative functionDescription給函數和參數以及返回值加描述,方便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基本上都是利用KernelFunctionFactoryfunction工廠創建的,其實插件的創建也是一樣通過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

示例代碼

本文源代碼

user avatar kklldog 頭像
點贊 1 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.