最近看了 Semantic Kernel 的應用介紹,整理一些筆記心得。
Introduction
Semantic Kernel 是微軟的開源 SDK,是一個簡單好用的工具。當你想在現有的應用程式上開發跟 AI 相關功能的時候,Semantic Kernel 可以用很簡單的方式導入 AI service (也就是 OpenAI、AzureOpenAI、HuggingFace 將 LLM 打包成的 API)。目前支援 C#、Python。
Overview
如上圖,可以分成兩個部分解釋 Semantic Kernel 的架構,Brain (大腦)跟 Body (身體)。大腦包含兩個部分 Models (語言模型)、Memory (長短期記憶)。身體指的就是 Plugins,應用程式裡包含的功能,這裡分為兩種:Semantic Functions (自然語言函式,也就是 Prompts)、Native Functions (程式語言函式 Ex:C#)。
Brain — Models
大語言模型(LLM),就是經過大量資料訓練出來的模型,類似於人類大腦,它能夠回答問題、寫文章、寫翻譯…。知名的 LLM 有 GPT-3.5、GPT-4、LLaMa…。LLM 非常多種,根據不同資料訓練出來的模型,他們會在某些領域上表現的比較好。像是 GPT-4 – 主要支援聊天功能、Curie – 支援語音文字轉換、Davinci – 支援圖像視覺生成。OpenAI 跟 Azure OpenAI 將這些模型打包成 API 給外部應用。
Semantic Kernel 內建呼叫 OpenAI Service API、Azure OpenAI Service API,開發者只要有 model Name、APIKey、Endpoint,就能夠將模型接進 kernel。程式碼如下:
//建立 Kernel 物件並接上模型服務
var kernel = new KernelBuilder()
.WithAzureCompletionService(
AzureOpenAIDeploymentName, // The name of your deployment (e.g., "text-davinci-003")
AzureOpenAIEndpoint, // The endpoint of your Azure OpenAI service
AzureOpenAIApiKey // The API key of your Azure OpenAI service
)
.Build();
Brain — Memories
記憶的部分,分成長短期記憶來解釋,短期記憶常見應用於 ChatGPT 聊天功能。在一來一往對話的過程中,使用者會覺得挖噢~好像真的在跟我聊天耶~原因是他將之前的對話通通暫存起來,在你說出下一句的時候,全部一起當作 prompt 輸入 LLM。這樣 LLM 就能夠根據上下文給予使用者相關度高的回饋。
至於長期記憶指的就是要補充 LLM 不足的知識,大語言模型不可能什麼都知道,因此需要開發者先將資料儲存好,讓 LLM 在做出回應的時候,能給予正確的答案。Semantic Kernel 提供記憶體儲存的函式,方便達成這樣的效果。程式碼範例如下:
var kernel = new KernelBuilder()
.WithAzureTextEmbeddingGenerationService(embedding_Model, aoai_Endpoint, api_Key)
.WithMemoryStorage(new VolatileMemoryStore())
.WithAzureChatCompletionService(deploy_Model, aoai_Endpoint, api_Key).Build();
await kernel.Memory.SaveInformationAsync(embedding_Name, id: "第1句", text: "素胚勾勒出青花筆鋒濃轉淡");
await kernel.Memory.SaveInformationAsync(embedding_Name, id: "第2句", text: "瓶身描繪的牡丹一如妳初妝");
await kernel.Memory.SaveInformationAsync(embedding_Name, id: "第3句", text: "冉冉檀香透過窗心事我了然");
await kernel.Memory.SaveInformationAsync(embedding_Name, id: "第4句", text: "宣紙上走筆至此擱一半");
var searchResult = await kernel.Memory.SearchAsync(embedding_Name, ask, minRelevanceScore: 0.8).FirstOrDefaultAsync();
var ans = searchResult != null ? searchResult.Metadata.Text : "很抱歉,知識庫沒有相關資料可以提供";
var variables = new ContextVariables
{
["ans_result"] = ans,
["query_input"] = ask
};
//叫用GPT模型等待生成結果
var result = (await kernel.RunAsync(variables, plugin["AssistantResults"])).Result;
Body — Plugins
在 Semantic Kernel 裡,可以整合 Semantic Function(自然語言)以及 Native Function(程式語言)。Semantic Function 指的就是 prompts,在使用 ChatGPT 時,下的指令、問句都是 prompts,Ex: “寫一篇關於皮蛋香菜臭豆腐的文章”、”寫一首狐狸究竟怎麼叫的歌詞”,使用平常說話的語言敘述需求,就是一種 prompts。
自然語言與程式語言是能夠互補的,LLM 無法做精密複雜的計算,但 C# 可以。LLM 無法告訴你今天是幾月幾號星期幾,但 C# 可以。而 C# 沒辦法生出一篇麻辣鴨血臭豆腐的文章。Semantic Kernel 能夠讓開發者方便的結合使用兩種語言函式。
如以下程式碼所示,手動規劃可以用 RunAsync 去達成開發者想完成的功能,只要將需要執行的函式按照順序放入即可。前一個函式會將輸出做為下一個函式的輸入,直到執行完畢。
而 Semantic Kernel 提供了一種自動規劃器,稱為 Planner。開發者可以不用自己排函式執行順序,而是將所有函式放入 Planner,交由 Planner 根據Prompt 需求,自動決定要使用什麼函式完成任務。要注意的是,Planner 是經由函式規格中的 description 去判斷函式的功能,如果希望 Planner 能達到很好的效果,description 需要描述清楚。
// 匯入 Plugins
var pluginsDirectory = Path.Combine(System.IO.Directory.GetCurrentDirectory(), "Plugins");
kernel.ImportSemanticFunctionsFromDirectory(pluginsDirectory,"WriterPlugin");
//手動規劃函式順序
ShortPoemFunction = kernel.Functions.GetFunction("WriterPlugin", "ShortPoem");
TranslateFunction = kernel.Functions.GetFunction("WriterPlugin", "Translate");
var result = (await kernel.RunAsync(ShortPoemFunction, TranslateFunction).Result;
//使用自動規劃器
var planner = new SequentialPlanner(kernel);
var plan = await planner.CreatePlanAsync("寫一首短詩,然後翻譯該詩為英文.");
Semantic Kernel 基本介紹就到這邊,感謝閱讀!