iT邦幫忙

2023 iThome 鐵人賽

DAY 24
0
AI & Data

OpenAI 從提示工程(Prompt Engineering)到語義核心(Semantic Kernel)的實踐系列 第 24

Semantic Kernel的實踐:Semantic Kernel - 整合embedding,以建立私有知識庫應用為例

  • 分享至 

  • xImage
  •  

前言

本篇來談談最多人關心的如何在ChatGPT模型中引用企業私有知識庫,目前最常見的做法不外乎是微調(fine-tuning)或embeddings的使用。本篇就來看看如何使用semantic kernel搭配embeddings模型與ChatGPT。

範例採用C#程式語言,並以主控台應用程式做為示範,使用的是.net 7.0。
此外GPT模型使用的是Azure OpenAI GPT-4,事實也可以依需求改用OpenAI服務,而模型也可以改用GPT-3.5。

至目前為止本系列文中的範例皆採用Microsoft.SemanticKernel套件,版號為0.24.230918.1-preview,然而下週Semantic Kernel預計會正式發行1.0版,因此後面文章若遇到1.0版發行,則會直接使用1.0版,而前面文章的範例,也會另行找時間更新,github上的程式碼也會同時更新。

embeddings概念

由於ChatGPT模型訓練集僅至2021/09為止,對於新的資料是未知的,而企業也常提心資料外洩的風險,因為希望找尋一種方式可以運用ChatGPT的能力又能確保有自已的私有資料知識庫,這個需求便可以使用embeddings來實現。

embeddings簡單來說是一種將文本資料轉成固定大小的數值向量方法,這些向量可以反映文本的語義和關係資訊,因此可以將企業私有資料分成小塊文本資料,然後轉化為向量儲存於向量資料庫中。然後當使用者提問時,也將使用者的提問prompt轉成向量,再將之與向量資料庫的向量進行比較,最終找出與提問最相關的向量資料,再交由ChatGPT模型生成文本回答使用者。而由於企業私有資料是儲存於獨立的向量資料庫,因此可以確保資料的安全性。

接著實際來做一遍示範:

  • 首先確認已在Azure OpenAI服務,部署二個模型分別是GPT-4模型與text-embedding-ada模型
  • 建立Kernel物件,配置使用上述2個模型服務,並且由於embedding需要有個向量資料庫,因此需要再配置MemoryStorage服務(由於本篇範例為求簡化,故以快閃記憶體充當永久性儲存的向量資料庫,因此在MemoryStorage注入了VolatileMemoryStore)
var kernel = new KernelBuilder()
            .WithAzureTextEmbeddingGenerationService(embedding_Model, aoai_Endpoint, api_Key)
            .WithMemoryStorage(new VolatileMemoryStore())
            .WithAzureChatCompletionService(
             deploy_Model,   // Azure OpenAI Deployment Name
             aoai_Endpoint, // Azure OpenAI Endpoint
             api_Key  // Azure OpenAI Key
            ).Build();

VolatileMemoryStore,semantic kernel內建提供用記憶向量資料的記憶體儲存功能,使用的是本機記憶體因此非永久性儲存。而從原始碼中可以看到在WithMemoryStorage是注入IMemoryStore的實作,換句話任何向量資料庫只要是有實作IMemoryStore,皆可做為semantic kernel支援的向量資料庫。

public KernelBuilder WithMemoryStorage(IMemoryStore storage)
{
    Verify.NotNull(storage);
    this._memoryStorageFactory = () => storage;
    return this;
}
  • 接著轉化企業私有知識為向量並儲存於向量資料庫中,本範例採用"政府檔案公開法"的法規做為示範(為求簡化,只轉入了少量法條)

此部份若為永久性儲存的向量資料庫,則不需每次都匯入資料。

await kernel.Memory.SaveInformationAsync(embedding_CollectionName, id: "第1條", text: "本細則依檔案法(以下簡稱本法)第二十九條規定訂定之。");
await kernel.Memory.SaveInformationAsync(embedding_CollectionName, id: "第2條第1項", text: "本法第二條第二款所稱管理程序,指依文書處理或機關業務相關法令規定,完成核定、發文或辦結之程序。");
await kernel.Memory.SaveInformationAsync(embedding_CollectionName, id: "第2條第2項", text: "本法第二條第二款所稱文字或非文字資料及其附件,指各機關處理公務或因公務而產生之各類紀錄資料及其附件,包括各機關所持有或保管之文書、圖片、紀錄、照片、錄影(音)、微縮片、電腦處理資料等,可供聽、讀、閱覽或藉助科技得以閱覽或理解之文書或物品。");
await kernel.Memory.SaveInformationAsync(embedding_CollectionName, id: "第3條", text: "各機關管理檔案,應依本法第四條規定,並參照檔案中央主管機關訂定之機關檔案管理單位及人員配置基準,設置或指定專責單位或人員。");
await kernel.Memory.SaveInformationAsync(embedding_CollectionName, id: "第4條第1項", text: "各機關依本法第五條規定,經該管機關核准,將檔案運往國外者,應先以微縮、電子或其他方式儲存,並經管理該檔案機關首長核定。");
await kernel.Memory.SaveInformationAsync(embedding_CollectionName, id: "第4條第2項", text: "前項檔案如屬永久保存之機關檔案,並應經檔案中央主管機關同意。");
await kernel.Memory.SaveInformationAsync(embedding_CollectionName, id: "第5條", text: "各機關依本法第六條第二項規定,將檔案中之器物交有關機構保管時,應訂定書面契約或作成紀錄存查。");
  • 建立semantic function,同樣的在prompt template裡以In-context learning方式,將知識庫找到的答案填入,再由ChatGPT模型做最後生成輸出。

這種embedding方式,也相同適用於需要精準內容的應用,以避免ChatGPT的幻覺現象。

這是從知識庫所搜尋到的結果
###
{{$ans_result}}
### 

請根據上述資料,簡短扼要的回答使用者的問題,不需要再廢話解釋資料來源
問題:{{$query_input}}
答案:

  • kernel掛載semantic function
// Import the Plugin from the plugins directory.
var pluginsDirectory = Path.Combine(System.IO.Directory.GetCurrentDirectory(), "Plugins");
var plugin = kernel.ImportSemanticSkillFromDirectory(pluginsDirectory, "QASkill");
  • 面對提問prompt先進行向量搜尋,minRelevanceScore參數可設定向量相關性的數值,數值愈高愈嚴格也代表提問要更精準,而數值太低則容易出現太鬆散的相關性(答非所問機率高)。
var searchResult = await kernel.Memory.SearchAsync(embedding_CollectionName, ask, minRelevanceScore: 0.8).FirstOrDefaultAsync();

var ans = searchResult != null ? searchResult.Metadata.Text : "很抱歉,知識庫沒有相關資料可以提供";

  • 接著交由ChatGPT做最後的內容生成
var variables = new ContextVariables
{
    ["ans_result"] = ans,
    ["query_input"] = ask
};

//叫用GPT模型等得生成結果
var result = (await kernel.RunAsync(variables, plugin["AssistantResults"])).Result;
  • 生成結果

https://ithelp.ithome.com.tw/upload/images/20231008/20126569gfAz4vB5dp.png

範例原始碼 : https://github.com/iangithub/sklearn/tree/main/KmSearch

結語

本篇展示了semantic kernel對Embedding的支援並以一個簡化的實作做為示範,對於私有知識庫應用來說相較於採用微調(fine-tuning),Embedding會是更容易並且效果會是更好的方式,不需要訓練專屬模型,且保有資料獨立的隱私性,並且有了semantic kernel,實作起來也是相當的容易。


上一篇
Semantic Kernel的實踐:Semantic Kernel - 認識 Connector連接器
下一篇
Semantic Kernel的實踐:Semantic Kernel - 串連多個semantic function共享上下文
系列文
OpenAI 從提示工程(Prompt Engineering)到語義核心(Semantic Kernel)的實踐30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言