在谷歌出現之前,網際網路主要是文本。 無論是新聞更新、體育比分、部落格文章還是電子郵件,ASCII 和 Unicode 都是正确的選擇。
推薦:用 NSDT場景設計器 快速搭建3D場景。
但如今,資料變得越來越複雜和多模式,大多以圖像、視訊、文本、3D 網格等非結構化形式出現。限制在 26 個字元和 10 個數字(或其他字元集更多)的日子已經一去不複返了 . 現在有更多的事情要處理。
想想你最喜歡的 YouTube 視訊、Spotify 歌曲或遊戲 NPC。
典型的資料庫無法處理這些類型的多模式資料。 它們隻能存儲和處理結構化資料(如簡單的文本字元串或數字)。 這确實限制了我們從 21 世紀的大量資料中提取有價值的商業見解和價值的能力。
幸運的是,機器學習技術和近似最近鄰搜尋的最新進展使得更好地利用非結構化資料成為可能:
- 深度學習模型和表示學習使用向量嵌入有效表示複雜資料。
- 矢量資料庫利用矢量嵌入來存儲和分析非結構化資料。
1、矢量資料庫?
矢量資料庫是一種可以使用矢量索引和檢索資料的資料庫,類似于傳統資料庫如何使用鍵或文本來使用索引搜尋項目。
矢量資料庫使用矢量索引實作矢量的快速檢索和插入,并提供典型的資料庫特性,如 CRUD 操作、過濾和可擴充性。
這為我們提供了兩全其美的優勢——我們獲得了傳統資料庫的 CRUD能力,以及存儲複雜的非結構化資料(如圖像、視訊和 3D 網格)的能力。
那麼,矢量資料庫很棒,對吧? 更棒的是擁有一個庫來使用它們,同時能夠同時處理非結構化資料! 一個非結構化資料庫來統領一切!
當然,我們正在談論 DocArray。 讓我們看看這個項目是關于什麼的。
2、DocArray
正如項目首頁上的描述所暗示的那樣,DocArray 是一個用于嵌套、非結構化和多模态資料的庫。
這意味着如果你想處理非結構化資料并将其表示為向量,DocArray 非常适合你。
DocArray 也是許多矢量資料庫的通用入口點。
對于本文的其餘部分,我們将使用 DocArray 在 Amazon Berkeley Objects 資料集中索引和搜尋資料。 此資料集包含帶有圖像和中繼資料(例如品牌、國家/地區和顔色)的産品項目,代表電子商務網站的庫存。
傳統資料庫雖然可以對中繼資料進行過濾,但無法搜尋圖像資料或其他非結構化資料格式。 這就是我們使用矢量資料庫的原因!
我們首先将 CSV 格式的 Amazon Berkeley 對象資料集的一個子集加載到 DocArray 中并計算向量嵌入。
然後,我們将對每個資料庫使用 DocArray,以使用向量執行搜尋和插入操作。
我們将在 Python 中通過 DocArray 使用以下資料庫:
- Milvus - 存儲計算分離的雲原生矢量資料庫
- Weaviate - 存儲對象和矢量的矢量搜尋引擎,可以通過 REST 或 GraphQL 通路
- Qdrant - 用 Rust 編寫的矢量資料庫,旨在在高負載下快速可靠
- Redis - 記憶體鍵值資料庫,支援具有向量搜尋功能的不同類型的資料結構
- ElasticSearch - 具有近似最近鄰搜尋功能的分布式 RESTful 搜尋引擎
- OpenSearch - 基于 Apache Lucene 的開源搜尋軟體,最初是從 ElasticSearch 派生出來的
- AnnLite - 一個具有過濾功能的快速近似最近鄰搜尋的 Python 庫
對于每個資料庫,我們将:
- 設定資料庫和安裝要求
- 索引矢量資料庫中的資料
- 執行帶過濾的矢量搜尋操作
- 顯示搜尋結果
3、準備資料
首先,我們将安裝一些依賴項,即 DocArray、Jina(用于雲身份驗證)和 CLIP-as-service 用戶端(用于生成嵌入):
pip install docarray[common] jina clip-client
讓我們下載下傳一個示例 CSV 資料集并使用 DocumentArray.from_csv() 将其加載到 DocumentArray 中:
wget https://github.com/jina-ai/product-recommendation-redis-docarray/raw/main/data/dataset.csv
from docarray import DocumentArray, Document
with open('dataset.csv') as fp:
da = DocumentArray.from_csv(fp)
我們使用 summary() 方法得到一個概覽:
╭────────────────────── Documents Summary ──────────────────────╮
│ │
│ Type DocumentArrayInMemory │
│ Length 5809 │
│ Homogenous Documents True │
│ Common Attributes ('id', 'mime_type', 'uri', 'tags') │
│ Multimodal dataclass False │
│ │
╰───────────────────────────────────────────────────────────────╯
╭───────────────────── Attributes Summary ─────────────────────╮
│ │
│ Attribute Data type #Unique values Has empty value │
│ ────────────────────────────────────────────────────────── │
│ id ('str',) 5809 False │
│ mime_type ('str',) 1 False │
│ tags ('dict',) 5809 False │
│ uri ('str',) 4848 False │
│ │
╰──────────────────────────────────────────────────────────────╯
我們還可以使用 plot_image_sprites() 方法顯示前幾項的圖像:
da[:12].plot_image_sprites()
每個産品都将中繼資料作為 tags 屬性中的字典包含:
da[0].tags
{'height': '1926',
'color': 'Blue',
'country': 'CA',
'width': '1650',
'brand': 'Thirty Five Kent'}
4、生成嵌入
接下來,我們将使用 Clip-as-service 将文檔編碼為向量。
首先,我們需要登入 Jina AI雲:
jina auth login
讓我們建立一個身份驗證令牌來使用該服務:
jina auth token create abo -e 30
然後,我們實際上可以使用該服務來生成嵌入:
from clip_client import Client
c = Client(
'grpcs://api.clip.jina.ai:2096', credential={'Authorization': 'your-auth-token'}
)
encoded_da = c.encode(da, show_progress=True)
5、準備搜尋檔案
如果要搜尋我們的資料庫,我們需要一些東西。 與 DocArray 中的所有内容一樣,基本機關是文檔。 是以,讓我們準備一個用于搜尋的查詢文檔。 我們将隻選擇資料集中的第一個産品:
doc = encoded_da[0]
doc.display()
6、索引資料
現在資料已準備就緒,我們可以對其進行索引并開始執行搜尋查詢。 在接下來的部分中,我們将對每個支援的資料庫進行索引。
6.1 Milvus
Milvus 是一個開源矢量資料庫,旨在為嵌入相似性搜尋和 AI 應用程式提供支援。 它是一個雲原生資料庫,存儲和計算在設計上是分離的。
這意味着可以單獨縮放每個層。 是以,Milvus 提供了一個可擴充且可靠的架構。
使用以下 YAML 啟動 Milvus 服務:
version: '3.5'
services:
etcd:
container_name: milvus-etcd
image: quay.io/coreos/etcd:v3.5.0
environment:
- ETCD_AUTO_COMPACTION_MODE=revision
- ETCD_AUTO_COMPACTION_RETENTION=1000
- ETCD_QUOTA_BACKEND_BYTES=4294967296
- ETCD_SNAPSHOT_COUNT=50000
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/etcd:/etcd
command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
minio:
container_name: milvus-minio
image: minio/minio:RELEASE.2022-03-17T06-34-49Z
environment:
MINIO_ACCESS_KEY: minioadmin
MINIO_SECRET_KEY: minioadmin
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/minio:/minio_data
command: minio server /minio_data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
standalone:
container_name: milvus-standalone
image: milvusdb/milvus:v2.1.4
command: ["milvus", "run", "standalone"]
environment:
ETCD_ENDPOINTS: etcd:2379
MINIO_ADDRESS: minio:9000
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus
ports:
- "19530:19530"
- "9091:9091"
depends_on:
- "etcd"
- "minio"
networks:
default:
name: milvus
docker-compose up
然後,建立一個連接配接到 Milvus 的 DocumentArray 執行個體。 確定使用 milvus 标簽安裝 DocArray:
pip install "docarray[milvus]"
milvus_da = DocumentArray(storage='milvus', config={
'n_dim': 768,
'columns': {
'color': 'str',
'country': 'str',
'width': 'int',
'height': 'int',
'brand': 'str',
}
})
# Index data
with milvus_da:
milvus_da.extend(encoded_da)
現在,使用 filter color='Blue' 搜尋類似于 doc 的項目:
filter = 'color == "Blue"'
results = milvus_da.find(doc,filter=filter, limit=5)
results[0].plot_image_sprites()
作為 LFAI & Data 的一部分,Milvus 代表了一個生産就緒的雲原生矢量資料庫。
6.2 Weaviate
Weaviate 是一個開源矢量搜尋引擎,它同時存儲對象和矢量,允許将矢量搜尋與結構化過濾相結合。
它提供容錯和可伸縮性等功能,可以通過 REST 或 GraphQL 通路。
使用以下 YAML 啟動 Weaviate 伺服器:
version: '3.4'
services:
weaviate:
command:
- --host
- 0.0.0.0
- --port
- '8080'
- --scheme
- http
image: semitechnologies/weaviate:1.16.1
ports:
- "8080:8080"
restart: on-failure:0
environment:
QUERY_DEFAULTS_LIMIT: 25
AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'true'
PERSISTENCE_DATA_PATH: '/var/lib/weaviate'
DEFAULT_VECTORIZER_MODULE: 'none'
ENABLE_MODULES: ''
CLUSTER_HOSTNAME: 'node1'
docker-compose up
然後,建立一個連接配接到 Weaviate 的 DocumentArray 執行個體。 確定使用 weaviate 标簽安裝 DocArray:
pip install "docarray[weaviate]"
weaviate_da = DocumentArray(storage='weaviate', config={
'n_dim': 768,
'columns': {
'color': 'str',
'country': 'str',
'product_type': 'str',
'width': 'int',
'height': 'int',
'brand': 'str',
}
})
# Index data
weaviate_da.extend(encoded_da)
現在,使用 filter color='Blue' 搜尋類似于 doc 的項目:
filter = {'path': 'color', 'operator': 'Equal', 'valueString': 'Blue'}
results = weaviate_da.find(doc,filter=filter, limit=5)
results[0].plot_image_sprites()
是以,Weaviate 提供具有過濾支援和複制、混合搜尋、動态批處理等功能的矢量搜尋功能。
6.3 Qdrant
Qdrant 是一個開源矢量資料庫。 用 Rust 編寫,即使在高負載下也能提供快速可靠的搜尋體驗。 實際上,它在 DocArray 的一百萬個基準測試中被列為最快的磁盤矢量資料庫(截至用于進行實驗的版本)。
Qdrant 帶有過濾支援和使用 HTTP 或 gRPC 的便捷 API。
使用以下 YAML 啟動 Qdrant 伺服器:
version: '3.4'
services:
qdrant:
image: qdrant/qdrant:v0.10.1
ports:
- "6333:6333"
- "6334:6334"
ulimits: # Only required for tests, as there are a lot of collections created
nofile:
soft: 65535
hard: 65535
docker-compose up
然後,建立一個連接配接到 Qdrant 的 DocumentArray 執行個體。 確定使用 qdrant 标簽安裝 DocArray:
qdrant_da = DocumentArray(storage='qdrant', config={
'n_dim': 768,
'columns': {
'color': 'str',
'country': 'str',
'product_type': 'str',
'width': 'int',
'height': 'int',
'brand': 'str',
}
})
# Index data
qdrant_da.extend(encoded_da)
現在,使用 filter color='Blue' 搜尋類似于 doc 的項目:
filter = {'must': [{'key': 'color', 'match': {'value': 'Blue'}}]}
results = qdrant_da.find(doc,filter=filter, limit=5)
results[0].plot_image_sprites()
Qdrant 提供快速可靠的搜尋服務。 它支援大規模過濾和矢量搜尋。
它的 gRPC 支援也使得批量索引變得友善,因為使用 gRPC 索引資料集比使用 HTTP 協定快得多。
6.4 Redis
Redis 是一個開源的記憶體鍵值資料庫。 Redis 支援不同類型的資料結構,并使用一組使用 TCP 套接字的指令提供通路。
在其 RediSearch 子產品 2.4 中,Redis 添加了矢量搜尋功能。 這意味着 Redis 可以被視為記憶體中的矢量資料庫。
使用以下 YAML 啟動 Redis 伺服器:
docker run -d -p 6379:6379 redis/redis-stack:latest
然後,建立一個連接配接到 Redis 的 DocumentArray 執行個體。 確定使用 redis 标簽安裝 DocArray:
pip install "docarray[redis]"
redis_da = DocumentArray(storage='redis', config={
'n_dim': 768,
'columns': {
'color': 'str',
'country': 'str',
'product_type': 'str',
'width': 'int',
'height': 'int',
'brand': 'str',
}
})
# Index data
redis_da.extend(encoded_da)
現在,使用 filter color='Blue' 搜尋類似于 doc 的項目:
filter = '@color:Blue'
results = redis_da.find(doc,filter=filter, limit=5)
results[0].plot_image_sprites()
由于 Redis 是記憶體存儲,是以與磁盤資料庫相比,它提供更快的搜尋查詢。 它在 DocArray 的一百萬個基準測試中被列為最快的資料庫伺服器。
如果你需要對矢量資料庫進行快速矢量搜尋和操作,同時能夠索引記憶體中的資料,請使用它。
6.5 ElasticSearch
ElasticSearch 是一個開源、分布式和 RESTful 搜尋引擎。 它可用于搜尋、存儲和管理資料。ElasticSearch 在 Elasticsearch 8.0 中引入了近似最近鄰搜尋。這意味着任何版本 > 8.0 的 ElasticSearch Server 都具有矢量搜尋功能。
使用以下 YAML 啟動 ElasticSearch 伺服器:
version: "3.3"
services:
elastic:
image: docker.elastic.co/elasticsearch/elasticsearch:8.2.0
environment:
- xpack.security.enabled=false
- discovery.type=single-node
ports:
- "9200:9200"
networks:
- elastic
networks:
elastic:
name: elastic
docker-compose up
然後,建立一個連接配接到 ElasticSearch 的 DocumentArray 執行個體。 確定使用 elasticsearch 标簽安裝 DocArray:
pip install "docarray[elasticsearch]"
elasticsearch_da = DocumentArray(storage='elasticsearch', config={
'n_dim': 768,
'columns': {
'color': 'str',
'country': 'str',
'product_type': 'str',
'width': 'int',
'height': 'int',
'brand': 'str',
}
})
# Index data
elasticsearch_da.extend(encoded_da, request_timeout=60)
現在,使用 filter color='Blue' 搜尋類似于 doc 的項目:
filter = {'match': {'color': 'Blue'}}
results = elasticsearch_da.find(doc,filter=filter, limit=5)
results[0].plot_image_sprites()
ElasticSearch 便于生産用例。 它提供可擴充性、資料分布、過濾、混合搜尋等功能。它具有安全性、可觀察性和雲原生性。
6.6 OpenSearch
OpenSearch 是一個可縮放、靈活且可擴充的開源搜尋程式,在 Apache 2.0 下獲得許可。
OpenSearch 由 Apache Lucene 提供支援,最初是從 ElasticSearch 派生出來的。 這意味着 OpenSearch 包含 ElasticSearch 的大部分功能。
與 ElasticSearch 一樣,OpenSearch 包括近似最近鄰搜尋,允許它執行向量相似性搜尋。
使用以下 YAML 啟動 OpenSearch 伺服器:
version: "3.3"
services:
opensearch:
image: opensearchproject/opensearch:2.4.0
environment:
- plugins.security.disabled=true
- discovery.type=single-node
ports:
- "9900:9200"
networks:
- os
networks:
os:
name: os
docker-compose up
然後,建立一個連接配接到 ElasticSearch 的 DocumentArray 執行個體。 確定使用 opensearch 标簽安裝 DocArray:
pip install "docarray[opensearch]"
opensearch_da = DocumentArray(storage='opensearch', config={
'n_dim': 768,
'columns': {
'color': 'str',
'country': 'str',
'product_type': 'str',
'width': 'int',
'height': 'int',
'brand': 'str',
}
})
# Index data
opensearch_da.extend(encoded_da)
現在,使用 filter color='Blue' 搜尋類似于 doc 的項目:
filter = {'match': {'color': 'Blue'}}
results = opensearch_da.find(doc,filter=filter, limit=5)
results[0].plot_image_sprites()
與 ElasticSearch 一樣,OpenSearch 便于生産用例。 它還提供與 AWS 雲的更好內建。 OpenSearch 還擁有比 ElasticSearch 更開放的許可證。
6.7 AnnLite
AnnLite 是一個 Python 庫,用于具有過濾功能的快速近似最近鄰搜尋。 由 Jina AI 建構,它作為庫(無用戶端-伺服器架構)提供簡單的矢量搜尋體驗。
要使用 AnnLite,請使用 annlite 标簽安裝 DocArray:
pip install "docarray[annlite]"
annlite_da = DocumentArray(storage='annlite', config={
'n_dim': 768,
'columns': {
'color': 'str',
'country': 'str',
'product_type': 'str',
'width': 'int',
'height': 'int',
'brand': 'str',
}
})
# Index data
annlite_da.extend(encoded_da)
現在,使用 filter color='Blue' 搜尋類似于 doc 的項目:
filter = {'color': {'$eq': 'Blue'}}
results = annlite_da.find(doc,filter=filter, limit=5)
results[0].plot_image_sprites()
AnnLite 易于安裝和使用。 通過 DocArray,它提供了具有過濾功能的出色本地矢量搜尋。 由于它不依賴于用戶端-伺服器架構,是以沒有網絡開銷,但它實作了 HNSW 以進行快速矢量搜尋。
7、結束語
矢量資料庫使我們能夠有效地利用非結構化資料并從中提取有用的見解。 他們可以執行向量搜尋,這對相似性比對、推薦、分析等很有用。
根據你的資源、用例和要求,選擇正确的資料庫可能具有挑戰性。 例如,你會為高速與低記憶體選擇不同的資料庫。
為了幫助你做出決定,我們釋出了使用 DocArray 的矢量資料庫的基準測試。 也就是說,你可能需要測試一些資料庫才能找到你的比對項。
通常情況下,測試意味着在使用之前學習每個資料庫,這需要花費大量時間和精力。 但是使用 DocArray 的統一 API,可以以相同的方式與所有這些資料庫對話。 隻需要更改一兩行代碼,然後 就可以使用一個新資料庫。
原文連結:http://www.bimant.com/blog/docarray-entry-of-vector-dbs/