Almacén vectorial en Azure Cosmos DB for MongoDB de núcleo virtual

SE APLICA A: núcleo virtual de MongoDB

Use base de datos vectorial integrada en Azure Cosmos DB para el núcleo virtual de MongoDB para conectar sin problemas las aplicaciones basadas en inteligencia artificial con los datos almacenados en Azure Cosmos DB. Esta integración puede incluir aplicaciones que hayas creado utilizando incrustaciones de Azure OpenAI. La base de datos vectorial integrada de forma nativa permite almacenar, indexar y consultar de forma eficaz los datos vectoriales de alta dimensión que se almacenan directamente en Azure Cosmos DB para núcleo virtual de MongoDB, junto con los datos originales a partir de los cuales se crean los datos vectoriales. Elimina la necesidad de transferir los datos a almacenes de vectores alternativos y conlleva costos adicionales.

¿Qué es un almacén de vectores?

Un almacén de vectores o base de datos vectoriales es una base de datos diseñada para almacenar y administrar incrustaciones de vectores, que son representaciones matemáticas de datos en un espacio de alta dimensión. En este espacio, cada dimensión corresponde a una característica de los datos y es posible que se usen decenas de miles de dimensiones para representar datos sofisticados. La posición de un vector en este espacio representa sus características. Se pueden vectorizar palabras, frases o documentos completos e imágenes, audio y otros tipos de datos.

¿Cómo funciona un almacén de vectores?

En un almacén de vectores, los algoritmos de búsqueda vectorial se usan para indexar e insertar consultas. Entre algunos algoritmos de vector de búsqueda conocidos se incluyen los mundos pequeños navegables jerárquicos (HNSW), archivo invertido (IVF), DiskANN, etc. La búsqueda vectorial es un método que ayuda a encontrar elementos similares en función de sus características de datos en lugar de coincidencias exactas en un campo de propiedad. Esta técnica es útil en aplicaciones como la búsqueda de texto similar, la búsqueda de imágenes relacionadas, la realización de recomendaciones o incluso la detección de anomalías. Se utiliza para consultar las incrustaciones vectoriales (listas de números) de los datos que ha creado mediante un modelo de Machine Learning con una API de inserciones. Algunos ejemplos de API de inserción podrían ser Incrustaciones de OpenAI de Azure o Hugging Face en Azure. El vector de búsqueda mide la distancia entre los vectores de datos y el vector de consulta. Los vectores de datos más cercanos al vector de consulta son los más similares semánticamente.

En la base de datos vectorial integrada de Azure Cosmos DB para núcleo virtual de MongoDB, las incrustaciones se pueden almacenar, indexar y consultar junto con los datos originales. Este enfoque elimina el coste adicional de replicar datos en una base de datos de vectores pura independiente. Además, esta arquitectura reúne las inserciones vectoriales y los datos originales, lo que facilita aún más las operaciones de datos multimodales; también permite una mayor coherencia, escala y rendimiento de los datos.

Crear un índice vectorial

Para realizar la búsqueda de similitud vectorial sobre las propiedades vectoriales de los documentos, primero tendrá que crear un índice vectorial.

Creación de un índice vectorial con HNSW

Puede crear índices (Hierarchical Navigable Small World) en niveles de clúster M40 y versiones posteriores. Para crear un índice HNSW, debe crear un índice vectorial con el parámetro "kind" establecido en "vector-hnsw" siguiendo esta plantilla:

{ 
    "createIndexes": "<collection_name>",
    "indexes": [
        {
            "name": "<index_name>",
            "key": {
                "<path_to_property>": "cosmosSearch"
            },
            "cosmosSearchOptions": { 
                "kind": "vector-hnsw", 
                "m": <integer_value>, 
                "efConstruction": <integer_value>, 
                "similarity": "<string_value>", 
                "dimensions": <integer_value> 
            } 
        } 
    ] 
}
Campo Tipo Description
index_name string Nombre único del índice.
path_to_property string Ruta de acceso a la propiedad que contiene el vector. Esta ruta de acceso puede ser una propiedad de nivel superior o una ruta de acceso de notación de puntos. Si se usa una ruta de acceso de notación de puntos, no pueden ser matrices todos los elementos que no son hoja. Los vectores deben ser number[] para indexarse y devolverse en los resultados del vector de búsqueda.
kind cadena Tipo de índice vectorial que se va a crear. Las opciones son vector-ivf y vector-hnsw. Observe que vector-ivf está disponible en todos los niveles de clúster y que vector-hnsw está disponible en los niveles de clúster M40 y versiones posteriores.
m integer El número máximo de conexiones por capa (de forma predeterminada 16; el valor mínimo es 2 y el valor máximo, 100). Un m mayor es adecuado para conjuntos de datos con requisitos de alta dimensionalidad o alta precisión.
efConstruction integer es el tamaño de la lista de candidatos dinámicos para construir el grafo (de forma predeterminada 64; el valor mínimo es 4 y el valor máximo, 1000). Un efConstruction mayor dará como resultado una mejor calidad del índice y una mayor precisión, pero también aumentará el tiempo necesario para compilar el índice. efConstruction tiene que ser al menos 2 * m
similarity cadena Métrica de similitud que se va a usar con el índice. Las opciones posibles son COS (distancia coseno), L2 (distancia euclidiana) o IP (producto interno).
dimensions integer Número de dimensiones para la similitud vectorial. El número máximo de dimensiones admitidas es 2000.

Hacer una búsqueda de vectores con HNSW

Para hacer una búsqueda vectorial, use la fase de canalización de agregación $search de la consulta con el operador cosmosSearch.

{
    "$search": {
        "cosmosSearch": {
            "vector": <query_vector>,
            "path": "<path_to_property>",
            "k": <num_results_to_return>,
            "efSearch": <integer_value>
        },
    }
  }
}

Campo Tipo Descripción
efSearch integer Tamaño de la lista de candidatos dinámicos para la búsqueda (de forma predeterminada 40). Un valor más alto proporciona una mejor recuperación a costa de velocidad.
k integer Número de resultados que se devolverán. debe ser igual o menor que efSearch

Nota:

La creación de un índice HSNW con grandes conjuntos de datos puede provocar que el recurso de núcleo virtual de Azure Cosmos DB for MongoDB se quede sin memoria, o que se reduzca el rendimiento de otras operaciones que se ejecutan en la base de datos. Si se encuentra con tales problemas, para mitigarlos, escale el recurso a un nivel de clúster superior o reduzca el tamaño del conjunto de datos.

Creación de un índice vectorial con IVF

Para crear un índice vectorial mediante el algoritmo IVF (Archivo invertido), utilice la plantilla createIndexes siguiente y establezca el parámetro "kind" en "vector-ivf":

{
  "createIndexes": "<collection_name>",
  "indexes": [
    {
      "name": "<index_name>",
      "key": {
        "<path_to_property>": "cosmosSearch"
      },
      "cosmosSearchOptions": {
        "kind": "vector-ivf",
        "numLists": <integer_value>,
        "similarity": "<string_value>",
        "dimensions": <integer_value>
      }
    }
  ]
}
Campo Tipo Description
index_name string Nombre único del índice.
path_to_property string Ruta de acceso a la propiedad que contiene el vector. Esta ruta de acceso puede ser una propiedad de nivel superior o una ruta de acceso de notación de puntos. Si se usa una ruta de acceso de notación de puntos, no pueden ser matrices todos los elementos que no son hoja. Los vectores deben ser number[] para indexarse y devolverse en los resultados del vector de búsqueda.
kind cadena Tipo de índice vectorial que se va a crear. Las opciones son vector-ivf y vector-hnsw. Observe que vector-ivf está disponible en todos los niveles de clúster y que vector-hnsw está disponible en los niveles de clúster M40 y versiones posteriores.
numLists integer Este entero es el número de clústeres que usa el índice del archivo invertido (IVF) para agrupar los datos vectoriales. Se recomienda establecer numLists en documentCount/1000 para un máximo de 1 millón de documentos y en sqrt(documentCount) para más de 1 millón. El uso de un valor de numLists igual a 1 es similar a realizar una búsqueda por fuerza bruta, la cual tiene un rendimiento limitado.
similarity string Métrica de similitud que se va a usar con el índice. Las opciones posibles son COS (distancia coseno), L2 (distancia euclidiana) o IP (producto interno).
dimensions integer Número de dimensiones para la similitud vectorial. El número máximo de dimensiones admitidas es 2000.

Importante

Establecer correctamente el parámetro numLists es importante para lograr una buena precisión y rendimiento. Se recomienda establecer numLists en documentCount/1000 para un máximo de 1 millón de documentos y en sqrt(documentCount) para más de 1 millón.

A medida que crece el número de elementos de la base de datos, debe ajustar numLists para que sea mayor para lograr un buen rendimiento de latencia del vector de búsqueda.

Si está experimentando con un escenario nuevo o creando una demo pequeña, puede empezar con numLists establecido en 1 para realizar una búsqueda por fuerza bruta en todos los vectores. Esto le proporcionará los resultados más precisos del vector de búsqueda, pero tenga en cuenta que la velocidad de búsqueda y la latencia serán lentas. Después de la configuración inicial, debe continuar y ajustar el parámetro numLists mediante las instrucciones anteriores.

Realización de una búsqueda de vectores con IVF

Para realizar una búsqueda vectorial, use la fase de canalización de agregación $search en una consulta de MongoDB. Para usar el índice de cosmosSearch, use el nuevo operador de cosmosSearch.

{
  {
  "$search": {
    "cosmosSearch": {
        "vector": <query_vector>,
        "path": "<path_to_property>",
        "k": <num_results_to_return>,
      },
      "returnStoredSource": True }},
  {
    "$project": { "<custom_name_for_similarity_score>": {
           "$meta": "searchScore" },
            "document" : "$$ROOT"
        }
  }
}

Para recuperar la puntuación de similitud (searchScore) junto con los documentos encontrados por la búsqueda vectorial, use el $project operador de inclusión searchScore y cámbiele el nombre por <custom_name_for_similarity_score> en los resultados. A continuación, el documento también se proyecta como objeto anidado. Tenga en cuenta que la puntuación de similitud se calcula mediante la métrica definida en el índice vectorial.

Importante

Los vectores deben ser number[] para indexarse. El uso de otro tipo, como double[], impide que el documento se indexe. Los documentos no indexados no se devolverán en el resultado de un vector de búsqueda.

Ejemplo mediante un índice HNSW.

En los ejemplos siguientes se describe cómo indexar vectores, agregar documentos con propiedades vectoriales, realizar una búsqueda vectorial y recuperar la configuración del índice.

use test;

db.createCollection("exampleCollection");

db.runCommand({ 
    "createIndexes": "exampleCollection",
    "indexes": [
        {
            "name": "VectorSearchIndex",
            "key": {
                "contentVector": "cosmosSearch"
            },
            "cosmosSearchOptions": { 
                "kind": "vector-hnsw", 
                "m": 16, 
                "efConstruction": 64, 
                "similarity": "COS", 
                "dimensions": 3
            } 
        } 
    ] 
});

Este comando crea un índice HNSW con la propiedad contentVector en los documentos almacenados en la colección especificada, exampleCollection. La propiedad cosmosSearchOptions especifica los parámetros del índice vectorial HNSW. Si el documento tiene el vector almacenado en una propiedad anidada, puede establecer esta propiedad mediante una ruta de acceso de notación de puntos. Por ejemplo, puede usar text.contentVector si contentVector es una subpropiedad de text.

Adición de vectores a la base de datos

Para agregar vectores a la colección de la base de datos, primero debe crear las incrustaciones mediante su propio modelo, las Incrustaciones de OpenAI de Azure u otra API (como Hugging Face en Azure). En este ejemplo se agregan nuevos documentos con incrustaciones de ejemplo:

db.exampleCollection.insertMany([
  {name: "Eugenia Lopez", bio: "Eugenia is the CEO of AdvenureWorks.", vectorContent: [0.51, 0.12, 0.23]},
  {name: "Cameron Baker", bio: "Cameron Baker CFO of AdvenureWorks.", vectorContent: [0.55, 0.89, 0.44]},
  {name: "Jessie Irwin", bio: "Jessie Irwin is the former CEO of AdventureWorks and now the director of the Our Planet initiative.", vectorContent: [0.13, 0.92, 0.85]},
  {name: "Rory Nguyen", bio: "Rory Nguyen is the founder of AdventureWorks and the president of the Our Planet initiative.", vectorContent: [0.91, 0.76, 0.83]},
]);

Siguiendo con el ejemplo anterior, cree otro vector, queryVector. La búsqueda vectorial mide la distancia entre queryVector y los vectores en la ruta de acceso contentVector de los documentos. Puede establecer el número de resultados que devuelve la búsqueda estableciendo el parámetro k, que se establece en 2 aquí. También puede establecer efSearch, que es un entero que controla el tamaño de la lista de vectores candidatos. Un valor mayor puede mejorar la precisión, pero la búsqueda será más lenta como resultado. Se trata de un parámetro opcional, con un valor predeterminado de 40.

const queryVector = [0.52, 0.28, 0.12];
db.exampleCollection.aggregate([
  {
    "$search": {
        "cosmosSearch": {
            "vector": "queryVector",
            "path": "contentVector",
            "k": 2,
            "efSearch": 40
        },
    }
  }
}
]);

En este ejemplo se realiza una búsqueda vectorial mediante queryVector como entrada a través del shell de Mongo. El resultado de la búsqueda es una lista de los dos elementos más similares al vector de consulta, ordenados por sus puntuaciones de similitud.

[
  {
    similarityScore: 0.9465376,
    document: {
      _id: ObjectId("645acb54413be5502badff94"),
      name: 'Eugenia Lopez',
      bio: 'Eugenia is the CEO of AdvenureWorks.',
      vectorContent: [ 0.51, 0.12, 0.23 ]
    }
  },
  {
    similarityScore: 0.9006955,
    document: {
      _id: ObjectId("645acb54413be5502badff97"),
      name: 'Rory Nguyen',
      bio: 'Rory Nguyen is the founder of AdventureWorks and the president of the Our Planet initiative.',
      vectorContent: [ 0.91, 0.76, 0.83 ]
    }
  }
]

Obtener definiciones de índice vectorial

Para recuperar la definición del índice vectorial de la colección, use el comando listIndexes:

db.exampleCollection.getIndexes();

Es este ejemplo, se devuelve vectorIndex con todos los parámetros de cosmosSearch que se usaron para crear el índice:

[
  { v: 2, key: { _id: 1 }, name: '_id_', ns: 'test.exampleCollection' },
  {
    v: 2,
    key: { contentVector: 'cosmosSearch' },
    name: 'vectorSearchIndex',
    cosmosSearch: {
      kind: 'vector-hnsw',
      m: 40,
      efConstruction: 64
      similarity: 'COS',
      dimensions: 3
    },
    ns: 'test.exampleCollection'
  }
]

Ejemplo mediante un índice IVF

En los ejemplos siguientes se describe cómo indexar vectores, agregar documentos con propiedades vectoriales, realizar una búsqueda vectorial y recuperar la configuración del índice.

Crear un índice vectorial

use test;

db.createCollection("exampleCollection");

db.runCommand({
  createIndexes: 'exampleCollection',
  indexes: [
    {
      name: 'vectorSearchIndex',
      key: {
        "vectorContent": "cosmosSearch"
      },
      cosmosSearchOptions: {
        kind: 'vector-ivf',
        numLists: 3,
        similarity: 'COS',
        dimensions: 3
      }
    }
  ]
});

Este comando crea un índice de vector-ivf con la propiedad vectorContent en los documentos almacenados en la colección especificada, exampleCollection. La propiedad cosmosSearchOptions especifica los parámetros para el índice de vector IVF. Si el documento tiene el vector almacenado en una propiedad anidada, puede establecer esta propiedad mediante una ruta de acceso de notación de puntos. Por ejemplo, puede usar text.vectorContent si vectorContent es una subpropiedad de text.

Adición de vectores a la base de datos

Para agregar vectores a la colección de la base de datos, primero debe crear las incrustaciones mediante su propio modelo, las Incrustaciones de OpenAI de Azure u otra API (como Hugging Face en Azure). En este ejemplo se agregan nuevos documentos con incrustaciones de ejemplo:

db.exampleCollection.insertMany([
  {name: "Eugenia Lopez", bio: "Eugenia is the CEO of AdvenureWorks.", vectorContent: [0.51, 0.12, 0.23]},
  {name: "Cameron Baker", bio: "Cameron Baker CFO of AdvenureWorks.", vectorContent: [0.55, 0.89, 0.44]},
  {name: "Jessie Irwin", bio: "Jessie Irwin is the former CEO of AdventureWorks and now the director of the Our Planet initiative.", vectorContent: [0.13, 0.92, 0.85]},
  {name: "Rory Nguyen", bio: "Rory Nguyen is the founder of AdventureWorks and the president of the Our Planet initiative.", vectorContent: [0.91, 0.76, 0.83]},
]);

Realización de una búsqueda vectorial

Para realizar una búsqueda vectorial, use la fase de canalización de agregación $search en una consulta de MongoDB. Para usar el índice de cosmosSearch, use el nuevo operador de cosmosSearch.

{
  {
  "$search": {
    "cosmosSearch": {
        "vector": <vector_to_search>,
        "path": "<path_to_property>",
        "k": <num_results_to_return>,
      },
      "returnStoredSource": True }},
  {
    "$project": { "<custom_name_for_similarity_score>": {
           "$meta": "searchScore" },
            "document" : "$$ROOT"
        }
  }
}

Para recuperar la puntuación de similitud (searchScore) junto con los documentos encontrados por la búsqueda vectorial, use el $project operador de inclusión searchScore y cámbiele el nombre por <custom_name_for_similarity_score> en los resultados. A continuación, el documento también se proyecta como objeto anidado. Tenga en cuenta que la puntuación de similitud se calcula mediante la métrica definida en el índice vectorial.

Siguiendo con el ejemplo anterior, cree otro vector, queryVector. La búsqueda vectorial mide la distancia entre queryVector y los vectores en la ruta de acceso vectorContent de los documentos. Puede establecer el número de resultados que devuelve la búsqueda estableciendo el parámetro k, que se establece en 2 aquí. También puede establecer nProbes, que es un entero que controla el número de clústeres cercanos que se inspeccionan en cada búsqueda. Un valor mayor puede mejorar la precisión, pero la búsqueda será más lenta como resultado. Se trata de un parámetro opcional con un valor predeterminado de 1 y no puede ser mayor que el valor de numLists especificado en el índice vectorial.

const queryVector = [0.52, 0.28, 0.12];
db.exampleCollection.aggregate([
  {
    $search: {
      "cosmosSearch": {
        "vector": queryVector,
        "path": "vectorContent",
        "k": 2
      },
    "returnStoredSource": true }},
  {
    "$project": { "similarityScore": {
           "$meta": "searchScore" },
            "document" : "$$ROOT"
        }
  }
]);

En este ejemplo se realiza una búsqueda vectorial mediante queryVector como entrada a través del shell de Mongo. El resultado de la búsqueda es una lista de los dos elementos más similares al vector de consulta, ordenados por sus puntuaciones de similitud.

[
  {
    similarityScore: 0.9465376,
    document: {
      _id: ObjectId("645acb54413be5502badff94"),
      name: 'Eugenia Lopez',
      bio: 'Eugenia is the CEO of AdvenureWorks.',
      vectorContent: [ 0.51, 0.12, 0.23 ]
    }
  },
  {
    similarityScore: 0.9006955,
    document: {
      _id: ObjectId("645acb54413be5502badff97"),
      name: 'Rory Nguyen',
      bio: 'Rory Nguyen is the founder of AdventureWorks and the president of the Our Planet initiative.',
      vectorContent: [ 0.91, 0.76, 0.83 ]
    }
  }
]

Obtener definiciones de índice vectorial

Para recuperar la definición del índice vectorial de la colección, use el comando listIndexes:

db.exampleCollection.getIndexes();

Es este ejemplo, se devuelve vectorIndex con todos los parámetros de cosmosSearch que se usaron para crear el índice:

[
  { v: 2, key: { _id: 1 }, name: '_id_', ns: 'test.exampleCollection' },
  {
    v: 2,
    key: { vectorContent: 'cosmosSearch' },
    name: 'vectorSearchIndex',
    cosmosSearch: {
      kind: 'vector-ivf',
      numLists: 3,
      similarity: 'COS',
      dimensions: 3
    },
    ns: 'test.exampleCollection'
  }
]

Búsqueda filtrada de vectores (versión preliminar)

Ahora puede ejecutar búsquedas de vectores con cualquier filtro de consulta compatible, como $lt, $lte, $eq, $neq, $gte, $gt, $in, $nin y $regex. Habilite la característica "búsqueda de vectores con filtro" en la pestaña "Características en versión preliminar" de la suscripción de Azure. Puede encontrar más información sobre las características en versión preliminar aquí.

En primer lugar, deberá definir un índice para el filtro además de un índice vectorial. Por ejemplo, puede definir el índice de filtro en una propiedad.

db.runCommand({ 
     "createIndexes": "<collection_name",
    "indexes": [ {
        "key": { 
            "<property_to_filter>": 1 
               }, 
        "name": "<name_of_filter_index>" 
    }
    ] 
});

A continuación, puede agregar el término "filter" a la búsqueda de vectores, como se muestra a continuación. En este ejemplo, el filtro busca documentos en los que la propiedad "title" no está en la lista de ["not in this text", "or this text"].


db.exampleCollection.aggregate([
  {
      '$search': {
          "cosmosSearch": {
              "vector": "<query_vector>",
              "path": <path_to_vector>,
              "k": num_results,
              "filter": {<property_to_filter>: {"$nin": ["not in this text", "or this text"]}}
          },
          "returnStoredSource": True }},
      {'$project': { 'similarityScore': { '$meta': 'searchScore' }, 'document' : '$$ROOT' }
}
]);

Importante

Mientras se encuentra en versión preliminar, la búsqueda filtrada de vectores puede requerir que ajuste los parámetros de índice vectorial para lograr una mayor precisión. Por ejemplo, aumentar m, efConstruction o efSearch cuando se usa HNSW, o numLists, o nProbes cuando se usa SIGHT, puede dar lugar a mejores resultados. Debe probar la configuración antes de usarla para asegurarse de que los resultados son satisfactorios.

Uso de herramientas de orquestación de LLM

Uso como base de datos vectorial con Semantic Kernel

Ahora puede usar Semantic Kernel para orquestar la recuperación de información desde el núcleo virtual de Azure Cosmos DB for MongoDB y el LLM. Obtenga más información aquí.

https://github.com/microsoft/semantic-kernel/tree/main/python/semantic_kernel/connectors/memory/azure_cosmosdb

Uso como base de datos vectorial con LangChain

Use LangChain para orquestar la recuperación de información desde el núcleo virtual de Azure Cosmos DB for MongoDB y el LLM. Obtenga más información aquí.

Uso como caché semántica con LangChain

Use LangChain y Azure Cosmos DB for MongoDB (núcleo virtual) para orquestar el almacenamiento en caché semántico, mediante respuestas de LLM previamente grabadas que pueden ahorrar costos de API de LLM y reducir la latencia de las respuestas. Obtenga más información aquí.

Características y limitaciones

  • Métricas de distancia admitidas: L2 (euclidiano), producto interno y coseno.
  • Métodos de indexación admitidos: IVFFLAT (GA) y HSNW (versión preliminar)
  • Indexación de vectores de hasta 2000 dimensiones de tamaño.
  • La indexación solo se aplica a un vector por ruta de acceso.
  • Solo se puede crear un índice por ruta de acceso vectorial.

Resumen

En esta guía se muestra cómo crear un índice vectorial, agregar documentos con datos vectoriales, realizar una búsqueda de similitud y recuperar la definición de índice. Con la base de datos vectorial integrada puede almacenar, indexar y consultar de forma eficaz datos vectoriales de alta dimensión directamente en el núcleo virtual de Azure Cosmos DB for MongoDB. Le permite desbloquear todo el potencial de los datos con incrustaciones vectoriales y le capacita para crear aplicaciones más precisas, potentes y eficaces.

Paso siguiente