月初試玩微軟的 RAG 範例,還弄了個 ChatGPT 版行車駕駛知識庫,修改範例過程認識一堆新名詞,Azure AI Search Service、Semantic Kernal、Embedding... 但見樹不見林,對整體概念還有點模糊。

前幾天保哥辦了場線上講座,請來 MVP Ian 介紹 Semantic Kernel 這個 LLM 整合框架。看完講座錄影,算是對 Semantic Kernel 有了清楚認識,收獲很多,寫篇筆記備忘。

Semantic Kernel 跟 LangChain 都是 LLM 框架,目標是提供一套串接整合機制,以簡化 LLM 相關應用程式的開發複雜度。LangChain 歷史較久,Semantic Kernel 則是微軟推出的框架,支援 C#、Python、Java,各語言支援程度不一,C# 支援最完整。(補充:LangChain 則支援 Python、JavaScript、Java 補充參考)

Semantic Kernel 2023 年 12 月才剛發佈 1.0 (LangChain 也差不多,2024 年 1 月推出 1.0),還很新,許多規格可能還會再變動,現階段投入要有心理準備。

LLM 應用程式可分成兩類:一種是 No Code/Low Code 工具,像是 OpenAI GPTs、Copilot Builder... 等;另一種是自己寫程式控制,此時套用 LangChain、Semantic Kernel 等框架可省很多事。

Semantic Kernel 框架(以下簡稱 SK)提供統一的連接器介面與外掛架構,並有現成連接器可以串接 OpenAI API、Azure AI Search... 等服務(亦可自行擴充實作自訂連接器),只需提供 API Url、API Key,給設定檔即可引用 ChatGPT 等服務,少寫許多程式碼。如以下 AddAzureOpenAIChatCompletion() 可透過內建連結器使用 OpenAI ChatGPT 模型,運用它的生成功能寫出聊天功能:

Kernel kernel = Kernel.CreateBuilder()
                .AddAzureOpenAIChatCompletion(
                    deploymentName: Gpt4DeploymentName,
                    endpoint: AzureOpenAIEndpoint,
                    apiKey: AzureOpenAIApiKey,
                    modelId: Gpt4ModelId)
                .Build();

在 SK 裡,服務或功能要包成 Function,Function 分為 Semantic Function (LLM 本身就會的,例如理解某段話的意思)、Native Function (LLM 不會,要自己寫程式,例如取得今天日期)。Plugin 則為相關 Function 的集合,單一 Function 亦可視為一個 Plugin。

Native Function 長得像以下這樣,KernelFunction 指定名稱與 Description 用途說明很重要,LLM 會依據其名稱及說明,在必要時呼叫它,取回資料融合進生成內容。

internal class DataTimePlugin
{
    [KernelFunction("GetCurrentDateTime")]
    [Description("Get the current date and time.'")]
    public string GetCurrentDateTime()
    {
        return DateTime.Now.ToString();
    }
}

將上述 Native Funnction 註冊到 SK 後,若使用者問到 "今天幾號?",LLM 會自動查詢它並回答 "今天是 2024 年 1 月 21 號",很神奇。

一般我們用 SK 開發 LLM 應用時,需設計執行步驟及順序,以上次駕駛人手冊查詢為例,程式先讀取使用者輸入,轉成向量後查詢向量索引找出相關文件,將文容內容轉為 Prompt 請 ChatGPT 生成回答內容。SK 提供另一種 Planner 規劃器模式,我們只需提供 Embbeding 向量化、查向量資料庫... 等 Plugin/Function,不需設計執行步驟,SK Planner 將自動判斷先做什麼再做什麼,該呼叫哪些 Function,充分展現人工智慧的威力。但 Planner 模式現階段穩定性欠佳,出錯率偏高,還不算可用的解決方案。

聊天功能還可用 YAML 定義 Prompt、溫度、Token 上限等,讓程式更簡潔,YAML 範例如下:

name: Chat
template: |
  <message role="system">你是一位萬事通助理,根據使用者的提問來回答問題,請一律使用 #zh-tw 回答</message>

  {{#each messages}}
    <message role="{{Role}}">{{~Content~}}</message>
  {{/each}}
template_format: handlebars
description: 使用聊天歷史來回應用戶的功能
input_variables:
  - name: messages
    description: 聊天歷史
    is_required: true
execution_settings:
  service1:
    model_id: gpt-4
    temperature: 0.6
  service2:
    model_id: gpt-3
    temperature: 0.4
  default:
    temperature: 0.5

程式端則用 KernelFunction prompt = kernel.CreateFunctionFromPromptYaml(yamlContent, promptTemplateFactory: new HandlebarsPromptTemplateFactory()); 依據 YAML 設定建立聊天功能,之後呼叫 InvokeStreamingAsync 傳入 prompt 即可生成回答。

var result = kernel.InvokeStreamingAsync<StreamingChatMessageContent>(
        prompt,
        arguments: new(openAIPromptExecutionSettings) {
            { "messages", chatMessages }
        });

影片還介紹了幾個實用的應用範例:

  • 生成 FB 英文貼文:兩段 Prompt,第一段依標題產生 FB 貼文、第二段將貼文翻成英文版。
  • 歸納旅館客戶評論:透過 Prompt 指定解讀並總結客人意見,指定輸出 JSON。(技巧:Prompt 要用範例引導結果確保輸出 JSON)
  • RAG 範例:將法條內容轉為 Embedding 向量,搜尋後依搜尋結果生成回答。(技巧:Prompt 要囑咐搜尋沒結果就直覺說找不到,要給沒參考資料的明確範例引導)

註:Azure AI Search 服務很貴,早期版本支援 Embedding 存本機記憶體的做法,但 1.0 拿掉了。

Ian 補充:講座的範例程式碼(v1.0)已經放上 Github 了,想實際玩看看的同學可參考。

Intrudocution to LLM framework - Semantic Kernel and some examples.


Comments

# by Ian

Hi 黑大; 當天的範例源碼 : https://github.com/iangithub/sklearn/tree/main/skv1_start 以v1.0改寫的

# by Jy

請問,Semantic Kernel可以使用本地端模型嗎? 像Mistral 7B或Breeze 7B之類,量化後的gguf格式的開源模型?

# by Jeffrey

to Ian, 感謝,很精采的分享。

# by Jeffrey

to Jy, SK 是個開發的框架,若未內建支援,依照其規格實作 Function 便能整合想要用的模型或服務。

Post a comment