💡 Exemplo completo funcionando disponível no GitHub:
parse-docx-to-markdown-chunks-dotnet

O Antigo Método Era Doloroso

A segmentação baseada em cabeçalhos Markdown é um caminho de preparação de recuperação .NET que transforma arquivos Office e PDF em texto de tamanho de seção antes da incorporação. Sem isso, as equipes costumam despejar um arquivo Word inteiro em um único vetor. O parágrafo de capa e a cláusula de dever compartilham uma única incorporação, de modo que a busca por cosseno classifica a seção errada. Encontrei isso em um guia interno de três páginas: toda consulta trazia primeiro o bloco de título porque o índice nunca viu a estrutura # / ## que os autores já haviam escrito.

Criar manualmente um conversor DOCX‑to‑Markdown significa percorrer estilos Open XML, mapear níveis de lista e ainda falhar quando o próximo upload é um PDF cujo caminho Markdown formatado retorna nulo. Janelas de tokens de tamanho fixo ignoram esses cabeçalhos. Corpora noturnas então misturam cascas vazias com manuais enormes porque ninguém filtrou primeiro pela contagem de páginas ou tamanho.

O custo real das incorporações de arquivo inteiro: respostas de seção errada, gasto desperdiçado em extrações de uploads inúteis e ausência de artefatos chunk-01.md que os operadores possam abrir durante um lote problemático.

Existe uma Maneira Melhor

GroupDocs.Parser for .NET substitui essa confusão por quatro chamadas focadas: GetDocumentInfo, GetFormattedText(FormattedTextMode.Markdown), GetText quando Markdown é nulo e um pequeno percorridor de cabeçalhos que grava chunk‑NN.md. O mesmo tipo Parser cobre a análise de Word DOCX e o fallback de texto PDF, de modo que você mantém um único caminho de serviço C#.

Você precisará:

  • .NET 8 SDK
  • GroupDocs.Parser 26.10.0 (temporary license)
  • Um Word DOCX (o exemplo tem 3 páginas / 14820 bytes) e, opcionalmente, um PDF
dotnet add package GroupDocs.Parser --version 26.10.0

O Novo Caminho: Inspecionar, Extrair, Recuar, Dividir

Aqui está a mesma preparação de recuperação após a mudança. O exemplo de console em parse-docx-to-markdown-chunks-dotnet grava informações, Markdown, texto PDF e quatro blocos de cabeçalho para o DOCX enviado.

Etapa 1 - Filtrar com GetDocumentInfo

Solicite o tipo de arquivo, a contagem de páginas e o tamanho antes de pagar por uma extração completa.

using var parser = new Parser(sourcePath);
var info = parser.GetDocumentInfo();

var sb = new StringBuilder();
sb.AppendLine($"Source: {Path.GetFileName(sourcePath)}");
sb.AppendLine($"File type: {info?.FileType}");
sb.AppendLine($"Pages: {info?.PageCount}");
sb.AppendLine($"Size: {info?.Size} bytes");
File.WriteAllText(outputPath, sb.ToString());

Registre esses fatos ao lado do ID do trabalho. No DOCX de exemplo você deverá ver um Microsoft Word Open XML Document, 3 páginas e 14820 bytes.

Etapa 2 - Preferir Markdown de GetFormattedText

Para Word e formatos que suportam extração formatada, mantenha os cabeçalhos ATX para o divisor.

using var parser = new Parser(sourcePath);
using TextReader? reader = parser.GetFormattedText(
    new FormattedTextOptions(FormattedTextMode.Markdown));

if (reader == null)
{
    return null;
}

string markdown = reader.ReadToEnd();
File.WriteAllText(outputPath, markdown, Encoding.UTF8);
return markdown;

Nulo é um sinal para mudar de caminho, não uma falha. Grave em UTF‑8 para que as ferramentas de blocos e os diffs do git permaneçam legíveis.

Etapa 3 - Recuar com GetText para PDF

Quando o modo Markdown retorna nulo, mantenha o arquivo no pipeline com uma camada de texto simples.

using var parser = new Parser(sourcePath);
using TextReader? reader = parser.GetText();
if (reader == null)
{
    return null;
}

string text = reader.ReadToEnd();
File.WriteAllText(outputPath, text, Encoding.UTF8);
return text;

Espere um .txt, não cabeçalhos # inventados. O host de exemplo grava Result/sample-pdf.txt para o ramo PDF.

Etapa 4 - Dividir Markdown em # e

Percorra as linhas; descarte quando aparecer um novo ATX # ou ##; grave chunk‑NN.md.

var chunks = new List<string>();
var current = new StringBuilder();
using (var reader = new StringReader(markdown))
{
    string? line;
    while ((line = reader.ReadLine()) != null)
    {
        bool isHeading = line.StartsWith("# ", StringComparison.Ordinal)
            || line.StartsWith("## ", StringComparison.Ordinal);
        if (isHeading && current.Length > 0)
        {
            chunks.Add(current.ToString().TrimEnd());
            current.Clear();
        }
        current.AppendLine(line);
    }
}

Exclua primeiro os arquivos obsoletos chunk-*.md. Linhas mais profundas ### permanecem dentro da seção atual. O DOCX de exemplo gera quatro arquivos em Result/chunks/.

Quando devo substituir incorporações de arquivo inteiro por este caminho?

Substitua incorporações de arquivo inteiro quando a ingestão mistura Word DOCX e PDF e o índice precisa de Markdown em tamanho de seção. Execute GetDocumentInfo primeiro, tente Markdown para arquivos Office, chame GetText quando o leitor formatado for nulo e divida somente quando existirem marcadores # / ##. Deixe o texto PDF não estruturado de lado até adicionar uma política de blocos separada. Essa ordem corresponde ao aplicativo de console de exemplo e mantém os modos de falha explícitos para os operadores.

O que Mudou para os Operadores

Antes Depois
Uma incorporação por arquivo Uma incorporação por bloco de cabeçalho
Markdown Open XML personalizado Modo Markdown de GetFormattedText
PDF descartado quando o leitor formatado é nulo GetText grava um artefato de texto
Nenhuma verificação prévia barata Verificação de contagem de páginas e tamanho funciona

Descarte cada Parser e TextReader. Aplique uma licença ou temporary license antes de volume noturno. Trate uploads como entrada não confiável e analise em um worker isolado.

Experimente em Seus Próprios Arquivos

Clone parse-docx-to-markdown-chunks-dotnet, restaure GroupDocs.Parser 26.10.0 e execute contra documents/sample.docx. Em seguida, aponte os mesmos quatro métodos para um dos seus manuais e abra os arquivos chunk-*.md gerados.