使用LLM嵌入與後設資料在Python中構建上下文感知搜尋
本文介紹如何構建一個結合嵌入相似性與結構化後設資料過濾的上下文感知語義搜尋引擎,涵蓋從生成嵌入到持久化索引的全過程。
當使用者輸入的內容與文件的字面表述不匹配時,傳統的關鍵詞搜尋就會失效。例如,一位支援工程師搜尋“登入一直失敗”,卻找不到標題為“OAuth2令牌重新整理競態條件”的工單,儘管這正是他們需要的。這正是上下文感知語義搜尋要解決的核心問題。
語義搜尋透過將文本轉換為稱為嵌入的稠密向量表示來解決這個問題,其中語義決定文本間的距離,而非精確的詞匹配。在此基礎上疊加結構化的後設資料過濾(按日期、狀態、團隊、優先順序),就得到了一個既理解使用者意圖又遵循上下文約束的系統。
本文全程演示瞭如何構建這樣一個系統:從本地預訓練模型生成嵌入、構建後設資料感知的索引、餘弦相似度排序,以及一個可在重啟後持久化且無需重新編碼的索引。
理解語義搜尋的工作原理
句子嵌入模型將字串轉換為固定長度的浮點數向量。模型經過訓練,使得語義相似的句子在高維空間中產生方向相近的向量。餘弦相似度測量兩個向量之間的夾角:cosine_similarity(A, B) = (A·B) / (||A|| ||B||)。當向量經過單位歸一化後(即長度等於1.0),相似度簡化為點積:A·B。分數範圍從-1(相反)到1(相同)。實際上,不相關的文件得分通常在0.1–0.25之間,強匹配的得分高於0.6。
那麼為什麼後設資料過濾很重要?嵌入模型編碼的是語義內容,它們不編碼文件的作者、所屬團隊或建立時間。這些屬性存在於文本之外,必須單獨處理。結合語義得分和後設資料約束,才能使搜尋在實際系統中變得有用。
資料集準備
我們使用20個工程支援工單,涵蓋三個團隊(基礎設施、後端、前端)、四個優先順序、兩種狀態以及兩個月的時間視窗。每個工單是一個字典,text欄位用於嵌入,其餘欄位用於過濾。
第一步:生成嵌入
使用all-MiniLM-L6-v2模型,將任意句子對映到384維向量。該模型完全在CPU上執行,從Hugging Face下載一次(約22MB)後本地快取,無需API金鑰。透過設定normalize_embeddings=True,每個輸出向量的L2範數恰好為1.0,這樣查詢時餘弦相似度簡化為點積。
第二步:構建索引
索引儲存嵌入矩陣及關聯的後設資料,並提供一個search方法,接受每個後設資料欄位的可選關鍵字引數。關鍵設計決策是先過濾後評分:後過濾會浪費點積計算,而先過濾確保min_score能丟棄不相關的結果。
第三步:執行查詢
文章展示了三種查詢:無過濾的純語義搜尋、按狀態和日期過濾的搜尋、跨團隊按優先順序過濾的搜尋。例如,查詢“資源耗盡和記憶體壓力”並過濾狀態為open、優先順序為high,可以返回跨團隊的相關工單。
透過本文,你將學會構建一個實用的上下文感知搜尋系統,並能在自己的專案中應用。