一、前言
最近一次的HCL Domino研討會,有兩位講者不約而同都提到了RAG在Domino上的整合運用,我也把自己目前理解與實測的部分整理出來,從語意查詢、Embedding、向量檢索,到Domino與外部向量資料庫的整合方式,提供給大家參考。
二、語意查詢:AI整合的核心主題
在談到與AI整合時,一個很常見的需求就是「用自然語言查詢既有資料」。
舉個例子:如果我們詢問系統「上個月是誰幫我簽核出差」,而系統中套表名稱是「差旅申請單」,傳統Notes查詢若只依賴固定關鍵字,系統無法直接理解「出差」與「差旅」在這個業務情境下的高度相關性,除非事先建立一套關鍵字對應規則。
另一個問題是「上個月」本身就是時間語意。系統必須先把自然語言轉換成明確的日期範圍,再進行查詢。也就是說,真正困難的地方不只是「找文字」,而是把使用者的自然語言轉換成系統可以執行的查詢條件。
一直以來,Notes的全文檢索(Full-Text Search)非常適合精準快速的文字查詢,但如果希望系統理解同義詞、上下文與口語化表達,就需要在傳統全文檢索之外增加語意理解能力。這不是說FTSearch做不到,而是需要額外的語意處理層。
三、Embedding與向量資料庫:語意相似度輔助工具
「向量檢索」與「全文檢索」最大的差異,在於它不是單純依靠文字是否完全匹配,而是利用Embedding模型將文字轉換成向量,透過向量之間的相似度來尋找語意上較接近的內容。
Embedding把文字在特定模型所形成的語意表示映射到向量空間,而相似度是模型、文字內容與上下文共同產生的結果,因此,Embedding不是同義詞字典,也不是文字檢索,當然也不見得是語意正確的絕對保證。
分工方式可視為,Embedding模型負責「把文字轉成向量」,向量資料庫則負責「儲存向量、建立索引並進行相似度搜尋」。真正讓大型資料集可以有效查詢的關鍵,是向量索引與近似最近鄰(ANN)等搜尋技術,而不是單純把數字存起來。
例如一筆「差旅申請單」可以把單號、表單名稱、開單人、出差地點、金額、內容說明、簽核人、簽核時間、簽核意見等適合被搜尋的欄位整理成文字,再送進Embedding模型,把這段文字轉換成固定維度的數字陣列,當作這段文字在「語意空間」裡的座標位置。
至於如何把文字轉換成一串數字,我們可以透過現成的Embedding
API來達成,本質上也是一支標準的REST API。簡單地說,它是一個「文字轉數字陣列」的服務:你傳一段文字進去,它回傳一串固定長度的浮點數陣列,這些數值代表在高維向量空間中語意資訊的相對位置,因此能捕捉詞彙間的潛在語義關聯,而這串數字陣列就代表這段文字的「語意座標」。
向量檢索與全文檢索的運作方式不同。向量檢索會根據向量之間的相似度或距離尋找相關內容,而向量索引則是用來加速這類最近鄰搜尋。
使用者查詢「上個月誰幫我簽核出差」時,也把這個查詢條件轉換成向量,再尋找與此向量座標最近的向量。語意相關的文字,在特定Embedding模型所建立的向量空間中,通常可能呈現較高的相似度。只要Embedding模型與資料內容能建立足夠的語意關聯,就有機會將相關文件排在前面。
這正是為什麼向量資料庫不需要你自己維護同義詞對照表,同義詞之間的關聯性,早在Embedding模型訓練時就已經被編進向量座標裡了,你不用手動告訴系統「出差相近於差旅」,模型自己就懂,這就是關鍵所在。但向量資料庫真正厲害的地方,不是存向量,而是能用索引結構快速找出最相近的向量,即使有大量資料,在適當的硬體、索引與查詢設定下,也能有讓你滿意的速度。
四、什麼是RAG
|
RAG = Retrieval(檢索)+ Augmented(資料增強)+ Generation(生成答案) |
RAG(Retrieval-Augmented Generation)通常可理解為「檢索增強生成」。它的核心流程是:先從企業資料或其他知識來源檢索出與問題相關的內容,經過驗證後再把這些內容提供給LLM,讓LLM根據檢索結果產生回答。
因此,RAG的重點其實不是一定要使用向量資料庫。向量搜尋只是RAG常見檢索實作方式之一,全文檢索、SQL條件查詢、Knowledge Graph,以及Hybrid Search都可以成為RAG的檢索來源。
Domino本身已經具有成熟的文件、欄位、全文檢索、ACL與Reader/Author等機制,所以比較合理的方向不是把Domino整個推翻重做,而是讓Domino負責它擅長的企業資料與權限管理,再由外部AI服務補上語意理解與生成能力。
至於Domino在實務上如何能達到這個目的,我測試了三種可行的方法給大家參考。但本文以下三種方案,主要討論「結構化表單資料」的檢索,例如單號、金額、簽核人等這類欄位組合而成的內容,其他延伸的議題,暫時不在本文討論範圍內。
五、Domino實現RAG的可行方案
RAG的重點在於「把檢索出的資料丟給LLM產生回應」這個流程本身,至於要用什麼方式檢索,並不影響RAG的本質。連接LLM的部分完全相同,所以這篇提出的三種方案都是針對不同方法提供檢索來源。
方法一:使用Domino的全文檢索
用Domino FTSearch+關鍵字轉換做檢索,本身也是RAG的一種實作方式。
如果使用者的問法跟文件用詞一致,FTSearch抓取相關文件的效果會非常好;缺點則在於口語化用詞的轉換問題。若能事先建立使用者與系統之間關鍵字的「對應默契」,就能大幅降低轉換失誤與系統空轉的機率,若是想開始踏入AI整合的企業而言,是非常務實的起點。
方法二:純Notes向量儲存與比對
第二種方法是把Embedding向量直接儲存在Notes文件中。
作法是在Notes表單中保留一個向量定位欄位,在文件建立或更新時,把關鍵字組成的字串同樣呼叫Embedding API(我使用的是Voyage AI)產生向量,將現有文字轉換成數字陣列的向量座標後,以分隔符號串成String後存檔。
•
輸入:字串(例如:「差旅申請單,出差地點:東京,出差事由:客戶拜訪,天數:5天」)
•
儲存:數字陣列(我測試的Voyage AI模型輸出是1024維向量浮點數,結果為[0.0123, -0.0456, 0.0891, ...])轉為字串("0.0123, -0.0456, 0.0891,…”)
接下來才是最困難的環節,Domino本身並沒有原生的向量索引結構,所以搜尋時,全文檢索無法做到向量索引的近似最近鄰演算法(ANN),只能以script迴圈逐筆取得每一筆文件,並解析向量,再計算比對距離,但文件筆數一多,每次查詢都要掃描全資料庫的文件來計算相似度,速度絕對會慢到懷疑人生,更別提若要以距離排序多筆的情況,效能只會更糟。
所以如果問Notes資料庫能不能做語意比對,答案是可以,但效能肯定會耗光所有的耐心和信心。
方法三:LotusScript+外部向量資料庫
第三種方法是用LotusScript去呼叫具備向量檢索能力的RDB來做比對。文件更新時,同樣由Domino呼叫Embedding API產生向量陣列,同時把向量及Notes文件的UNID一併同步到外部資料庫。
查詢時,同樣要先把使用者的問題轉成向量,並將這個向量併入SELECT條件,丟到RDB做ORDER BY embedding <=> strQueryVector這種向量距離排序,取得最相似的UNID清單後,再回到Domino用NotesDatabase.GetDocumentByUNID撈出實際的文件內容。需要注意的是,向量資料庫回傳的UNID只代表「候選文件」,並不代表使用者已經具有該文件的存取權限。因是自行測試,我的範例是以PostgreSQL搭配pgvector擴充套件為例(PostgreSQL本身是關聯式資料庫,但透過pgvector擴充套件後,可以支援向量資料儲存、距離運算與向量索引),下方SQL裡的「<=>」是pgvector提供的向量距離運算子,若改用其他向量資料庫,語法或索引能力會不同,但底層邏輯應是一致的。
|
strSQL = "SELECT unid, embedding <=>
'" & strQueryVector & "' AS distance " & _ "FROM approval_vectors ORDER BY
distance LIMIT 5" |
這種架構的優點是把「語意表示」與「高效向量搜尋」交給外部軟體處理,而Domino仍然保留原本的企業資料與業務邏輯。對資料量較大、查詢用語多變的系統而言,絕對比單純在Notes內逐筆計算更為實際。
六、三種方案比較
以上三種方法只是提供架構供參考,不是絕對的效能保證,實踐方式仍取決於操作習慣、資料量、索引方式、硬體、網路延遲、Embedding模型與查詢策略等會有許多變化,可以自行就企業現況選擇最適合的方案。三者的差異整理如下:
|
方案 |
檢索方式 |
額外建置成本 |
查詢效能 |
適用情境 |
|
方法一:全文檢索 |
FTSearch+關鍵字轉換 |
低(設定對應檔) |
快,但需詞彙對應 |
用詞固定、既有系統成熟、希望快速導入AI |
|
方法二:純Notes向量比對 |
Script逐筆計算向量距離 |
中(改表單、寫Agent) |
隨資料量增加而變慢 |
資料量小、驗證概念用 |
|
方法三:Domino+外部向量資料庫 |
RDB端做向量索引搜尋 |
高(需額外RDB與同步機制) |
高,可擴充 |
資料量大、期望高效能 |
七、實務的挑戰與延伸思考
本質限制:向量檢索不擅長精確計數
向量相似度查詢的主要目的,是找出「相似內容」,而不是進行精確計數或複雜條件篩選,例如「上個月金額超過10萬元的差旅申請有幾筆?」這類問題,這是語意距離查詢的本質限制。不過這一點可以參考我之前的WebMCP技術報告,透過LLM搭配精準的Function Calling,後端原有的核心業務邏輯與複雜的簽核公式完全就不需要做任何調整。
資料安全性:向量資料庫與Domino文件級ACL的落差
Domino在安全層級上強項,就是對文件層級的存取權限精準控制,ACL搭配讀者欄位、作者欄位,可以做到「每一筆文件」的精細授權。但當我們把關鍵字轉成向量、同步存入外部系統後,就有可能產生資安的風險。
比較保險的作法,是把「向量檢索」跟「Domino權限檢查」拆成兩個步驟:先用向量距離取得UNID清單,再用當前使用者的身份去實際存取文件,讓Domino原生的文件級安全機制再次驗證,而不是直接讀取RDB資料內容。如果因權限篩掉導致可用資料不足,可以再放大Top-K範圍重新搜尋。
這個精神其實和之前WebMCP技術報告裡談的「前端宣告、後端零改動、原生Session延用」是一致的:AI或向量檢索只是多一層輔助手段,真正的授權判斷,還是得回到Domino。
資料同步與生命週期維護
另一個現實面的問題,是向量資料的生命週期維護。除了儲存時呼叫Embedding
API寫入向量,也要考慮文件被刪除或修改時,RDB裡對應的向量記錄如何跟著異動。
因此,正式架構最好把Embedding同步視為一個可監控、可重試、可補償的資料同步流程,而不是單純在儲存時呼叫API,向量資料的更新跟Notes資料庫及文件的異動,也要綁在同一個流程裡一併考量。
另外,在不同的Embedding Model Version時,產出的向量結果也有可能有差異,所以不同版本的Embedding模型產生的資料,不見得可以混合比較,建議在存取資料時,除了UNID外,也一併存入Model Version,並思考如何比對資料版本及更新向量索引的機制。
延伸方向:關鍵字+向量的Hybrid
Search
最後補充一個延伸方向:業界目前愈來愈常見的作法,其實不見得一定要在「全文檢索」與「向量檢索」之間二選一,也可兩者互補,也就是所謂的Hybrid Search。
FTSearch較適合精確詞彙、編號、專有名詞,SQL等結構化查詢則適合明確條件;Vector Search則適合自然語言、同義詞與語意相似的查詢。兩邊各自取得候選結果後,再依權重合併排序。
這代表上面所提的方法一與方法三並非絕對互斥,而是可以互補,兩者的結果再交由後端邏輯或LLM做最終整合。這是後續若要把RAG做得更完整,最值得繼續研究的方向,也是我接下來準備挑戰的課題。
八、結論
若是公司內部使用者穩定且熟悉,方法一(全文檢索+關鍵字轉換)通常已經夠用,改造成本最低。
方法二則比較適合像我這種專門用來驗證概念,或資料量真的很小的情境,不建議直接用於正式環境。
如果資料量大、查詢方法多變,且考量未來擴充的系統,方法三(LotusScript+外部向量資料庫)會是值得投資的方向,雖然成本較高,但換來的是絕佳的效能與延展性。
不過真正成熟的系統,不應該只有三選一,而應該把FTSearch、SQL、Vector Search、Tool
Calling與Domino原生功能全整合起來。
Notes誕生的年代,比AI的種種研發早了三十年,若直接拿兩者的功能或整合程度做比較,其實並不是在同一個基準上。沒有什麼軟體可以永遠青春不老,也沒有什麼概念能夠永遠立於不敗之地,當年的全文檢索,直到今天依然傲視群雄。只是新的時代來臨,卻又急需擁抱AI轉型潮的Domino而言,未來比較值得思考的方向,不是「Domino能不能變成AI平台」,而是「如何讓AI安全地使用Domino既有的資料、流程與權限」。只要方向對了,Domino依然可以站穩企業AI架構中的重要業務系統,而RAG則為連接兩者的重要橋樑。

沒有留言:
張貼留言