向量檢索在大模型應用場景的技術和實踐

1. 向量檢索應用簡介

向量是多維數學空間裏的一個點,在各維度上的座標的一串數字。這個點就是來源於真實世界的物體進行數字化之後在數學空間的投影。那麼不同點之間有一個數學關係,就是距離,距離遠近就代表兩個物體的相似程度。

非結構化數據轉換成向量的過程稱爲  embedding 。通過深度學習的訓練,可以將真實世界數字化後的離散特徵提取出來,投影到數學空間上,成爲一個數學意義上的向量,同時很神奇的保留着通過向量之間的距離表示語義相似度的能力,這就是  embedding  的效果。
在大語言模型出現之前(2020 年以前),向量檢索這項技術就已經發展成熟。隨着深度學習的技術,廣泛應用於圖片、音頻、視頻的搜索和推薦、人臉識別、語音識別等傳統人工智能應用領域。
大模型的出現改變了人機交互方式,帶來了人工智能技術的新革命,一下子火起來,進入了一個大模型的時代。當然現在處於初期階段,在實際應用上還存在很多問題。
首先是知識能力不夠強,大模型記憶比較有限,比如 6 億參數,130 億參數,就像人的腦細胞一樣,能記住的東西有限。
其次大模型訓練週期和成本都很高,所以沒法跟上實時熱點,比如我們說 chatgpt 只知道 2021 年前發生的事情,因爲他只訓練了 2021 年前的數據。此外大模型還有幻覺問題,回答會歪曲事實。
除了知識方面,大模型也很難保證隱私數據安全。比如我爲大模型提供了一些關於自己的私人數據,當這個大模型爲其他人提供服務的時候,這些隱私信息很有可能作爲答案被說出來。最後大模型的推理成本也很高,回答一個問題的成本是很高的。
那麼如何增強大模型的知識能力,同時也保護私有數據的安全性呢?我們可以看看下圖右側的這個例子。比如提問的時候附帶上一些氣象局的信息,大模型將會依據這些額外信息準確回答問題。
這種通過外置的數據資料和工具來增強大模型能力的技術體系,稱爲提示詞工程。
從以上討論可以看出,大模型應用離不開提示詞工程。提示詞工程怎麼做呢?主要就是爲大模型整理一個資料庫,然後在訪問流程上,先從海量資料庫裏找到最匹配的內容,拼接提示詞來增強回答,本質上就是一個搜索引擎。
向量檢索技術可以非常完美地支持這個場景。現在萬物皆可 embedding,向量就是 AI 理解世界的通用形式,而向量檢索的工程技術則連接 AI 和這些資料,爲 AI 提供知識和記憶。
以下兩張圖是工程上向量技術來支持提示詞工程的流程。
因此大模型應用現階段是離不開向量檢索技術的,向量數據庫也會是每個大模型應用裏必然要用到的組件,正如關係型數據庫在 web 應用裏一樣。
2. 向量檢索技術概述
向量相關的工程技術裏最核心的當然是向量檢索算法,即如何在海量向量裏找到跟目標向量最相似的 K 個,又叫 topK。
最簡單地當然是暴力算法, 將目標向量與集合裏每個向量的距離都算一遍,然後排個序,取前面 K 個就行了。這樣有個明顯的問題,隨着數據量增加,耗時會線性增長到無法接受的程度,比如我的數據日積月累,今天只要 10 毫秒,明天可能就需要 100 毫秒,後天可能就需要一秒,再過一個星期,可能就要分鐘級別了。而向量檢索速度直接影響到大模型回答問題的速度,這個就很難接受。
如何解決?最簡單地就是通過分佈式計算來解決。比如 1 億向量,分成十份,放十臺機器上並行計算,那相比用一臺機器來說就快了十倍。而且數據即使增長的話,我也就增加機器就行,結果也是保證精確的。當然這樣算力成本就會很高。
因此業界探索有沒有可能放棄全局最優解,尋找局部最優解,來節省計算量。由此發展出了近似最近鄰算法,業界有四種算法:哈希、樹搜索、倒排、圖搜索。哈希、樹搜索、倒排這三種類似,都是通過某種分類的方式,將數據預分類,劃分空間,對號入座來減少計算量;而圖搜索則是一種比較新的思路。
我們考覈算法的效果,主要看兩個指標,一是性能,也就是查詢的耗時以及能承受的 QPS;另一個就是召回率,代表查詢準確度。我們將近似算法查出來的結果跟從全局視角看的結果的集合對比,重疊度就是召回率。比如暴力算法,那他召回率就是 100%,近似算法則有高有低,有的也可以逼近 99% 以上。
接下來我將介紹下具體的算法思路。
IVF 即倒排索引,倒排索引是搜索引擎的核心技術之一,指的從文檔網頁裏提取關鍵詞,來建立倒排檢索結構。那麼對向量數據來說,關鍵詞是什麼呢?真實世界的向量在空間分佈上一般會扎堆分佈,具備聚類特徵,請看下圖。
通過 k-means 算法將向量的聚類中心提取出來,那這個向量所處的聚類中心就是這個向量的關鍵詞,用這個來建立倒排索引,就可以像搜索引擎一樣,先命中聚類中心,再暴力搜索聚類中心下面的各個向量,這樣相比全局搜索能過濾大量的數據。如果覺得找一個聚類中心不夠準確,也可以多找幾個,找的越多,結果越準。
通過聚類的思想能不能進一步做優化?答案是可以的,就是使用乘積量化技術,可以將一個 D 維浮點向量降維成一個 M 維的二進制向量,這樣不僅僅是存儲空間的壓縮,也壓縮了內存使用和計算量。
思路是首先將 D 維向量分解成 M 個子向量,然後用子向量訓練,得到聚類中心,編成編號來代替子向量,這樣就從一串浮點數,編成一個小整數,起到壓縮效果。示例中 D=128,M=8,算下來壓縮了 64 倍。
圖算法是一種比較新的近似向量檢索思路,它基於最小世界理論,就是說世界上任意兩個人,都可以通過六跳聯繫起來。如果把向量看做人的話,按向量間的距離關係構造一個這樣類似於真實世界的「小世界網絡」,通過貪心算法,按距離建立聯繫一跳一跳逼近目標的向量定點。
隨着小世界裏的點不斷插入,根據前面講的挑選近鄰點(熟人)構建邊的思路,新插入的點會越來越侷限於一個小圈子,這樣的話跟一個很遠的點建立聯繫就需要非常多的跳數了。因此怎麼破圈呢?通過一些“機緣巧合”讓新插入的點也能跟遠處的點連起來是關鍵。
業界摸索出了 HNSW 算法,即採用類似鏈表查找算法裏的跳錶的思路。鏈表是一維的,圖是二維 的。我們來建立不同層級的圖,往上指數遞減定點數量來形成稀疏圖,這樣越稀疏的圖自然就越能連接遠方。
向量檢索需要結合一套分佈式系統設計來做工程落地。相關話題在數據類的分佈式存儲系統的工程理論都已經非常成熟,向量數據在存儲層面也沒有特別的地方,因此只要在存儲系統上實現向量能力即可。
因此向量檢索系統的架構,是一套向量數據存儲系統加上向量檢索能力,再附加上一些標量字段的存儲和過濾能力。比如我可以給向量數據打上一些字符串標籤用於特定場景的過濾。
考慮到向量存儲體量不會特別大,即使百億級的向量算到存儲空間上也不是一個非常大的規模,因此主要還是考慮算力擴展性,追求小巧精悍和極致性能。因此採用下圖右側所示架構,同時着重關注單節點的列式數據存儲格式的實現。
隨着數據規模的增長,爲了能夠更方便地彈性擴展算力,這裏的技術趨勢也必然會往雲原生和存算分離的方向發展,在遇到流量高峯時能快速拉起多副本的算力來承接。
3. 向量檢索工程實踐
百度的大模型場景跟業界通用的大模型應用場景類似,主要也是用向量檢索技術來做增強知識和提示詞工程。在百度的大模型場景裏,向量檢索技術會面對一個實際的大規模的工程挑戰。
百度智能雲在 2020 年就已經在 ElasticSearch 上集成向量檢索能力了,並廣泛應用於百度自己的業務線,有着充分的工程實踐,並且能基於公有云的資源提供雲原生的運維保障。如今在大模型場景下,需要針對新的挑戰進行技術優化。
百度智能雲是國內雲廠商裏最早提供託管 ES 服務的,經過這麼多年的發展,持續迭代增強產品能力。
在 ES 中使用向量檢索的功能非常簡單,這裏給大家做個演示。先用 ES 標準方式建表,指定一些向量索引相關的參數,通過 ES 的標準 bulk 方式批量導入數據,然後通過我們定義的跟 ES 風格接近的語法進行查詢。
百度 ElasticSearch 的架構由管控平臺和 BES 集羣實例兩部分組成。管控平臺是全局層面來進行一些統一的集羣管理、監控報警,以及執行定時創建刪除 merge 索引的任務的平臺。BES 集羣實例則是一套構件在雲服務器 BBC 和雲磁盤 CDS 上面的 ElasticSearch 集羣服務,前面通過 BLB 四層代理做節點負載均衡。磁盤上的數據可以通過策略定期下沉存儲到對象存儲 BOS 上,降低存儲成本。
向量數據在 ES 的標準架構下按下圖所示方式組織和訪問。
我們選擇自研插件,一是希望基於  C++  實現來獲得更貼近底層的極限性能,二是能改寫存儲格式等也是方便做到更極致的性能,三是能更靈活地控制檢索邏輯,改寫執行計劃來實現比較複雜的查詢。
這裏核心的向量檢索引擎部分,我們選擇基於社區優秀的向量庫實現做二次開發。我們對比了下 nmslib 和 faiss 各自在 ES 上的開箱性能(沒做優化)。可以看出 hnsw 整體比較耗內存,其中 nmslib 的實現更勝一籌。因此我們在此基礎上做進一步優化。
HNSW 構圖過程中每插入一個點需要檢索計算,插入大量的點也是一筆很大的計算開銷,因此導入數據會很慢,導致前臺阻塞。
這裏改造成異步構建索引的機制,數據寫入落盤之後就可以直接返回。然後後臺通過 ES 的合併策略或者用戶的定時或主動觸發的方式來觸發在後臺構建 HNSW 索引,並且使用獨立線程池構建,以免對前臺查詢請求造成影響。
這裏同時也對 ES 的片段合併策略進行優化,在最終合併時統一構圖,來降低逐個合併構圖帶來的中間計算開銷。
有很多場景提出先按標量條件過濾數據再進行向量檢索的需求,例如爲向量數據打上標籤,要保證檢索出來的向量能匹配上標籤。標準的 HNSW 實現無法做到這一點,如果先 HNSW 再做過濾呢,則無法保證返回的結果完整。因此我們改造了 HNSW 實現,讓算法在遍歷圖挑選近鄰的過程中,只考慮符合 filter 條件的定點。
實際測試的時候,發現性能和召回不是很理想。通過測試數據和研究一些資料發現,在過濾比例升高時,因爲頂點被過濾導致能連通的路徑變少,直接影響了 HNSW 算法的收斂速度,以及很容易走進死衚衕導致召回率低。資料表明,過濾比達到 90% 以上時,性能和召回率會急劇下降。
因此這裏我們選擇改寫執行計劃,將標量過濾和暴力檢索算法結合,可以取得令人滿意的效果。
4. 總結展望
來看一張流傳已久的圖。就像人類從猴子進化到直立智人一樣,半/非結構化數據的存儲系統也經歷了從最簡單的 key-value 發展出各種更加複雜的結構的系統,最後長得越來越像傳統數據庫。
業界的向量數據庫隨着大模型的熱度也紛紛冒出來,有這些專用的向量數據庫,創業團隊入局的商用的、開源的。一些傳統開源的存儲系統也都加上了向量能力。
結合自身業務場景,百度自研了 Puck/Tinker 向量檢索算法,比業界開源向量庫具備一定優勢,曾獲得 BigANN 大賽第一。
百度智能雲將結合百度自研算法,推出專用型向量數據庫,來更好地支撐雲上大模型業務和相關應用,敬請期待!

以上就是今天分享的全部內容。

本文分享自微信公衆號 - 百度開發者中心(baidudev)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章