一、向量數據庫產生的背景
1、非結構化數據檢索問題
結構化數據是指可以表示成二維表格的數據,它有明確固定的字段和類型。而非結構化數據是指不能表示成二維表格的數據,例如:文本、圖片、視頻。抖音集團的產品矩陣每天都會產生海量的數據,其中結構化數據只占一小部分,大部分數據都是非結構化數據,業界通常認為非結構化數據會占全部數據的80%,但是對于抖音集團的業務形態,非結構化數據的占比只會更高。如何利用好這些非結構化數據對我們產品功能的完善,業務效果的提升都至關重要。
對非結構化數據的檢索,以文本檢索為例,傳統上使用倒排索引,結合BM25,TF-IDF算法進行。這種方法有一些問題:
- 文本泛化能力、語義檢索能力不足。
- 基于切詞結果,難以推廣到圖片視頻等多模態場景。
- 數據持續增長時性能不足。
但是,現在有了深度學習,這產生了向量表示法,通過語言模型(如doc2vec、bert、LLM等),將文本轉換為向量,從而將非結構化數據檢索問題轉化為向量近似檢索問題。
2、向量檢索的核心概念
向量檢索是從一堆向量里找到和某個給定向量相似的一批向量,這里有三個問題需要明確:
- 如何衡量向量間的相似性?通常使用的度量方式有歐氏距離、內積和余弦距離。
- 需要檢索出多少個結果?通常指定一個整數topK。
- 如何評估檢索效果?需要平衡檢索精度和檢索效率兩個指標
通常受限于算力和響應時間,向量檢索得到的是近似最優結果。常見的做法可以分為三類(三類也可結合進行):
- 近似最近鄰算法(ANN)。借助輔助結構進行剪枝,以加快檢索速度,常見的有:HNSW,IVF。
- 量化算法。通過降低相關性計算開銷來加速檢索過程,如PQ算法,標量量化。
- 實現上的優化。SIMD硬件指令集加速方案;內存編排:提高cache命中率。
抖音集團實踐:
- 在ANN算法方面,我們對開源HNSW進行了優化,并自主研發了IVF算法,在保持檢索精度的同時提高了性能;
- 在量化方面,除了PQ量化外,我們還自主研發了一套標量量化算法,支持int16、int8和int4量化,實現了單張T4顯卡(2億候選向量)的檢索;
- 在SIMD和內存編排等實現層面的優化上也做了大量的工作。
3、從檢索算法到向量數據庫
把向量檢索的這些功能整合起來,就形成了向量數據庫。
向量數據庫的接口包括存儲和檢索向量。在功能劃分上,包含存儲、檢索和分析。同時,作為在線服務,高可用、高性能和易用性都要具備。
完成這些后,一個具備核心向量檢索功能的向量數據庫就誕生了。這是一個存算一體的向量數據庫。
二、向量數據庫的技術演進
1、向量標量混合檢索
當向量數據庫推向業務場景時,我們發現,向量數據通常與結構化數據配合使用。例如,在將文檔表示為向量的同時,還需要存儲文檔所屬的部門,以方便在檢索時進行權限過濾。這類需求可以抽象為使用與向量相關的結構化數據進行過濾。
業界對于這種過濾需求通常有兩種解決方案:
- 后過濾。將topK的結果擴大一定倍數,檢索出更多的向量,然后用結構化數據做過濾,留下topK個。對于向量檢索和DSL過濾結果的重合較少的情況,可能會出現召回結果不足topK的情況。因此,這種方法適用于結構化過濾掉的比例較低,向量召回結果比例較高的場景。
- 先過濾。先使用DSL過濾數據集,然后在結果中進行向量檢索。這種方案適用于DSL過濾結果較少的場景;如果結果較大的話,性能會有明顯的下降。
業界通常結合兩種方案,對檢索任務進行編排,通過分析數據分布,來決定使用哪種方案。但是,隨著數據量的增加,仍然可能會出現兩種檢索鏈路性能都不好的情況。
抖音集團實踐:為解決這一問題,技術團隊研發了DSL定向引擎,支持在檢索過程中同時進行向量檢索和DSL過濾(結構化過濾)。該引擎具有以下特點:
- 高性能:因為在進行DSL過濾時,只需提取部分向量進行相似度計算,這會打斷內存連續性,從而降低向量檢索的性能。因此,DSL過濾判斷的開銷必須足夠低,要求它遠低于向量檢索的開銷,以確保在線檢索性能。
- 邏輯完備:DSL語法可以支持根據場景和用戶的不同定制相應的檢索過濾條件,以支持業務在線檢索。
- 按需終止:如果在向量檢索和過濾過程中遍歷了足夠多的節點,可以保證檢索效果,則應盡快退出該檢索過程。
- 執行計劃優化:根據DSL過濾結果預估結合向量分布情況,綜合決策要執行的檢索鏈路。
除了DSL定向引擎之外,我們還實現了子索引拆分、自適應精度調節和在線多路索引歸并等多種定制化能力,打造了一整套向量檢索工具庫。
2、存算一體升級為存算分離
盡管功能逐漸完備,但我們向量數據庫在初期是基于存算一體(存儲和計算都在同一臺機器上)的架構實現的,但在推廣過程中,這種架構在使用上的一些問題也逐漸顯現出來。比如在文檔檢索的場景中,一部分文檔質量較高,需要高精度的召回,全局的文檔作為補充,我們還需要區分部門內和部門外的文檔列表來分開展示。這就要求在同一份向量數據上產生不同的可檢索集、不同精度的索引以及不同的候選集。
在存算一體框架下,為了避免影響線上檢索流程,我們使用少量線程異步地完成索引的重建流程。為適配數據分布的變化,這個索引還要定期重建。另外,在有些業務場景中,需要使用不同候選、不同精度的檢索策略。如果為每種策略都建立一套索引,這會進一步放大索引構建的資源消耗,導致索引構建效率低、還會影響在線服務穩定性。
為此,我們逐步開展了存算分離的架構升級工作。
我們的存算分離架構,主要分成三個部分:
- 向量存儲。用戶將他們的向量存儲在向量存儲中。
- 批式構建。批式構建集群自動調度向量索引的構建流程。在此過程中,會篩選候選集,根據不同的精度要求適配不同的參數,構建相應的索引,然后通過P2P管道分發給在線的多副本檢索服務。
- 在線檢索服務。負責實時在線檢索。
這種設計除了解決一份向量多個索引、支持多個場景的問題,還帶來以下優勢:
- 節省了索引構建資源,一次構建,多處分發。
- 加快索引構建,因為存算一體中,為了不影響實時檢索性能,構建過程只能使用少量線程(不能使CPU滿負荷運行),而存算分離后,就沒有這個限制,可以將CPU滿負荷運行。
- 在線檢索服務穩定性得到明顯提升,因為構建過程不再影響在線檢索服務。
- 對自動調參特別友好。基于這套存算分離的框架,我們搭建了一套自動調參的工具庫,支持用戶在寫入向量數據后、在索引構建前以及上線后,持續對索引的構建參數和檢索參數進行調優。
3、流式更新
隨著對時效性要求較高的業務接入,如何有效的提升新內容的檢索效率,成為業務關注的重點。例如,在文檔檢索場景中,如果一篇文檔剛寫完,或者新授權了一個文檔,用戶需要等待半個小時才能檢索到,這在業務上是無法接受的。為了解決這個問題,我們開發了流式更新能力。
加入了流式更新能力的索引構建過程分為兩個部分。
- 優化批式加流式的更新事件產生過程。在新版本的索引上線之前,有一個批式構建過程,這個過程需要一些時間。在構建過程中,仍有新的數據更新事件出現,這需要在批式版本更新完成時,將流式更新事件訂閱回撥到批式更新開始時的事件時間。等到追平這個延遲后,再繼續流式更新事件。
- 對索引更新的改造。為了實時更新索引,我們對向量索引進行了并發安全的改造,包括HNSW和IVF索引。在提供在線檢索服務的同時,我們基本可以實現向量的增刪改查。這里單獨把DSL索引提出來,是因為DSL索引對數據一致性的要求比較高,一條DSL更新操作寫入的字段較多,數據一致性安全和更新并發性安全會明顯影響在線檢索性能。因此,我們采用了雙buf的方案,寫入操作只發生在更新buf上,檢索Buf支持無鎖的檢索流程,整體的雙buf方案也能做到秒級的更新延遲。
4、云原生轉變
隨著抖音集團產品矩陣中的產品越來越多接入向量數據庫,為每個業務都搭建一套存算分離的框架的成本較高,包括部署成本、運維成本和硬件成本。為解決這一問題,我們對存算分離的框架進行了進一步迭代。
- 多租戶編排改造
①向量存儲部分改造為向量存儲集群。
②索引構建部分改造為索引構建集群。
③在線檢索服務改造成支持多租戶形式。
我們的資源調度模塊可以自動化的去拉取數據開始索引構建任務,然后分發給在線多租戶檢索服務。改造后的在線檢索服務支持多路索引,這能進一步降低在線服務的開銷。在初期,為了保證服務穩定性,我們的在線檢索服務編排是手動進行的。
- 自動化調度
隨著業務增長,索引體積越來越大,為了保證多租戶服務的穩定性。優化手動編排,人工選擇集群不合理等問題。我們開發了自動化調度框架。
對在線檢索服務編排的改造,主要采用slot化的方式。一個slot是索引的一個最小調度單元。通過索引元信息管理調度服務會根據在線檢索服務配額和實時調用流量,自動調入調出slot。
為了配合自動化調度方案的上線,我們開發了很多輔助模塊。例如,索引的流量感知模塊,用于為調度服務提供信息,以盡快響應整個索引的流量變化。再比如索引配額管理系統,避免有的索引流量突增,影響整個在線檢索集群的穩定性。
其中一個關鍵的模塊是索引的精確計價系統。為了降低整體在線服務的計算成本,我們會將一些小內存的、低請求量的索引調度到同一個實例上。此時,如何統計和分攤成本就很關鍵了。我們實現了一個精確到時鐘周期的開銷監控,以進行服務的成本統計和分攤。
5、火山引擎向量數據庫VikingDB技術全景
隨著大語言模型的浪潮興起,向量數據庫的商業價值也慢慢凸顯出來。我們決定在火山引擎上線我們的云原生向量數據庫,提供和抖音集團內部向量數據庫完全一致的服務,也會把內部探索和優化的成果同步到這個產品上。
它整體的產品結構如下圖所示。整個產品基于火山引擎的云基礎設施,提供經過我們深度打磨和優化的各個引擎,提供從多模態數據寫入,到向量生成,再到在線檢索,以及上線后的彈性調度和監控的一整套全鏈路解決方案。
用戶接入時,通過我們的多語言SDK或http API寫入自己的非結構化數據。然后,使用查詢分析工具對數據進行管理和分析。進行簡單配置后,即可自動化調度。從非結構化數據到向量生產的pipeline,都通過平臺自動化調度實現。數據寫入完成后,還支持在索引上線前進行自動調參,上線后進行流式更新,以及持續的自動調參以優化整體在線檢索效果和資源成本。在在線檢索階段,支持整體服務的按需自適應彈性調度。從數據寫入到在線檢索的各個階段,有全鏈路的監控和告警,以保證在線服務的穩定性。基于這套產品,我們預期會在大語言模型的智能問答、智能搜索、智能推薦廣告、版權去重等場景下展開廣泛應用。
這套云原生向量數據庫有以下幾個關鍵優勢。
- 極致性能:內置多種火山引擎內部自研索引算法,支持內部多個百億庫,百億級向量檢索規模,檢索性能在10ms內。
- 實時性:支持向量數據實時寫入、實時更新,支持實時索引、自動索引。
- 穩定高效:存算分離架構,單數據多場景,節約計算資源,提高在線穩定性,保證高可用性。
- 多場景最佳實踐:20+內部業務,多個百億級別庫檢索實踐,內部多個大模型場景的落地實踐,例如:飛書問答,飛書文檔,搜索中臺、電商搜索等。
三、向量數據庫的應用展望
介紹完我們在云原生向量數據庫上的技術和優勢后,這一節對向量數據庫做一些展望。
1、對大語言模型(LLM)的能力補充
在大語言模型中,prompt是給大語言模型的輸入。prompt的信息含量會影響最終回答的質量。然而,由于算法原理和計算能力的限制,prompt的長度是有限制的。無論是多輪調校,還是個性化問答的感知,還是特定領域的知識灌入,都需要更長的prompt。其次,由于訓練樣本的限制,大語言模型的時效性存在缺陷,只能知道訓練數據截止時輸入的信息,對于需要時效性回答的場景需要支持手段。對于這個問題,向量數據庫可以在一定程度上解決。
- 補充大模型長期記憶。對于多輪調校和個性化回答,把調校過程和用戶的問答結果都通過文本編碼寫入向量數據庫中,然后在用戶提問的過程中,把問題轉化為向量,在向量數據庫中查找長期記憶去回顧歷史,找到和當前問題最相近的歷史調校結果和用戶自己的問答,灌入大語言模型的context中優化整個回答的質量。
- 補充特定領域知識。可以在向量數據庫中灌入領域知識。在用戶提問的時候,提前把相關的文本信息檢索出來,灌入大模型的context中,去優化大語言模型在專業領域的回答效果。
- 優化大模型的時效性問題。比如實時熱點新聞,可以通過流式更新能力,把實時信息寫入向量數據庫中。在用戶提問實時熱點問題時,通過向量數據庫把熱點信息檢索出來,放到大語言模型的上下文中去優化回答效果。
2、大語言模型(LLM)潛在的安全解決方案
大語言模型除了prompt長度限制外,另一個突出問題是數據安全問題。例如,支付行業建議大家在支付場景謹慎使用ChatGPT。而在互聯網行業,很多公司也禁用了chatGPT,這都是出于安全角度考慮。
目前,在安全方面有兩個關注點:
第一,用戶的提問會被記錄下來,這可能導致問題被泄露。
第二,A用戶的提問可能被作為訓練數據訓練模型,導致其他用戶B在使用時獲得A用戶提問時提供的隱私信息。這些問題預期可以通過控制問答數據的使用方式來解決。
但是,另一類問題從大語言模型的機制上就難以解決。大語言模型中包含的信息越多,回答質量就越好。理論上,我們在訓練大語言模型的時候,或者優化它的時候,希望它具有全局所有的信息。然而,回歸到業務場景,企業內部可能會有密級比較高的文檔,或者說不同人對信息的權限是不一樣的。如果大語言模型擁有了全局的信息,也就包含了高密級的信息,那么沒有權限的用戶就可能通過大語言模型的問答來獲取自己權限以外的信息。使用向量數據庫后,這一問題就可以大大緩解。我們可以通過向量數據庫的管理機制,制定分層權限的知識庫體系。這樣,每個用戶在提問時,只能從自己有權限的知識庫中檢索信息,并將檢索到的信息作為context來優化當前這輪回答。
最后,基于向量數據庫在非結構化數據檢索方面的能力,我們甚至整個行業都認為,向量數據庫將成為整個大模型生態的基礎設施,支撐大模型在業界的推廣和應用。