Настройка векторной квантизации и уменьшения хранилища для небольших векторов в поиске ИИ Azure

Внимание

Эти функции доступны в общедоступной предварительной версии в разделе "Дополнительные условия использования". REST API 2024-03-01-Preview предоставляет новые типы данных, свойства сжатия векторов stored и свойство.

В этой статье описывается векторная квантизация и другие методы сжатия векторных индексов в службе "Поиск ИИ Azure".

Оценка параметров

В первую очередь просмотрите три варианта уменьшения объема хранилища, используемого векторными полями. Эти параметры не являются взаимоисключающими.

Мы рекомендуем скалярную квантизацию, так как она сжимает размер вектора в памяти и на диске с минимальными усилиями, и, как правило, обеспечивает большую выгоду в большинстве сценариев. В отличие от этого, узкие типы (за исключением Float16) требуют особых усилий для их создания и stored экономии на диске, что не так дорого, как память.

Подход Зачем использовать эту опцию
Назначение небольших примитивных типов данных полям векторов Узкие типы данных, такие как Float16, Int16и Int8, потребляют меньше места в памяти и на диске, но у вас должна быть модель внедрения, которая выводит векторы в узком формате данных. Кроме того, у вас должна быть пользовательская логика квантизации, которая выводит небольшие данные. Третий вариант использования, требующий меньше усилий, — переадресовка собственных Float32 внедрения, созданных большинством моделей Float16.
Исключение необязательного хранилища извлекаемых векторов Векторы, возвращаемые в ответе запроса, хранятся отдельно от векторов, используемых во время выполнения запроса. Если вам не нужно возвращать векторы, вы можете отключить извлекаемое хранилище, уменьшая общий объем хранилища дисков на поле до 50 процентов.
Добавление скалярной квантизации Используйте встроенную скалярную квантизацию для сжатия собственных Float32Int8внедрений в . Этот параметр сокращает объем хранилища в памяти и на диске без снижения производительности запросов. Небольшие типы данных, такие как Int8 создание векторных индексов, которые менее богаты содержимым, чем Float32 у внедренных типов данных. Для смещения потери информации встроенная сжатие включает параметры обработки после запроса с помощью несжатых внедренных внедренных и перераспределений, чтобы вернуть более релевантные результаты. Повторное использование и чрезмерное использование являются конкретными функциями встроенной скалярной квантизации Float32 или Float16 полей и не могут использоваться при внедрении, которые проходят настраиваемую квантизацию.

Все эти параметры определены в пустом индексе. Чтобы реализовать любой из них, используйте интерфейсы REST API портал Azure, 2024-03-01-preview или бета-версию пакета AZURE SDK.

После определения индекса можно загрузить и индексировать документы в виде отдельного шага.

Вариант 1. Назначение узких типов данных полям векторов

Векторные поля хранят векторные внедрения, которые представлены в виде массива чисел. При указании типа поля необходимо указать базовый примитивный тип данных, используемый для хранения каждого числа в этих массивах. Тип данных влияет на то, сколько занимает каждое число.

С помощью API предварительной версии можно назначать узкие примитивные типы данных для уменьшения требований к хранилищу полей векторов.

  1. Просмотрите типы данных для полей векторов:

    • Collection(Edm.Single) 32-разрядная плавающая точка (по умолчанию)
    • Collection(Edm.Half) 16-разрядная плавающая точка
    • Collection(Edm.Int16) 16-разрядное целое число со знаком
    • Collection(Edm.SByte) 8-разрядное целое число со знаком

    Примечание.

    В настоящее время двоичные типы данных не поддерживаются.

  2. Выберите тип данных, допустимый для выходных данных модели внедрения или для векторов, которые проходят настраиваемую квантизацию.

    Большинство моделей внедрения выводят 32-разрядные числа с плавающей запятой, но при применении пользовательской квантизации выходные данные могут быть Int16 или Int8. Теперь можно определить векторные поля, принимаюющие меньший формат.

    Модели внедрения текста имеют собственный формат выходных Float32данных, который сопоставляется Collection(Edm.Single) с поиском ИИ Azure. Вы не можете сопоставить выходные данные с Int8 тем, что приведение из floatint нее запрещено. Однако вы можете приведение от Float32Float16 (или) к (или Collection(Edm.Half)) и это простой способ использовать узкие типы данных без дополнительной работы.

    В следующей таблице приведены ссылки на несколько моделей внедрения, использующих узкие типы данных.

    Модель внедрения Собственные выходные данные Допустимые типы в поиске ИИ Azure
    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 версии 3 с помощью int8 embedding_type Int8 Collection(Edm.SByte)
  3. Убедитесь, что вы понимаете компромиссы узкого типа данных. Collection(Edm.Half) имеет меньше информации, что приводит к снижению разрешения. Если данные являются однородными или плотными, потеря дополнительных деталей или нюансов может привести к неприемлемым результатам во время запроса, так как есть меньше деталей, которые можно использовать для разбиений близлежащих векторов.

  4. Определите и создайте индекс. Для этого шага можно использовать портал Azure, 2024-03-01-preview или бета-пакет azure SDK.

  5. Проверьте результаты. Предполагая, что поле вектора помечается как извлекаемое, используйте обозреватель поиска или REST API для проверки соответствия содержимого поля типу данных. Не забудьте использовать правильную 2024-03-01-preview версию API для запроса, в противном случае новые свойства не отображаются.

Чтобы проверка размер векторного индекса, используйте портал Azure или предварительную версию 2024-03-01-preview.

Примечание.

Тип данных поля используется для создания структуры физических данных. Если вы хотите изменить тип данных позже, удалите и перестроите индекс или создайте второе поле с новым определением.

Вариант 2. Установка stored свойства для удаления извлекаемого хранилища

Это stored свойство является новым логическим определением поля вектора, которое определяет, выделяется ли хранилище для извлекаемого содержимого поля вектора. Если в ответе запроса не требуется векторное содержимое, можно сохранить до 50 процентов хранилища на поле, установив stored значение false.

Поскольку векторы не доступны для чтения, они обычно опущены в ответе запроса, отображаемом на странице поиска. Однако если вы используете векторы в нижней обработке, например передача результатов запроса в модель или процесс, использующий векторное содержимое, следует задать 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 задается во время создания индекса в векторных полях и является необратимым. Если вы хотите получить содержимое позже, необходимо удалить и перестроить индекс или создать и загрузить новое поле с новым атрибутом.

  • По умолчанию задано значение true и retrievable задано stored значение false. В конфигурации по умолчанию сохраняется извлекаемая копия, но она не возвращается автоматически в результатах. Если stored значение равно true, вы можете переключаться retrievable между true и false в любое время, не перестроив индекс. Если stored значение равно false, retrievable должно иметь значение false и не может быть изменено.

Вариант 3. Настройка скалярной квантизации

Встроенная скалярная квантизация рекомендуется, так как она сокращает требования к памяти и хранилищу дисков, а также добавляет повторное использование и чрезмерное использование для смещения последствий меньшего индекса. Встроенная скалярная квантизация может применяться к векторным полям, Float32 содержащим или Float16 данным.

Чтобы использовать встроенное векторное сжатие:

  • Добавьте vectorSearch.compressions в индекс поиска. Алгоритм сжатия, поддерживаемый в этой предварительной версии, — скалярная квантизация.
  • Задайте необязательные свойства, чтобы уменьшить влияние индексации потери. Оба rerankWithOriginalVectors и defaultOversampling обеспечивают оптимизацию во время выполнения запроса.
  • Добавьте vectorSearch.profiles.compression в новый профиль вектора.
  • Назначьте новый профиль вектора новому полю вектора.

Добавление параметров сжатия и установка необязательных свойств

В определении индекса, созданном с помощью REST API 2024-03-01-preview, добавьте 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. Это необязательное свойство. Значение по умолчанию — "истина".

  • 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до, поэтому убедитесь, что содержимое равно Float32 или Float16.

    В службе "Поиск ИИ Azure" эквиваленты Float32 модели данных сущностей (EDM) и Float16 типов Collection(Edm.Single)Collection(Edm.Half)соответственно.

    {
       "name": "DescriptionVector",
       "type": "Collection(Edm.Single)",
       "searchable": true,
       "retrievable": true,
       "dimensions": 1536,
       "vectorSearchProfile": "my-vector-profile"
    }
    
  3. Загрузите индекс с помощью индексаторов для индексирования модели извлечения или API-интерфейсов для индексации модели принудительной отправки.

Скалярная квантизация уменьшает разрешение каждого числа в каждом векторном внедрении. Вместо описания каждого числа в виде 32-разрядного числа с плавающей запятой используется 8-разрядное целое число. Он определяет диапазон чисел (обычно 99-й процентиль минимального и максимального) и делит их на конечное число уровней или ячейки, присваивая каждому ячейке идентификатор. В 8-разрядной скалярной квантизации существует 2^8 или 256, возможные ячейки.

Каждый компонент вектора сопоставляется с ближайшим репрезентативным значением в этом наборе уровней квантизации в процессе с округлением реального числа до ближайшего целого числа. В квантизованном 8-разрядном векторе номер идентификатора стоит вместо исходного значения. После квантизации каждый вектор представлен массивом идентификаторов для ячеек, к которым принадлежат его компоненты. Эти квантизованные векторы требуют гораздо меньше битов для хранения по сравнению с исходным вектором, что снижает требования к хранилищу и объем памяти.

Пример индекса с 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" }
                    ]
                }
            }
        ]
    }
}

Запрос к квантизованному полю вектора с помощью переполнения

Синтаксис запроса в этом примере применяется к полям векторов с помощью встроенной скалярной квантизации. По умолчанию поля векторов, использующие скалярную квантизацию, также используют rerankWithOriginalVectors и defaultOversampling устраняют последствия меньшего векторного индекса. Эти параметры указаны в индексе поиска.

В запросе можно переопределить значение по умолчанию. Например, если defaultOversampling значение равно 10.0, его можно изменить на что-то другое в запросе запроса.

Параметр oversampling можно задать, даже если индекс не имеет явного rerankWithOriginalVectors значения или defaultOversampling определения. Предоставление 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 значение или вводит превышение значения во время запроса, даже если конфигурация сжатия индекса не указала параметры чрезмерного использования или повторного использования.

См. также