Condividi tramite


Configurare la quantizzazione vettoriale e l'archiviazione ridotta per vettori più piccoli in Azure AI Search

Importante

Queste funzionalità sono disponibili in anteprima pubblica in Condizioni supplementari per l'utilizzo. Le API REST 2024-03-01-Preview e versioni successive forniscono i nuovi tipi di dati, le proprietà di compressione vettoriale e la proprietà stored.

Questo articolo descrive la quantizzazione dei vettori e altre tecniche per comprimere gli indici vettoriali in Azure AI Search.

Valutare le opzioni

Come primo passaggio, esaminare le tre opzioni per ridurre la quantità di spazio di archiviazione usato dai campi vettoriali. Queste opzioni non si escludono reciprocamente.

È consigliabile usare la quantizzazione scalare perché comprime le dimensioni del vettore in memoria e su disco con uno sforzo minimo e tende a offrire il massimo vantaggio nella maggior parte degli scenari. Al contrario, i tipi narrow (ad eccezione di Float16) richiedono uno sforzo particolare per essere creati stored consente di risparmiare sull'archiviazione su disco, cosa che ha un impatto inferiore rispetto alla memoria.

Approccio Perché usare questa opzione
Aggiungere la quantizzazione scalare Usare la quantizzazione scalare predefinita per comprimere gli incorporamenti Float32 nativi per Int8. Questa opzione riduce l'archiviazione in memoria e su disco senza ridurre le prestazioni delle query. Tipi di dati più piccoli come Int8 producono indici vettoriali meno ricchi di contenuto rispetto a quelli con incorporamenti Float32. Per compensare la perdita di informazioni, la compressione predefinita include opzioni per l'elaborazione post-query usando incorporamenti non compressi e sovracampionamento per restituire risultati più rilevanti. La ricategorizzazione e il sovracampionamento sono funzionalità specifiche della quantizzazione scalare predefinita dei campi Float32 o Float16 e non possono essere usate sugli incorporamenti che subiscono una quantizzazione personalizzata.
Assegnare tipi di dati primitivi più piccoli ai campi vettoriali Tipi di dati narro, ad esempio Float16, Int16, Int8 e byte (binario) utilizzano meno spazio in memoria e su disco, ma è necessario disporre di un modello di incorporamento che restituisce vettori in un formato di dati ristretto. In alternativa, è necessario avere una logica di quantizzazione personalizzata che restituisce dati di piccole dimensioni. Un terzo caso d'uso che richiede meno sforzi consiste nel ricalibrare gli incorporamenti nativi Float32 prodotti dalla maggior parte dei modelli per Float16. Per informazioni dettagliate sui vettori binari, vedere Vettori binari di indice.
Eliminare l'archiviazione facoltativa dei vettori recuperabili I vettori restituiti in una risposta di query vengono archiviati separatamente dai vettori usati durante l'esecuzione della query. Se non è necessario restituire vettori, è possibile disattivare l'archiviazione recuperabile, riducendo l'archiviazione complessiva per disco per campo fino al 50%.

Tutte queste opzioni sono definite in un indice vuoto. Per implementarli, usare le API REST 2024-03-01-preview del portale di Azure o un pacchetto beta di Azure SDK.

Dopo aver definito l'indice, è possibile caricare e indicizzare i documenti come passaggio separato.

Opzione 1: Configurare la quantizzazione scalare

La quantizzazione scalare predefinita è consigliata perché riduce i requisiti di memoria e archiviazione su disco e aggiunge ricategorizzazione e sovracampionamento per compensare gli effetti di un indice più piccolo. La quantizzazione scalare predefinita può essere applicata ai campi vettoriali contenenti dati Float32 o Float16.

Per usare la compressione vettoriale predefinita:

  • Aggiungere vectorSearch.compressions a un indice di ricerca. L'algoritmo di compressione supportato in questa anteprima è la quantizzazione scalare.
  • Impostare proprietà facoltative per attenuare gli effetti dell'indicizzazione con perdita di dati. Sia rerankWithOriginalVectors che defaultOversampling offrono ottimizzazioni durante l'esecuzione delle query.
  • Aggiungere vectorSearch.profiles.compression a un nuovo profilo vettoriale.
  • Assegnare il nuovo profilo vettore a un nuovo campo vettoriale.

Aggiungere le impostazioni di compressione e impostare le proprietà facoltative

In una definizione di indice creata usando l'API REST 2024-03-01-preview aggiungere una sezione compressions. Usare il codice JSON seguente come modello.

"compressions": [

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

Punti principali:

  • kindDeve essere impostato su scalarQuantization. Questo è l'unico metodo di quantizzazione attualmente supportato.

  • rerankWithOriginalVectors usa i vettori originali non compressi per ricalcolare la somiglianza e ricategorizzare i risultati principali restituiti dalla query di ricerca iniziale. I vettori non compressi sono presenti nell'indice di ricerca anche se stored è false. Questa proprietà è facoltativa. Il valore predefinito è true.

  • defaultOversampling considera un set più ampio di potenziali risultati per compensare la riduzione delle informazioni dalla quantizzazione. La formula per i risultati potenziali è costituita dak nella query, con un moltiplicatore di sovracampionamento. Ad esempio, se la query specifica un k di 5 e se il sovracampionamento è 20, la query richiede di fatto 100 documenti per l'uso durante la ricategorizzazione, usando il vettore originale non compresso a tale scopo. Vengono restituiti solo i primi k risultati classificati di nuovo. Questa proprietà è facoltativa. Il valore predefinito è 4.

  • quantizedDataTypeDeve essere impostato su int8. Questo è l'unico tipo di dati primitivo attualmente supportato. Questa proprietà è facoltativa. Il valore predefinito è int8.

Aggiungere un'impostazione di compressione a un profilo vettoriale

La quantizzazione scalare viene specificata come proprietà in un nuovo profilo vettoriale. La creazione di un nuovo profilo vettoriale è necessaria per la compilazione di indici compressi in memoria.

All'interno del profilo è necessario usare l'algoritmo HNSW (Hierarchical Navigable Small Worlds). La quantizzazione predefinita non è supportata con KNN esaustivo.

  1. Creare un nuovo profilo vettoriale e aggiungere una proprietà di compressione.

    "profiles": [
       {
          "name": "my-vector-profile",
          "compression": "my-scalar-quantization", 
          "algorithm": "my-hnsw-vector-config-1",
          "vectorizer": null
       }
     ]
    
  2. Assegnare un profilo vettoriale a un nuovo campo vettoriale. La quantizzazione scalare riduce il contenuto a Int8, quindi assicurarsi che il contenuto sia Float32 o Float16.

    In Azure AI Search, gli equivalenti di Entity Data Model (EDM) di tipi Float32 e Float16 sono rispettivamente Collection(Edm.Single) e Collection(Edm.Half).

    {
       "name": "DescriptionVector",
       "type": "Collection(Edm.Single)",
       "searchable": true,
       "retrievable": true,
       "dimensions": 1536,
       "vectorSearchProfile": "my-vector-profile"
    }
    
  3. Caricare l'indice usando indicizzatori per l'indicizzazione del modello pull o API per l'indicizzazione del modello push.

La quantizzazione scalare riduce la risoluzione di ogni numero all'interno di ogni incorporamento di vettori. Anziché descrivere ogni numero come numero a virgola mobile a 32 bit, usa un intero a 8 bit. Identifica un intervallo di numeri (in genere il 99° percentile minimo e massimo) e li divide in un numero finito di livelli o bin, assegnando a ogni bin un identificatore. Nella quantizzazione scalare a 8 bit sono presenti 2^8 o 256 bin possibili.

Ogni componente del vettore viene sottoposto a mapping al valore rappresentativo più vicino all'interno di questo set di livelli di quantizzazione in un processo simile all'arrotondamento di un numero reale all'intero più vicino. Nel vettore a 8 bit quantizzato il numero di identificatore prende il posto del valore originale. Dopo la quantizzazione, ogni vettore è rappresentato da una matrice di identificatori per i bin a cui appartengono i relativi componenti. Questi vettori quantizzati richiedono molti meno bit da archiviare rispetto al vettore originale, riducendo così i requisiti di archiviazione e il footprint di memoria.

Opzione 2: Assegnare tipi di dati ristretti ai campi vettoriali

I campi vettoriali archiviano gli incorporamenti vettoriali, rappresentati come matrice di numeri. Quando si specifica un tipo di campo, si specifica il tipo di dati primitivo sottostante usato per contenere ogni numero all'interno di queste matrici. Il tipo di dati influisce sulla quantità di spazio impiegato da ogni numero.

Usando le API di anteprima, è possibile assegnare tipi di dati primitivi narrow per ridurre i requisiti di archiviazione dei campi vettoriali.

  1. Esaminare i tipi di dati per i campi vettoriali:

    • Collection(Edm.Single) Virgola mobile a 32 bit (valore predefinito)
    • Collection(Edm.Half) Virgola mobile a 16 bit
    • Collection(Edm.Int16) Intero con segno a 16 bit
    • Collection(Edm.SByte) Intero con segno a 8 bit

    Nota

    I tipi di dati binari non sono attualmente supportati.

  2. Scegliere un tipo di dati valido per l'output del modello di incorporamento o per i vettori sottoposti a quantizzazione personalizzata.

    La maggior parte dei modelli di incorporamento restituisce numeri a virgola mobile a 32 bit, ma se si applica una quantizzazione personalizzata, l'output potrebbe essere Int16 o Int8. È ora possibile definire campi vettoriali che accettano il formato più piccolo.

    I modelli di incorporamento del testo hanno un formato di output nativo di Float32, che esegue il mapping a Collection(Edm.Single) in Azure AI Search. Non è possibile eseguire il mapping dell'output a Int8 perché il cast da float a int non è consentito. Tuttavia, è possibile eseguire il cast da Float32 a Float16 (o Collection(Edm.Half)) e questo è un modo semplice per usare tipi di dati narrow senza sforzi aggiuntivi.

    Nella tabella seguente vengono forniti collegamenti a diversi modelli di incorporamento che usano i tipi di dati narrow.

    Modello di incorporamento Output nativo Tipi validi in Azure AI Search
    text-embedding-ada-002 Float32 Collection(Edm.Single) oppure Collection(Edm.Half)
    text-embedding-3-small Float32 Collection(Edm.Single) oppure Collection(Edm.Half)
    text-embedding-3-large Float32 Collection(Edm.Single) oppure Collection(Edm.Half)
    Modelli di incorporamento di Cohere V3 con int8 embedding_type Int8 Collection(Edm.SByte)
  3. Assicurarsi di comprendere i compromessi di un tipo di dati ristretto. Collection(Edm.Half) contiene meno informazioni, cosa che porta a una risoluzione inferiore. Se i dati sono omogenei o densi, la perdita di dettagli o sfumature aggiuntive potrebbe causare risultati inaccettabili in fase di query perché saranno disponibili meno dettagli per distinguere i vettori vicini.

  4. Definire e compilare l'indice. È possibile usare il portale di Azure, 2024-03-01-preview, o un pacchetto beta di Azure SDK per questo passaggio.

  5. Verifica dei risultati. Supponendo che il campo vettoriale sia contrassegnato come recuperabile, usare Esplora ricerche o l'API REST per verificare che il contenuto del campo corrisponda al tipo di dati. Assicurarsi di usare la versione corretta dell'API 2024-03-01-preview per la query; in caso contrario, le nuove proprietà non verranno visualizzate.

Per controllare le dimensioni dell'indice vettoriale, usare il portale di Azure o 2024-03-01-preview.

Nota

Il tipo di dati del campo viene usato per creare la struttura dei dati fisici. Se si vuole modificare un tipo di dati in un secondo momento, eliminare e ricompilare l'indice oppure creare un secondo campo con la nuova definizione.

Opzione 3: Impostare la proprietà stored per rimuovere l'archiviazione recuperabile

La proprietà stored è un nuovo valore booleano in una definizione di campo vettoriale che determina se l'archiviazione viene allocata per il contenuto del campo vettoriale recuperabile. Se non è necessario il contenuto vettoriale in una risposta di query, è possibile risparmiare fino al 50% di spazio di archiviazione per campo impostando stored su false.

Poiché i vettori non sono leggibili, vengono in genere omessi in una risposta di query di cui viene eseguito il rendering in una pagina di ricerca. Tuttavia, se si usano vettori nell'elaborazione downstream, ad esempio passando i risultati della query a un modello o a un processo che utilizza il contenuto vettoriale, è necessario mantenere stored impostato su true e scegliere una tecnica diversa per ridurre al minimo le dimensioni del vettore.

L'esempio seguente mostra la raccolta di campi di un indice di ricerca. Impostare stored su false per rimuovere definitivamente l'archiviazione recuperabile per il campo vettore.

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" 
         } 
       ] 
     } 

Punti principali:

  • Si applica solo ai campi vettoriali.

  • Influisce sull'archiviazione su disco ma non sulla memoria e non ha alcun effetto sulle query. L'esecuzione di query usa un indice vettoriale separato non interessato dalla proprietà stored.

  • La proprietà stored viene impostata durante la creazione dell'indice nei campi vettoriali ed è irreversibile. Se si vuole recuperare il contenuto in un secondo momento, è necessario eliminare e ricompilare l'indice oppure creare e caricare un nuovo campo con la nuova attribuzione.

  • Le impostazioni predefinite sono stored impostato su true e retrievable impostato su false. In una configurazione predefinita viene archiviata una copia recuperabile, ma non viene restituita automaticamente nei risultati. Quando stored è true, è possibile impostare retrievable su true e false in qualsiasi momento senza dover ricompilare un indice. Quando stored è false, anche retrievable deve essere false e non può essere modificato.

Indice di esempio con vectorCompression, tipi di dati e proprietà archiviata

Ecco un esempio composito di un indice di ricerca che specifica tipi di dati narrow, archiviazione ridotta e compressione vettoriale.

  • "HotelNameVector" fornisce un esempio di tipo di dati narrow, con un nuovo cast dei valori Float32 originali in Float16, espresso come Collection(Edm.Half) nell'indice di ricerca.
  • Anche "HotelNameVector" ha stored impostato su false. Gli incorporamenti aggiuntivi usati in una risposta di query non vengono archiviati. Quando stored è false, anche retrievable deve essere false.
  • "DescriptionVector" fornisce un esempio di compressione vettoriale. La compressione vettoriale viene definita nell'indice, a cui viene fatto riferimento in un profilo, e quindi assegnata a un campo vettoriale. Anche "DescriptionVector" ha stored impostato su 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" }
                    ]
                }
            }
        ]
    }
}

Eseguire una query su un campo vettoriale quantizzato usando il sovracampionamento

La sintassi della query in questo esempio si applica ai campi vettoriali che usano la quantizzazione scalare predefinita. Per impostazione predefinita, i campi vettoriali che usano la quantizzazione scalare usano anche rerankWithOriginalVectors e defaultOversampling per attenuare gli effetti di un indice vettore più piccolo. Tali impostazioni vengono specificate nell'indice di ricerca.

Nella query è possibile eseguire l'override del valore predefinito di sovracampionamento. Ad esempio, se defaultOversampling è 10.0, è possibile modificarlo in un altro elemento nella richiesta di query.

È possibile impostare il parametro di sovracampionamento anche se l'indice non ha una definizione di rerankWithOriginalVectors o di defaultOversampling in modo esplicito. Se si specifica oversampling in fase di query, le impostazioni dell'indice per tale query vengono sovrascritte e la query viene eseguita con un valore rerankWithOriginalVectors effettivo come 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   
            }
      ]    
    }

Punti principali:

  • Si applica ai campi vettoriali che subiscono la compressione vettoriale, in base all'assegnazione del profilo vettoriale.

  • Esegue l'override del valore defaultOversampling o introduce il sovracampionamento in fase di query, anche se la configurazione della compressione dell'indice non specifica le opzioni di sovracampionamento o ricategorizzazione.

Vedi anche