Compartilhar via


Indexar blobs e arquivos Markdown na Pesquisa de IA do Azure

Observação

Esse recurso está atualmente em visualização pública. Essa versão prévia é fornecida sem um contrato de nível de serviço e não é recomendada para cargas de trabalho de produção. Alguns recursos podem não ter suporte ou podem ter restrição de recursos. Para obter mais informações, consulte Termos de Uso Complementares de Versões Prévias do Microsoft Azure.

Na Pesquisa de IA do Azure, os indexadores do Armazenamento de Blobs do Azure, dos Arquivos do Azure e do OneLake dão suporte a um modo de análise markdown 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 com suporte: Armazenamento de Blobs do Azure, Armazenamento de Arquivos do Azure, OneLake no Microsoft Fabric.

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

    O Armazenamento do Microsoft Azure para indexadores de blob e indexadores de arquivos é uma instância de desempenho padrão (uso geral v2) que dá suporte a camadas de acesso frequente, esporádico 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 parâmetro submode 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 Descrição
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 (não cabeçalho) do arquivo Markdown. Você pode omitir o submodo, a menos que queira 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 o submodo oneToMany, você deve examinar Indexação de 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 do mesmo blob.

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

Parâmetros opcionais de análise Markdown

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

Nome do Parâmetro Valores permitidos Descrição
markdownHeaderDepth h1, h2, h3, h4, h5, h6(default) Esse parâmetro determina o nível de cabeçalho mais profundo que é considerado ao analisar, permitindo o tratamento flexível da estrutura do documento (por exemplo, quando markdownHeaderDepth é definido como h1, o analisador reconhece apenas 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, ele assume h6 como padrão.

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 Markdown.

Elementos Markdown com suporte

A análise Markdown dividirá apenas 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.

Conteúdo de Markdown de exemplo

O seguinte conteúdo 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, em que cada documento corresponde a uma seção de conteúdo específica do arquivo Markdown com base nos metadados de cabeçalho nesse 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 o Markdown bruto encontrado em um local específico, com base nos metadados de cabeçalho nesse ponto do documento.

  • sections: um objeto que contém subcampos para os metadados de cabeçalho até o nível de cabeçalho desejado. Por exemplo, quando markdownHeaderDepth é definido como h3, contém campos de cadeia de caracteres h1, h2 e h3. Esses campos são indexados espelhando essa estrutura no índice ou por meio de mapeamentos de campo no formato /sections/h1, sections/h2 etc. Confira 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 cadeia de caracteres que contém o valor do cabeçalho h2. Cadeia de caracteres vazia se não estiver definida neste ponto do documento.
    • (Opcional) h3– uma cadeia de caracteres que contém o valor do cabeçalho h3. Cadeia de caracteres vazia se não estiver definida neste ponto do documento.
    • (Opcional) h4– uma cadeia de caracteres que contém o valor do cabeçalho h4. Cadeia de caracteres vazia se não estiver definida neste ponto do documento.
    • (Opcional) h5– uma cadeia de caracteres que contém o valor do cabeçalho h5. Cadeia de caracteres vazia se não estiver definida neste ponto do documento.
    • (Opcional) h6– uma cadeia de caracteres que contém 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. Esse campo é usado para ordenar as seções em sua sequência original conforme elas 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

Uma configuração de índice de exemplo pode ser semelhante a esta:

{
  "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 do indexador para análise um para muitos

Se os nomes de campo e os tipos de dados se alinharem, o indexador de blob poderá inferir o mapeamento sem um mapeamento de campo explícito presente na solicitação, portanto, uma configuração do 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" }
  },
}

Observação

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

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

Esse 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 "levantá-los" 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, confira Mapeamentos de campo.

Digamos que você tenha um índice de pesquisa com os seguintes campos: raw_content do tipo Edm.String, h1_header do tipo Edm.String e h2_header do tipo Edm.String. Para mapear o 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 como "markdown" e use o parâmetro markdownHeaderDepth opcional para definir a profundidade máxima do título para agrupamento. 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 Markdown completo como uma única cadeia de caracteres. Esse 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 maneira aninhada correspondente aos cabeçalhos e seu respectivo conteúdo. Os campos são acessíveis por meio de mapeamentos de campo fazendo referência ao caminho, por exemplo, /sections/content. Os objetos nessa matriz têm as seguintes propriedades:

    • header_level: uma cadeia de caracteres que indica o nível do cabeçalho (h1, h2, h3 etc.) na sintaxe Markdown. Esse campo ajuda a entender a hierarquia e a estruturação do conteúdo.

    • header_name: uma cadeia de caracteres que contém o texto do cabeçalho como ele aparece no documento Markdown. Esse 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. Esse campo captura as informações detalhadas ou a descrição associada ao cabeçalho. Se não houver conteúdo diretamente em um cabeçalho, essa será uma cadeia de caracteres vazia.

    • ordinal_position: um valor inteiro que indica a posição da seção dentro da hierarquia do documento. Esse campo é usado para ordenar as seções em sua sequência original conforme elas 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 que a matriz sections de nível superior, permitindo a representação de vários níveis de conteúdo aninhado. Cada objeto de subseção também inclui propriedades header_level, header_name, content e ordinal_position, habilitando uma estrutura recursiva que representa e hierarquia do conteúdo Markdown.

Aqui está o Markdown de exemplo que estamos usando para explicar um esquema de índice que é 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 Markdown. Dada a estrutura do Markdown de exemplo com suas duas seções e uma única subseção, o índice deve ser semelhante ao seguinte exemplo:

{
  "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 do 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 h2 ("##"), precisamos de campos sections 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 é incrementada com base no local 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 presentes no conteúdo Markdown, não necessariamente contendo seções aninhadas para h1 por meio de 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 você quiser extrair campos com nomes personalizados do documento, poderá usar mapeamentos de campo para fazer isso. Usando o mesmo exemplo de Markdown de 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 modo semelhante à forma como os caminhos do documento estão em outputFieldMappings, exceto que o caminho começa com /sections em vez de /document. Portanto, 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 semelhante a este: todos os arquivos Markdown têm um título de documento no primeiro h1, um título de subseção no primeiro h2 e um resumo no conteúdo do parágrafo final abaixo do h1 final. 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 partes relevantes desse documento. Para usar essa funcionalidade com mais eficiência, os documentos que você planeja indexar devem compartilhar a mesma estrutura de cabeçalho hierárquico.

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."
}

Observação

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

Próximas etapas