今年AI大模型應(yīng)用呈井噴式發(fā)展,其中,LangChain、Haystack等端到端大語言模型應(yīng)用框架更是將向量數(shù)據(jù)庫推出了新熱點。
向量數(shù)據(jù)庫(vector database,也有人稱矢量數(shù)據(jù)庫),簡單地說,它們是以向量格式管理、存儲和檢索數(shù)據(jù)的數(shù)據(jù)庫。
為什么向量數(shù)據(jù)庫對AI如此重要?
因為它在處理高維數(shù)據(jù)方面具有先天優(yōu)勢,從圖像處理到推薦系統(tǒng),向量數(shù)據(jù)庫無疑是幕后的英雄。它的主要功能包括:
- 管理:向量數(shù)據(jù)庫以原始數(shù)據(jù)形式處理數(shù)據(jù),能夠有效地組織和管理數(shù)據(jù),便于AI模型應(yīng)用。
- 存儲:能夠存儲向量數(shù)據(jù),包括各種AI模型需要使用到的高維數(shù)據(jù)。
- 檢索:向量數(shù)據(jù)庫特別擅長高效地檢索數(shù)據(jù),這一個特點能夠確保AI模型在需要的時候快速獲得所需的數(shù)據(jù)。這也是向量數(shù)據(jù)庫能夠在一些推薦系統(tǒng)或者檢索系統(tǒng)中得到應(yīng)用的重要原因。
因此,我們說向量數(shù)據(jù)庫讓AI有了記憶,這個記憶不僅僅是記錄存儲、也包括檢索和管理。就像人類的記憶一樣,我們通過同學的畢業(yè)照總是能夠認得這個人是誰;我們在和朋友聊天的時候也常常會一起回憶過去。
那么向量數(shù)據(jù)庫是如何工作的?
向量數(shù)據(jù)庫的核心是通過使用數(shù)學模型來管理向量數(shù)據(jù)。
那么什么又是向量?簡單地說,向量是一個既有方向又有大小的數(shù)字對象。在向量數(shù)據(jù)庫中,向量可以用于表示復(fù)雜的數(shù)據(jù),例如:圖像、文本。
每個數(shù)據(jù)片段都被轉(zhuǎn)換成高維空間中的向量管理起來。當我們需要查找相似的數(shù)據(jù)片段時,數(shù)據(jù)庫不需要遍歷篩選選每個條目。而是通過計算向量之間的距離來匹配,向量越接近,數(shù)據(jù)就越相似。這種方式非常高效,通過這種方式檢索數(shù)據(jù)可以比傳統(tǒng)關(guān)系型數(shù)據(jù)庫更快地處理大批量數(shù)據(jù)。
下面是個文本向量存儲的示例圖:
下面是圖片向量化存儲與檢索的示例圖:
大家都知道,通用大模型的運行涉及巨大的計算資源,因此許多大模型都基于MaaS,私有化成本很高。與之相矛盾的是在具體行業(yè)大模型應(yīng)用中往往對數(shù)據(jù)安全要求高,并且需要與相關(guān)業(yè)務(wù)或領(lǐng)域知識深入融合,才能做到安全、專業(yè)。LangChain等大模型應(yīng)用框架為行業(yè)大模型應(yīng)用提供了一個經(jīng)典解決方案,而開源的向量數(shù)據(jù)庫又為LangChain等大模型應(yīng)用解決方案提供了基礎(chǔ)支撐,其實向量數(shù)據(jù)庫在許多應(yīng)用場景(如:企業(yè)知識庫、推薦系統(tǒng)、檔案管理等)也非常有用。因此,向量數(shù)據(jù)庫也成為大模型應(yīng)用發(fā)展的一個熱門技術(shù)。
八個優(yōu)秀的開源向量數(shù)據(jù)庫項目
開源社區(qū)對向量數(shù)據(jù)庫的發(fā)展功不可沒,許多開源向量數(shù)據(jù)庫項目在性能、靈活性和魯棒性方面表現(xiàn)都非常優(yōu)秀,下面列舉8個目前最佳的開源向量數(shù)據(jù)庫項目,這些開業(yè)項目應(yīng)該能夠為你的AI解決方案提供最佳技術(shù)選型。
1.Milvus
https://Github.com/milvus-io/milvus
Milvus是由Zilliz提供的一個高度可定制的開源向量數(shù)據(jù)庫,旨在為嵌入式相似性搜索等AI應(yīng)用提供支持。目前Milvus已經(jīng)發(fā)布了 2.0 ,Milvus 2.0是一個云原生向量數(shù)據(jù)庫,設(shè)計上采用存儲、計算分離。Milvus2.0中的所有組件都支持無狀態(tài),這樣做就使得整個的應(yīng)用更加靈活而有彈性。
Milvus建立在Faiss、Annoy、HNSW等主流向量搜索庫之上,旨在對包含數(shù)百萬、數(shù)十億甚至數(shù)萬億個向量的密集向量數(shù)據(jù)集進行相似性搜索。
Milvus還支持數(shù)據(jù)分片、數(shù)據(jù)持久化、流數(shù)據(jù)攝取、向量和標量數(shù)據(jù)之間的混合搜索以及許多其他高級功能。建議使用Kube.NETes部署Milvus,以獲得最佳可用性和彈性。
Milvus采用共享存儲架構(gòu),存儲、計算分離,具備計算節(jié)點的水平可擴展性。遵循數(shù)據(jù)平面和控制平面分解原則,Milvus包括四層:接入層、協(xié)調(diào)服務(wù)、工作節(jié)點和存儲。在擴展或災(zāi)難恢復(fù)方面,這些層可以做到相互獨立。
下面是Milvus的架構(gòu)圖。
Milvus的主要特性包括:
- 支持萬億向量數(shù)據(jù)集上的毫秒級搜索:在萬億向量數(shù)據(jù)集上測試平均延遲(毫秒級)。
- 簡化的非結(jié)構(gòu)化數(shù)據(jù)管理:豐富API、跨客戶端一致的用戶體驗。
- 始終保持高可靠性:Milvus的內(nèi)置復(fù)制和故障轉(zhuǎn)移/回切功能可確保數(shù)據(jù)和應(yīng)用程序在發(fā)生中斷時保持業(yè)務(wù)連續(xù)性。
- 高度可擴展和彈性性能:組件級的可伸縮性使其可以按需伸縮。Milvus可以根據(jù)負載類型在組件級別自動縮放,使資源調(diào)度更加高效。
- 混合搜索能力:除了向量,Milvus還支持“布爾類型”、“整數(shù)”、“浮點數(shù)”等數(shù)據(jù)類型。
- 統(tǒng)一Lambda結(jié)構(gòu):Milvus將流和批處理結(jié)合起來進行數(shù)據(jù)存儲,以平衡及時性和效率。它的統(tǒng)一界面使向量相似性搜索變得輕而易舉。強大的社區(qū)支持和行業(yè)的認可:擁有超過1000個企業(yè)用戶,GitHub超23K Star,以及活躍的開源社區(qū)。
更多內(nèi)容可以參考官網(wǎng):https://milvus.io
Demo:https://milvus.io/milvus-demos/
文檔: https://milvus.io/docs
2.Faiss
https://github.com/facebookresearch/faiss
Faiss由Facebook的AI Research團隊開發(fā)的向量數(shù)據(jù)庫,在高維矢量搜索方面表現(xiàn)出色。是一個搜索效率非常突出的向量庫,這也使其成為一些實時性要求高的應(yīng)用程序的絕佳選擇。Faiss是一個高效的相似性搜索和密集向量聚類庫。它包含的算法可以搜索任何大小的向量集,甚至多達超過RAM的向量大小。它還包含用于評估和參數(shù)調(diào)整的支持代碼。Faiss是用C++編寫的,帶有Python/ target=_blank class=infotextkey>Python/numpy的完整包裝,一些常用的算法是在GPU上實現(xiàn)的。
Faiss是通過存儲一組向量的索引,并提供了一個函數(shù)在它們當中進行比較,從而實現(xiàn)搜索。
目前Faiss在GitHub上的Star已經(jīng)超過24K。
基于CPU、GPU的python安裝方法如下:
$ conda install -c pytorch faiss-cpu
$ conda install -c pytorch faiss-gpu
以上只能安裝一個,不能同時安裝兩個,因為后者是前者的超集。
3.Annoy
https://github.com/spotify/annoy
Annoy (Approximate Nearest Neighbors Oh Yeah)是由Spotify創(chuàng)建的一個輕量級且功能強大的向量數(shù)據(jù)庫。它專為快速搜索大型數(shù)據(jù)集而設(shè)計,非常適合需要快速響應(yīng)的應(yīng)用。它是一個C++庫,但支持在Python中使用。
它通過創(chuàng)建大型的只讀文件數(shù)據(jù)結(jié)構(gòu),并將這些數(shù)據(jù)結(jié)構(gòu)映射到內(nèi)存中,以便許多進程可以共享相同的數(shù)據(jù)。
ANNOY的核心是一種基于隨機投影和樹的算法。它由Erik Bernhardsson于2015年在Spotify工作時開發(fā)。ANNOY設(shè)計目標是實現(xiàn)在100到1000個密集維度的數(shù)據(jù)集中進行搜索。為了計算最近的鄰居,它將點集分成兩半,并遞歸地進行,直到每個集合都有k個項目。通常k應(yīng)該在100左右(見下圖)。
關(guān)于Annoy的主要特征官方介紹如下:
- 支持多種相似算法:歐氏距離、曼哈頓距離、余弦距離、漢明距離、內(nèi)積距離。余弦距離等價于歸一化向量的歐幾里得距離= sqrt(2-2*cos(u,v))
- 如果你沒有太多的維度(比如<=100),效果會更好,但即使是1000維的維度,它的表現(xiàn)也還是非常優(yōu)秀。
- 內(nèi)存占用小
- 允許在多個進程之間共享內(nèi)存
- 索引創(chuàng)建與查找是分開的(特別是,一旦創(chuàng)建了樹,就不能添加更多的項)
- 原生Python支持,已在2.7、3.6和3.7中測試。
- 在磁盤上構(gòu)建索引,以便索引無法放入內(nèi)存的大數(shù)據(jù)集
python語言下的安裝annoy:
pip install annoy
python語言下的使用annoy:
from annoy import AnnoyIndex
import random
f = 40 # Length of item vector that will be indexed
t = AnnoyIndex(f, 'angular')
for i in range(1000):
v = [random.gauss(0, 1) for z in range(f)]
t.add_item(i, v)
t.build(10) # 10 trees
t.save('test.ann')
# ...
u = AnnoyIndex(f, 'angular')
u.load('test.ann') # super fast, will just mmap the file
print(u.get_nns_by_item(0, 1000)) # will find the 1000 nearest neighbors
4.Nmslib
https://github.com/nmslib/nmslib
Nmslib (Non-Metric Space Library)是一個于非度量空間的開源向量數(shù)據(jù)庫。是一個高效的跨平臺相似性搜索庫,也是一個評估相似性搜索方法的工具包,并且它的核心庫沒有任何第三方依賴項。
該項目的目標是創(chuàng)建一個用于能夠在通用以及非度量空間中進行搜索的全面工具包,包括:通用搜索方法、近似搜索方法、各種度量空間訪問方法以及非度量空間的方法。
Nmslib是一個可擴展的庫,可以添加新的搜索方法和距離函數(shù)。支持在C++和Python、JAVA中使用,例如:可以使用Java等語言構(gòu)建一個查詢服務(wù)器。
5.Qdrant
https://github.com/qdrant/qdrant
Qdrant是一個包含向量數(shù)據(jù)庫和向量相似度搜索引擎的開源項目。它提供了一組便捷的API來執(zhí)行存儲、搜索和管理向量數(shù)據(jù),并且能夠同時存儲payload數(shù)據(jù),這就有利于自定義的數(shù)據(jù)過濾,這個方面在各種神經(jīng)網(wǎng)絡(luò)、基于語義的匹配、分面搜索、精準推薦等應(yīng)用程序非常有用。
Qdrant是用Rust語言開發(fā)的,因此它能在高負載下也具備高效、可靠特性。Qdrant的使用非常簡單:
(1)使用Docker啟動
docker run -p 6333:6333 qdrant/qdrant
br
(2)在python中使用
安裝:
pip install qdrant-client
連接:
from qdrant_client import QdrantClient
qdrant = QdrantClient("http://localhost:6333") # Connect to existing Qdrant instance, for production
qdrant的特點如下:
- 過濾和有效數(shù)據(jù):Qdrant使JSON格式存儲Payload(有效數(shù)據(jù))與向量相關(guān)聯(lián),支持should、must和must_not條件的各種組合檢索方式,確保能夠檢索所有向量,這點與ElasticSearch的后過濾不同。
- 支持豐富的數(shù)據(jù)類型:Payload適應(yīng)不同的數(shù)據(jù)類型和查詢條件,包括字符串匹配、數(shù)值范圍、地理位置等。這些篩選條件使您能夠在相似性匹配的基礎(chǔ)上創(chuàng)建自定義業(yè)務(wù)邏輯。
- 查詢計劃和Payload索引:查詢規(guī)劃器利用存儲的Payload信息來優(yōu)化查詢。
- 硬件加速:利用現(xiàn)代CPU x86-x64架構(gòu),Qdrant在現(xiàn)代硬件上提供更快的搜索性能。
- 寫入前記錄日志:Qdrant通過更新確認確保數(shù)據(jù)的持久性,即使在停電期間也是如此。更新日志存儲所有操作,從而可以輕松地重建最新的數(shù)據(jù)庫狀態(tài)。
- 分布式部署:從v0.8.0開始,Qdrant支持分布式部署。多個Qdrant機器形成一個集群,通過Raft協(xié)議進行協(xié)調(diào),以進行水平擴展。
- 獨立運行:Qdrant支持獨立運行,不依賴外部數(shù)據(jù)庫或編排控制器,簡化了配置。
6.Chroma
https://github.com/chroma-core/chroma
Chroma是一個開源嵌入式向量數(shù)據(jù)庫。基于Chroma可以輕松構(gòu)建LLM應(yīng)用程序。Chroma的設(shè)計非常簡單、易用、靈活,可以滿足各種場景下的應(yīng)用。它支持使用第三方的embedding模型執(zhí)行查詢和元數(shù)據(jù)過濾。
下面是Chroma與OpenAI embedding搭配使用的架構(gòu)示意圖:
基于Docker的Chromadb可以參考:
- docker-compose:https://github.com/chroma-core/chroma/blob/main/docker-compose.yml
- dockerFile: https://github.com/chroma-core/chroma/blob/main/Dockerfile
在具體應(yīng)用開發(fā)上,Python下使用Chroma也非常簡單。
安裝:
pip install chromadb
四個核心API的使用:
import chromadb
# setup Chroma in-memory, for easy prototyping. Can add persistence easily!
client = chromadb.Client()
# Create collection. get_collection, get_or_create_collection, delete_collection also available!
collection = client.create_collection("all-my-documents")
# Add docs to the collection. Can also update and delete. Row-based API coming soon!
collection.add(
documents=["This is document1", "This is document2"], # we handle tokenization, embedding, and indexing automatically. You can skip that and add your own embeddings as well
metadatas=[{"source": "notion"}, {"source": "google-docs"}], # filter on these!
ids=["doc1", "doc2"], # unique for each doc
)
# Query/search 2 most similar results. You can also .get by id
results = collection.query(
query_texts=["This is a query document"],
n_results=2,
# where={"metadata_field": "is_equal_to_this"}, # optional filter
# where_document={"$contains":"search_string"} # optional filter
)
Chroma的主要特點包括:
- 簡單:類型完整、測試全面、文檔完整
- 整合:支持LangChain(python和js)、LlamaIndex等等。
- 開發(fā)、測試、生產(chǎn)過程:在python notebook中運行的API可直接應(yīng)用到集群環(huán)境。
- 功能豐富:查詢、過濾、密度估計等
- 免費、開源
7.LanceDB
https://github.com/lancedb/lancedb
LanceDB是一個開源的支持持久存儲的向量搜索數(shù)據(jù)庫,這個開源項目可以大大簡化embeddings的檢索、過濾和管理。
LanceDB的內(nèi)核是用Rust開發(fā)的,并使用Lance構(gòu)建(Lance是一種為高性能ML工作負載設(shè)計的開源列格式)。Python和JavaScript等語言可以使用API操作LanceDB。
Python的使用方式如下:
安裝:
pip install lancedb
檢索:
import lancedb
uri = "data/sample-lancedb"
db = lancedb.connect(uri)
table = db.create_table("my_table",
data=[{"vector": [3.1, 4.1], "item": "foo", "price": 10.0},
{"vector": [5.9, 26.5], "item": "bar", "price": 20.0}])
result = table.search([100, 100]).limit(2).to_df()
LanceDB的主要功能特點如下:
- 無需管理服務(wù)器的生產(chǎn)規(guī)模向量搜索。
- 支持存儲、查詢以及過濾向量、元數(shù)據(jù)和多模態(tài)數(shù)據(jù)(文本、圖像、視頻、點云等)。
- 支持向量相似度搜索、全文檢索和SQL語法。
- 支持Python和JavaScript/Typescript。
- 零拷貝、自動版本控制,無需額外基礎(chǔ)架構(gòu)即可管理數(shù)據(jù)版本。
- 支持基于GPU構(gòu)建向量索引。
- 支持與LangChain?、LlamaIndex、Apache-Arrow、Pandas、Polars、DuckDB等生態(tài)集成。
8.Vectra
https://github.com/Stevenic/vectra
Vectra是一個Node.js的本地向量數(shù)據(jù)庫,其功能類似于Pinecone或Qdrant,但區(qū)別是Vectra使用本地文件構(gòu)建。每個Vectra索引都對應(yīng)磁盤上的一個文件夾。文件夾中包含一個index.json文件,文件內(nèi)容包含索引的所有向量以及這些索引的元數(shù)據(jù)。創(chuàng)建索引時,可以指定索引的元數(shù)據(jù)屬性,只有這些字段才會存儲在index.json文件中。而項目的其他元數(shù)據(jù)將會被保存到一個有GUID指定的文件中。
運行時,整個Vectra索引都被加載到內(nèi)存中,因此它的檢索效率非常高,甚至是實時的,但是它不適合用于類似需要保留長上下文的聊天機器人場景。Vectra更適合用于一些小的語料庫、靜態(tài)數(shù)據(jù)或者一些問答文檔的檢索等應(yīng)用場景。
在Node.js中的使用如下:
安裝:
$ npm install vectra
創(chuàng)建實例:
if (!await index.isIndexCreated()) {
await index.createIndex();
}
創(chuàng)建索引:
import { LocalIndex } from 'vectra';
const index = new LocalIndex(path.join(__dirname, '..', 'index'));
添加數(shù)據(jù)到索引:
import { OpenAIApi, Configuration } from 'openai';
const configuration = new Configuration({
apiKey: `<YOUR_KEY>`,
});
const api = new OpenAIApi(configuration);
async function getVector(text: string) {
const response = await api.createEmbedding({
'model': 'text-embedding-ada-002',
'input': text,
});
return response.data.data[0].embedding;
}
async function addItem(text: string) {
await index.insertItem({
vector: await getVector(text),
metadata: { text }
});
}
// Add items
await addItem('apple');
await addItem('oranges');
await addItem('red');
await addItem('blue');
檢索數(shù)據(jù):
async function query(text: string) {
const vector = await getVector(input);
const results = await index.queryItems(vector, 3);
if (results.length > 0) {
for (const result of results) {
console.log(`[${result.score}] ${result.item.metadata.text}`);
}
} else {
console.log(`No results found.`);
}
}
await query('green');
/*
[0.9036569942401076] blue
[0.8758153664568566] red
[0.8323828606103998] apple
*/
await query('banana');
/*
[0.9033128691220631] apple
[0.8493374123092652] oranges
[0.8415324469533297] blue
*/
總之
以上這些開源向量數(shù)據(jù)庫每一個都有自己獨特的一面。選擇使用哪一款取決于項目的具體需求。如果您正在處理一個需要高速數(shù)據(jù)檢索的項目,那么Annoy可能是最合適的。但如果項目涉及非度量空間,那么Nmslib可能才是首選的。一個合適的向量數(shù)據(jù)庫可以成為AI解決方案當中的記憶海綿體,讓AI不僅能推理還能記憶、檢索,提升AI應(yīng)用的效果。