Indexar blobs e ficheiros Markdown no Pesquisa de IA do Azure

Nota

O Pesquisa de IA do Azure está disponível através do portal Azure, APIs REST e SDKs do Azure. Também sustenta o Foundry IQ, a camada de conhecimento gerida que transforma conteúdos empresariais em bases de conhecimento reutilizáveis e conscientes de permissões para agentes no portal Microsoft Foundry.

Importante

Estas funcionalidades e capacidades permitem a ligação a outros serviços da Microsoft e a serviços de terceiros. A utilização destes serviços está sujeita aos respetivos termos e pode resultar no processamento ou armazenamento de dados fora do limite de conformidade do Azure, bem como no fluxo de dados para o limite de conformidade do Azure.

É sua responsabilidade gerir se os seus dados irão fluir para além dos limites de conformidade e geográficos da sua organização e quaisquer implicações relacionadas, e garantir que as permissões, limites e aprovações apropriadas sejam providenciadas.

És responsável por rever e testar cuidadosamente as aplicações que constróis no contexto dos teus casos de uso específicos e por tomar todas as decisões e personalizações apropriadas. Isto inclui implementar as suas próprias mitigações de IA responsável, como metaprompts, filtros de conteúdo ou outros sistemas de segurança, e assegurar que as suas aplicações cumprem os padrões adequados de qualidade, fiabilidade, segurança e confiabilidade. Para mais informações, consulte a Nota de Transparência Pesquisa de IA do Azure.

No Pesquisa de IA do Azure, os indexadores para Armazenamento de Blobs do Azure, Ficheiros do Azure e Microsoft OneLake suportam um modo de análise markdown para ficheiros Markdown. Os ficheiros markdown podem ser indexados de duas formas:

  • Modo de análise de um para muitos, que cria múltiplos documentos de pesquisa por ficheiro Markdown.
  • Modo de análise individual, que cria um documento de pesquisa por cada ficheiro Markdown.

Dica

Depois de rever este artigo, continue para Tutorial: Pesquisar dados de Markdown de Armazenamento de Blobs do Azure.

Pré-requisitos

Parâmetros do modo de análise Markdown

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

POST https://[service name].search.windows.net/indexers?api-version=2026-04-01
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 blob indexer fornece um submode parâmetro para determinar a estrutura de saída dos documentos de pesquisa. O modo de análise Markdown oferece as seguintes opções de submodo:

Modo de Análise submodo Pesquisa no documento Descrição
markdown oneToMany Múltiplo por blob (padrão) Divide o Markdown em múltiplos documentos de pesquisa, cada um representando uma secção de conteúdo (sem cabeçalho) do ficheiro Markdown. Podes omitir o submodo a menos que queiras análise sintática um-para-um.
markdown oneToOne Um por blob Analisa o Markdown num único documento de pesquisa, com secções mapeadas para cabeçalhos específicos no ficheiro Markdown.

Para o oneToMany submodo, deve rever Indexar um blob para produzir vários documentos de pesquisa e compreender como o indexador de blobs gere a desambiguação da chave do documento para vários documentos de pesquisa gerados a partir do mesmo blob.

Secções posteriores descrevem cada submodo com mais detalhe. Se não estiver familiarizado com clientes e conceitos de indexadores, veja Criar um indexador de pesquisa. Deves também estar familiarizado com os detalhes da configuração básica do blob indexer, que não é repetida aqui.

Parâmetros opcionais de análise Markdown

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

Nome do parâmetro Valores permitidos Descrição
markdownHeaderDepth h1, h2, h3, h4, h5, h6 (default) Este parâmetro determina o nível de cabeçalho mais profundo considerado ao analisar, permitindo um tratamento flexível da estrutura do documento (por exemplo, quando markdownHeaderDepth está definido para h1, o analisador só reconhece cabeçalhos de topo que começam por "#", e todos os cabeçalhos de nível inferior são tratados como texto simples). Se não for especificado, por padrão é h6.

Esta configuração pode ser alterada após a criação do indexador. No entanto, a estrutura dos documentos de pesquisa resultantes pode mudar consoante o conteúdo do Markdown.

Elementos Markdown suportados

A análise Markdown só divide o conteúdo baseando-se nos cabeçalhos. Todos os outros elementos, como listas, blocos de código e tabelas, são tratados como texto simples e passados para um campo de conteúdo.

Conteúdo Markdown de exemplo

O seguinte conteúdo Markdown é utilizado para os exemplos desta 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 de um para muitos analisa ficheiros Markdown em múltiplos documentos de pesquisa, onde cada documento corresponde a uma secção de conteúdo específica do ficheiro Markdown com base nos metadados do cabeçalho nesse ponto do documento. O Markdown é analisado com base em cabeçalhos nos documentos de pesquisa, que contêm o seguinte conteúdo:

  • content: Uma cadeia que contém o Markdown bruto encontrado numa localização específica, 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é ao nível desejado do cabeçalho. Por exemplo, quando markdownHeaderDepth é definido para h3, contém corpos h1de cadeia , h2, e h3. Estes campos são indexados espelhando esta estrutura no índice, ou através de mapeamentos de campos no formato /sections/h1, /sections/h2, e assim sucessivamente. Consulte as configurações de índice e indexador nos exemplos seguintes para exemplos em contexto. Os subcampos contidos são:

    • h1 - Uma cadeia contendo o valor do cabeçalho h1. String vazia se não estiver definida neste ponto do documento.
    • (Opcional) h2- Uma cadeia contendo o valor do cabeçalho h2. String vazia se não estiver definida neste ponto do documento.
    • (Opcional) h3- Uma cadeia contendo o valor do cabeçalho h3. String vazia se não estiver definida neste ponto do documento.
    • (Opcional) h4- Uma cadeia contendo o valor do cabeçalho h4. String vazia se não estiver definida neste ponto do documento.
    • (Opcional) h5- Uma cadeia contendo o valor do cabeçalho h5. String vazia se não estiver definida neste ponto do documento.
    • (Opcional) h6- Uma cadeia contendo o valor do cabeçalho h6. String vazia se não estiver definida neste ponto do documento.
  • ordinal_position: Um valor inteiro que indica a posição da secção dentro da hierarquia do documento. Este campo é usado para ordenar as secções na sua sequência original conforme 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 de um-para-muitos

Um exemplo de configuração de índice pode parecer algo assim:

{
  "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 sintática um-para-muitos

Se os nomes dos campos e os tipos de dados estiverem alinhados, o indexador de blob pode inferir o mapeamento sem a presença explícita de mapeamento de campos no pedido, pelo que uma configuração de indexador correspondente à configuração de índice fornecida pode ser assim:

POST https://[service name].search.windows.net/indexers?api-version=2026-04-01
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 de ser definido explicitamente aqui, uma vez que oneToMany é o padrão.

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

Este ficheiro Markdown resultaria em três documentos de pesquisa após indexação, devido às três secções de conteúdo. O documento de pesquisa resultante da primeira secçã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 num índice de pesquisa

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

O exemplo seguinte ilustra este cenário. Para mais informações sobre mapeamentos de campos em geral, veja mapeamentos de campos.

Assuma um índice de pesquisa com os seguintes campos: raw_content de tipo Edm.String, h1_header de tipo Edm.String, e h2_header de tipo Edm.String. Para mapear o seu Markdown na 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 seria o seguinte:

{
  {
    "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 sintática um-para-um

No modo de análise sintática um-para-um, todo o documento Markdown é indexado como um único documento de pesquisa, preservando a hierarquia e a estrutura do conteúdo original. Este modo é mais útil quando os ficheiros a indexar partilham uma estrutura comum, para que 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 do cabeçalho para o chunking. Se não for especificado, por padrão, define-se como h6, abrangendo todas as profundidades de cabeçalhos possíveis.

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

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

  • sections: Um array de objetos que contém a representação hierárquica das secções dentro do documento Markdown. Cada secção é representada como um objeto dentro deste array e capta a estrutura do documento de forma aninhada, correspondendo aos cabeçalhos e respetivos conteúdos. Os campos são acessíveis através de mapeamentos de campos, referenciando o caminho, por exemplo /sections/content. Os objetos neste array têm as seguintes propriedades:

    • header_level: Uma cadeia que indica o nível do cabeçalho (h1, h2, h3, e assim sucessivamente) na sintaxe Markdown. Esta área ajuda a compreender a hierarquia e a estruturação do conteúdo.

    • header_name: Uma cadeia 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 secção.

    • content: Uma cadeia contendo conteúdo textual que imediatamente segue o cabeçalho, até ao próximo cabeçalho. Este campo capta a informação detalhada ou descrição associada ao cabeçalho. Se não houver conteúdo diretamente sob um cabeçalho, o valor é uma cadeia vazia.

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

    • sections: Um array que contém objetos que representam subsecções aninhadas sob a secção atual. Este array segue a mesma estrutura do array de topo sections , permitindo a representação de múltiplos níveis de conteúdo aninhado. Cada subobjeto também inclui header_level, header_name, content, e ordinal_position propriedades, permitindo uma estrutura recursiva que representa a hierarquia do conteúdo Markdown.

Aqui está o exemplo de Markdown que estamos a usar para explicar os esquemas de índice desenhados 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 sintática um-para-um

Se não usar mapeamentos de campo, a forma do índice deve refletir a forma do conteúdo Markdown. Dada a estrutura do Markdown de amostra, com as suas duas secções e uma única subsecção, o índice deverá ser semelhante ao seguinte exemplo:

{
  "name": "my-markdown-index",
  "fields": [
  {
    "name": "id",
    "type": "Edm.String",
    "key": true
  },
  {
    "name": "document_content",
    "type": "Edm.String"
  },
  {
    "name": "sections",
    "type": "Collection(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.Int32"
    },
    {
      "name": "sections",
      "type": "Collection(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.Int32"
      }]
    }]
  }]
}

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

POST https://[service name].search.windows.net/indexers?api-version=2026-04-01
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 sintática um-para-um

Como o Markdown que queremos indexar só vai para uma profundidade de h2 ("##"), precisamos sections de campos aninhados a uma profundidade de 2 para corresponder a isso. Esta 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 pode ver, a posição ordinal aumenta com base na localização do conteúdo dentro do documento.

Se os níveis de cabeçalho forem omitidos no conteúdo, a estrutura do documento resultante reflete os cabeçalhos presentes no conteúdo Markdown e não contém necessariamente secções aninhadas consecutivas de h1 até h6. Por exemplo, quando o documento começa em h2, o primeiro elemento no array de secções de topo é h2.

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

Para extrair campos com nomes personalizados do documento, pode usar mapeamentos de campos. Usando a mesma amostra 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",
    }
  ]
}

Extrair campos específicos do Markdown analisado é tratado de forma semelhante aos caminhos dos documentos em outputFieldMappings, exceto que o caminho começa com /sections em vez de /document. Por exemplo, /sections/0/content mapearia para o conteúdo sob o item na posição 0 no array de secções.

Um exemplo de um caso de uso forte pode ser algo assim: todos os ficheiros 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 por baixo do último h1. Pode usar os seguintes mapeamentos de campo para indexar apenas 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, extrairias apenas as partes relevantes desse documento. Para utilizar esta funcionalidade da forma mais eficaz, os documentos que pretende indexar devem partilhar a mesma estrutura hierárquica de cabeçalhos.

O documento de pesquisa resultante no índice seria o seguinte:

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

Nota

Estes exemplos especificam como usar estes modos de análise inteiramente com ou sem mapeamentos de campo, mas pode aplicar ambos num cenário se for adequado para si.

Gerir documentos antigos na reindexação do Markdown

Ao usar o modo de análise de um para muitos, reindexar um ficheiro Markdown modificado pode resultar em documentos obsoletos ou duplicados se as secções forem removidas. Este comportamento é específico do modo um-para-muitos e não se aplica à análise sintática um-para-um.

Visão geral do comportamento

Modo de análise de um para muitos

No oneToMany modo, cada secção Markdown (baseada em cabeçalhos) é indexada como um documento de pesquisa separado. Quando o ficheiro é reindexado:

  • Sem eliminação automática: O indexador sobrescrive documentos existentes por novos, mas não apaga documentos que já não correspondem a qualquer conteúdo do ficheiro atualizado.
  • Potencial para duplicados: Este problema surge especificamente apenas quando mais secções são eliminadas do que inseridas entre execuções de indexação. Nesses casos, documentos remanescentes da versão anterior permanecem no índice, levando a entradas obsoletas que já não refletem o estado atual do ficheiro fonte.

Modo de análise sintática um-para-um

No oneToOne modo, todo o ficheiro Markdown é indexado como um único documento de pesquisa. Quando o ficheiro é reindexado:

  • Comportamento de sobrescrever: O documento existente é totalmente substituído pela nova versão.
  • Sem secções obsoletas: Quando o ficheiro é reindexado, o documento existente é substituído pela versão atualizada e o conteúdo removido deixa de ser incluído. A única exceção é se o caminho do ficheiro ou o URI do blob mudar, o que pode resultar na criação de um novo documento juntamente com o antigo.

Opções de solução alternativa

Para garantir que o índice reflete o estado atual dos seus ficheiros Markdown, considere uma das seguintes abordagens:

Opção 1. Eliminação suave com metadados

Este método utiliza uma eliminação suave para eliminar documentos associados a um blob específico. Para mais informações, veja deteção de alterações e eliminações usando indexadores para Armazenamento do Azure em Pesquisa de IA do Azure.

Passos:

  1. Marque o blob como eliminado definindo um campo de metadados.
  2. Deixe o indexador correr. Apaga todos os documentos no índice associado a esse blob.
  3. Remova o marcador de eliminação suave e volte a indexar o ficheiro.

Opção 2. Usa a API de eliminação

Antes de reindexar um ficheiro Markdown modificado, elimine explicitamente os documentos existentes associados a esse ficheiro usando a API de eliminação. Pode escolher uma das seguintes opções:

  • Identifique manualmente documentos obsoletos individuais, identificando duplicados no índice a serem eliminados. Isto pode ser viável para pequenas mudanças bem compreendidas, mas pode ser demorado.
  • (Recomendado) Remover todos os documentos gerados a partir do mesmo ficheiro pai antes de reindexar, garantindo que se evitam inconsistências.

Passos:

  1. Identifique o ID dos documentos associados ao ficheiro. Use uma consulta como o exemplo seguinte para obter os IDs de chave de documento (por exemplo, id ou chunk_id) para todos os documentos ligados a um ficheiro específico. Substitua metadata_storage_path pelo campo apropriado no seu índice que corresponda ao caminho do ficheiro ou ao URI do blob. Este campo deve ser fundamental.

    GET https://[service name].search.windows.net/indexes/[index name]/docs?api-version=2026-04-01
    Content-Type: application/json
    api-key: [admin key]
    
    
      {
          "filter": "metadata_storage_path eq 'https://<storage-account>.blob.core.windows.net/<container-name>/<file-name>.md'",
          "select": "id"
      }
    
  2. Emita um pedido de eliminação dos documentos com as chaves identificadas.

    POST https://[service name].search.windows.net/indexes/[index name]/docs/index?api-version=2026-04-01
    Content-Type: application/json
    api-key: [admin key]
    
    {
      "value": [
        {
          "@search.action": "delete",
          "id": "aHR0c...jI1"
        },
        {
          "@search.action": "delete",
          "id": "aHR0...MQ2"
        }
      ]
    }
    
  3. Reindexe o ficheiro atualizado.

Próximos passos