iT邦幫忙

2024 iThome 鐵人賽

DAY 28
0
生成式 AI

Semantic Kernel 的魔力-用.NET探索生成式應用系列 第 28

RAG 篇章 - 運用快閃記憶體實現向量檢索

  • 分享至 

  • xImage
  •  

上一篇講了 RAG 應用裡很重要的向量處理,這次要來聊聊怎麼用快閃記憶體來搞定向量資料的儲存以及進行快速檢索的做法。這個示範不使用任何向量資料庫產品,單純以快閃記憶體做為儲存媒介,適合用來做 POC 驗證或是少量資料的RAG應用,由於是快閃記憶體所以當應用重啟時,就要再重新做一次向量處理及儲存。

註 : 目前 Semantic Kernel 關於 Memory 的模組正在進行新的調整,新的模組提供更多可用於 RAG 應用的彈性設定及資料處理,建議關注此一變化,相關變化我也會分享於個人blog 連結

不囉嗦直上程式

  • 建立 Kernel 物件
    上一篇提到做向量處理,需要專用的 embedding 模型,因此這個範例使用的是部署在Azure OpenAI 上的OpenAI text-embedding-3-large 模型。
Kernel kernel = Kernel.CreateBuilder()
    .AddAzureOpenAITextEmbeddingGeneration(
        endpoint: Config.aoai_endpoint,
        deploymentName: Config.aoai_embedding_deployment,
        apiKey: Config.aoai_apiKey)
    .Build();
  • 取得實作 ITextEmbeddingGenerationService 介面的服務
    實作 ITextEmbeddingGenerationService 介面的服務,用於進行文字 Embedding 的處理。以本次範例來說,即是實作了 OpenAI TextEmbedding,當然這也是semantic kernel 內建提供的。
var embeddingGenerator = kernel.GetRequiredService<ITextEmbeddingGenerationService>();
  • 建立快閃記憶體儲存物件
VolatileMemoryStore memoryStore = new();
  • 取得 ISemanticTextMemory 的實作
    提供在語義記憶體儲存保存、檢索文字資訊的方法。
SemanticTextMemory textMemory = new(memoryStore, embeddingGenerator);
  • 準備原始文字資料
    範例使用一般文字陣列,實作上也可以是從文件中讀取。並且設定一個 collection Name,可以做為檢索時過濾條件,這有助於減少檢索不必要的文字內容。
string collectionName = "Law";

string[] kmEntries =
[
    """
    1.為規定勞動條件最低標準,保障勞工權益,加強勞雇關係,促進社會與經濟發展,特制定本法;本法未規定者,適用其他法律之規定。
    2.雇主與勞工所訂勞動條件,不得低於本法所定之最低標準。
    """,
    """
    勞動契約,分為定期契約及不定期契約。臨時性、短期性、季節性及特定性工作得為定期契約;有繼續性工作應為不定期契約。派遣事業單位與派遣勞工訂定之勞動契約,應為不定期契約。
    定期契約屆滿後,有下列情形之一,視為不定期契約:
    一、勞工繼續工作而雇主不即表示反對意思者。
    二、雖經另訂新約,惟其前後勞動契約之工作期間超過九十日,前後契約間斷期間未超過三十日者。
    前項規定於特定性或季節性之定期工作不適用之。
    """,
    """
    未符合下列規定者,雇主不得與勞工為離職後競業禁止之約定:
    一、雇主有應受保護之正當營業利益。
    二、勞工擔任之職位或職務,能接觸或使用雇主之營業秘密。
    三、競業禁止之期間、區域、職業活動之範圍及就業對象,未逾合理範疇。
    四、雇主對勞工因不從事競業行為所受損失有合理補償。
    前項第四款所定合理補償,不包括勞工於工作期間所受領之給付。
    違反第一項各款規定之一者,其約定無效。
    離職後競業禁止之期間,最長不得逾二年。逾二年者,縮短為二年。
    """
];
  • 向量處理並儲存
    呼叫 SemanticTextMemory 物件的 SaveInformationAsync 方法,進行向量處理並儲存,這裡的參數包含每一筆分割資料的識別碼ID、整個文件的 collection Name以及文字內容。
foreach (var km in kmEntries)
{
    await textMemory.SaveInformationAsync(
        collection: collectionName,
        text: km,
        id: Guid.NewGuid().ToString());
}
  • 向量檢索
    呼叫 SemanticTextMemory 物件的 SearchAsync 方法,進行向量檢索。
    這裡的參數:
  1. 使用 collection Name做為檢索時過濾條件。
  2. 使用者提問文字
  3. 檢索回傳最大資料數
  4. 相似度檢索值,設定愈高,表示相關性要愈強的資料才會被檢索出來,其值介於0~1之間。
var result = await textMemory.SearchAsync(collection: collectionName, query: "我離職後,不能再從事類似性質的工作嗎", limit: 2, minRelevanceScore: 0.5).ToListAsync();
foreach (var item in result)
{
    Console.WriteLine($"Id: {item.Metadata.Id}, Text: {item.Metadata.Text}, Relevance: {item.Relevance} \n\n");
}
  • 向量檢索結果
    請注意,這個範例僅是檢索出參考資料的原始文字內容,並沒有再做最後生成式回應,因此可以看到檢索結果會是資料的原文,而非再次生成後的內容。
Id: 14ffaf83-8c68-4527-bd98-4c5f52a334dd, 
Text: 未符合下列規定者,雇主不得與勞工為離職後競業禁止之約定:
一、雇主有應受保護之正當營業利益。
二、勞工擔任之職位或職務,能接觸或使用雇主之營業秘密。
三、競業禁止之期間、區域、職業活動之範圍及就業對象,未逾合理範疇。
四、雇主對勞工因不從事競業行為所受損失有合理補償。
前項第四款所定合理補償,不包括勞工於工作期間所受領之給付。
違反第一項各款規定之一者,其約定無效。
離職後競業禁止之期間,最長不得逾二年。逾二年者,縮短為二年。, 
Relevance: 0.5336888432502747

結語

今天介紹了怎麼利用快閃記憶體來儲存和檢索向量資料,對於 RAG 架構裡的向量檢索 有了初步的認識及實作,接下來的文章將再以實際的向量儲存資料庫,實作更真實的 RAG 應用。


上一篇
RAG 篇章 - 向量概念
下一篇
RAG 篇章 - 使用 Qdrant 向量資料庫
系列文
Semantic Kernel 的魔力-用.NET探索生成式應用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言