模式設計實作
資訊檢索 (IR) 系統,也稱為搜尋,對於各種 AI 應用程式來說是不可或缺的,例如檢索增生 (RAG)、圖像搜尋和產品推薦。開發 IR 系統的第一步是設計資料模型,這包括分析業務需求、決定如何組織資訊,以及為資料編制索引,使其在語意上可被搜尋。
Milvus 支援透過集合模式來定義資料模型。集合可組織文本和圖像等非結構化資料,以及它們的向量表示,包括用於語義搜索的各種精確度的密集和稀疏向量。此外,Milvus 還支援儲存和過濾稱為「標量」的非向量資料類型。Scalar 類型包括 BOOL、INT8/16/32/64、FLOAT/DOUBLE、VARCHAR、JSON 和 Array。
為搜尋新聞文章而設計的資料模式範例
搜尋系統的資料模式設計包括分析業務需求,並將資訊抽象為模式表達的資料模式。舉例來說,若要搜尋一段文字,就必須透過「嵌入」(embedding)將字面上的字串轉換成向量,使向量搜尋成為「索引」。除了這個基本要求之外,可能還需要儲存其他屬性,例如出版時間戳和作者。這些元資料允許透過篩選來精細語意搜尋,僅傳回在特定日期之後或由特定作者出版的文字。它們也可能需要與主要文字一起檢索,以便在應用程式中呈現搜尋結果。為了組織這些文字片段,應該為每個片段指定一個唯一的識別碼,以整數或字串表示。這些元素對於達成複雜的搜尋邏輯非常重要。
設計良好的模式非常重要,因為它可以抽象出資料模型,並決定是否可以透過搜尋來達成業務目標。此外,由於插入到資料集中的每一行資料都需要遵循模式,因此對維持資料一致性和長期品質大有幫助。從技術角度來看,定義良好的模式可帶來組織良好的列資料儲存和更乾淨的索引結構,進而提升搜尋效能。
舉例說明:新聞搜尋
假設我們想要為新聞網站建立搜尋功能,而且我們有一個包含文字、縮圖和其他元資料的新聞資料庫。首先,我們需要分析如何利用這些資料來支援搜尋的商業需求。假設需求是根據縮圖和內容摘要擷取新聞,並將作者資訊和發佈時間等元資料作為過濾搜尋結果的條件。這些需求可以進一步細分為
若要透過文字搜尋圖片,我們可以透過多模態嵌入模型將圖片嵌入向量,該模型可以將文字和圖片資料映射到相同的潛在空間中。
透過文字嵌入模型,將文章的摘要文字嵌入向量中。
若要依據發表時間進行篩選,日期會儲存在標量欄位中,並且需要為標量欄位建立索引,以進行有效的篩選。其他更複雜的資料結構,例如 JSON,也可以儲存在標量中,並對其內容執行篩選搜尋 (JSON 索引是即將推出的功能)。
為了擷取圖片縮圖的位元組,並將其呈現在搜尋結果頁面上,圖片的 url 也會被儲存。同樣地,摘要文字和標題也是如此。(如果需要,我們也可以將原始文字和圖片檔案資料儲存為標量欄位)。
為了改善摘要文字的搜尋結果,我們設計了一種混合搜尋方法。對於其中一種檢索路徑,我們使用正規的嵌入模型來從文字產生密集向量,例如 OpenAI 的
text-embedding-3-large
或開放原始碼的bge-large-en-v1.5
。這些模型善於表現文字的整體語意。另一種途徑是使用稀疏嵌入模型,例如 BM25 或 SPLADE 來產生稀疏向量,類似全文檢索,善於掌握文字中的細節和個別概念。由於 Milvus 的多向量功能,它支援在同一資料收集中使用兩者。對多個向量的搜尋可以在單一hybrid_search()
作業中完成。最後,我們還需要一個 ID 欄位來識別每個個別的新聞頁面,在 Milvus 的術語中正式稱為「實體」。這個欄位會被用來做為主索引鍵 (或簡稱 "pk")。
欄位名稱 | article_id (主鍵) | 標題 | 作者資訊 | 出版資訊 | image_url | 圖片向量 | 摘要 | 摘要密度向量 | 摘要稀疏向量 |
---|---|---|---|---|---|---|---|---|---|
類型 | INT64 | VARCHAR | JSON | INT32 | VARCHAR | FLOAT_VECTOR | VARCHAR | FLOAT_VECTOR | 稀疏浮點向量 |
需要索引 | N | N | N (即將支援) | Y | N | Y | N | Y | Y |
如何實作範例模式
建立模式
首先,我們創建一個 Milvus 客戶端實例,用來連接 Milvus 伺服器並管理集合和資料。
要建立模式,我們使用 create_schema()
來建立模式物件,並使用 add_field()
來新增欄位到模式。
from pymilvus import MilvusClient, DataType
collection_name = "my_collection"
# client = MilvusClient(uri="http://localhost:19530")
client = MilvusClient(uri="./milvus_demo.db")
schema = MilvusClient.create_schema(
auto_id=False,
)
schema.add_field(field_name="article_id", datatype=DataType.INT64, is_primary=True, description="article id")
schema.add_field(field_name="title", datatype=DataType.VARCHAR, max_length=200, description="article title")
schema.add_field(field_name="author_info", datatype=DataType.JSON, description="author information")
schema.add_field(field_name="publish_ts", datatype=DataType.INT32, description="publish timestamp")
schema.add_field(field_name="image_url", datatype=DataType.VARCHAR, max_length=500, description="image URL")
schema.add_field(field_name="image_vector", datatype=DataType.FLOAT_VECTOR, dim=768, description="image vector")
schema.add_field(field_name="summary", datatype=DataType.VARCHAR, max_length=1000, description="article summary")
schema.add_field(field_name="summary_dense_vector", datatype=DataType.FLOAT_VECTOR, dim=768, description="summary dense vector")
schema.add_field(field_name="summary_sparse_vector", datatype=DataType.SPARSE_FLOAT_VECTOR, description="summary sparse vector")
您可能會注意到MilvusClient
中的參數uri
,它是用來連線到 Milvus 伺服器的。您可以如下設定這些參數。
如果您只需要一個本機向量資料庫來進行小規模的資料或原型製作,將 uri 設定為一個本機檔案,例如
./milvus.db
,是最方便的方法,因為它會自動利用Milvus Lite將所有資料儲存在這個檔案中。如果您有大規模的資料,例如超過一百萬個向量,您可以在Docker 或 Kubernetes 上架設效能更高的 Milvus 伺服器。在此設定中,請使用伺服器位址和連接埠作為您的 uri,例如
http://localhost:19530
。如果您啟用 Milvus 的驗證功能,請使用「<your_username>:<your_password>」作為令牌,否則請勿設定令牌。如果您使用Zilliz Cloud(Milvus 的完全管理雲端服務),請調整
uri
和token
,它們對應於 Zilliz Cloud 中的Public Endpoint 和 API key。
至於auto_id
在MilvusClient.create_schema
,AutoID 是主要欄位的屬性,決定是否啟用主要欄位的自動遞增。 由於我們設定欄位article_id
為主索引鍵,並希望手動新增文章 id,因此我們設定auto_id
False 來停用此功能。
將所有欄位加入模式物件後,我們的模式物件與上表中的項目一致。
定義索引
使用各種欄位定義模式之後,包括圖片和摘要資料的元資料和向量欄位,下一步就是準備索引參數。索引對於最佳化向量的搜尋和擷取、確保有效率的查詢效能至關重要。在下一節中,我們將為集合中指定的向量和標量欄位定義索引參數。
index_params = client.prepare_index_params()
index_params.add_index(
field_name="image_vector",
index_type="AUTOINDEX",
metric_type="IP",
)
index_params.add_index(
field_name="summary_dense_vector",
index_type="AUTOINDEX",
metric_type="IP",
)
index_params.add_index(
field_name="summary_sparse_vector",
index_type="SPARSE_INVERTED_INDEX",
metric_type="IP",
)
index_params.add_index(
field_name="publish_ts",
index_type="INVERTED",
)
一旦設定並套用索引參數,Milvus 就能優化處理向量和標量資料的複雜查詢。此索引可增強資料集中類似性搜尋的效能與精確度,讓我們能根據影像向量與摘要向量有效率地檢索文章。透過利用 AUTOINDEX
對於密集向量、 SPARSE_INVERTED_INDEX
對稀疏向量和 INVERTED_INDEX
for 標量,Milvus 可以快速識別並傳回最相關的結果,大幅改善資料擷取過程的整體使用者經驗與效能。
索引和指標有許多種類。關於它們的更多資訊,您可以參考Milvus 索引類型和Milvus 度量類型。
建立資料庫
定義模式和索引後,我們使用這些參數建立一個「集合」。對 Milvus 來說,集合就像關係資料庫的資料表。
client.create_collection(
collection_name=collection_name,
schema=schema,
index_params=index_params,
)
我們可以透過描述集合來驗證集合是否已成功建立。
collection_desc = client.describe_collection(
collection_name=collection_name
)
print(collection_desc)
其他注意事項
載入索引
在 Milvus 中建立資料集時,您可以選擇立即載入索引,或是延遲到大量擷取某些資料之後。通常情況下,您不需要對此做出明確的選擇,因為上面的示例顯示,索引會在集合創建後立即自動為任何擷取的資料建立。這樣就可以立即搜尋擷取的資料。但是,如果您在建立資料集後有大量的大量插入,並且在某一點之前不需要搜尋任何資料,您可以在建立資料集時省略 index_params 來延遲索引建立,並且在擷取所有資料後,明確呼叫 load 來建立索引。此方法對於在大型集合上建立索引更有效率,但在呼叫 load() 之前無法進行任何搜尋。
如何為多租戶定義資料模型
多租戶的概念常用於單一軟體應用程式或服務需要服務多個獨立使用者或組織的情況,每個使用者或組織都有自己獨立的環境。這種情況常見於雲端運算、SaaS (軟體即服務) 應用程式和資料庫系統。舉例來說,雲端儲存服務可能會利用多租用權,讓不同的公司在共用相同底層基礎架構的同時,分別儲存和管理他們的資料。此方法可最大化資源利用率和效率,同時確保每個租戶的資料安全性和隱私。
區分租戶的最簡單方法就是將他們的資料和資源彼此隔離。每個租戶可以獨佔存取特定資源,或與其他租戶共享資源,以管理 Milvus 實體,例如資料庫、集合和分割。有特定的方法與這些實體結盟,以實現 Milvus 多重租戶。您可以參考Milvus 多重租用頁面以獲得更多資訊。