Поделиться через


Сжатие векторов с помощью скалярной или двоичной квантизации

Поиск ИИ Azure поддерживает скалярную и двоичную квантизацию для уменьшения размера векторов в индексе поиска. Рекомендуется использовать квантизацию, так как она сокращает объем памяти и дискового хранилища для внедрения float16 и float32. Чтобы компенсировать эффекты потерь сжатия, можно добавить передискретизацию и пересчет.

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

  • Начните с векторных полей и конфигурации vectorSearch к индексу.
  • Добавить vectorSearch.compressions
  • Добавьте scalarQuantization- или binaryQuantization-конфигурацию и присвойте ей имя
  • Задайте необязательные свойства для смягчения последствий неточного индексирования.
  • Создание нового профиля вектора, использующего именованную конфигурацию
  • Создание поля вектора с новым профилем вектора
  • Загрузите индекс с данными float32 или float16, которые квантизованы во время индексирования с заданной конфигурацией
  • При необходимости запросите квантизированные данные с помощью параметра oversampling. Если векторное поле не указывает передискретизацию в своём определении, её можно добавить во время выполнения запроса.

Подсказка

Поиск ИИ Azure: сокращение затрат на вектор до 92,5% с помощью новых методов сжатия сравнивает стратегии сжатия и объясняет экономию в хранилище и затратах. Она также включает метрики для измерения релевантности на основе нормализованного дисконтированного кумулятивного прироста (NDCG), демонстрируя, что данные можно сжимать без ущерба для качества поиска.

Предварительные условия

  • Векторные поля в индексе поиска с vectorSearch конфигурацией, указывающей алгоритм иерархических навигационных небольших миров (HNSW) или исчерпывающий алгоритм K-Ближайшего соседа (KNN) и новый профиль вектора.

Поддерживаемые методы квантизации

Квантизация применяется к векторным полям, которые принимают векторы с плавающей запятой. В примерах в этой статье тип данных поля - Collection(Edm.Single) для входящих float32 внедрений, и float16 также поддерживается. При получении векторов в поле с настроенным сжатием подсистема выполняет квантизацию, чтобы уменьшить объем векторных данных в памяти и на диске.

Поддерживаются два типа квантизации:

  • Скалярная квантизация сжимает значения с плавающей запятой в более узкие типы данных. Поиск ИИ в настоящее время поддерживает int8, который составляет 8 битов, уменьшая размер векторного индекса четыре раза.

  • Двоичная квантизация преобразует числа с плавающей точкой в двоичные биты, каждый из которых занимает 1 бит. Это приводит к сокращению размера индекса вектора до 28 раз.

Примечание.

Хотя бесплатные сервисы поддерживают квантизацию, они не предоставляют полную экономию хранилища из-за ограниченного объема.

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

Версии API определяют, какое поведение пересчёта действует в вашем коде. Новейший API предварительной версии поддерживает новый подход к пересчёту оценок для двоичной квантизации. Индексы, созданные с помощью 2025-03-01-preview, могут использовать новые методы пересчёта.

Версия API Тип квантизации Свойства переоценки
2024-07-01 Скалярная и двоичная квантизация по векторным индексам, построенным с использованием иерархически навигаемых графов Small World (HNSW) для поиска сходства. rerankWithOriginalVectors
2024-11-01-превью Скалярная и двоичная квантизация на графах HNSW rescoringOptions.enableRescoring и rescoreStorageMethod.preserveOriginals.
2025-03-01-превью Двоичная квантизация на графах HNSW Предыдущие сочетания параметров по-прежнему поддерживаются, но двоичная квантизация теперь может быть изменена при удалении исходных внедренных значений: rescoringOptions.enableRescoringrescoringOptions.rescoreStorageMethod=discardOriginals

Только графы HNSW позволяют пересчет. Исчерпывающий KNN не поддерживает пересчет оценок.

Обобщенный процесс пересчета:

  1. Векторный запрос выполняется по сжатым векторным полям.
  2. Векторный запрос возвращает лучшие k кандидатов, полученных при перерасчете.
  3. k суперсэмплированные кандидаты переоцениваются с помощью несжатых исходных векторов или скалярного произведения двоичной квантизации. 1. После пересчета результаты корректируются таким образом, чтобы сначала отображались более релевантные совпадения.

Добавление "сжатия" в индекс поиска

В этом разделе объясняется, как указать vectorsSearch.compressions раздел в индексе. В следующем примере показано частичное определение индекса с коллекцией полей, включающей векторное поле.

Пример сжатия включает оба scalarQuantization или binaryQuantization. Можно указать столько конфигураций сжатия, сколько вам нужно, а затем назначить нужные векторным профилям.

Синтаксис для vectorSearch.Compressions варьируется между стабильными и предварительными версиями REST API: предварительная версия добавляет больше возможностей для оптимизации хранилища, а также вносит изменения в существующий синтаксис. Обратная совместимость сохраняется с помощью внутренних сопоставлений API, но мы рекомендуем использовать новые свойства в коде, предназначенные для версии 2024-11-01-preview и будущих версий.

Используйте REST API создания индекса или обновления индекса для настройки параметров сжатия.

POST https://[servicename].search.windows.net/indexes?api-version=2024-07-01

{
  "name": "my-index",
  "fields": [
    { "name": "Id", "type": "Edm.String", "key": true, "retrievable": true, "searchable": true, "filterable": true },
    { "name": "content", "type": "Edm.String", "retrievable": true, "searchable": true },
    { "name": "vectorContent", "type": "Collection(Edm.Single)", "retrievable": false, "searchable": true, "dimensions": 1536,"vectorSearchProfile": "vector-profile-1"},
  ],
  "vectorSearch": {
    "profiles": [ 
      {
          "name": "vector-profile-1",
          "algorithm": "use-hnsw",
          "compression": "use-scalar"
      }
    ],
    "algorithms": [ 
      {
        "name": "use-hnsw",
        "kind": "hnsw",
        "hnswParameters": { },
        "exhaustiveKnnParameters": null
      }
    ],
    "compressions": [
      {
        "name": "use-scalar",
        "kind": "scalarQuantization",
        "scalarQuantizationParameters": {
          "quantizedDataType": "int8"
        },
        "rerankWithOriginalVectors": true,
        "defaultOversampling": 10
      },
      {
        "name": "use-binary",
        "kind": "binaryQuantization",
        "rerankWithOriginalVectors": true,
        "defaultOversampling": 10
      }
    ]
  }
}

Основные моменты:

  • kind должен быть установлен на scalarQuantization или binaryQuantization.

  • rerankWithOriginalVectors использует исходные несжатые векторы для пересчета сходства и повторного вычисления лучших результатов, возвращаемых первоначальным поисковым запросом. Несжатые векторы существуют в индексе поиска, даже если stored ложно. Это необязательное свойство. Значение по умолчанию — true.

  • defaultOversampling рассматривает более широкий набор потенциальных результатов для компенсации уменьшения объема информации, вызванного квантизацией. Формула потенциальных результатов состоит из k запроса с мультипликатором передискретизации. Например, если запрос указывает значение k равное 5, а дискретизация составляет 20, то запрос фактически запрашивает 100 документов для повторной ранжировки, используя исходный несжатый вектор для этой цели. Возвращаются только результаты k, изменённые в порядке согласно рейтингу. Это необязательное свойство. Значение по умолчанию — 4.

  • quantizedDataType является необязательным и применяется только к скалярной квантизации. Если вы добавите его, его необходимо установить в значение int8. Это единственный примитивный тип данных, поддерживаемый для скалярной квантизации в настоящее время. По умолчанию — int8.

Добавление алгоритма поиска векторов

Алгоритм HNSW или eKNN можно использовать в REST API 2024-11-01-preview или более поздней версии. Для стабильной версии используйте только HNSW. Если требуется пересчет оценки, необходимо выбрать HNSW.

"vectorSearch": {
    "profiles": [ ],
    "algorithms": [
      {
          "name": "use-hnsw",
          "kind": "hnsw",
          "hnswParameters": {
              "m": 4,
              "efConstruction": 400,
              "efSearch": 500,
              "metric": "cosine"
          }
      }
    ],
     "compressions": [ <see previous section>] 
}

Создание и назначение нового профиля вектора

Чтобы использовать новую конфигурацию квантизации, необходимо создать новый профиль вектора. Создание нового профиля вектора необходимо для создания сжатых индексов в памяти. Новый профиль использует HNSW.

  1. В том же определении индекса создайте новый профиль вектора и добавьте свойство сжатия и алгоритм. Ниже приведены два профиля, по одному для каждого подхода квантизации.

    "vectorSearch": {
        "profiles": [
           {
              "name": "vector-profile-hnsw-scalar",
              "compression": "use-scalar", 
              "algorithm": "use-hnsw",
              "vectorizer": null
           },
           {
              "name": "vector-profile-hnsw-binary",
              "compression": "use-binary", 
              "algorithm": "use-hnsw",
              "vectorizer": null
           }
         ],
         "algorithms": [  <see previous section> ],
         "compressions": [ <see previous section> ] 
    }
    
  2. Назначьте профиль вектора новому полю вектора. Тип данных поля — float32 или float16.

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

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

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

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

Двоичная квантизация сжимает высокомерные векторы путем представления каждого компонента в виде одного бита либо 0, либо 1. Этот метод резко сокращает объем памяти и ускоряет операции сравнения векторов, которые являются важными для задач поиска и извлечения. Тесты производительности показывают сокращение размера векторного индекса до 96 %.

Это особенно эффективно для эмбеддингов с размерностями больше 1024. Для небольших измерений рекомендуется протестировать качество двоичной квантизации или попробовать скалярную. Кроме того, мы обнаружили, что двоичная квантизация выполняется очень хорошо, когда внедрение сосредоточено примерно на нуле. Большинство популярных моделей внедрения, таких как OpenAI, Cohere и Mistral, сосредоточены около нуля.

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

Синтаксис запроса для сжатого или квантизованного поля вектора совпадает с несжатыми полями векторов, если вы не хотите переопределять параметры, связанные с передискретизацией и пересчётом. Вы можете добавить параметр oversampling для вызова передискретизации и пересчета оценки во время запроса.

Помните, что в индексе содержится определение параметров сжатия векторов, которые имеют настройки для rerankWithOriginalVectors и defaultOversampling, чтобы уменьшить последствия сжатия с потерями. Значения по умолчанию можно переопределить, чтобы изменить поведение во время запроса. Например, если defaultOversampling значение равно 10.0, его можно изменить на что-то другое в запросе запроса.

Параметр oversampling можно задать, даже если индекс не имеет явного определения rerankWithOriginalVectors или defaultOversampling. Предоставление oversampling во время запроса переопределяет параметры индекса для этого запроса и выполняет запрос с эффективным значением rerankWithOriginalVectors true.

POST https://[service-name].search.windows.net/indexes/demo-index/docs/search?api-version=2024-07-01

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

Основные моменты:

  • Применяется к полям векторов, которые проходят сжатие векторов в соответствии с назначением профиля вектора.

  • Переопределяет defaultOversampling значение или вводит дополнительную выборку во время запроса, даже если конфигурация сжатия индекса не указала параметры дополнительной выборки или перераспределения.