Creación de un almacén de vectores

En la Búsqueda de Azure AI, un almacén vectorial tiene un esquema de índice que define los campos vectoriales y no vectoriales, una configuración vectorial para los algoritmos que crean el espacio de inserción y una configuración sobre las definiciones de los campos vectoriales que se usan en las solicitudes de consulta. La API Crear índice crea el almacén de vectores.

Sigue estos pasos para indexar los datos vectoriales:

Este artículo se aplica a la versión disponible con carácter general del vector de búsqueda sin versión preliminar, que presupone que el código de la aplicación llama a recursos externos para fragmentación y codificación.

Nota:

¿Busca instrucciones de migración de 2023-07-01-preview? Consulte Actualización de las API de REST.

Requisitos previos

  • Azure AI Search, en cualquier región y en cualquier nivel. La mayoría de los servicios existentes admiten el vector de búsqueda. En el caso de los servicios creados antes de enero de 2019, hay un subconjunto pequeño que no puede admitir la búsqueda de vectores. Si no se puede crear o actualizar un índice que contiene campos vectoriales, se trata de un indicador. En esta situación, se debe crear un nuevo servicio.

  • Incrustaciones de vectores preexistentes en los documentos de origen. Azure AI Search no genera vectores en la versión de búsqueda de vectores disponible con carácter general de las API de REST y los SDK de Azure. Se recomiendan modelos de inserción de Azure OpenAI, pero puede usar cualquier modelo para la vectorización. Para más información, consulta Generar inserciones.

  • Debes conocer el límite de dimensiones del modelo usado para crear las inserciones y la similitud que se calcula. En Azure OpenAI, para text-embedding-ada-002, la longitud del vector numérico es 1536. La similitud se calcula mediante cosine. Los valores válidos son de 2 a 3072 dimensiones.

  • Debes estar familiarizado con la creación de un índice. El esquema debe incluir un campo para la clave de documento, otros campos que quieras buscar o filtrar, y otras configuraciones para comportamientos necesarios durante la indexación y las consultas.

Preparación de documentos para la indexación

Antes de la indexación, reúne una carga de documentos que incluyan campos de datos vectoriales y no vectoriales. La estructura del documento debe ajustarse al esquema de índice.

Asegúrate de que los documentos:

  1. Proporcionen un campo o una propiedad de metadatos que identifique de forma única cada documento. Todos los índices de búsqueda requieren una clave de documento. Para satisfacer los requisitos de clave del documento, un documento de origen debe tener un campo o propiedad que pueda identificarlo de forma única en el índice. Este campo de origen debe asignarse a un campo de índice de tipo Edm.String y key=true en el índice de búsqueda.

  2. Proporciona datos vectoriales (una matriz de números de punto flotante de precisión sencilla) en los campos de origen.

    Los campos vectoriales contienen datos numéricos generados por modelos de inserción, una inserción por campo. Se recomiendan los modelos de inserción en Azure OpenAI, como text-embedding-ada-002 para documentos de texto o la Image Retrieval REST API para imágenes. Solo se admiten campos vectoriales de nivel superior de índice. Actualmente no se admiten los subcampos vectoriales.

  3. Proporciona otros campos con contenido alfanumérico legible para la respuesta de consulta y para escenarios de consulta híbrida que incluyan búsqueda de texto completo o clasificación semántica en la misma solicitud.

El índice de búsqueda debe incluir campos y contenido para todos los escenarios de consulta que quieras admitir. Supongamos que quieres buscar o filtrar por nombres de producto, versiones, metadatos o direcciones. En este caso, la búsqueda de similitud no es especialmente útil. La búsqueda de palabras clave, la búsqueda geográfica o los filtros sería una mejor opción. Un índice de búsqueda que incluye una colección completa de campos de datos vectoriales y no vectoriales proporciona máxima flexibilidad para la construcción de consultas y la composición de respuestas.

Un breve ejemplo de una carga de documentos que incluye campos vectoriales y no vectoriales se encuentra en la sección de carga de datos vectoriales de este artículo.

Añadir una configuración de vector de búsqueda

Una configuración de vector especifica el algoritmo de vector de búsqueda y los parámetros usados durante la indexación para crear información sobre el "vecino más próximo" entre los nodos vectoriales:

  • Mundos pequeños navegables jerárquicos (HNSW)
  • KNN exhaustivo

Si eliges HNSW en un campo, puedes optar por un KNN exhaustivo en el momento de la consulta. Sin embargo, la otra dirección no funcionará: si eliges exhaustivo, no puedes solicitar más adelante la búsqueda de HNSW porque las estructuras de datos adicionales que habilita la búsqueda aproximada no existen.

¿Busca instrucciones de migración de versión preliminar a estable? Consulte los pasos necesarios en Actualización de las API de REST.

La versión de la API de REST 2023-11-01 admite una configuración de vectores que tiene:

  • Algoritmos vectorSearch, vecinos más cercanos hnsw y exhaustiveKnn, con parámetros para la indexación y la puntuación.
  • vectorProfiles para varias combinaciones de configuraciones de algoritmos.

Asegúrate de tener una estrategia para vectorizar el contenido. La versión estable no proporciona vectorizadores para la inserción integrada.

  1. Usa la API Crear o actualizar un índice para crear el índice.

  2. Añade una sección vectorSearch en el índice que especifique los algoritmos de búsqueda usados para crear el espacio de inserción.

     "vectorSearch": {
         "algorithms": [
             {
                 "name": "my-hnsw-config-1",
                 "kind": "hnsw",
                 "hnswParameters": {
                     "m": 4,
                     "efConstruction": 400,
                     "efSearch": 500,
                     "metric": "cosine"
                 }
             },
             {
                 "name": "my-hnsw-config-2",
                 "kind": "hnsw",
                 "hnswParameters": {
                     "m": 8,
                     "efConstruction": 800,
                     "efSearch": 800,
                     "metric": "cosine"
                 }
             },
             {
                 "name": "my-eknn-config",
                 "kind": "exhaustiveKnn",
                 "exhaustiveKnnParameters": {
                     "metric": "cosine"
                 }
             }
    
         ],
         "profiles": [
           {
             "name": "my-default-vector-profile",
             "algorithm": "my-hnsw-config-2"
           }
         ]
     }
    

    Puntos clave:

    • Nombre de la configuración. El nombre debe ser único dentro del índice.
    • profiles añaden una capa de abstracción para acomodar definiciones más enriquecidas. Un perfil se define en vectorSearch y, a continuación, se hace referencia por nombre en cada campo vectorial.
    • "hnsw" y "exhaustiveKnn" son los algoritmos de vecinos más próximos aproximados (ANN) que se usan para organizar el contenido vectorial durante la indexación.
    • El valor predeterminado de "m" (recuento de vínculos bidireccionales) es 4. El rango es de 4 a 10. Los valores inferiores deben devolver menos ruido en los resultados.
    • El valor predeterminado "efConstruction" es 400. El rango va de 100 a 1000. Es el número de vecinos más próximos usados durante la indexación.
    • El valor predeterminado "efSearch" es 500. El rango va de 100 a 1000. Es el número de vecinos más próximos usados durante la búsqueda.
    • "metric" debe ser "coseno" si usas Azure OpenAI; de lo contrario, usa la métrica de similitud asociada al modelo de inserción que estás usando. Los valores admitidos son cosine, dotProduct y euclidean.

Añadir un campo vectorial a la colección de campos

La colección de campos debe incluir un campo para la clave de documento, los campos vectoriales y cualquier otro campo que necesites para escenarios de búsqueda híbrida.

Los campos vectoriales son de tipo Collection(Edm.Single) y valores de punto flotante de precisión sencilla. Un campo de este tipo también tiene una propiedad dimensions y especifica una configuración vectorial.

Usa esta versión si solo quieres características disponibles con carácter general.

  1. Usa Crear o actualizar un índice para crear el índice.

  2. Define un campo vectorial con los atributos siguientes. Puedes almacenar una inserción generada por campo. Para cada campo vectorial:

    • type debe ser Collection(Edm.Single).
    • dimensions es el número de dimensiones generadas en el modelo de inserción. Para text-embedding-ada-002, es 1536.
    • vectorSearchProfile es el nombre de un perfil definido en otra parte del índice.
    • searchable debe ser true.
    • retrievable puede ser true o false. True devuelve los vectores sin formato (1536) como texto sin formato y consume espacio de almacenamiento. Establécelo en true si vas a pasar un resultado vectorial a una aplicación de nivel inferior.
    • filterable, facetable, sortable deben ser false.
  3. Añade campos no vectoriales filtrables a la colección, como "title" con filterable establecido en true, si deseas invocar un prefiltro o postfiltro en la consulta vectorial.

  4. Añade otros campos que definan la sustancia y la estructura del contenido textual que estás indexando. Como mínimo, necesitas una clave de documento.

    También debes agregar campos que sean útiles en la consulta o en su respuesta. En el ejemplo siguiente se muestran campos vectoriales para el título y el contenido ("titleVector", "contentVector") que son equivalentes a los vectores. También proporciona campos para contenido textual equivalente ("title", "content") útil para ordenar, filtrar y leer en un resultado de búsqueda.

    En el ejemplo siguiente se muestra la colección de campos:

    PUT https://my-search-service.search.windows.net/indexes/my-index?api-version=2023-11-01&allowIndexDowntime=true
    Content-Type: application/json
    api-key: {{admin-api-key}}
    {
        "name": "{{index-name}}",
        "fields": [
            {
                "name": "id",
                "type": "Edm.String",
                "key": true,
                "filterable": true
            },
            {
                "name": "title",
                "type": "Edm.String",
                "searchable": true,
                "filterable": true,
                "sortable": true,
                "retrievable": true
            },
            {
                "name": "titleVector",
                "type": "Collection(Edm.Single)",
                "searchable": true,
                "retrievable": true,
                "dimensions": 1536,
                "vectorSearchProfile": "my-default-vector-profile"
            },
            {
                "name": "content",
                "type": "Edm.String",
                "searchable": true,
                "retrievable": true
            },
            {
                "name": "contentVector",
                "type": "Collection(Edm.Single)",
                "searchable": true,
                "retrievable": true,
                "dimensions": 1536,
                "vectorSearchProfile": "my-default-vector-profile"
            }
        ],
        "vectorSearch": {
            "algorithms": [
                {
                    "name": "my-hnsw-config-1",
                    "kind": "hnsw",
                    "hnswParameters": {
                        "m": 4,
                        "efConstruction": 400,
                        "efSearch": 500,
                        "metric": "cosine"
                    }
                }
            ],
            "profiles": [
                {
                    "name": "my-default-vector-profile",
                    "algorithm": "my-hnsw-config-1"
                }
            ]
        }
    }
    

Carga de datos vectoriales para la indexación

El contenido que proporciones para la indexación debe ajustarse al esquema de índice e incluir un valor de cadena único para la clave de documento. Los datos vectorizados previamente se cargan en uno o varios campos vectoriales, que pueden coexistir con otros campos que contienen contenido alfanumérico.

Puedes usar metodologías de incorporar o extracción para la ingesta de datos.

Usa documentos de índice (2023-11-01), documentos de índice (2023-10-01-Preview) o Agregar, actualizar o eliminar documentos (2023-07-01-Preview) para insertar documentos que contengan datos vectoriales.

POST https://{{search-service-name}}.search.windows.net/indexes/{{index-name}}/docs/index?api-version=2023-11-01
Content-Type: application/json
api-key: {{admin-api-key}}
{
    "value": [
        {
            "id": "1",
            "title": "Azure App Service",
            "content": "Azure App Service is a fully managed platform for building, deploying, and scaling web apps. You can host web apps, mobile app backends, and RESTful APIs. It supports a variety of programming languages and frameworks, such as .NET, Java, Node.js, Python, and PHP. The service offers built-in auto-scaling and load balancing capabilities. It also provides integration with other Azure services, such as Azure DevOps, GitHub, and Bitbucket.",
            "category": "Web",
            "titleVector": [
                -0.02250031754374504,
                 . . . 
                        ],
            "contentVector": [
                -0.024740582332015038,
                 . . .
            ],
            "@search.action": "upload"
        },
        {
            "id": "2",
            "title": "Azure Functions",
            "content": "Azure Functions is a serverless compute service that enables you to run code on-demand without having to manage infrastructure. It allows you to build and deploy event-driven applications that automatically scale with your workload. Functions support various languages, including C#, F#, Node.js, Python, and Java. It offers a variety of triggers and bindings to integrate with other Azure services and external services. You only pay for the compute time you consume.",
            "category": "Compute",
            "titleVector": [
                -0.020159931853413582,
                . . .
            ],
            "contentVector": [
                -0.02780858241021633,
                 . . .
            ],
            "@search.action": "upload"
        }
        . . .
    ]
}

Comprobación del contenido de los campos vectoriales

Con fines de validación, puedes consultar el índice mediante el explorador de búsqueda en Azure Portal o una llamada a la API de REST. Dado que Azure AI Search no puede convertir un vector en texto legible, intenta devolver campos del mismo documento que proporcionen evidencia de la coincidencia. Por ejemplo, si la consulta vectorial tiene como destino el campo "titleVector", puedes seleccionar "title" para los resultados de la búsqueda.

Los campos se deben atribuir como "retrievable" para incluirlos en los resultados.

Puedes usar el Explorador de búsquedas para consultar el índice. El explorador de búsqueda tiene dos vistas: vista de consulta (valor predeterminado) y vista JSON.

  • Usa la vista JSON para las consultas vectoriales y pega una definición JSON de la consulta vectorial que deseas ejecutar.

  • Usa la vista de consulta predeterminada para obtener una confirmación rápida de que el índice contiene vectores. La vista de consulta es para la búsqueda de texto completo. Aunque no se puede usar para las consultas vectoriales, puedes enviar una búsqueda vacía (search=*) para comprobar el contenido. El contenido de todos los campos, incluidos los campos vectoriales, se devuelve como texto sin formato.

Actualizar un almacén de vectores

Para actualizar un almacén de vectores, modifique el esquema y, si es necesario, vuelva a cargar documentos para rellenar nuevos campos. Las API para las actualizaciones de esquema incluyen Crear o actualizar índice (REST), CreateOrUpdateIndex en el SDK de Azure para .NET, create_or_update_index en el SDK de Azure para Python y métodos similares en otros SDK de Azure.

Las instrucciones estándar para actualizar un índice se tratan en Anulación y recompilación de índices.

Entre los puntos clave se incluyen:

  • La eliminación y recompilación suele ser necesaria para las actualizaciones de los campos existentes y su eliminación.

  • Sin embargo, se puede actualizar un esquema existente con las siguientes modificaciones, sin que se requiera ninguna recompilación:

    • Agregue nuevos campos a una colección de campos.
    • Agregue nuevas configuraciones de vector, asignadas a nuevos campos, pero no a los campos existentes que ya se hayan vectorizado.
    • Cambie "retrievable" (recuperable, los valores son true o false) en un campo existente. Los campos vectoriales deben ser buscables y recuperables, pero si quiere deshabilitar el acceso a un campo vectorial en situaciones en las que la eliminación y la recompilación no son factibles, puede establecer que se pueda recuperar en false.

Pasos siguientes

Como paso siguiente, se recomienda Datos vectoriales de consulta en un índice de búsqueda.

Los ejemplos de código del repositorio azure-search-vector muestran flujos de trabajo de un extremo a otro que incluyen definición de esquema, vectorización, indexación y consultas.

Hay código de demostración para Python, C# y JavaScript.