入門Semantic Kernel:OneApi整合與HelloWorld

董瑞鹏發表於2024-05-08

引言

從這一章節開始正式進入我們的 Semantic Kernel 的學習之旅了。

什麼是Semantic Kernel

Semantic Kernel是一個輕量級的開源框架,透過 Semantic Kernel 可以快速使用不同程式語言(C#/Python/Java)結合 LLMs(OpenAI、Azure OpenAI、Hugging Face 等模型) 構建智慧應用,簡化將人工智慧(AI)整合到現有解決方案中的過程。

Semantic Kernel 的特點

  1. 模組化外掛架構Semantic Kernel 提供了一個模組化的外掛架構,允許開發者透過結合自定義和預定義的智慧外掛來解決複雜的業務問題。這種架構使得傳統程式碼能夠與智慧外掛無縫協作,從而簡化了傳統應用程式向智慧化轉型的過程。

  2. 多模型整合能力Semantic Kernel 支援多種 AI 模型,包括但不限於 Azure OpenAI ServiceOpenAI,以及 Hugging Face 提供的離線模型。透過 Semantic Kernel 的連結器功能,開發者可以快速地將這些 AI“大腦”整合到自己的智慧應用中,大幅提升應用的智慧化水平。

  3. 多樣化的連結器生態系統:除了連線 AI 模型,Semantic Kernel 的連結器還支援連線向量資料庫、商業軟體、業務中介軟體等多種服務。這種多樣化的連結能力,使得 Semantic Kernel 能夠適應更多的業務場景,推動業務流程的智慧化轉型。

  4. 全面的語言相容性Semantic Kernel 支援主流的程式語言,包括C#PythonJava。這種全面的語言支援,使得不同背景的開發者都能夠輕鬆地利用 Semantic Kernel 來挖掘 AI 的潛力,並將其應用到自己的專案中。

  5. 低門檻的開發體驗Semantic Kernel 設計注重使用者體驗,提供了簡單易用的介面和文件。即使是 AI 領域的新手,也能夠快速上手,實現零成本入門,從而降低了開發智慧應用的門檻。

核心概念

Semantic Kernel基本組成

image

Semantic Kernel 中,核心概念包括:

核心(Kernel)

如果說 Semantic KernelCopilot Agent 的核心 AI 編排層,那 Kernel 物件就是 AI 編排層的核心物件。

image

從上圖我們可以看出Kernel的核心包括:

  • 配置: 包括 AI 模型、外掛、連結器等的配置資訊。

  • 上下文管理:它維護應用程式的上下文資訊,確保在執行任務時,可以訪問到正確的資料和狀態。

  • 服務協調Kernel 物件協調不同的 AI 服務和外掛,確保它們能夠協同工作,完成複雜的任務。

  • 執行引擎:它作為執行引擎,根據規劃器生成的計劃,排程和執行相應的操作。

外掛(Plugins)

外掛是 AI 解決方案的構建塊,它們是一組可以暴露給 AI 應用程式和 AI 服務的函式,允許它們訪問完成特定任務所需的資料。

Semantic Kernel 中的函式

Semantic Function 是用自然語言編寫的提示(Prompt)模板,傳送給 AI 服務;而 Native Function是用 C#Python 編寫的傳統函式,可以透過規劃器和函式呼叫被 AI 服務呼叫。

記憶(Memories

Memories 是用於儲存資料的專用外掛,它們在執行過程中為你的核心提供必要的上下文,以便你的 AI 服務能夠正常執行。

規劃器(Planners

規劃器可以接收使用者的目標,並幫助我們動態生成一個包含實現該特定目標的執行步驟的計劃。規劃器使用 AI 模型根據核心中指定的函式和服務生成計劃。

透過整合這些概念和元件,Semantic Kernel 可以實現智慧的語義理解、任務規劃和智慧決策,從而為使用者提供更加智慧、靈活和個性化的互動體驗。它可以應用於各種領域,如虛擬助手、智慧客服、自然語言互動系統等,為使用者和企業提供更加智慧和高效的解決方案。

從下面這張圖可以更好的理解各核心元件之間的關係

image

Sematic Kernel 對接 OneApi

透過我們上一篇文章的,我們瞭解到了 OneApi,是以OpenAI的格式,所以在SK中可以使用OpenAIConnector來操作、在Semantic Kernel類庫中已經預設整合。

使用 UseSecrets 儲存機密資訊

  • 在我們的啟動項右鍵機密資訊管理

image

配置項 Json 檔案

  "OneApiSpark": {
    "Endpoint": "http://localhost:3000",
    "ModelId": "SparkDesk-v3.5",
    "ApiKey": "sk-LAYzQaWssCYYEVHP1d6a3fFa111745249e94F0364a0cF37c"
  }

從 OpenAI 到本地服務的請求轉換

自定義 HttpClientHandler

OpenAI 或者 Azure OpenAI 的擴充套件,請求會傳送到"api.openai.com"或者"openai.azure.com",這時候就需要我們透過自定的HttpClientHandler 重定向的模型基礎 URL轉發到我們的http://localhost:3000 OneApi 的服務地址。

  • 核心程式碼
public class OpenAICustomHandler : HttpClientHandler
{
    /// <summary>
    /// 用於OpenAI或Azure OpenAI請求時重定向的模型基礎URL。
    /// </summary>
    private readonly string modelUrl;
    private static readonly string[] sourceArray = ["api.openai.com", "openai.azure.com"];

    /// <summary>
    /// 使用指定的模型URL初始化<see cref="OpenAICustomHandler"/>類的新例項。
    /// </summary>
    /// <param name="modelUrl">用於OpenAI或Azure OpenAI請求的基礎URL。</param>
    public OpenAICustomHandler(string modelUrl)
    {
        // 確保modelUrl不是null或空
        if (string.IsNullOrWhiteSpace(modelUrl))
            throw new ArgumentException("模型URL不能為空或空白。", nameof(modelUrl));

        this.modelUrl = modelUrl;
    }

    /// <summary>
    /// 非同步傳送HTTP請求,對於OpenAI或Azure OpenAI服務的請求,將URL重定向到指定的模型URL。
    /// </summary>
    /// <param name="request">要傳送的HTTP請求訊息。</param>
    /// <param name="cancellationToken">可以用來取消操作的取消令牌。</param>
    /// <returns>表示非同步操作的任務物件。</returns>
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // 檢查請求是否針對OpenAI或Azure OpenAI服務
        if (request.RequestUri != null &&
            (sourceArray.Contains(request.RequestUri.Host)))
        {
            // 修改請求URI,以包含模型URL
            request.RequestUri = new Uri(modelUrl + request.RequestUri.PathAndQuery);
        }
        // 呼叫基類方法實際傳送HTTP請求
        return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
    }
}

Semantic Kernel HelloWorld

我們先透過一個簡單的示例學習一下 Kernel 物件的建立使用

  • VS 建立控制檯專案SK_CreateKernel
  • Nuget安裝Semantic Kernel的依賴
PM> NuGet\Install-Package Microsoft.SemanticKernel -Version 1.10.0
  • 下面我們示例將藉助Prompt提示詞用的Semantic function來推理一下使用者的意圖

Steps

簡單的流程可以總結為:

Build KernelPrompt TemplateCreate Semantic functionKernel Invoke Semantic function

var config = ConfigExtensions.FromConfig<OpenAIConfig>("OneApiSpark");
//自定義HttpClientHandler
var openAICustomHandler = new OpenAICustomHandler(config.Endpoint);
using HttpClient client = new(openAICustomHandler);
//Create Kernel
Kernel kernel = Kernel.CreateBuilder()
    .AddOpenAIChatCompletion(
        modelId: config.ModelId,
        apiKey: config.ApiKey,
        httpClient: client)
    .Build();
// 接收使用者入參
string request = Console.ReadLine()!;
// create prompt to the chat service
string prompt = "這個請求的意圖是什麼? {{$request}}";

// Create a kernel arguments object and add the  request
var kernelArguments = new KernelArguments
            {
                { "request", request }
            };
var streamingKernelContentsAsync = kernel.InvokePromptStreamingAsync(prompt, kernelArguments);
await foreach (var content in streamingKernelContentsAsync)
{
    Console.WriteLine(content);
}
Console.ReadKey();

上面的程式碼我們透過Kernel物件用prompt建立了一個Semantic function,內容是揣測使用者輸入的文字意圖,藉助大模型的推理能力很簡單的就可以做到這個功能。

Run一下

image

  • 輸入
I want to send an email to the marketing team celebrating their recent milestone
  • 輸出
這個
請求的意圖
是傳送一封
電子郵件給市場團隊
,慶祝他們最近達成
的一個重要成就。


在程式設計或自動化的上下文中,實現這個意圖可能涉及以下幾個步驟:


1. 確定市場團隊的聯絡資訊,包括電子郵件地址。

2. 編寫郵件內容,確保包含對最近里程碑的慶祝和肯定。
3.
 使用適當的郵件傳送協議(如SMTP)或郵件服務API(如SendGrid, Mailgun等)來傳送郵件。

4. 確保郵件格式正確,包括主題行、正文、簽名等。

5. 測試郵件傳送功能以確保郵件能夠成功送達。

如果你需要具體的程式碼示例或進一步的幫助來實現這個功能,請提供更多的上下文或技術要求。

最後

本章介紹了 Semantic Kernel 的特點、核心概念以及與 OneApi 的對接方式,算是我們SK學習的 HelloWorld,展示瞭如何利用 Semantic Kernel 構建智慧應用並與線上大模型進行整合。

參考文獻

  • Semantic Kernel Cookbook
  • Prompting AI models with Semantic Kernel
  • What is Semantic Kernel

本文示例原始碼

本文原始碼

😄歡迎關注筆者公眾號一起學習交流,獲取更多有用的知識~

image

相關文章