當前位置: 妍妍網 > 碼農

實戰教學:用Semantic Kernel框架整合騰訊混元大模型套用

2024-01-27碼農

導語 |

眾所周知,Semantic Kernel 主要支持國外的兩款大模型,但這對於開發者而言,顯然是不夠的,尤其是當我們希望對接國內的大模型時,我們應該怎麽做呢?如何用 Semantic Kernel 透過 oneapi 來整合騰訊混元大模型套用 ?今天,我們特邀

智用人工智慧套用研究院 CTO 張善友老師

,他將為我們帶來手把手實戰教學。

作者簡介

張善友,智用人工智慧套用研究院 CTO,畢業於蘭州大學數學系,專註於雲原生開發,推崇開源文化, 使用開源軟體構建雲原生軟體系統,營運微信公眾號「dotNet 跨平台」和 "新一代智慧套用",推廣和普及雲原生技術在企業業務開發的套用。 從事 .NET 平台開發 20 年,業余愛好寫作,在個人技術部落格上撰寫了大量的系列技術文章,並在騰訊雲開發者社群開設專欄。

引言

騰訊混元大模型(Tencent Hunyuan)是由騰訊研

發的大語言模型,具備強大的中文創作能力,復雜語境下的邏輯推理能力,以及可靠的任務執行能力。具體參見:

騰訊混元大模型-騰訊雲 (tencent.com)

Semantic Kernel的功能特性

Semantic Kernel(簡稱SK)是一個輕量級的 SDK(軟體開發套件),

旨在實作人工智慧大型語言模型(LLM)與傳統程式語言的整合。

這個工具包允許開發者將傳統的程式語言與最新的大型語言模型相結合,以建立更智慧、更強大的應用程式, SK 目前支持三種主流的程式語言 C#、Python 和 Java,其中 C# 的核心 API 已經釋出了 1.0 版本,詳見

https://github.com/microsoft/semantic-kernel

Semantic Kernel 提供了以下功能和特性:

● 樣版和連結:它提供開箱即用的樣版和連結,使開發者能夠輕松地將大型語言模型的"提示"(suggestion)整合到其應用程式中。

● 深度整合:Semantic Kernel允許開發者在應用程式中充分利用與 Microsoft 365 Copilot 和 Bing 相同的人工智慧協調模式,從而提高應用程式的智慧程度。

● 應用程式整合:開發者可以將 Semantic Kernel 用於將語言模型與應用程式的開發技能和積累進行整合,從而增強應用程式的功能。

● 在使用語意內核開發解決方案時,我們可以使用一系列元件來為我們的應用程式提供更好的體驗。並非所有這些都是強制性的,但建議熟悉它們。下面列出了符合語意內核的元件:

○ 內核(kernel): 在內核中,我們將註冊所有連結器和外掛程式,此外還要配置運行程式所需的內容。此外,我們還可以添加對日誌和遙測的支持,以檢查程式的狀態和效能,並在必要時協助偵錯。

○ 記憶(memory): 我們來到允許我們為使用者問題提供上下文的元件。這意味著我們的外掛程式可以回憶過去與使用者的對話,為他們提出的問題提供背景資訊。

○ 計劃器(planner): 計劃器是一個函式,它接受使用者的提示並返回執行計劃來執行請求。計劃器是SK 擴充套件性最強的一個元件,也是實作 Agent 的關鍵元件。

○ 連線(connector):連結器在 SK 中起著非常重要的作用,因為它們充當不同元件之間的橋梁,使它們之間能夠交換資訊。這些連結器可以被開發為與外部系統互動,例如與騰訊混元模型互動或使用 SQLite 資料庫作為我們開發的記憶體。

○ 外掛程式(plugin):外掛程式可以被描述為一組函式,無論是原生的還是語意的,都暴露給 AI 服務和應用程式。

手把手配置One-API系統

Semantic kernel 可以支持各種大模型,今天我們就來看一看如何把 SK 和騰訊混元大模型整合起來。我們使用 MIT 協定的開源計畫「one-api」:以 OpenAI 介面管理&分發系統,支持現有大模型場景,可用於二次分發管理 key,僅單可執行檔,已打包好 Docker 映像,一鍵部署,開箱即用,

https://github.com/songquanpeng/one-api

簡單而言,我們使用 Semantic kernel 的 OpenAI connector 連線到 oneapi,這樣就可以使用 OpenAI 的介面存取騰訊混元大模型。

OneAPI 支持使用 docker 部署,操作簡單,fork one-api 倉庫,使用倉柯瑞提供的 docker-compose.yml 搭建就很簡單。具體命令如下:docker-compose up -d

等待套用啟動完成後,在瀏覽器中輸入 IP+埠,例如:

http://192.168.10.12:3000

,系統本身是開箱即用,直接使用預設的 root 使用者登入系統即可。初始帳號使用者名稱為 root,密碼為 123456。在登入系統後,我們需要立刻到使用者管理中將密碼修改成其它的。

而渠道則可以簡單理解為各個大模型廠商,可以是原始廠商,也支持代理廠商,每家廠商又可以支持多種模型,點選渠道,然後點選添加新的渠道。

型別:選擇 騰訊混元,會自動帶出下面的模型:hunyuan

名稱:自己自擬名字即可,一個代號

分組:模型分組使用,支持多選。目前僅支持內建的 3 種分組,分別是:default、vip、svip

模型:選完型別後會自動彈出來,支持多選,也支持自己填寫

模型重新導向:假如使用者傳入的模型是 A,系統可以自動改成 B

金鑰:從大模型廠商獲得的 API Key,每家廠商的填寫格式可能都不一樣,選完型別以後會有提示,按照提示填寫,填寫金鑰為騰訊雲的金鑰管理— API 金鑰管理裏獲取 APPID、SecretId 和 Secretkey

接著,我們建立令牌,供客戶端或呼叫方使用,其作用跟大模型廠商的令牌或金鑰的概念和作用是一樣的。點選令牌,然後點選添加新的令牌,如圖添加即可,過期時間可以選擇永不過期。

如圖,然後點選復制即可:

這個令牌相當於 OpenAI 的 apikey:

sk-1Ib4X0HmR4HzXXZ644D1DdCa96934f0199Dc2b0e162b524d

日誌展示使用者充值和額度消耗記錄,普通使用者與管理員使用者檢視的範圍不一樣,普通使用者只能看到自己的。

以上我們便已經安裝並配置好了 One API 系統,那麽如何給終端使用呢?其實很簡單,使用客戶端或編程的方式呼叫 One API 的 API 介面就行了,使用方式與OpenAI API 一致。相當於只需要將 OpenAI 的網址改成你部署的 One API 系統的網址、將 OpenAI 的 API Key 改成你的令牌即可。One API 將代理使用者向實際的大模型發出請求並接收響應,如下圖所示:

另外需要特殊說明下,前面我們提到每個使用者分組是可以支持多個渠道的(即多個模型負載均衡),如果你在客戶端想指定使用某個渠道,可以透過在令牌後面添加渠道 ID 的方式指定使用哪一個渠道處理本次請求,例如:Authorization: Bearer ONE_API_KEY-CHANNEL_ID。 註意,需要是管理員使用者建立的令牌才能指定渠道ID。

SK+one-api+

openai connector

整合騰訊混元大模型

透過 oneapi 我們將騰訊混元大模型轉換為 OpenAI 的格式,透過 SK 的 OpenAI 的 Connector 存取,這裏需要做的是把 openai 的 Endpoint 指向 oneapi,這個我們可以透過一個自訂的 HttpClient 來完成這項工作,例如下面的這個範例:

internal classOpenAIHttpclientHandler : HttpClientHandler{private KernelSettings _kernelSettings;publicOpenAIHttpclientHandler(KernelSettings settings) {this._kernelSettings = settings; }protectedoverrideasync Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {if (request.RequestUri.LocalPath == "/v1/chat/completions") { UriBuilder uriBuilder = new UriBuilder(request.RequestUri) { Scheme = this._kernelSettings.Scheme, Host = this._kernelSettings.Host, Port = this._kernelSettings.Port }; request.RequestUri = uriBuilder.Uri; }returnawaitbase.SendAsync(request, cancellationToken); }}

上面我們做好了所有的準備工作,接下來就是要把所有的元件組裝起來,讓它們協同工作。因此開啟 Visual studio code 建立一個 c# 計畫 sk-csharp-hello-world,其中 Program.cs 內容如下:

using System.Reflection;using config;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Logging;using Microsoft.SemanticKernel;using Microsoft.SemanticKernel.ChatCompletion;using Microsoft.SemanticKernel.Connectors.OpenAI;using Microsoft.SemanticKernel.PromptTemplates.Handlebars;using Plugins;var kernelSettings = KernelSettings.LoadSettings();var handler = new OpenAIHttpclientHandler(kernelSettings);IKernelBuilder builder = Kernel.CreateBuilder();builder.Services.AddLogging(c => c.SetMinimumLevel(LogLevel.Information).AddDebug());builder.AddChatCompletionService(kernelSettings,handler);builder.Plugins.AddFromType<LightPlugin>();Kernel kernel = builder.Build();// Load prompt from resourceusing StreamReader reader = new(Assembly.GetExecutingAssembly().GetManifestResourceStream("prompts.Chat.yaml")!);KernelFunction prompt = kernel.CreateFunctionFromPromptYaml( reader.ReadToEnd(), promptTemplateFactory: new HandlebarsPromptTemplateFactory());// Create the chat historyChatHistory chatMessages = [];// Loop till we are cancelledwhile (true){// Get user input System.Console.Write("User > "); chatMessages.AddUserMessage(Console.ReadLine()!);// Get the chat completions OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new() { };var result = kernel.InvokeStreamingAsync<StreamingChatMessageContent>( prompt, arguments: new KernelArguments(openAIPromptExecutionSettings) { { "messages", chatMessages } });// Print the chat completions ChatMessageContent? chatMessageContent = null;awaitforeach (var content in result) { System.Console.Write(content);if (chatMessageContent == null) { System.Console.Write("Assistant > "); chatMessageContent = new ChatMessageContent( content.Role ?? AuthorRole.Assistant, content.ModelId!, content.Content!, content.InnerContent, content.Encoding, content.Metadata); }else { chatMessageContent.Content += content; } } System.Console.WriteLine(); chatMessages.Add(chatMessageContent!);}

首先,我們做的第一件事是匯入一堆必要的名稱空間,使一切正常(第 1 行到第 9 行)。

然後,我們建立一個內核構建器的例項(透過模式,而不是因為它是建構函式),這將有助於塑造我們的內核。

IKernelBuilder builder = Kernel.CreateBuilder();

你需要知道每時每刻都在發生什麽嗎?答案是肯定的!讓我們在內核中添加一個日誌。我們在第 14 行添加了日誌的支持。

我們想使用 Azure,OpenAI 中使用 Microsoft 的 AI 模型,以及我們騰訊混元的 AI 模型,我們可以將它們包含在我們的內核中。正如我們在 15 行看到的那樣:

///<summary>/// Adds a chat completion service to the list. It can be either an OpenAI、 Azure OpenAI or tencent hunyuan backend service .///</summary>///<param name="kernelBuilder"></param>///<param name="kernelSettings"></param>///<exception cref="ArgumentException"></exception>internalstatic IKernelBuilder AddChatCompletionService(this IKernelBuilder kernelBuilder, KernelSettings kernelSettings, HttpClientHandler handler) {switch (kernelSettings.ServiceType.ToUpperInvariant()) {case ServiceTypes.AzureOpenAI: kernelBuilder = kernelBuilder.AddAzureOpenAIChatCompletion(kernelSettings.DeploymentId, endpoint: kernelSettings.Endpoint, apiKey: kernelSettings.ApiKey, serviceId: kernelSettings.ServiceId, kernelSettings.ModelId);break;case ServiceTypes.OpenAI: kernelBuilder = kernelBuilder.AddOpenAIChatCompletion(modelId: kernelSettings.ModelId, apiKey: kernelSettings.ApiKey, orgId: kernelSettings.OrgId, serviceId: kernelSettings.ServiceId);break;case ServiceTypes.HunyuanAI: kernelBuilder = kernelBuilder.AddOpenAIChatCompletion(modelId: kernelSettings.ModelId, apiKey: kernelSettings.ApiKey, httpClient: new HttpClient(handler));break;default:thrownew ArgumentException($"Invalid service type value: {kernelSettings.ServiceType}"); }return kernelBuilder; }}

我們可以為內核中匯入在不同模型後端使用的外掛程式,如第 16 行所示。為此,我們匯入第 21 行到第 25 行中的語意函式。我們所做的是傳遞 yaml 檔編寫的語意提示詞。之後我們的內核和我們的外掛程式就可以使用了。

接下來開啟一個聊天迴圈,使用 SK 的流式傳輸 InvokeStreamingAsync,如第 42 行到 46 行程式碼所示,執行起來就可以體驗下列的效果:

結語

有了 Semantic kernel 這個新框架,無論我們是在桌面上使用 AvaloniaUI 構建套用,還是在伺服器上使用 ASP.NET Core 構建後端服務,都為未來將人工智慧整合到我們的開發中奠定了基礎。也許最重要的是,我們更應該關註使用其公司數據將新的人工智慧服務整合到其應用程式中,並始終確保該數據的私密合規性。

騰訊雲TVP」 公眾號後台回復 「大模型」 ,即可下載本文完整的原始碼~

歡迎關註「騰訊雲TVP」,期待你的「在看」~👇