iT邦幫忙

2024 iThome 鐵人賽

DAY 5
0

生成式 AI 的強大,相信大家都已經認同。然而,即使是生成式 AI,其模型依然依賴機器學習的預訓練。因此,在不依賴外部資訊的情況下,所有的回應都是基於過去訓練資料所生成的內容。因此,對於即時性的資訊,模型無法提供準確的答案。以日期為例,如果透過 API 詢問 LLM 模型,是無法得到正確的日期,或者只會返回一個錯誤的結果。

但如果是使用ChatGPT平台(hatgpt.com)詢問,卻是可以得到正確日期的,這其中的關鍵就是 Plugin,Plugin 的魔力在於可以為 LLM 模型提供額外的能力擴展,例如:讀取外部檔案、Web Search、對接外部系統等,在ChatGPT平台上內建的 Web Search 便可以視為 Plugins 的展現。

實作 Plugin - 以日期為例

回到一開始提到的情境 —— 透過 Plugin 取得當前日期並提供給 LLM 模型。使用 Semantic Kernel 建置生成式應用時,如何實作 Plugin 並與 LLM 模型互動呢?所謂的 Plugin 其實是一個綜合體,它允許設計多個功能(functions)。簡單來說,Plugin 的設計概念類似於一個類別擁有多個方法,每個方法都可以實現不同的功能,並與 LLMs 進行互動。一般來說一個 Plugin 裡的 function 都會是符合這個 Plugin 主要用途而設計,才會收斂在同一個 Plugin 裡。例如要設計一個與日期時間相關的 Plugin ,那麼這個 Plugin 裡的 functions 原則上都是與日期時間相關的。

  • 實作 Plugin
public class DateTimePlugin
{
    public string GetCurrentDateTime()
    {
        return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
    }
}
  • Kernel 掛載 Plugin
    特別需要說明的是,一個 Kernel 可以掛載多個 Plugin。
var builder = Kernel.CreateBuilder()
                .AddAzureOpenAIChatCompletion(
                    endpoint: Config.aoai_endpoint,
                    deploymentName: Config.aoai_deployment,
                    apiKey: Config.aoai_apiKey);
builder.Plugins.AddFromType<DateTimePlugin>();
Kernel kernel = builder.Build();
  • 從 prompt 中呼叫 Plugin
    在 prompt 中呼叫 Plugin,需要使用 {{plugin類別名稱.plugin function名稱}} 的格式將其置入 prompt 中,這樣在 InvokePromptAsync 的過程中,就能夠呼叫 Plugin 中所指定的方法。
Console.WriteLine(await kernel.InvokePromptAsync("current time is {{DateTimePlugin.GetCurrentDateTime}}. 今天是幾月幾號? 距離跨年還有幾天"));
  • 自動呼叫 Plugin
    這種自動呼叫是透過 function calling 機制實現的。要達成這個機制,有一個關鍵點:每個 function 都必須使用自然語言進行描述。這些描述讓 LLMs 在互動時能夠自動理解,並在需要時選擇適當的 function。因此,首先要為 DateTimePlugin 添加相關的描述,讓模型能夠在適當的情境下自動調用它。
public class DateTimePlugin
{
    [KernelFunction, Description("Retrieves real world the current date time")]
    public string GetCurrentDateTime()
    {
        return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
    }
}

接著 InvokePromptAsync 須加上 ToolCallBehavior 的設定,設定為 AutoInvokeKernelFunctions

OpenAIPromptExecutionSettings settings = new() { ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions };
Console.WriteLine(await kernel.InvokePromptAsync("今天是幾月幾號? 距離跨年還有幾天", new(settings)));

Semantic Kernel 內建 Plugins

事實上 Semantic Kernel 也為常見的使用情境,提供了一些內建已撰寫好的 Plugin ,開發者只需要視需求在建立 kernel 物件時進行掛載就可以,例如:ConversationSummaryPlugin。若要使用 Semantic Kernel 內建的 Plugins 請安裝以下套件。

dotnet add package Microsoft.SemanticKernel.Plugins.Core --version 1.19.0-alpha

接著,可以根據情境需求在適當的時間主動呼叫 Plugin。不同於前面提到的自動呼叫或在 prompt 中呼叫,使用 Plugin 時也可以遵循傳統應用的做法,根據程式的流程規則在必要時主動呼叫。寫法如下:首先,從 kernel 中使用 Plugin 的類別名稱取得對應的 Plugin(前提是在建立 kernel 時已經掛載該 Plugin)。一旦取得 Plugin,便可以在 kernel.InvokeAsync 方法中,透過 function name 指定使用該 Plugin 中的特定功能。

KernelPlugin summaryPlugin = kernel.Plugins["ConversationSummaryPlugin"];
FunctionResult summary = await kernel.InvokeAsync(summaryPlugin["SummarizeConversation"], new() { ["input"] = news });
Console.WriteLine("Generated Summary:");
Console.WriteLine(summary.GetValue<string>());

結語

本篇內容介紹了如何建立 Plugins,以及透過 Prompt 呼叫、自動呼叫與依程式規則呼叫等三種方式來使用 Plugin。事實上,Plugin 的設計不僅限於此。在本文中,旨在讓讓各位讀者先理解 Plugin 的基本作用。接下來的文章中,我會再更深入探討 Plugin 的設計與更進階的使用方式。


上一篇
建立 Kernel 不同的寫法與 Role Prompt 的實現
下一篇
Plugin 的魔力 — 設計具有傳入參數的 Function
系列文
Semantic Kernel 的魔力-用.NET探索生成式應用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言