共用方式為


在 Python 中為 NoSQL 的 Azure Cosmos DB 中的索引和查詢向量

使用向量索引和搜尋之前,您必須先啟用此功能。 本文涵蓋下列步驟:

  1. 在適用於 NoSQL 的 Azure Cosmos DB 中啟用向量搜尋功能
  2. 設定 Azure Cosmos DB 容器以進行向量搜尋
  3. 製作向量內嵌原則
  4. 將向量索引新增至容器索引編製原則
  5. 使用向量索引和向量內嵌原則建立容器
  6. 對儲存的數據執行向量搜尋

本指南會逐步解說建立向量資料、編製資料索引、然後查詢容器中資料的流程。

必要條件

啟用功能

向量搜尋適用於 NoSQL 的 Azure Cosmos DB 需要完成下列步驟來啟用此功能:

  1. 瀏覽至您的 Azure Cosmos DB for NoSQL 資源頁面。

  2. 選取 [設定] 功能表項目下的 [功能] 窗格。

  3. 選取 [適用於 NoSQL 的 Azure Cosmos DB 中的向量搜尋]。

  4. 閱讀功能的描述,以確認您想要啟用此功能。

  5. 選取 [啟用] 以在適用於 NoSQL 的 Azure Cosmos DB 中開啟向量搜尋。

    提示

    或者,使用 Azure CLI 來更新您的帳戶的功能以支援 NoSQL 向量搜尋。

    az cosmosdb update \
         --resource-group <resource-group-name> \
         --name <account-name> \
         --capabilities EnableNoSQLVectorSearch
    

注意

註冊要求將會自動核准;不過,可能需要 15 分鐘才會生效。

下列步驟假設您知道如何設定 Cosmos DB NoSQL 帳戶和建立資料庫。 現有容器目前不支援向量搜尋功能,因此您必須建立新的容器,並指定容器層級的向量內嵌原則,以及容器建立時的向量索引編製原則。

讓我們以建立網際網路型書店的資料庫為例,而且您要儲存每本書的標題、作者、ISBN 和描述。 我們也會定義兩個屬性來包含向量內嵌。 第一個是“contentVector”屬性,其中包含從書籍文字內容產生的文字內嵌 (例如,在建立內嵌之前串連 “title”、“author”、“isbn” 和 “description” 屬性)。 第二個是從書籍封面影像產生的“coverImageVector”。

  1. 針對您要執行向量搜尋的欄位建立和儲存向量內嵌。
  2. 指定向量內嵌原則中的向量內嵌路徑。
  3. 在容器的索引編製原則中包含任何所需的向量索引。

對於本文的後續各節,我們會針對容器中儲存的項目考慮下列結構:

{
  "title": "book-title", 
  "author": "book-author", 
  "isbn": "book-isbn", 
  "description": "book-description", 
  "contentVector": [2, -1, 4, 3, 5, -2, 5, -7, 3, 1], 
  "coverImageVector": [0.33, -0.52, 0.45, -0.67, 0.89, -0.34, 0.86, -0.78] 
}

為您的容器建立向量內嵌原則

接下來,您必須定義容器向量原則。 此原則提供的資訊用來告知 Azure Cosmos DB 查詢引擎,如何處理 VectorDistance 系統函數中的向量屬性。 這也會告知向量索引編製原則所需的資訊,您應該選擇指定一個。 容器向量原則中包含下列資訊:

  • “path”:包含向量的屬性路徑
  • “datatype”:向量元素的類型 (預設值 Float32)
  • “dimensions”:路徑中每個向量的長度 (預設值 1536)
  • “distanceFunction”:用來計算距離/相似度的計量 (預設值 Cosine)

對於具有書籍詳細資料的範例,向量原則可能看起來類似範例 JSON:

vector_embedding_policy = { 
    "vectorEmbeddings": [ 
        { 
            "path": "/coverImageVector", 
            "dataType": "float32", 
            "distanceFunction": "dotproduct", 
            "dimensions": 8 
        }, 
        { 
            "path": "/contentVector", 
            "dataType": "float32", 
            "distanceFunction": "cosine", 
            "dimensions": 10 
        } 
    ]    
} 

在索引編製原則中建立向量索引

一旦決定了向量內嵌路徑,就必須將向量索引新增至索引編製原則。 對於此範例,索引編製原則看起來會像這樣:

indexing_policy = { 
    "includedPaths": [ 
        { 
            "path": "/*" 
        } 
    ], 
    "excludedPaths": [ 
        { 
            "path": "/\"_etag\"/?",
            "path": "/coverImageVector/*",
            "path": "/contentVector/*"
            
        } 
    ], 
    "vectorIndexes": [ 
        {"path": "/coverImageVector", 
         "type": "quantizedFlat" 
        }, 
        {"path": "/contentVector", 
         "type": "quantizedFlat" 
        } 
    ] 
} 

重要

已新增至索引編製原則的 "excludedPaths" 區段以確保插入效能最佳化的向量路徑。 若未將向量路徑新增至 "excludedPaths",將會導致向量插入的 RU 費用和延遲較高。

重要

目前,Azure Cosmos DB for NoSQL 中的向量搜尋僅在新容器上受到支援。 您必須在建立容器期間同時設定容器向量原則和任何向量索引編製原則,因為稍後無法將其修改。

使用向量原則建立容器

目前,Azure Cosmos DB for NoSQL 的向量搜尋功能僅在新容器上受到支援,因此您必須在建立容器期間套用向量原則,並且稍後無法將其修改。

try:     
    container = db.create_container_if_not_exists( 
                    id=CONTAINER_NAME, 
                    partition_key=PartitionKey(path='/id'), 
                    indexing_policy=indexing_policy, 
                    vector_embedding_policy=vector_embedding_policy) 
    print('Container with id \'{0}\' created'.format(id)) 

except exceptions.CosmosHttpResponseError: 
        raise 

執行向量相似度搜尋查詢

一旦您使用所需的向量原則建立容器,並將向量資料插入容器中,您就可以在查詢中使用向量距離系統函數來執行向量搜尋。 假設您想要藉由查看描述來搜尋食譜相關書籍,您必須先取得查詢文字的內嵌。 在此情況下,您可能會想要針對查詢文字產生內嵌 - 「食譜」。 一旦您對搜尋查詢具有內嵌,就可以在向量搜尋查詢的 VectorDistance 函數中使用該內嵌,並取得與您查詢類似的所有項目,如下所示:

SELECT TOP 10 c.title, VectorDistance(c.contentVector, [1,2,3,4,5,6,7,8,9,10]) AS SimilarityScore   
FROM c  
ORDER BY VectorDistance(c.contentVector, [1,2,3,4,5,6,7,8,9,10])   

此查詢會擷取書籍標題,以及與您查詢相關的相似度分數。 以下是 Python 中的範例:

query_embedding = [1,2,3,4,5,6,7,8,9,10] 
# Query for items 
for item in container.query_items( 
            query='SELECT c.title, VectorDistance(c.contentVector,@embedding) AS SimilarityScore FROM c ORDER BY VectorDistance(c.contentVector,@embedding)', 
            parameters=[ 
                {"name": "@embedding", "value": query_embedding} 
            ], 
            enable_cross_partition_query=True): 
    print(json.dumps(item, indent=True))