分享方式:


在 Azure AI 搜尋服務中,為較小的向量設定向量量化和減少儲存空間

重要

此功能在補充使用規定下處於公開預覽狀態。 2024-03-01-Preview REST API 和後續預覽 API 提供了新的資料類型、向量壓縮屬性與 stored 屬性。

本文說明在 Azure AI 搜尋服務中,壓縮向量索引的向量量化和其他技術。

評估選項

在第一個步驟中,請檢閱三個選項,減少向量欄位所使用的儲存空間大小。 這些選項並非互斥。

我們建議採用純量量化,因為會以最少的投入,壓縮記憶體和磁碟上的向量大小,而且在大部分案例中通常會提供最大效益。 相較之下,窄類型 (除了 Float16 之外) 需要特別投入,且 stored 會儲存在磁碟儲存體上,不像記憶體那般昂貴。

方法 為何要使用此選項
新增純量量化 使用內建純量量化來壓縮原生 Float32 內嵌至 Int8。 此選項可減少記憶體和磁碟上的儲存空間,且查詢效能不會降低。 較小的資料類型 (例如 Int8) 會產生內容比 Float32 內嵌少的向量索引。 為了克服資訊遺失,內建壓縮會包含使用未壓縮內嵌和過度取樣來傳回更相關結果的查詢後處理選項。 重新排名和過度取樣是 Float32Float16 欄位內建純量化的特定功能,無法用於進行自訂量化的內嵌。
將較小的基本資料類型指派給向量欄位 窄資料類型,例如 Float16Int16Int8byte (二進位) 在記憶體和磁碟上耗用較少的空間,但您必須有內嵌模型,以窄資料格式輸出向量。 或者,您必須具有輸出小型資料的自訂量化邏輯。 需要較少投入的第三個使用案例是將大部分模型所產生的原生 Float32 內嵌重新轉換成 Float16。 如需二進位向量的詳細資訊,請參閱索引二進位向量
排除可擷取向量的選擇性儲存 查詢回應中傳回的向量會與查詢執行期間所使用的向量分開儲存。 如果您不需要傳回向量,您可以關閉可擷取的儲存空間,減少高達 50% 的整體各欄位磁碟記憶體。

所有這些選項都是在空的索引上定義。 若要實作其中任何一項,請使用 Azure 入口網站、2024-03-01-preview REST API 或搶鮮版 (Beta) Azure SDK 套件。

定義索引之後,您可以載入文件並編製索引,作為個別步驟。

選項 1:設定純量量化

建議使用內建純量量化,因為可以減少記憶體和磁碟儲存需求,並新增重新排名和過度取樣,以克服較小索引的影響。 內建純量量化可以套用至包含 Float32Float16 資料的向量欄位。

若要使用內建向量壓縮:

  • vectorSearch.compressions 新增至搜尋索引。 此預覽中支援的壓縮演算法是純量量化
  • 設定選擇性屬性,以減輕遺失索引的影響。 rerankWithOriginalVectorsdefaultOversampling 都會在查詢執行期間提供優化。
  • vectorSearch.profiles.compression 新增至新的向量設定檔。
  • 將新的向量設定檔指派給新的向量欄位。

新增壓縮設定並設定選擇性屬性

在使用 2024-03-01-preview REST API建立的索引定義中,新增 compressions 區段。 使用下列 JSON 作為範本。

"compressions": [

      {  
        "name": "my-scalar-quantization",  
        "kind": "scalarQuantization",  
        "rerankWithOriginalVectors": true,  (optional)
        "defaultOversampling": 10.0,  (optional)
        "scalarQuantizationParameters": {  (optional)
             "quantizedDataType": "int8",  (optional)
        }
      }  
   ]

重點︰

  • kind 必須設定為 scalarQuantization。 這是目前唯一支援的量化方法。

  • rerankWithOriginalVectors 會使用原始未壓縮的向量來重新計算相似度,並將初始搜尋查詢所傳回的前幾個結果重新排名。 即使 stored 為 false,未壓縮的向量仍存在於搜尋索引中。 這個屬性為選擇性。 預設為 true。

  • defaultOversampling 會考慮一組更廣泛的潛在結果,以克服量化資訊減少的問題。 潛在結果的公式包含查詢中的 k,以及過度取樣乘數。 例如,如果查詢指定 k (總計 5),且過度取樣為 20,則查詢會有效要求 100 份文件用於重新排名,並針對該目的使用原始未壓縮的向量。 只會傳回前 k 個重新排名的結果。 這個屬性為選擇性。 預設值為 4。

  • quantizedDataType 必須設定為 int8。 這是目前唯一支援的基本資料類型。 這個屬性為選擇性。 預設值為 int8

將壓縮設定新增至向量設定檔

純量量化會指定為向量設定檔中的屬性。 您必須建立新的向量設定檔,才能在記憶體中建置壓縮索引。

在設定檔中,您必須使用階層式導覽小型世界 (HNSW) 演算法。 完整 KNN 不支援內建量化。

  1. 建立新的向量設定檔,並新增壓縮屬性。

    "profiles": [
       {
          "name": "my-vector-profile",
          "compression": "my-scalar-quantization", 
          "algorithm": "my-hnsw-vector-config-1",
          "vectorizer": null
       }
     ]
    
  2. 將向量設定檔指派給新的向量欄位。 純量量化會將內容縮減為 Int8,因此請確定您的內容是 Float32Float16

    在 Azure AI 搜尋服務中,與 Float32Float16 類型相當的實體資料模型 (EDM) 分別是 Collection(Edm.Single)Collection(Edm.Half)

    {
       "name": "DescriptionVector",
       "type": "Collection(Edm.Single)",
       "searchable": true,
       "retrievable": true,
       "dimensions": 1536,
       "vectorSearchProfile": "my-vector-profile"
    }
    
  3. 使用索引器來載入索引,以提取模型索引,或使用推送模型索引的 API。

純量量化可減少每個向量內嵌中各個數字的解析度。 純量量化會使用 8 位數的整數,而不是將每個數字描述為 32 位元的浮點數。 純量量化會識別數字範圍 (通常是第 99 個百分位數下限和上限),並分割成有限數目的層級或間隔,並且為每個間隔指派識別碼。 在 8 位元的純量量化中,有 2^8 或 256 個可能的間隔。

向量的每個元件都會對應至這一組量化層級內最接近的代表值,其過程類似於將實數四捨五入為最接近的整數。 在量化的 8 位數向量中,識別碼編號會取代原始值。 量化之後,每個向量都會以其元件所屬間隔的識別碼陣列表示。 相較於原始向量,這些量化向量所需的儲存間隔少很多,因此可減少儲存需求和磁碟使用量。

選項 2:將窄資料類型指派給向量欄位

向量欄位會儲存向量內嵌,以數字陣列表示。 當您指定欄位類型時,您可以指定用來儲存這些陣列內每個數字的基本資料類型。 資料類型會影響每個數字佔用多少空間。

您可以使用預覽 API 指派窄型基本資料類型,以減少向量欄位的儲存需求。

  1. 檢閱向量欄位的資料類型

    • Collection(Edm.Single) 32 位元浮點數 (預設值)
    • Collection(Edm.Half) 16 位元浮點數
    • Collection(Edm.Int16) 16 位元帶正負號的整數
    • Collection(Edm.SByte) 8 位元帶正負號的整數

    注意

    目前不支援二進位資料類型。

  2. 針對內嵌模型的輸出,或針對進行自訂量化的向量,選擇有效的資料類型。

    大部分的內嵌模型都會輸出 32 位元浮點數,但如果您套用自訂量化,則輸出可能會是 Int16Int8。 您現在可以定義接受較小格式的向量欄位。

    文字內嵌模型具有原生輸出格式 Float32,對應至 Azure AI 搜尋服務中的 Collection(Edm.Single)。 您無法將輸出對應至 Int8,因為禁止從 float 轉換成 int。 不過,您可以從 Float32 轉換成 Float16 (或 Collection(Edm.Half)),這是使用窄資料類型的簡單方式,不需要額外的工作。

    下表提供數個使用窄資料類型的內嵌模型連結。

    內嵌模型 原生輸出 Azure AI 搜尋服務中的有效類型
    text-embedding-ada-002 Float32 Collection(Edm.Single)Collection(Edm.Half)
    text-embedding-3-small Float32 Collection(Edm.Single)Collection(Edm.Half)
    text-embedding-3-large Float32 Collection(Edm.Single)Collection(Edm.Half)
    Cohere V3 內嵌模型,搭配 int8 embedding_type Int8 Collection(Edm.SByte)
  3. 請務必了解使用窄資料類型的取捨。 Collection(Edm.Half) 資訊較少,會導致解析度較低。 如果您的資料是同質或密集資料,遺失額外的詳細資料或細微差別可能會導致查詢時間發生難以接受的結果,因為可用來區分附近向量的詳細資料較少。

  4. 定義及建置索引。 您可以使用 Azure 入口網站、2024-03-01-preview 或此步驟的搶鮮版 (Beta) Azure SDK 套件。

  5. 查看結果。 假設向量欄位標示為可擷取,請使用搜尋總管REST API 來確認欄位內容符合資料類型。 請務必針對查詢使用正確的 2024-03-01-preview API 版本,否則不會顯示新的屬性。

若要檢查向量索引大小,請使用 Azure 入口網站或 2024-03-01-preview

注意

欄位的資料類型可用來建立實體資料結構。 如果您想要在稍後變更資料類型,請卸除並重建索引,或使用新的定義建立第二個欄位。

選項 3:設定 stored 屬性以移除可擷取的儲存體

stored 屬性是向量欄位定義上的新布林值,可決定是否為可擷取的向量欄位內容配置儲存體。 如果您在查詢回應中不需要向量內容,您可以將 stored 設定為 false,為每個欄位節省高達 50% 的儲存體。

由於向量並非肉眼可讀取,所以在搜尋頁面上轉譯的查詢回應中,通常會被省略。 不過,如果您在下游處理中使用向量,例如將查詢結果傳遞至取用向量內容的模型或流程,您應該繼續將 stored 設定為 true,並選擇不同的技術來將向量大小降到最低。

下列範例會顯示搜尋索引的欄位集合。 將 stored 設定為 false,以永久移除向量欄位的可擷取儲存空間。

PUT https://[service-name].search.windows.net/indexes/[index-name]?api-version=2024-03-01-preview  
   Content-Type: application/json  
   api-key: [admin key]  
 
     { 
       "name": "myindex", 
       "fields": [ 
         { 
           "name": "myvector", 
           "type": "Collection(Edm.Single)", 
           "retrievable": false, 
           "stored": false, 
           "dimensions": 1536, 
           "vectorSearchProfile": "vectorProfile" 
         } 
       ] 
     } 

重點︰

  • 僅適用於向量欄位

  • 影響磁碟上的儲存空間,而非記憶體,且不會影響查詢。 查詢執行會使用不受 stored 屬性影響的不同向量索引。

  • 在向量欄位的索引建立期間,會設定 stored 屬性,而且無法復原。 如果您想要稍後擷取內容,您必須卸除並重建索引,或建立並載入具有新屬性的新欄位。

  • 預設值為 stored 設為 true,retrievable 設為 false。 在預設設定中,會儲存可擷取的副本,但不會在結果中自動傳回。 當 stored 為 true 時,您可以隨時在 true 和 false 之間切換 retrievable,而不需要重建索引。 當 stored 為 false 時,retrievable 必須是 false 且無法變更。

具有 vectorCompression、資料類型和儲存屬性的範例索引

以下是搜尋索引的複合範例,指定窄資料類型、減少的儲存空間和向量壓縮。

  • 「HotelNameVector」提供窄資料類型範例,將原始 Float32 值重新轉換為 Float16,以搜尋索引中的 Collection(Edm.Half) 表示。
  • 「HotelNameVector」也會將 stored 設定為 false。 查詢回應中使用的額外內嵌不會儲存。 當 stored 為 false 時,retrievable 也必須為 false。
  • 「DescriptionVector」提供向量壓縮的範例。 向量壓縮已定義在索引中,在設定檔中參考,然後指派給向量欄位。 「DescriptionVector」也將 stored 設為 false。
### Create a new index
POST {{baseUrl}}/indexes?api-version=2024-03-01-preview  HTTP/1.1
    Content-Type: application/json
    api-key: {{apiKey}}

{
    "name": "hotels-vector-quickstart",
    "fields": [
        {
            "name": "HotelId", 
            "type": "Edm.String",
            "searchable": false, 
            "filterable": true, 
            "retrievable": true, 
            "sortable": false, 
            "facetable": false,
            "key": true
        },
        {
            "name": "HotelName", 
            "type": "Edm.String",
            "searchable": true, 
            "filterable": false, 
            "retrievable": true, 
            "sortable": true, 
            "facetable": false
        },
        {
            "name": "HotelNameVector",
            "type": "Collection(Edm.Half)",
            "searchable": true,
            "retrievable": false,
            "dimensions": 1536,
            "stored": false,
            "vectorSearchProfile": "my-vector-profile-no-compression"
        },
        {
            "name": "Description", 
            "type": "Edm.String",
            "searchable": true, 
            "filterable": false, 
            "retrievable": false, 
            "sortable": false, 
            "facetable": false
        },
        {
            "name": "DescriptionVector",
            "type": "Collection(Edm.Single)",
            "searchable": true,
            "retrievable": false,
            "dimensions": 1536,
            "stored": false,
            "vectorSearchProfile": "my-vector-profile-with-compression"
        },
        {
            "name": "Category", 
            "type": "Edm.String",
            "searchable": true, 
            "filterable": true, 
            "retrievable": true, 
            "sortable": true, 
            "facetable": true
        },
        {
            "name": "Tags",
            "type": "Collection(Edm.String)",
            "searchable": true,
            "filterable": true,
            "retrievable": true,
            "sortable": false,
            "facetable": true
        },
        {
            "name": "Address", 
            "type": "Edm.ComplexType",
            "fields": [
                {
                    "name": "City", "type": "Edm.String",
                    "searchable": true, "filterable": true, "retrievable": true, "sortable": true, "facetable": true
                },
                {
                    "name": "StateProvince", "type": "Edm.String",
                    "searchable": true, "filterable": true, "retrievable": true, "sortable": true, "facetable": true
                }
            ]
        },
        {
            "name": "Location",
            "type": "Edm.GeographyPoint",
            "searchable": false, 
            "filterable": true, 
            "retrievable": true, 
            "sortable": true, 
            "facetable": false
        }
    ],
"vectorSearch": {
    "compressions": [
        {
            "name": "my-scalar-quantization",
            "kind": "scalarQuantization",
            "rerankWithOriginalVectors": true,
            "defaultOversampling": 10.0,
                "scalarQuantizationParameters": {
                    "quantizedDataType": "int8"
                }
        }
    ],
    "algorithms": [
        {
            "name": "my-hnsw-vector-config-1",
            "kind": "hnsw",
            "hnswParameters": 
            {
                "m": 4,
                "efConstruction": 400,
                "efSearch": 500,
                "metric": "cosine"
            }
        },
        {
            "name": "my-hnsw-vector-config-2",
            "kind": "hnsw",
            "hnswParameters": 
            {
                "m": 4,
                "metric": "euclidean"
            }
        },
        {
            "name": "my-eknn-vector-config",
            "kind": "exhaustiveKnn",
            "exhaustiveKnnParameters": 
            {
                "metric": "cosine"
            }
        }
    ],
    "profiles": [      
        {
            "name": "my-vector-profile-with-compression",
            "compression": "my-scalar-quantization",
            "algorithm": "my-hnsw-vector-config-1",
            "vectorizer": null
        },
        {
            "name": "my-vector-profile-no-compression",
            "compression": null,
            "algorithm": "my-eknn-vector-config",
            "vectorizer": null
        }
    ]
},
    "semantic": {
        "configurations": [
            {
                "name": "my-semantic-config",
                "prioritizedFields": {
                    "titleField": {
                        "fieldName": "HotelName"
                    },
                    "prioritizedContentFields": [
                        { "fieldName": "Description" }
                    ],
                    "prioritizedKeywordsFields": [
                        { "fieldName": "Tags" }
                    ]
                }
            }
        ]
    }
}

使用過度取樣查詢量化向量欄位

此範例中的查詢語法適用於使用內建純量量化的向量欄位。 根據預設,使用純量量化的向量欄位也會使用 rerankWithOriginalVectorsdefaultOversampling 來減輕較小向量索引的影響。 這些設定已指定在搜尋索引中

在查詢上,您可以覆寫過度取樣預設值。 例如,如果 defaultOversampling 為 10.0,您可以將其變更為查詢要求中的其他值。

即使索引沒有明確的 rerankWithOriginalVectorsdefaultOversampling 定義,您也可以設定過度取樣參數。 在查詢時間提供 oversampling 會覆寫該查詢的索引設定,並以有效的 rerankWithOriginalVectors 為 true 來執行查詢。

POST https://[service-name].search.windows.net/indexes/[index-name]/docs/search?api-version=2024-03-01-Preview   
  Content-Type: application/json   
  api-key: [admin key]   

    {    
       "vectorQueries": [
            {    
                "kind": "vector",    
                "vector": [8, 2, 3, 4, 3, 5, 2, 1],    
                "fields": "myvector",
                "oversampling": 12.0,
                "k": 5   
            }
      ]    
    }

重點︰

  • 適用於進行向量壓縮的向量欄位 (根據向量設定檔指派)。

  • 覆寫 defaultOversampling 值,或在查詢時引入過度取樣,即使索引的壓縮設定未指定過度取樣或重新排名選項也一樣。

另請參閱