💡 Exemple complet fonctionnel disponible sur GitHub : parse-docx-to-markdown-chunks-dotnet

L’ancienne méthode était pénible

Le fractionnement en morceaux basé sur les titres Markdown est un chemin de préparation à la récupération .NET qui transforme les fichiers Office et PDF en texte de taille de section avant l’indexation. Sans cela, les équipes déposent souvent un fichier Word entier dans un seul vecteur. Le paragraphe de couverture et la clause de responsabilité partagent le même embedding, si bien que la recherche cosinus classe la mauvaise section. Je l’ai constaté sur un guide interne de trois pages : chaque requête récupérait d’abord le bloc de titre parce que l’index ne voyait jamais la structure # / ## déjà écrite par les auteurs.

Construire soi‑même un convertisseur DOCX‑to‑Markdown signifie parcourir les styles Open XML, mapper les niveaux de listes, et échouer quand le prochain téléchargement est un PDF dont le chemin Markdown formaté renvoie null. Les fenêtres de tokens de taille fixe ignorent ces titres. Les corpus nocturnes mélangent alors des coquilles vides avec d’énormes manuels parce que personne ne filtre d’abord par nombre de pages ou taille.

Le vrai coût des embeddings de fichier complet : réponses hors section, dépenses d’extraction gaspillées sur des téléchargements indésirables, et aucun artefact chunk-01.md que les opérateurs puissent ouvrir lors d’un lot défectueux.

Il existe une meilleure méthode

GroupDocs.Parser pour .NET remplace ce désordre par quatre appels ciblés : GetDocumentInfo, GetFormattedText(FormattedTextMode.Markdown), GetText lorsque le Markdown est null, et un petit explorateur de titres qui écrit chunk-NN.md. Le même type Parser couvre l’analyse Word DOCX et le repli texte PDF, ainsi vous ne conservez qu’un seul chemin de service C#.

Vous aurez besoin de :

  • .NET 8 SDK
  • GroupDocs.Parser 26.10.0 (licence temporaire)
  • Un fichier Word DOCX (l’exemple fait 3 pages / 14820 octets) et, éventuellement, un PDF
dotnet add package GroupDocs.Parser --version 26.10.0

La nouvelle méthode : inspecter, extraire, revenir en arrière, diviser

Voici la même préparation à la récupération après le changement. L’exemple console sous parse-docx-to-markdown-chunks-dotnet écrit les informations, le Markdown, le texte PDF et quatre morceaux de titres pour le DOCX fourni.

Étape 1 - Vérifier avec GetDocumentInfo

Demandez le type de fichier, le nombre de pages et la taille avant de payer pour une extraction complète.

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());

Consignez ces faits à côté de l’ID du travail. Sur le DOCX d’exemple vous devriez voir « Microsoft Word Open XML Document », 3 pages et 14820 octets.

Étape 2 - Privilégier le Markdown avec GetFormattedText

Pour Word et les formats qui supportent l’extraction formatée, conservez les titres ATX pour le séparateur.

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 est un signal pour changer de chemin, pas un plantage. Écrivez en UTF‑8 afin que les outils de découpage et les diff Git restent lisibles.

Étape 3 - Revenir en arrière avec GetText pour le PDF

Lorsque le mode Markdown renvoie null, maintenez le fichier dans le pipeline avec une couche texte brut.

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;

Attendez‑vous à un fichier .txt, pas à des titres # inventés. L’hôte d’exemple écrit Result/sample-pdf.txt pour la branche PDF.

Étape 4 - Diviser le Markdown sur # et

Parcourez les lignes ; videz le tampon lorsqu’un nouveau titre ATX # ou ## apparaît ; écrivez 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);
    }
}

Supprimez d’abord les fichiers chunk-*.md obsolètes. Les lignes plus profondes ### restent à l’intérieur de la section courante. Le DOCX d’exemple produit quatre fichiers sous Result/chunks/.

Quand devrais‑je remplacer les embeddings de fichier complet par ce chemin ?

Remplacez les embeddings de fichier complet lorsque l’ingestion mélange Word DOCX et PDF et que l’index a besoin de Markdown de taille section. Exécutez d’abord GetDocumentInfo, essayez le Markdown pour les fichiers Office, appelez GetText lorsque le lecteur formaté est null, et ne découpez que lorsque des marqueurs # / ## existent. Laissez le texte PDF non structuré tel quel jusqu’à ce que vous ajoutiez une politique de découpage séparée. Cet ordre correspond à l’application console d’exemple et garde les modes d’échec explicites pour les opérateurs.

Ce qui a changé pour les opérateurs

Avant Après
Un embedding par fichier Un embedding par bloc de titre
Markdown Open XML personnalisé Mode Markdown GetFormattedText
PDF abandonné sur lecteur formaté null GetText écrit un artefact texte
Aucun pré‑contrôle économique Le filtrage par nombre de pages et taille fonctionne

Libérez chaque Parser et TextReader. Appliquez une licence ou une licence temporaire avant un volume nocturne. Traitez les téléchargements comme des entrées non fiables et analysez-les dans un worker isolé.

Essayez‑le avec vos propres fichiers

Clonez parse-docx-to-markdown-chunks-dotnet, restaurez GroupDocs.Parser 26.10.0, et exécutez‑le sur documents/sample.docx. Puis pointez les mêmes quatre méthodes sur l’un de vos manuels et ouvrez les fichiers chunk-*.md générés.