使用SK與Ollama實現本地LLM模型連接

Ian Chen
playtech
Published in
6 min readMay 6, 2024

--

上個月底我與二位朋友合著一本ChatGPT開發書籍,其中一個主題是Semantic Kernel,書中的範例多數以連接Azure OpenAI GPT 模型做為教學示範,因此有讀者詢問是不是Semantic Kernel只能與Azure OpenAI GPT連接呢?

Oh…這誤會可大了

Semantic Kernel 做為一個開源框架,當然是支援多種連接模型方式的,事實上書中也有示範如何連接 hugging face 與本地模型的,只是受限篇幅關係,未提供太多的範例示範,本篇打算以Ollama實現本地模型部署,再以Semantic Kernel示範如何與本地模型連接。

主機硬體,採用8核CPU、32GB RAM規格,以CPU模式進行(當然有GPU的話,效能會更好),而 Ollama 則是採用 Docker 容器運行, docker exec -it ollama ollama run llama3:8b 指令下載 llama3:8b 模型並運行,AP 面則使用 Semantic Kernel 1.10.0 版本建立一個對話的 Console 應用,程式碼行數約 50 行。

  1. 採用 Docker 容器運行Ollama,成功執行的話,Ollama 會在本機監聽 Port 11434 ,開啟瀏覽器查看 localhost:1434,如果有顯示 Ollama is running ,就代表 Ollama 已經成功啟動。使用容器的好處就是不會汙染了實體本機,另一方面環境配置也都包裝好了,省事不少,想要怎麼測怎麼搞都行。
docker run --name ollama -v ollama:/root/.ollama -p 11434:11434 ollama/ollama

2. 下載 Meta 的 llama3:8b 模型(相對較小的模型)並運行,所有已上架的模型可以在library (ollama.com)找到。

docker exec -it ollama ollama run llama3:8b

3. 新增 Console 應用(使用.net 8 .0),並安裝 Semantic Kernel 1.10.0 版本,建立 kernel 物件,並配置好 modelId 以及 endpoint,由於我們要連接的是本地 host 的模型,因此 endpoint 指向 Ollama 運行的端點 localhost:1434

 var kernel = Kernel.CreateBuilder()
.AddOpenAIChatCompletion(modelId: "llama3:8b", apiKey: null, endpoint: new Uri("http://localhost:11434"))
.Build();

4. 接著就可以開始測試對話,要注意的是不同模型所使用的 Prompt 技巧不同,因此當更換模型時,Prompt 通常需要做調整,例如 llama3:8b 模型,要求回應時使用中文,放在 system Prompt是行不通的,必須在每一次的 user prompt 後面加上提示,才能控制模型輸出中文(然後也不是100%保證每次都乖乖的回應中文),由於採用的模型相對是較小的模型,其能力上當然就會有所受限。

如果發生連接 Timeout的例外,那麼很大的機率是硬體配置太低,因此模型運算太久,導致 HttpClient的連接timeout了。

// Create chat history
ChatHistory history = new("你是一位萬能的AI助手");

// Get chat completion service
var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();
Console.WriteLine("Assistant > 我是AI助手,我能幫你什麼嗎?");

// Start the conversation
Console.Write("User > ");
string? userInput;
while ((userInput = Console.ReadLine()) != null)
{
history.AddUserMessage(userInput + ",請以中文回答");

// Get the response from the AI
var result = chatCompletionService.GetStreamingChatMessageContentsAsync(
history,
kernel: kernel);

// Stream the results
string fullMessage = "";
var first = true;
await foreach (var content in result)
{
if (content.Role.HasValue && first)
{
Console.Write("Assistant > ");
first = false;
}
Console.Write(content.Content);
fullMessage += content.Content;
}
Console.WriteLine();

// Add the message from the agent to the chat history
history.AddAssistantMessage(fullMessage);

// Get user input again
Console.Write("User > ");
}

Console.ReadLine();

這個範例的程式碼,可以上我的 github 查看devllmapp/OtherSample/llama3Sample at main · iangithub/devllmapp

關於如何使用 Semantic Kernel 的細節,歡迎斗內一下我們的新書,給還願意出版繁體中文技術書籍的作者們一點動力 :)

--

--

Ian Chen
playtech

Microsoft MVP / Microsoft Certified Trainer(MCT)