💡 Pełny działający przykład dostępny na GitHubie: parse-docx-to-markdown-chunks-dotnet
Stara metoda była bolesna
Chunkowanie Markdown oparte na nagłówkach jest ścieżką przygotowania pobierania w .NET, która zamienia pliki Office i PDF na tekst o rozmiarze sekcji przed ich osadzeniem. Bez tego zespoły często wrzucają cały plik Worda do jednego wektora. Akapit wprowadzający i klauzula obowiązkowa dzielą jedno osadzenie, więc wyszukiwanie kosinusowe ocenia niewłaściwą sekcję. Doświadczyłem tego na trzystronnym wewnętrznym przewodniku: każde zapytanie najpierw wyciągało blok tytułowy, ponieważ indeks nigdy nie widział struktury # / ## napisaną przez autorów.
Tworzenie własnego konwertera DOCX‑to‑Markdown oznacza przechodzenie przez style Open XML, mapowanie poziomów list i nadal niepowodzenia, gdy kolejny upload jest PDF, którego sformatowana ścieżka Markdown zwraca null. Okna tokenów o stałym rozmiarze ignorują te nagłówki. Nocne korpusy mieszają wtedy puste skorupy z ogromnymi podręcznikami, ponieważ nikt nie sprawdzał najpierw liczby stron ani rozmiaru.
Rzeczywisty koszt osadzania całych plików: odpowiedzi z niewłaściwych sekcji, zmarnowane wydatki na ekstrakcję przy niepotrzebnych uploadach oraz brak artefaktów
chunk-01.md, które operatorzy mogą otworzyć podczas złej partii.
Jest lepszy sposób
GroupDocs.Parser dla .NET zastępuje to zamieszanie czterema skoncentrowanymi wywołaniami: GetDocumentInfo, GetFormattedText(FormattedTextMode.Markdown), GetText gdy Markdown jest null oraz mały przeglądnik nagłówków, który zapisuje chunk-NN.md. Ten sam typ Parser obsługuje parsowanie Word DOCX i awaryjny tekst PDF, więc masz jedną ścieżkę usługi C#.
You will need:
- .NET 8 SDK
- GroupDocs.Parser 26.10.0 (tymczasowa licencja)
- Plik Word DOCX (przykład ma 3 strony / 14820 bajtów) oraz opcjonalnie PDF
dotnet add package GroupDocs.Parser --version 26.10.0
Nowy sposób: sprawdź, wyodrębnij, awaryjny fallback, podziel
Oto to samo przygotowanie pobierania po zmianie. Przykład konsolowy w parse-docx-to-markdown-chunks-dotnet zapisuje informacje, Markdown, tekst PDF i cztery fragmenty nagłówków dla dostarczonego DOCX.
Krok 1 – sprawdź za pomocą GetDocumentInfo
Zapytaj o typ pliku, liczbę stron i rozmiar przed opłaceniem pełnej ekstrakcji.
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());
Zaloguj te fakty obok identyfikatora zadania. W przykładowym DOCX powinieneś zobaczyć dokument Microsoft Word Open XML, 3 strony i 14820 bajtów.
Krok 2 – preferuj Markdown z GetFormattedText
Dla Worda i formatów, które obsługują sformatowaną ekstrakcję, zachowaj nagłówki ATX dla podziału.
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 jest sygnałem do zmiany ścieżki, a nie awarią. Zapisz w UTF‑8, aby narzędzia do fragmentów i diffy git były czytelne.
Krok 3 – awaryjny fallback z GetText dla PDF
Gdy tryb Markdown zwraca null, utrzymaj plik w potoku z warstwą zwykłego tekstu.
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;
Oczekuj .txt, a nie wymyślonych nagłówków #. Przykładowy host zapisuje Result/sample-pdf.txt dla gałęzi PDF.
Krok 4 – podziel Markdown na # i
Przeglądaj linie; opróżnij, gdy pojawi się nowy ATX # lub ##; zapisz 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);
}
}
Najpierw usuń przestarzałe pliki chunk-*.md. Głębsze linie ### pozostają w bieżącej sekcji. Przykładowy DOCX generuje cztery pliki w Result/chunks/.
Kiedy powinienem zastąpić osadzanie całych plików tą ścieżką?
Zastąp osadzanie całych plików, gdy przyjmowanie miesza Word DOCX i PDF, a indeks potrzebuje Markdown o rozmiarze sekcji. Najpierw uruchom GetDocumentInfo, spróbuj Markdown dla plików Office, wywołaj GetText, gdy sformatowany czytnik jest null, i podziel tylko wtedy, gdy istnieją znaczniki # / ##. Pozostaw nieustrukturyzowany tekst PDF w spokoju, aż dodasz osobną politykę podziału. Ta kolejność odpowiada przykładowej aplikacji konsolowej i utrzymuje tryby awarii wyraźne dla operatorów.
Co się zmieniło dla operatorów
| Przed | Po |
|---|---|
| Jedno osadzenie na plik | Jedno osadzenie na blok nagłówka |
| Niestandardowy Open XML Markdown | Tryb Markdown GetFormattedText |
| PDF odrzucony przy null sformatowanym czytniku | GetText zapisuje artefakt tekstowy |
| Brak taniego wstępnego sprawdzenia | Liczba stron i rozmiar jako bramka |
Zwolnij każdy Parser i TextReader. Zastosuj licencję lub tymczasową licencję przed nocnym wolumenem. Traktuj uploady jako nieufne dane wejściowe i parsuj w odizolowanym workerze.
Wypróbuj to na własnych plikach
Sklonuj parse-docx-to-markdown-chunks-dotnet, przywróć GroupDocs.Parser 26.10.0 i uruchom przeciwko documents/sample.docx. Następnie skieruj te same cztery metody na jeden ze swoich podręczników i otwórz wygenerowane pliki chunk-*.md.