生成式 AI 的強大,相信大家都已經認同。然而,即使是生成式 AI,其模型依然依賴機器學習的預訓練。因此,在不依賴外部資訊的情況下,所有的回應都是基於過去訓練資料所生成的內容。因此,對於即時性的資訊,模型無法提供準確的答案。以日期為例,如果透過 API 詢問 LLM 模型,是無法得到正確的日期,或者只會返回一個錯誤的結果。
但如果是使用ChatGPT平台(hatgpt.com)詢問,卻是可以得到正確日期的,這其中的關鍵就是 Plugin,Plugin 的魔力在於可以為 LLM 模型提供額外的能力擴展,例如:讀取外部檔案、Web Search、對接外部系統等,在ChatGPT平台上內建的 Web Search 便可以視為 Plugins 的展現。
回到一開始提到的情境 —— 透過 Plugin 取得當前日期並提供給 LLM 模型。使用 Semantic Kernel 建置生成式應用時,如何實作 Plugin 並與 LLM 模型互動呢?所謂的 Plugin 其實是一個綜合體,它允許設計多個功能(functions)。簡單來說,Plugin 的設計概念類似於一個類別擁有多個方法,每個方法都可以實現不同的功能,並與 LLMs 進行互動。一般來說一個 Plugin 裡的 function 都會是符合這個 Plugin 主要用途而設計,才會收斂在同一個 Plugin 裡。例如要設計一個與日期時間相關的 Plugin ,那麼這個 Plugin 裡的 functions 原則上都是與日期時間相關的。
public class DateTimePlugin
{
public string GetCurrentDateTime()
{
return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
}
}
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();
Console.WriteLine(await kernel.InvokePromptAsync("current time is {{DateTimePlugin.GetCurrentDateTime}}. 今天是幾月幾號? 距離跨年還有幾天"));
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 也為常見的使用情境,提供了一些內建已撰寫好的 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 的設計與更進階的使用方式。