Define una proyección de índice para la indexación entre padre e hijo

Nota

Búsqueda de Azure AI está disponible a través del portal de Azure, las API REST y los SDK de Azure. También respalda Foundry IQ, la capa de conocimiento administrada que transforma el contenido empresarial en bases de conocimiento reutilizables y compatibles con permisos para agentes en el portal de Microsoft Foundry.

Si está fragmentando contenido para un patrón RAG o una vectorización, puede especificar una proyección de índice para controlar la indexación uno a varios, donde el contenido de origen (uno) se proyecta en uno o varios índices (muchos). La intención de una proyección de índice es controlar si los elementos del documento primario, como un nombre de archivo o una fecha de creación:

  • Repetir para cada elemento secundario (bloque) dentro de un único índice
  • Se indexan como documentos de búsqueda independientes en el mismo índice
  • O bien, se ingieren en índices independientes.

Se recomienda repetir campos primarios en un único índice porque tener diferentes formas de documento o dividir contenido en dos índices puede ser difícil de consultar, especialmente en la búsqueda clásica en la que no se admiten las combinaciones de índice.

En Búsqueda de Azure AI, la fragmentación se realiza mediante aptitudes y, por tanto, depende de los indexadores. Para definir una proyección de índice, especifíquela en un conjunto de aptitudes.

Requisitos previos

El conjunto de aptitudes contiene la proyección del indexador que da forma a los datos para la indexación de uno a muchos. Un conjunto de aptitudes también podría tener otras aptitudes, como una aptitud de inserción como AzureOpenAIEmbedding si el escenario incluye vectorización integrada.

Elección de un enfoque

Las proyecciones de índice generan documentos "secundarios" para cada documento "principal". Elija cómo gestionar el contenido padre:

Enfoque Descripción Configuración
Índice único, repetición de campos primarios (recomendado) Los campos primarios se repiten para cada fragmento. Todos los documentos tienen una forma uniforme. Establezca tanto el indexador targetIndexName como la proyección de índice targetIndexName al mismo índice. Establezca projectionMode a skipIndexingParentDocuments.
Índice único, formas de documento mixtas Coexisten los documentos principales y los documentos con fragmentos. Los documentos primarios tienen campos de fragmento nulos. Establezca ambos targetIndexName valores en el mismo índice. Establezca projectionMode en includeIndexingParentDocuments (o déjelo, ya que es el valor predeterminado).
Dos o más índices independientes Índice primario para búsquedas de metadatos, índice secundario para la búsqueda. No hay combinaciones durante las consultas. Establezca indexador targetIndexName en índice primario. Cambie la proyección del índice targetIndexName al índice secundario. La lista selectors determina la cantidad y composición del índice secundario.

Para la mayoría de los escenarios RAG, use el primer enfoque. Consulte el ejemplo de RAG clásico.

  1. Cree un índice diseñado para fragmentos, con los campos primarios incluidos.
  2. Cree un conjunto de habilidades con una habilidad de fragmentación y indexProjections.
  3. Cree un indexador apuntando a su origen de datos admitido.

Si el origen de datos admite el seguimiento de cambios, el indexador sincroniza los cambios automáticamente.

Crea un índice para la indexación uno a muchos

Tanto si crea un índice para fragmentos que repiten valores primarios como índices independientes para la colocación de campos primarios y secundarios, el índice principal usado para la búsqueda está diseñado en torno a fragmentos de datos. El esquema de índice debe tener los siguientes campos:

  • Campo de clave de documento que identifica de forma única cada documento. Debe definirse como el tipo Edm.String con analizador keyword.

  • Campo que asocia cada fragmento con su elemento primario. Debe ser de tipo Edm.String. No puede ser el campo de clave de documento y debe tener filterable establecido en true. Se conoce como parent_id en los ejemplos y como un valor de clave proyectado en este artículo.

  • Otros campos para el contenido, como los campos de texto o fragmentos vectorizados.

Debe existir un índice en el servicio de búsqueda antes de crear el conjunto de aptitudes o ejecutar el indexador. El selectors elemento que defina en el conjunto de habilidades debe incluir estos campos.

Esquema de índice único que incluye campos padre e hijo.

Un único índice diseñado en torno a fragmentos con contenido primario que se repite para cada fragmento es el patrón predominante para escenarios de búsqueda de vectores y RAG. La capacidad de asociar el contenido primario correcto a cada fragmento se habilita a través de proyecciones de índice.

El esquema siguiente es un ejemplo que cumple los requisitos de las proyecciones de índice. En este ejemplo:

  • Los campos primarios son el parent_id y el título, y se repiten para cada fragmento.
  • Los campos secundarios son los fragmentos vectoriales y no vectoriales. El chunk_id es el identificador de documento de este índice.

Puede usar el portal de Azure, las API REST o un SDK de Azure para crear un índice.

Use un cliente REST o la acción Azure portal Agregar índice y la opción JSON para crear el índice.

{
    "name": "my_consolidated_index",
    "fields": [
        {"name": "chunk_id", "type": "Edm.String", "key": true, "filterable": true, "analyzer": "keyword"},
        {"name": "parent_id", "type": "Edm.String", "filterable": true},
        {"name": "title", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "retrievable": true},
        {"name": "chunk", "type": "Edm.String","searchable": true,"retrievable": true},
        {"name": "chunk_vector", "type": "Collection(Edm.Single)", "searchable": true, "retrievable": false, "stored": false, "dimensions": 1536, "vectorSearchProfile": "hnsw"}
    ],
    "vectorSearch": {
        "algorithms": [{"name": "hnsw", "kind": "hnsw", "hnswParameters": {}}],
        "profiles": [{"name": "hnsw", "algorithm": "hnsw"}]
    }
}

Adición de proyecciones de índice a un conjunto de habilidades

Las proyecciones de índice se definen dentro de una definición de conjunto de aptitudes y se definen principalmente como una matriz de selectors, donde cada selector corresponde a un índice de destino diferente en el servicio de búsqueda. Esta sección comienza con la sintaxis y los ejemplos del contexto, seguido de la referencia de parámetros.

Las proyecciones de índice están disponibles con carácter general. Se recomienda la API estable más reciente:

Esta es una carga de ejemplo para una definición de proyecciones de índices que puede usar para proyectar la salida de páginas individuales mediante la aptitud Dividir texto como sus propios documentos en el índice de búsqueda.

Si el documento primario incluye metadatos de permisos para el acceso de nivel de documento, como metadata_user_ids, metadata_group_idso metadata_spo_site_url, incluya esos campos en mappings. Cada fragmento debe heredarlos para que se apliquen filtros de permisos en tiempo de consulta. Para obtener más información, vea Elegir dónde rellenar los campos de ACL.

"indexProjections": {
    "selectors": [
        {
            "targetIndexName": "my_consolidated_index",
            "parentKeyFieldName": "parent_id",
            "sourceContext": "/document/pages/*",
            "mappings": [
                {
                    "name": "chunk",
                    "source": "/document/pages/*",
                    "sourceContext": null,
                    "inputs": []
                },
                {
                    "name": "chunk_vector",
                    "source": "/document/pages/*/chunk_vector",
                    "sourceContext": null,
                    "inputs": []
                },
                {
                    "name": "title",
                    "source": "/document/title",
                    "sourceContext": null,
                    "inputs": []
                }
            ]
        }
    ],
    "parameters": {
        "projectionMode": "skipIndexingParentDocuments"
    }
}

Referencia de parámetros

Parámetros de proyección de índice Definición
selectors Matriz con parámetros para el corpus de búsqueda principal, normalmente el índice diseñado alrededor de fragmentos. Puede enviar contenido a varios índices secundarios especificando varios selectores. Los esquemas de índice deben existir en el servicio de búsqueda antes de ejecutar el indexador.
parameters Diccionario de parámetros de propiedades de configuración específicas de la proyección del índice.

Los parámetros tienen los siguientes elementos como parte de su definición.

Parámetros Definición
parameters.projectionMode Parámetro opcional que proporciona instrucciones al indexador. Los valores válidos incluyen includeIndexingParentDocuments y skipIndexingParentDocuments.

El mejor valor para este parámetro es skipIndexingParentDocuments. Debe usarlo cuando los documentos fragmentados sean el destino de búsqueda principal.

Si no establece skipIndexingParentDocuments para projectionMode, obtendrá includeIndexingParentDocuments automáticamente porque es el valor predeterminado. Agrega documentos de búsqueda adicionales al índice que son nulos en fragmentos, pero incluyen contenido específico del elemento principal. Por ejemplo, si cinco ARCHIVOS PDF contribuyen con 100 fragmentos al índice, el número de documentos del índice es 105. Los cinco documentos creados para los campos primarios tienen valores NULL para los campos de fragmento (secundario), lo que hace que sean sustancialmente diferentes de la mayor parte de los documentos del índice. Por este motivo, se recomienda projectionMode establecer en skipIndexingParentDocuments.

Los selectores tienen los siguientes elementos como parte de su definición.

Selectores Definición
selectors.targetIndexName Nombre del índice en el que se proyectan los datos de índice. O bien se trata del índice fragmentado único con campos principales repetidos, o bien es el índice secundario si utiliza índices independientes para el contenido principal y secundario.
selectors.parentKeyFieldName Nombre del campo que proporciona la clave para el documento primario.
selectors.sourceContext La anotación de enriquecimiento que define la granularidad con la que se asignan los datos a documentos de búsqueda individuales. Para obtener más información, consulte Lenguaje de anotación de entrada y contexto de aptitud.
selectors.mappings Una matriz de asignaciones de datos enriquecidos a campos del índice de búsqueda. Cada mapeo consta de:
name: el nombre del campo en el índice de búsqueda en el que se deben indexar los datos.
source: ruta de acceso de la anotación de enriquecimiento de la que se deben extraer los datos.

Cada elemento mapping también puede definir datos de forma recursiva con un campo opcional sourceContext y inputs, similar al almacén de conocimiento o la aptitud Conformador. Dependiendo de la aplicación, estos parámetros permiten dar forma a los datos en campos de tipo Edm.ComplexType en el índice de búsqueda. Algunos LLM no aceptan un tipo complejo en los resultados de búsqueda, por lo que el LLM que usa determina si un mapeo de tipos complejos es útil o no.

El mappings parámetro es importante. Debe asignar explícitamente todos los campos del índice secundario, salvo los campos de ID, como la clave del documento y el ID principal.

Este requisito contrasta con otras convenciones de asignación de campos en Búsqueda de Azure AI. Para algunos tipos de origen de datos, el indexador puede asignar implícitamente campos basados en nombres similares o características conocidas (por ejemplo, los indexadores de blobs usan la ruta de acceso de almacenamiento de metadatos única como clave de documento predeterminada). Sin embargo, para las proyecciones del indexador, debe especificar explícitamente todas las asignaciones de campos en el lado "muchos" de la relación.

Importante

No cree una asignación de campos para el campo de clave del elemento principal. Al hacerlo, se interrumpe el seguimiento de cambios y la actualización de datos sincronizada.

Revisar asignaciones de campos

Los indexadores están relacionados con tres tipos diferentes de asignaciones de campos. Antes de ejecutar el indexador, compruebe las asignaciones de campos y sepa cuándo usar cada tipo.

Las asignaciones de campos se definen en un indexador y se usan para asignar un campo de origen a un campo de índice. Las asignaciones de campos se usan para rutas de datos que toman los datos del origen y los pasan para la indexación, sin ningún paso intermedio de procesamiento de aptitudes. Normalmente, un indexador puede asignar automáticamente campos con el mismo nombre y tipo. Las asignaciones de campos explícitas solo son necesarias cuando hay discrepancias. En la indexación de uno a varios y los patrones descritos hasta ahora, es posible que no necesite asignaciones de campos.

Las asignaciones de campos de salida se definen en un indexador y se usan para asignar contenido enriquecido generado por un conjunto de aptitudes a un campo en el índice principal. Los fragmentos se consideran contenido enriquecido por crear mediante una habilidad (Text Split), pero no se necesita una asignación de campos de salida en los fragmentos o las proyecciones de índice definidas por una instrucción de asignación mediante selectores.

Las selectors.mappings se definen en un conjunto de habilidades y se asignan a los campos del índice secundario. En los casos en los que el índice secundario también incluye campos primarios (como en la solución de índice consolidado), debe configurar asignaciones de campos para cada campo que tenga contenido, incluido el campo de título de nivel primario, suponiendo que desee que el título aparezca en cada documento fragmentado. Si va a usar índices principales y secundarios independientes, el selector debe tener asignaciones de campos solo en los campos de nivel secundario.

Nota

Tanto las asignaciones de campos de salida como las asignaciones de selectores aceptan nodos de árbol de documentos enriquecidos como entradas de origen. Saber cómo especificar una ruta de acceso a cada nodo es esencial para configurar la ruta de acceso de datos. Para obtener más información sobre la sintaxis de ruta de acceso, consulte Referencia a una ruta de acceso a nodos enriquecidos y definición de conjunto de aptitudes para obtener ejemplos.

Ejecución del indexador

Una vez que haya creado un origen de datos, índices y conjunto de aptitudes, estará listo para crear y ejecutar el indexador. Este paso coloca la canalización en ejecución.

Puede consultar el índice de búsqueda después de que finalice el procesamiento para probar la solución.

Ciclo de vida del contenido

Dependiendo del origen de datos subyacente, un indexador normalmente puede proporcionar un seguimiento de cambios continuo y la detección de eliminación. En esta sección se explica el ciclo de vida de contenido de la indexación uno a varios en relación con la actualización de datos.

Para los orígenes de datos que proporcionan seguimiento de cambios y detección de eliminaciones, un proceso de indexador puede captar los cambios en sus datos de origen. Cada vez que ejecute el indexador y el conjunto de aptitudes, las proyecciones de índice se actualizan si el conjunto de aptitudes o los datos de origen subyacentes han cambiado. Los cambios detectados por el indexador se propagan a través del proceso de enriquecimiento a las proyecciones del índice, lo que garantiza que los datos proyectados sean una representación actual del contenido en el origen de datos. La actividad de actualización de datos se captura en un valor de clave proyectado para cada fragmento. Este valor se actualiza cuando cambian los datos subyacentes.

Nota

Aunque puede editar manualmente los datos de los documentos proyectados mediante la API de inserción de índices, debe evitar hacerlo. Las actualizaciones manuales de un índice se sobrescriben en la siguiente invocación de canalización, suponiendo que el documento de los datos de origen se actualice y el origen de datos tenga habilitado el seguimiento de cambios o la detección de eliminación.

Contenido actualizado

Si agrega contenido nuevo al origen de datos, se agregan nuevos fragmentos o documentos secundarios al índice en la siguiente ejecución del indexador.

Si modifica el contenido existente en el origen de datos, los fragmentos se actualizan incrementalmente en el índice de búsqueda si el origen de datos que usa admite el seguimiento de cambios y la detección de eliminación. Por ejemplo, si una palabra o oración cambia en un documento, el fragmento del índice de destino que contiene esa palabra o oración se actualiza en la siguiente ejecución del indexador. Otros tipos de actualizaciones, como cambiar un tipo de campo y algunas atribución, no se admiten para campos existentes. Para obtener más información sobre las actualizaciones permitidas, consulte Actualización de un esquema de índice.

Algunos orígenes de datos, como Azure Storage admiten el seguimiento de cambios y eliminación de forma predeterminada, en función de la marca de tiempo. Otros orígenes de datos, como Microsoft OneLake, Azure SQL o Azure Cosmos DB deben configurarse para el seguimiento de cambios.

Contenido eliminado

Si el contenido de origen ya no existe (por ejemplo, si se acorta el texto para tener menos fragmentos), se elimina el documento secundario correspondiente en el índice de búsqueda. Los documentos secundarios restantes también obtienen su clave actualizada para incluir un nuevo valor hash, incluso si su contenido no ha cambiado de otro modo.

Si un documento primario se elimina completamente del origen de datos, los documentos secundarios correspondientes solo se eliminan si una definición de origen de datos detecta dataDeletionDetectionPolicy la eliminación. Si no tiene configurado dataDeletionDetectionPolicy y necesita eliminar un documento primario del origen de datos, debe eliminar manualmente los documentos secundarios si ya no se quieren.

Valor de clave proyectado

Para garantizar la integridad de los datos para el contenido actualizado y eliminado, la actualización de datos en la indexación de uno a varios se basa en un valor de clave proyectado en el lado "varios". Si va a usar utilizando la vectorización integrada o el asistente Importar datos, el valor de clave proyectado es el campo parent_id en la parte fragmentada o de "varios" del índice.

Un valor de clave proyectado es un identificador único que el indexador genera para cada documento. Garantiza la unicidad y permite que el seguimiento de cambios y eliminación funcione correctamente. Esta clave contiene los siguientes segmentos:

  • Hash aleatorio para garantizar la unicidad. Este hash cambia si el documento primario se actualiza en ejecuciones posteriores del indexador.
  • Clave del documento primario.
  • Trayectoria de anotación de enriquecimiento que identifica el contexto del documento generado.

Por ejemplo, si divide un documento primario con el valor de clave "aa1b22c33" en cuatro páginas y, a continuación, cada una de esas páginas se proyecta como su propio documento a través de proyecciones de índice:

  • aa1b22c33
  • aa1b22c33_pages_0
  • aa1b22c33_pages_1
  • aa1b22c33_pages_2

Si el documento primario se actualiza en los datos de origen, quizás resultando en más páginas fragmentadas, el hash aleatorio cambia, se agregan más páginas, y el contenido de cada fragmento se actualiza para coincidir con lo que se encuentre en el documento de origen.

Ejemplo de índices de padre e hijo separados

En esta sección se muestra un ejemplo de índices padre e hijo independientes. Es un patrón poco común, pero es posible que tenga requisitos de aplicación que se cumplan mejor mediante este enfoque. En este escenario, va a proyectar contenido principal-secundario en dos índices separados.

  1. Cree dos esquemas de índice.

    Cada esquema tiene los campos de su grano concreto, con el campo de identificador primario común a ambos índices para su uso en una consulta de búsqueda. El corpus de búsqueda principal es el índice secundario, pero puede generar una consulta de búsqueda para recuperar los campos principales de cada coincidencia en el resultado. Búsqueda de Azure AI no admite combinaciones en el momento de la consulta, por lo que el código de la aplicación o la capa de orquestación necesitaría combinar o intercalar los resultados que se pueden pasar a una aplicación o proceso.

    El índice primario tiene un campo y un título parent_id. El parent_id es la clave del documento. No necesita la configuración de búsqueda vectorial a menos que desee vectorizar campos en el nivel de documento primario.

    {
        "name": "my-parent-index",
        "fields": [
    
            {"name": "parent_id", "type": "Edm.String", "key":true, "filterable": true},
            {"name": "title", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "retrievable": true}
        ]
    }
    

    El índice secundario tiene los campos fragmentados, además del campo parent_id. Si utiliza la vectorización integrada, perfiles de puntuación, el clasificador semántico o analizadores, deberá configurarlos en el índice secundario.

    {
        "name": "my-child-index",
        "fields": [
            {"name": "chunk_id", "type": "Edm.String", "key": true, "filterable": true, "analyzer": "keyword"},
            {"name": "parent_id", "type": "Edm.String", "filterable": true},
             {"name": "chunk", "type": "Edm.String","searchable": true,"retrievable": true},
            {"name": "chunk_vector", "type": "Collection(Edm.Single)", "searchable": true, "retrievable": false, "stored": false, "dimensions": 1536, "vectorSearchProfile": "hnsw"}
        ],
        "vectorSearch": {
            "algorithms": [{"name": "hsnw", "kind": "hnsw", "hnswParameters": {}}],
            "profiles": [{"name": "hsnw", "algorithm": "hnsw"}]
        },
        "scoringProfiles": [],
        "semanticConfiguration": [],
        "analyzers": []
    }
    
  2. Actualice el indexador para especificar parent-index como destino.

    La definición del indexador especifica los componentes de la canalización. En la definición del indexador, el nombre del índice que se va a proporcionar es el índice primario. Si necesita asignaciones de campos para los campos de nivel superior, defínalas en outputFieldMappings. En el caso de la indexación de uno a varios que usa índices independientes, la definición del indexador podría ser similar al ejemplo siguiente.

    {
      "name": "my-indexer",
      "dataSourceName": "my-ds",
      "targetIndexName": "my-parent-index",
      "skillsetName" : "my-skillset",
      "parameters": { },
      "fieldMappings": (optional) Maps fields in the underlying data source to fields in an index,
      "outputFieldMappings" : (required) Maps skill outputs to fields in an index,
    }
    
  3. Agregue indexProjections al conjunto de habilidades.

    Este es un ejemplo de una definición de proyección de índice que especifica la ruta de acceso de datos que el indexador debe usar para indexar el contenido. Especifica el nombre del índice secundario en la definición de la proyección del índice, así como las asignaciones de cada campo secundario o de nivel de fragmento. Este es el único lugar en el que se especifica el nombre del índice secundario.

    Observe que parameters es null y usa el valor predeterminado includeIndexingParentDocuments. El indexador rellena el índice primario. La lista selectors se utiliza para proyectar los documentos de bloques en el índice secundario.

    "indexProjections": {
        "selectors": [
            {
                "targetIndexName": "my-child-index",
                "parentKeyFieldName": "parent_id",
                "sourceContext": "/document/pages/*",
                "mappings": [
                    {
                        "name": "chunk",
                        "source": "/document/pages/*",
                        "sourceContext": null,
                        "inputs": []
                    },
                    {
                        "name": "chunk_vector",
                        "source": "/document/pages/*/chunk_vector",
                        "sourceContext": null,
                        "inputs": []
                    }
                ]
            }
        ],
        "parameters": {}
    }
    
  4. Ejecute el indexador. Si anteriormente ejecutó el indexador, recuerde restablecerlo primero.

    Debe tener dos índices rellenados con el contenido adecuado. Consulte los índices en el Explorador de búsqueda para comprobar que cada uno tiene el contenido correcto.

Paso siguiente

La fragmentación de datos y la indexación uno a varios forman parte del patrón RAG clásico en Búsqueda de Azure AI. Continúe con el siguiente tutorial y el ejemplo de código para obtener más información sobre él.