Partilhar via


Indexar blobs e arquivos de Markdown no Azure AI Search

Nota

Esta funcionalidade está atualmente em pré-visualização pública. Essa visualização é fornecida sem um contrato de nível de serviço e não é recomendada para cargas de trabalho de produção. Algumas funcionalidades poderão não ser suportadas ou poderão ter capacidades limitadas. Para obter mais informações, veja Termos Suplementares de Utilização para Pré-visualizações do Microsoft Azure.

No Azure AI Search, os indexadores do Armazenamento de Blobs do Azure, Arquivos do Azure e OneLake dão suporte a um markdown modo de análise para arquivos Markdown. Os arquivos Markdown podem ser indexados de duas maneiras:

  • Modo de análise um-para-muitos, criando vários documentos de pesquisa por arquivo Markdown
  • Modo de análise um-para-um, criando um documento de pesquisa por arquivo Markdown

Pré-requisitos

  • Uma fonte de dados suportada: armazenamento de Blob do Azure, armazenamento de arquivos do Azure, OneLake no Microsoft Fabric.

    Para OneLake, certifique-se de atender a todos os requisitos do indexador OneLake.

    O Armazenamento do Azure para indexadores de blob e indexadores de arquivos é uma instância de desempenho padrão (v2 de uso geral) que dá suporte a camadas de acesso quente, frio e frio.

Parâmetros do modo de análise Markdown

Os parâmetros do modo de análise são especificados em uma definição de indexador quando você cria ou atualiza um indexador.

POST https://[service name].search.windows.net/indexers?api-version=2024-11-01-preview
Content-Type: application/json
api-key: [admin key]

{
  "name": "my-markdown-indexer",
  "dataSourceName": "my-blob-datasource",
  "targetIndexName": "my-target-index",
  "parameters": {
    "configuration": {
      "parsingMode": "markdown",
      "markdownParsingSubmode": "oneToMany",
      "markdownHeaderDepth": "h6"
    }
  },
}

O indexador de blob fornece um submode parâmetro para determinar a saída da estrutura dos documentos de pesquisa. O modo de análise Markdown fornece as seguintes opções de submodo:

parsingMode submodo Pesquisar documento Description
markdown oneToMany Múltiplos por blob (padrão) Divide o Markdown em vários documentos de pesquisa, cada um representando uma seção de conteúdo (sem cabeçalho) do arquivo Markdown. Você pode omitir o submodo, a menos que queira uma análise um-para-um.
markdown oneToOne Um por blob Analisa o Markdown em um documento de pesquisa, com seções mapeadas para cabeçalhos específicos no arquivo Markdown.

Para oneToMany o submodo, você deve revisar Indexando um blob para produzir muitos documentos de pesquisa para entender como o indexador de blob lida com a desambiguação da chave do documento para vários documentos de pesquisa produzidos a partir do mesmo blob.

As seções posteriores descrevem cada submodo com mais detalhes. Se você não estiver familiarizado com clientes e conceitos de indexador, consulte Criar um indexador de pesquisa. Você também deve estar familiarizado com os detalhes da configuração básica do indexador de blob, que não é repetida aqui.

Parâmetros opcionais de análise de Markdown

Os parâmetros diferenciam maiúsculas de minúsculas.

Nome do parâmetro Valores Permitidos Description
markdownHeaderDepth h1, h2, h3, h4, h5, h6(default) Este parâmetro determina o nível de cabeçalho mais profundo que é considerado durante a análise, permitindo o tratamento flexível da estrutura do documento (por exemplo, quando markdownHeaderDepth é definido como h1, o analisador só reconhece cabeçalhos de nível superior que começam com "#", e todos os cabeçalhos de nível inferior são tratados como texto sem formatação). Se não for especificado, o padrão será h6.

Essa configuração pode ser alterada após a criação inicial do indexador, no entanto, a estrutura dos documentos de pesquisa resultantes pode mudar dependendo do conteúdo do Markdown.

Elementos Markdown suportados

A análise de Markdown só dividirá o conteúdo com base em cabeçalhos. Todos os outros elementos, como listas, blocos de código, tabelas e assim por diante, são tratados como texto sem formatação e passados para um campo de conteúdo.

Exemplo de conteúdo de Markdown

O seguinte conteúdo de Markdown é usado para os exemplos nesta página:

# Section 1
Content for section 1.

## Subsection 1.1
Content for subsection 1.1.

# Section 2
Content for section 2.

Usar o modo de análise um-para-muitos

O modo de análise um-para-muitos analisa arquivos Markdown em vários documentos de pesquisa, onde cada documento corresponde a uma seção de conteúdo específica do arquivo Markdown com base nos metadados do cabeçalho naquele ponto do documento. O Markdown é analisado com base em cabeçalhos em documentos de pesquisa que contêm o seguinte conteúdo:

  • content: Uma cadeia de caracteres que contém a marcação bruta encontrada em um local específico, com base nos metadados do cabeçalho nesse ponto do documento.

  • sections: Um objeto que contém subcampos para os metadados do cabeçalho até o nível de cabeçalho desejado. Por exemplo, quando markdownHeaderDepth é definido como h3, contém campos h1de cadeia de caracteres , h2e h3. Estes campos são indexados espelhando esta estrutura no índice, ou através de mapeamentos de campo no formato /sections/h1, sections/h2, etc. Consulte as configurações de índice e indexador nos exemplos a seguir para obter exemplos no contexto. Os subcampos contidos são:

    • h1 - Uma cadeia de caracteres que contém o valor do cabeçalho h1. Cadeia de caracteres vazia se não estiver definida neste ponto do documento.
    • (Opcional) h2- Uma string contendo o valor do cabeçalho h2. Cadeia de caracteres vazia se não estiver definida neste ponto do documento.
    • (Opcional) h3- Uma string contendo o valor do cabeçalho h3. Cadeia de caracteres vazia se não estiver definida neste ponto do documento.
    • (Opcional) h4- Uma string contendo o valor do cabeçalho h4. Cadeia de caracteres vazia se não estiver definida neste ponto do documento.
    • (Opcional) h5- Uma string contendo o valor do cabeçalho h5. Cadeia de caracteres vazia se não estiver definida neste ponto do documento.
    • (Opcional) h6- Uma string contendo o valor do cabeçalho h6. Cadeia de caracteres vazia se não estiver definida neste ponto do documento.
  • ordinal_position: Um valor inteiro que indica a posição da seção dentro da hierarquia do documento. Este campo é utilizado para ordenar as secções na sua sequência original tal como aparecem no documento, começando com uma posição ordinal de 1 e incrementando sequencialmente para cada cabeçalho.

Esquema de índice para análise um-para-muitos

Um exemplo de configuração de índice pode ter esta aparência:

{
  "name": "my-markdown-index",
  "fields": [
  {
    "name": "id",
    "type": "Edm.String",
    "key": true
  },
  {
    "name": "content",
    "type": "Edm.String",
  },
  {
    "name": "ordinal_position",
    "type": "Edm.Int32"
  },
  {
    "name": "sections",
    "type": "Edm.ComplexType",
    "fields": [
    {
      "name": "h1",
      "type": "Edm.String"
    },
    {
      "name": "h2",
      "type": "Edm.String"
    }]
  }]
}

Definição de indexador para análise um-para-muitos

Se os nomes de campo e os tipos de dados estiverem alinhados, o indexador de blob poderá inferir o mapeamento sem um mapeamento de campo explícito presente na solicitação, portanto, uma configuração de indexador correspondente à configuração de índice fornecida poderá ter esta aparência:

POST https://[service name].search.windows.net/indexers?api-version=2024-11-01-preview
Content-Type: application/json
api-key: [admin key]

{
  "name": "my-markdown-indexer",
  "dataSourceName": "my-blob-datasource",
  "targetIndexName": "my-target-index",
  "parameters": {
    "configuration": { "parsingMode": "markdown" }
  },
}

Nota

O submode não precisa ser definido explicitamente aqui porque oneToMany é o padrão.

Saída do indexador para análise um-para-muitos

Este arquivo Markdown resultaria em três documentos de pesquisa após a indexação, devido às três seções de conteúdo. O documento de pesquisa resultante da primeira seção de conteúdo do documento Markdown fornecido conteria os seguintes valores para content, sections, h1, e h2:

{
  {
    "content": "Content for section 1.\r\n",
    "sections": {
      "h1": "Section 1",
      "h2": ""
    },
    "ordinal_position": 1
  },
  {
    "content": "Content for subsection 1.1.\r\n",
    "sections": {
      "h1": "Section 1",
      "h2": "Subsection 1.1"
    },
    "ordinal_position": 2
  },
  {
    "content": "Content for section 2.\r\n",
    "sections": {
      "h1": "Section 2",
      "h2": ""
    },
    "ordinal_position": 3
  }
}   

Mapear campos um-para-muitos em um índice de pesquisa

Os mapeamentos de campo associam um campo de origem a um campo de destino em situações em que os nomes e tipos de campo não são idênticos. Mas os mapeamentos de campo também podem ser usados para corresponder partes de um documento Markdown e "elevá-las" para campos de nível superior do documento de pesquisa.

O exemplo a seguir ilustra esse cenário. Para obter mais informações sobre mapeamentos de campo em geral, consulte mapeamentos de campo.

Suponha um índice de pesquisa com os seguintes campos: raw_content do tipo Edm.String, h1_header do tipo Edm.Stringe h2_header do tipo Edm.String. Para mapear seu Markdown para a forma desejada, use os seguintes mapeamentos de campo:

"fieldMappings" : [
    { "sourceFieldName" : "/content", "targetFieldName" : "raw_content" },
    { "sourceFieldName" : "/sections/h1", "targetFieldName" : "h1_header" },
    { "sourceFieldName" : "/sections/h2", "targetFieldName" : "h2_header" },
  ]

O documento de pesquisa resultante no índice teria a seguinte aparência:

{
  {
    "raw_content": "Content for section 1.\r\n",
    "h1_header": "Section 1",
    "h2_header": "",
  },
  {
    "raw_content": "Content for section 1.1.\r\n",
    "h1_header": "Section 1",
    "h2_header": "Subsection 1.1",
  },
  {
    "raw_content": "Content for section 2.\r\n",
    "h1_header": "Section 2",
    "h2_header": "",
  }
}

Usar o modo de análise um-para-um

No modo de análise um-para-um, todo o documento Markdown é indexado como um único documento de pesquisa, preservando a hierarquia e a estrutura do conteúdo original. Esse modo é mais útil quando os arquivos a serem indexados compartilham uma estrutura comum, para que você possa usar essa estrutura comum no índice para tornar os campos relevantes pesquisáveis.

Dentro da definição do indexador, defina o parsingMode para "markdown" e use o parâmetro opcional markdownHeaderDepth para definir a profundidade máxima de cabeçalho para fragmentação. Se não for especificado, o padrão será h6, capturando todas as profundidades de cabeçalho possíveis.

O Markdown é analisado com base em cabeçalhos em documentos de pesquisa que contêm o seguinte conteúdo:

  • document_content: Contém o texto completo de Markdown como uma única cadeia de caracteres. Este campo serve como uma representação bruta do documento de entrada.

  • sections: Uma matriz de objetos que contém a representação hierárquica das seções dentro do documento Markdown. Cada seção é representada como um objeto dentro dessa matriz e captura a estrutura do documento de forma aninhada correspondente aos cabeçalhos e seu respetivo conteúdo. Os campos são acessíveis através de mapeamentos de campo fazendo referência ao caminho, por exemplo /sections/content. Os objetos nesta matriz têm as seguintes propriedades:

    • header_level: Uma cadeia de caracteres que indica o nível do cabeçalho (h1, , h3h2, etc.) na sintaxe Markdown. Este campo ajuda na compreensão da hierarquia e estruturação do conteúdo.

    • header_name: Uma cadeia de caracteres que contém o texto do cabeçalho tal como aparece no documento Markdown. Este campo fornece um rótulo ou título para a seção.

    • content: Uma cadeia de caracteres que contém conteúdo de texto que segue imediatamente o cabeçalho, até o próximo cabeçalho. Este campo captura as informações detalhadas ou a descrição associada ao cabeçalho. Se não houver conteúdo diretamente sob um cabeçalho, esta é uma cadeia de caracteres vazia.

    • ordinal_position: Um valor inteiro que indica a posição da seção dentro da hierarquia do documento. Este campo é utilizado para ordenar as secções na sua sequência original tal como aparecem no documento, começando com uma posição ordinal de 1 e incrementando sequencialmente para cada bloco de conteúdo.

    • sections: Uma matriz que contém objetos que representam subseções aninhadas na seção atual. Essa matriz segue a mesma estrutura da matriz de nível sections superior, permitindo a representação de vários níveis de conteúdo aninhado. Cada objeto de subseção também inclui header_level, header_name, contente ordinal_position propriedades, permitindo uma estrutura recursiva que representa e hierarquia do conteúdo Markdown.

Aqui está o exemplo de Markdown que estamos usando para explicar um esquema de índice projetado em torno de cada modo de análise.

# Section 1
Content for section 1.

## Subsection 1.1
Content for subsection 1.1.

# Section 2
Content for section 2.

Esquema de índice para análise um-para-um

Se você não estiver utilizando mapeamentos de campo, a forma do índice deverá refletir a forma do conteúdo de Markdown. Dada a estrutura da amostra Markdown com suas duas seções e subseção única, o índice deve ser semelhante ao exemplo a seguir:

{
  "name": "my-markdown-index",
  "fields": [
  {
    "name": "document_content",
    "type": "Edm.String",
  {
    "name": "sections",
    "type": "Edm.ComplexType",
    "fields": [
    {
      "name": "header_level",
      "type": "Edm.String",
    },
    {
      "name": "header_name",
      "type": "Edm.String",
    },
    {
      "name": "content",
      "type": "Edm.String"
    },
    {
      "name": "ordinal_position",
      "type": "Edm.Int"
    },
    {
      "name": "sections",
      "type": "Edm.ComplexType",
      "fields": [
      {
        "name": "header_level",
        "type": "Edm.String",
      },
      {
        "name": "header_name",
        "type": "Edm.String",
      },
      {
        "name": "content",
        "type": "Edm.String"
      },
      {
        "name": "ordinal_position",
        "type": "Edm.Int"
      }]
    }]
  }
}

Definição de indexador para análise um-para-um

POST https://[service name].search.windows.net/indexers?api-version=2024-11-01-preview
Content-Type: application/json
api-key: [admin key]

{
  "name": "my-markdown-indexer",
  "dataSourceName": "my-blob-datasource",
  "targetIndexName": "my-target-index",
  "parameters": {
    "configuration": {
      "parsingMode": "markdown",
      "markdownParsingSubmode": "oneToOne",
    }
  }
}

Saída do indexador para análise um-para-um

Como o Markdown que queremos indexar só vai para uma profundidade de ("##"), precisamos sections de h2 campos aninhados a uma profundidade de 2 para corresponder a isso. Essa configuração resultaria nos seguintes dados no índice:

  "document_content": "# Section 1\r\nContent for section 1.\r\n## Subsection 1.1\r\nContent for subsection 1.1.\r\n# Section 2\r\nContent for section 2.\r\n",
  "sections": [
    {
      "header_level": "h1",
      "header_name": "Section 1",
      "content": "Content for section 1.",
      "ordinal_position": 1,
      "sections": [
        {
          "header_level": "h2",
          "header_name": "Subsection 1.1",
          "content": "Content for subsection 1.1.",
          "ordinal_position": 2,
        }]
    }],
    {
      "header_level": "h1",
      "header_name": "Section 2",
      "content": "Content for section 2.",
      "ordinal_position": 3,
      "sections": []
    }]
  }

Como você pode ver, a posição ordinal aumenta com base na localização do conteúdo dentro do documento.

Também deve ser observado que, se os níveis de cabeçalho forem ignorados no conteúdo, a estrutura do documento resultante refletirá os cabeçalhos que estão presentes no conteúdo de Markdown, não contendo necessariamente seções aninhadas para h1 através h6 consecutivamente. Por exemplo, quando o documento começa em h2, o primeiro elemento na matriz de seções de nível superior é h2.

Mapear campos um-para-um em um índice de pesquisa

Se quiser extrair campos com nomes personalizados do documento, você pode usar mapeamentos de campo para fazer isso. Usando o mesmo exemplo de Markdown como antes, considere a seguinte configuração de índice:

{
  "name": "my-markdown-index",
  "fields": [
    {
      "name": "document_content",
      "type": "Edm.String",
    },
    {
      "name": "document_title",
      "type": "Edm.String",
    },
    {
      "name": "opening_subsection_title"
      "type": "Edm.String",
    }
    {
      "name": "summary_content",
      "type": "Edm.String",
    }
  ]
}

A extração de campos específicos do Markdown analisado é tratada de forma semelhante a como os caminhos do documento estão em outputFieldMappings, exceto que o caminho começa com /sections em vez de /document. Assim, por exemplo, /sections/0/content mapearia para o conteúdo sob o item na posição 0 na matriz de seções.

Um exemplo de um caso de uso forte pode ser mais ou menos assim: todos os arquivos Markdown têm um título de documento no primeiro h1, um título de subseção no primeiro h2e um resumo no conteúdo do parágrafo final abaixo do parágrafo final h1. Você pode usar os seguintes mapeamentos de campo para indexar somente esse conteúdo:

"fieldMappings" : [
  { "sourceFieldName" : "/content", "targetFieldName" : "raw_content" },
  { "sourceFieldName" : "/sections/0/header_name", "targetFieldName" : "document_title" },
  { "sourceFieldName" : "/sections/0/sections/header_name", "targetFieldName" : "opening_subsection_title" },
  { "sourceFieldName" : "/sections/1/content", "targetFieldName" : "summary_content" },
]

Aqui você extrairia apenas as peças relevantes desse documento. Para usar essa funcionalidade de forma mais eficaz, os documentos que você planeja indexar devem compartilhar a mesma estrutura hierárquica de cabeçalho.

O documento de pesquisa resultante no índice teria a seguinte aparência:

{
  "content": "Content for section 1.\r\n",
  "document_title": "Section 1",
  "opening_subsection_title": "Subsection 1.1",
  "summary_content": "Content for section 2."
}

Nota

Esses exemplos especificam como usar esses modos de análise inteiramente com ou sem mapeamentos de campo, mas você pode aproveitar ambos em um cenário, se isso atender às suas necessidades.

Próximos passos