前言
上一篇文章介紹了使用SemanticKernel/C#的RAG簡易實踐,在上篇文章中我使用的是相容OpenAI格式的線上API,但實際上會有很多本地離線的場景。今天跟大家介紹一下在SemanticKernel/C#中如何使用Ollama中的對話模型與嵌入模型用于本地離線場景。
開始實踐
本文使用的對話模型是gemma2:2b,嵌入模型是all-minilm:latest,可以先在Ollama中下載下傳好。
2024年2月8号,Ollama中的相容了OpenAI Chat Completions API,具體見https://ollama.com/blog/openai-compatibility。
是以在SemanticKernel/C#中使用Ollama中的對話模型就比較簡單了。
var kernel = Kernel.CreateBuilder()
.AddOpenAIChatCompletion(modelId: "gemma2:2b", apiKey: , endpoint: new Uri("http://localhost:11434")).Build();
這樣建構kernel即可。
簡單嘗試一下效果:
public async Task<string> Praise()
{
var skPrompt = """
你是一個誇人的專家,回複一句話誇人。
你的回複應該是一句話,不要太長,也不要太短。
""";
var result = await _kernel.InvokePromptAsync(skPrompt);
var str = result.ToString();
return str;
}
就這樣設定就成功在SemanticKernel中使用Ollama的對話模型了。
現在來看看嵌入模型,由于Ollama并沒有相容OpenAI的格式,是以直接用是不行的。
Ollama的格式是這樣的:
OpenAI的請求格式是這樣的:
curl https://api.openai.com/v1/embeddings \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-d '{
"input": "Your text string goes here",
"model": "text-embedding-3-small"
}'
OpenAI的傳回格式是這樣的:
{
"object": "list",
"data": [
{
"object": "embedding",
"index": 0,
"embedding": [
-0.006929283495992422,
-0.005336422007530928,
... (omitted for spacing)
-4.547132266452536e-05,
-0.024047505110502243
],
}
],
"model": "text-embedding-3-small",
"usage": {
"prompt_tokens": 5,
"total_tokens": 5
}
}
是以通過請求轉發的方式是不行的。
之前也有人在ollama的issue提了這個問題:
似乎也有準備實作嵌入接口的相容:
目前試了一下還沒有相容。
在SemanticKernel中需要自己實作一些接口來使用Ollama的嵌入模型,但是經過搜尋,我發現已經有大佬做了這個事,github位址:https://github.com/BLaZeKiLL/Codeblaze.SemanticKernel。
使用方法見:https://github.com/BLaZeKiLL/Codeblaze.SemanticKernel/tree/main/dotnet/Codeblaze.SemanticKernel.Connectors.Ollama
大佬實作了ChatCompletion、EmbeddingGeneration與TextGenerationService,如果你隻使用到EmbeddingGeneration可以看大佬的代碼,在項目裡自己添加一些類,來減少項目中的包。
這裡為了友善,直接安裝大佬的包:
建構ISemanticTextMemory:
public async Task<ISemanticTextMemory> GetTextMemory3()
{
var builder = new MemoryBuilder();
var embeddingEndpoint = "http://localhost:11434";
var cancellationTokenSource = new System.Threading.CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token;
builder.WithHttpClient(new HttpClient());
builder.WithOllamaTextEmbeddingGeneration("all-minilm:latest", embeddingEndpoint);
IMemoryStore memoryStore = await SqliteMemoryStore.ConnectAsync("memstore.db");
builder.WithMemoryStore(memoryStore);
var textMemory = builder.Build();
return textMemory;
}
現在開始試試效果,基于昨天的分享做改進,今天上傳一個txt文檔。
一個私有文檔如下所示,隐私資訊已替換:
各位同學:
你好,為了幫助大家平安、順利地度過美好的大學時光,學校專門引進“網際網路+”高校安全教育服務平台,可通過手機端随時随地學習安全知識的網絡微課程。大學生活多姿多彩,牢固掌握安全知識,全面提升安全技能和素質。請同學們務必在規定的學習時間完成該課程的學習與考試。
請按如下方式自主完成學習和考試:
1、手機端學習平台入口:請關注微信公衆号“XX大學”或掃描下方二維碼,進入後點選公衆号菜單欄【學術導航】→【XX微課】,輸入賬号(學号)、密碼(學号),點【登入】後即可綁定資訊,進入學習平台。
2、網頁端學習平台入口:打開浏覽器,登入www.xxx.cn,成功進入平台後,即可進行安全知識的學習。
3、平台開放時間:2024年4月1日—2024年4月30日,必須完成所有的課程學習後才能進行考試,試題共計50道,滿分為100分,80分合格,有3次考試機會,最終成績取最優分值。
4、答疑qq群号:123123123。
學習平台登入流程
1. 手機端學習平台入口:
請掃描下方二維碼,關注微信公衆号“XX大學”;
公衆号菜單欄【學術導航】→【XX微課】,選擇學校名稱,輸入賬号(學号)、密碼(學号),點【登入】後即可綁定資訊,進入學習平台;
遇到問題請點【線上課服】或【常見問題】,進行咨詢(咨詢時間:周一至周日8:30-17:00)。
2. 網頁端學習平台入口:
打開浏覽器,登入www.xxx.cn,成功進入平台後,即可進行安全知識的學習。
3. 安全微課學習、考試
1) 微課學習
點選首頁【學習任務中】的【2024年春季安全教育】,進入課程學習;
展開微課清單,點選微課便可開始學習;
大部分微課是點選繼續學習,個别微課是向上或向左滑動學習;
微課學習完成後會有“恭喜,您已完成本微課的學習”的提示,需點選【确定】,再點選【傳回課程清單】,方可記錄微課完成狀态;
2) 結課考試
完成該項目的所有微課學習後,點選【考試安排】→【參加考試】即可參加結課考試。
上傳文檔:
切割為三段:
存入資料:
回一個問題,比如“答疑qq群号是多少?”:
雖然耗時有點久,大概幾十秒,但是回答對了:
再嘗試回答一個問題:
回答效果不是很好,而且由于配置不行,本地跑也很慢,如果有條件可以換一個模型,如果沒有條件并且不是一定要離線運作的話,可以接一個免費的api,在結合本地的嵌入模型。
換成線上api的Qwen/Qwen2-7B-Instruct,效果還不錯:
總結
本次實踐的主要收獲是如何在SemanticKernel中使用Ollama中的對話模型與嵌入模型用于本地離線場景。在實踐RAG的過程中,發現影響效果的最主要在兩個地方。
第一個地方是切片大小的确定:
var lines = TextChunker.SplitPlainTextLines(input, 20);
var paragraphs = TextChunker.SplitPlainTextParagraphs(lines, 100);
第二個地方是要擷取幾條相關資料與相關度的設定:
var memoryResults = textMemory.SearchAsync(index, input, limit: 3, minRelevanceScore: 0.3);
相關度太高一條資料也找