💡 Esempio completo funzionante disponibile su GitHub: parse-docx-to-markdown-chunks-dotnet
Il vecchio modo era doloroso
Il chunking di Markdown basato su intestazioni è un percorso di preparazione al recupero .NET che trasforma i file Office e PDF in testo di dimensione sezione prima dell’incorporamento. Senza di esso, i team spesso scaricano un intero file Word in un unico vettore. Il paragrafo di copertina e la clausola di dovere condividono un unico embedding, quindi la ricerca coseno classifica la sezione sbagliata. Mi è capitato su una guida interna di tre pagine: ogni query estraeva prima il blocco del titolo perché l’indice non vedeva la struttura # / ## già scritta dagli autori.
Creare manualmente un convertitore DOCX‑to‑Markdown significa percorrere gli stili Open XML, mappare i livelli delle liste e fallire comunque quando il prossimo upload è un PDF il cui percorso Markdown formattato restituisce null. Le finestre di token a dimensione fissa ignorano quelle intestazioni. I corpora notturni mescolano quindi gusci vuoti con enormi manuali perché nessuno ha filtrato prima per numero di pagine o dimensione.
Il vero costo degli embedding dell’intero file: risposte nella sezione sbagliata, spese di estrazione sprecate su upload inutili, e nessun artefatto
chunk-01.mdche gli operatori possano aprire durante un batch difettoso.
C’è un modo migliore
GroupDocs.Parser per .NET sostituisce quel caos con quattro chiamate mirate: GetDocumentInfo, GetFormattedText(FormattedTextMode.Markdown), GetText quando Markdown è null, e un piccolo walker delle intestazioni che scrive chunk‑NN.md. Lo stesso tipo Parser gestisce l’analisi di Word DOCX e il fallback al testo PDF, così mantieni un unico percorso di servizio C#.
Avrai bisogno di:
- .NET 8 SDK
- GroupDocs.Parser 26.10.0 (licenza temporanea)
- Un file Word DOCX (il campione è di 3 pagine / 14820 byte) e opzionalmente un PDF
dotnet add package GroupDocs.Parser --version 26.10.0
Il nuovo modo: ispeziona, estrai, fallback, dividi
Ecco la stessa preparazione al recupero dopo il cambiamento. Il campione console sotto parse-docx-to-markdown-chunks-dotnet scrive informazioni, Markdown, testo PDF e quattro chunk di intestazione per il DOCX fornito.
Passo 1 - Filtra con GetDocumentInfo
Richiedi il tipo di file, il numero di pagine e la dimensione prima di pagare per un’estrazione 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());
Registra questi fatti accanto all’ID del lavoro. Sul DOCX di esempio dovresti vedere un Microsoft Word Open XML Document, 3 pagine e 14820 byte.
Passo 2 - Preferisci Markdown da GetFormattedText
Per Word e formati che supportano l’estrazione formattata, mantieni le intestazioni ATX per lo splitter.
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;
Null è un segnale per cambiare percorso, non un crash. Scrivi in UTF‑8 così gli strumenti di chunk e i diff di git rimangono leggibili.
Passo 3 - Fallback con GetText per PDF
Quando la modalità Markdown restituisce null, mantieni il file nella pipeline con uno strato di testo semplice.
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;
Attendi .txt, non intestazioni # inventate. L’host di esempio scrive Result/sample-pdf.txt per il ramo PDF.
Passo 4 - Dividi Markdown su # e
Scorri le righe; svuota quando appare un nuovo ATX # o ##; scrivi 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);
}
}
Cancella prima i file chunk-*.md obsoleti. Le linee più profonde ### rimangono all’interno della sezione corrente. Il DOCX di esempio genera quattro file sotto Result/chunks/.
Quando dovrei sostituire gli embedding dell’intero file con questo percorso?
Sostituisci gli embedding dell’intero file quando l’ingestione mescola Word DOCX e PDF e l’indice necessita di Markdown a dimensione di sezione. Esegui prima GetDocumentInfo, prova Markdown per i file Office, chiama GetText quando il lettore formattato è null, e dividi solo quando esistono i marcatori # / ##. Lascia il testo PDF non strutturato intatto finché non aggiungi una politica di chunk separata. Questo ordine corrisponde all’app console di esempio e mantiene i modi di fallimento espliciti per gli operatori.
Cosa è cambiato per gli operatori
| Prima | Dopo |
|---|---|
| Un embedding per file | Un embedding per blocco di intestazione |
| Markdown Open XML personalizzato | GetFormattedText modalità Markdown |
| PDF scartato su lettore formattato null | GetText scrive un artefatto di testo |
| Nessun controllo preliminare economico | Controllo preliminare su numero di pagine e dimensione |
Disporre di ogni Parser e TextReader. Applica una licenza o licenza temporanea prima del volume notturno. Tratta gli upload come input non attendibili e analizza in un worker isolato.
Provalo sui tuoi file
Clona parse-docx-to-markdown-chunks-dotnet, ripristina GroupDocs.Parser 26.10.0 ed esegui su documents/sample.docx. Poi indirizza gli stessi quattro metodi verso uno dei tuoi manuali e apri i file chunk-*.md generati.