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


Векторы индексов и запросов в Azure Cosmos DB для NoSQL в Java

Прежде чем использовать индексирование векторов и поиск, необходимо сначала включить эту функцию. В этой статье рассматриваются следующие задачи:

  1. Включение векторного поиска в Azure Cosmos DB для NoSQL
  2. Настройка контейнера Azure Cosmos DB для поиска векторов
  3. Разработка векторной политики внедрения
  4. Добавление векторных индексов в политику индексирования контейнеров
  5. Создание контейнера с векторными индексами и политикой внедрения векторов
  6. Выполнение векторного поиска хранимых данных

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

Необходимые компоненты

Включение функции

Для поиска векторов для Azure Cosmos DB для NoSQL требуется включение функций. Выполните следующие действия, чтобы зарегистрировать:

  1. Перейдите на страницу ресурсов Azure Cosmos DB для NoSQL.
  2. В меню "Параметры" выберите область "Компоненты".
  3. Выберите "Векторный поиск в Azure Cosmos DB для NoSQL".
  4. Ознакомьтесь с описанием функции, чтобы подтвердить ее включение.
  5. Выберите "Включить", чтобы включить векторный поиск в Azure Cosmos DB для NoSQL.

Совет

Кроме того, используйте Azure CLI для обновления возможностей учетной записи для поддержки поиска векторов NoSQL.

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

Примечание.

Запрос на регистрацию будет автоматически утвержден; однако для принятия в силу может потребоваться 15 минут.

В следующих шагах предполагается, что вы знаете, как настроить учетную запись NoSQL Cosmos DB и создать базу данных. Функция поиска векторов в настоящее время не поддерживается в существующих контейнерах, поэтому необходимо создать новый контейнер и указать политику внедрения вектора на уровне контейнера и политику индексирования векторов во время создания контейнера.

Давайте рассмотрим пример создания базы данных для интернет-магазина книг, и вы храните название, автор, ISBN и описание каждой книги. Мы также определяем два свойства, которые содержат векторные внедрения. Первым является свойство contentVector, которое содержит вставки текста, созданные из текстового содержимого книги (например, объединение свойств "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] 
} 

Сначала создайте CosmosContainerProperties объект.

CosmosContainerProperties collectionDefinition = new CosmosContainerProperties(UUID.randomUUID().toString(), "Partition_Key_Def");

Создание политики внедрения вектора для контейнера

Затем необходимо определить политику вектора контейнера. Эта политика предоставляет сведения, используемые для информирования обработчика запросов Azure Cosmos DB о том, как обрабатывать свойства векторов в системных функциях VectorDistance. Это также сообщает политике индексирования векторов необходимых сведений, следует указать его. Следующие сведения включаются в содержащуюся векторную политику:

  • "path": путь свойства, содержащий векторы
  • "datatype": тип элементов вектора (по умолчанию Float32)
  • "измерения": длина каждого вектора в пути (по умолчанию 1536)
  • "distanceFunction": метрика, используемая для вычисления расстояния или сходства (по умолчанию Cosine)

В нашем примере с сведениями о книге векторная политика может выглядеть как пример JSON:

// Creating vector embedding policy
CosmosVectorEmbeddingPolicy cosmosVectorEmbeddingPolicy = new CosmosVectorEmbeddingPolicy();

CosmosVectorEmbedding embedding1 = new CosmosVectorEmbedding();
embedding1.setPath("/coverImageVector");
embedding1.setDataType(CosmosVectorDataType.FLOAT32);
embedding1.setDimensions(8L);
embedding1.setDistanceFunction(CosmosVectorDistanceFunction.COSINE);

CosmosVectorEmbedding embedding2 = new CosmosVectorEmbedding();
embedding2.setPath("/contentVector");
embedding2.setDataType(CosmosVectorDataType.FLOAT32);
embedding2.setDimensions(10L);
embedding2.setDistanceFunction(CosmosVectorDistanceFunction.DOT_PRODUCT);

cosmosVectorEmbeddingPolicy.setCosmosVectorEmbeddings(Arrays.asList(embedding1, embedding2, embedding3));

collectionDefinition.setVectorEmbeddingPolicy(cosmosVectorEmbeddingPolicy);

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

После решения путей внедрения векторов необходимо добавить в политику индексирования векторные индексы. В настоящее время функция поиска векторов для Azure Cosmos DB для NoSQL поддерживается только в новых контейнерах, поэтому необходимо применить политику вектора во время создания контейнера и ее нельзя изменить позже. В этом примере политика индексирования будет выглядеть примерно так:

IndexingPolicy indexingPolicy = new IndexingPolicy();
indexingPolicy.setIndexingMode(IndexingMode.CONSISTENT);
ExcludedPath excludedPath1 = new ExcludedPath("/coverImageVector/*");
ExcludedPath excludedPath2 = new ExcludedPath("/contentVector/*");
indexingPolicy.setExcludedPaths(ImmutableList.of(excludedPath1, excludedPath2));

IncludedPath includedPath1 = new IncludedPath("/*");
indexingPolicy.setIncludedPaths(Collections.singletonList(includedPath1));

// Creating vector indexes
CosmosVectorIndexSpec cosmosVectorIndexSpec1 = new CosmosVectorIndexSpec();
cosmosVectorIndexSpec1.setPath("/coverImageVector");
cosmosVectorIndexSpec1.setType(CosmosVectorIndexType.QUANTIZED_FLAT.toString());

CosmosVectorIndexSpec cosmosVectorIndexSpec2 = new CosmosVectorIndexSpec();
cosmosVectorIndexSpec2.setPath("/contentVector");
cosmosVectorIndexSpec2.setType(CosmosVectorIndexType.DISK_ANN.toString());

indexingPolicy.setVectorIndexes(Arrays.asList(cosmosVectorIndexSpec1, cosmosVectorIndexSpec2, cosmosVectorIndexSpec3));

collectionDefinition.setIndexingPolicy(indexingPolicy);

Наконец, создайте контейнер с политикой индекса контейнера и политикой векторного индекса.

database.createContainer(collectionDefinition).block();

Внимание

Векторный путь, добавленный в раздел "исключенныеPaths" политики индексирования, чтобы обеспечить оптимизированную производительность для вставки. Не добавляя векторный путь к "исключеннымPaths", будет взиматься более высокая плата за единицу запросов и задержку для вставок векторов.

Выполнение запроса поиска сходства векторов

Создав контейнер с требуемой политикой векторов и вставив в контейнер векторные данные, можно выполнить векторный поиск с помощью функции системы "Вектор расстояние " в запросе. Предположим, что вы хотите искать книги о рецептах продуктов питания, глядя на описание, сначала необходимо получить внедрения текста запроса. В этом случае может потребоваться создать внедрения для текста запроса — "рецепт еды". После внедрения поискового запроса его можно использовать в функции 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])   

Этот запрос извлекает названия книги, а также оценки сходства в отношении запроса. Ниже приведен пример в Java:

float[] embedding = new float[10];
for (int i = 0; i < 10; i++) {
    array[i] = i + 1;
}
ArrayList<SqlParameter> paramList = new ArrayList<SqlParameter>();
  paramList.add(new SqlParameter("@embedding", embedding));
  SqlQuerySpec querySpec = new SqlQuerySpec("SELECT c.title, VectorDistance(c.contentVector,@embedding) AS SimilarityScore  FROM c ORDER BY VectorDistance(c.contentVector,@embedding)", paramList);
  CosmosPagedIterable<Family> filteredFamilies = container.queryItems(querySpec, new CosmosQueryRequestOptions(), Family.class);

  if (filteredFamilies.iterator().hasNext()) {
      Family family = filteredFamilies.iterator().next();
      logger.info(String.format("First query result: Family with (/id, partition key) = (%s,%s)",family.getId(),family.getLastName()));
  }

Следующие шаги