💡 전체 작동 예제가 GitHub에 있습니다: parse-docx-to-markdown-chunks-dotnet

이전 방식은 고통스러웠다

헤딩 기반 Markdown 청킹은 .NET 검색 전처리 경로로, Office 및 PDF 파일을 섹션 크기의 텍스트로 변환한 뒤 임베딩합니다. 이 과정을 생략하면 팀이 전체 Word 파일을 하나의 벡터로 덤프하는 경우가 많습니다. 표지 문단과 의무 조항이 하나의 임베딩을 공유하게 되어 코사인 검색이 잘못된 섹션을 순위에 올립니다. 저는 3페이지 분량의 내부 가이드에서 이 문제를 겪었습니다: 모든 쿼리가 제목 블록을 먼저 반환했는데, 인덱스가 저자들이 이미 작성한 # / ## 구조를 전혀 보지 못했기 때문입니다.

DOCX를 Markdown으로 직접 변환하는 작업은 Open XML 스타일을 탐색하고, 리스트 레벨을 매핑하며, 다음 업로드가 PDF일 때 포맷된 Markdown 경로가 null을 반환하면 여전히 실패합니다. 고정 크기 토큰 윈도우는 이러한 헤딩을 무시합니다. 밤새 처리되는 코퍼스는 페이지 수나 크기에 대한 사전 검사가 없기 때문에 빈 껍데기와 거대한 매뉴얼이 뒤섞이게 됩니다.

전체 파일 임베딩의 실제 비용: 잘못된 섹션 답변, 쓸모없는 업로드에 대한 추출 비용 낭비, 그리고 배치가 나쁠 때 운영자가 열어볼 수 있는 chunk-01.md 아티팩트가 없음.

더 나은 방법이 있다

GroupDocs.Parser for .NET은 이 혼란을 네 가지 집중 호출로 대체합니다: GetDocumentInfo, GetFormattedText(FormattedTextMode.Markdown), Markdown이 null일 때 GetText, 그리고 chunk-NN.md를 작성하는 작은 헤딩 워커. 동일한 Parser 타입이 Word DOCX 파싱과 PDF 텍스트 폴백을 모두 처리하므로 하나의 C# 서비스 경로만 유지하면 됩니다.

필요한 것:

  • .NET 8 SDK
  • GroupDocs.Parser 26.10.0 (temporary license)
  • Word DOCX 파일(샘플은 3페이지 / 14820바이트) 및 선택적으로 PDF
dotnet add package GroupDocs.Parser --version 26.10.0

새로운 방식: 검사, 추출, 폴백, 분할

전환 후 동일한 검색 전처리 예시입니다. parse-docx-to-markdown-chunks-dotnet 콘솔 샘플은 정보, Markdown, PDF 텍스트, 그리고 제공된 DOCX에 대한 네 개의 헤딩 청크를 기록합니다.

Step 1 - GetDocumentInfo 로 게이트

전체 추출 비용을 지불하기 전에 파일 유형, 페이지 수, 크기를 확인합니다.

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

작업 ID 옆에 이러한 사실을 로그합니다. 샘플 DOCX에서는 Microsoft Word Open XML Document, 3페이지, 14820바이트가 표시됩니다.

Step 2 - GetFormattedText 로 Markdown 우선 사용

Word 및 포맷된 추출을 지원하는 형식에서는 분할기를 위해 ATX 헤딩을 유지합니다.

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은 경로를 전환하라는 신호이며, 오류가 아닙니다. UTF-8로 기록해 청크 도구와 git diff가 읽기 쉬운 상태를 유지합니다.

Step 3 - PDF에 대해 GetText 로 폴백

Markdown 모드가 null을 반환하면 일반 텍스트 레이어로 파이프라인에 파일을 유지합니다.

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;

.txt 파일을 기대하고, 인위적인 # 헤딩은 기대하지 마세요. 샘플 호스트는 PDF 분기에서 Result/sample-pdf.txt를 작성합니다.

Step 4 - # 및 ## 로 Markdown 분할

라인을 순회하고 새 ATX # 또는 ##가 나타날 때 플러시하여 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);
    }
}

먼저 오래된 chunk-*.md 파일을 삭제합니다. 더 깊은 ### 라인은 현재 섹션 안에 머무릅니다. 샘플 DOCX는 Result/chunks/ 아래에 네 개의 파일을 생성합니다.

언제 전체 파일 임베딩을 이 경로로 교체해야 할까?

입력에 Word DOCX와 PDF가 혼합되고 인덱스가 섹션 크기의 Markdown을 필요로 할 때 전체 파일 임베딩을 교체합니다. 먼저 GetDocumentInfo를 실행하고, Office 파일에 대해 Markdown을 시도하며, 포맷된 리더가 null일 때 GetText를 호출하고, # / ## 마커가 존재할 때만 분할합니다. 별도의 청크 정책을 추가하기 전까지는 구조화되지 않은 PDF 텍스트를 그대로 두세요. 이 순서는 샘플 콘솔 앱과 일치하며 운영자를 위한 실패 모드를 명확히 합니다.

운영자를 위한 변경 사항

이전 이후
파일당 하나의 임베딩 헤딩 블록당 하나의 임베딩
맞춤형 Open XML 마크다운 GetFormattedText Markdown 모드
PDF가 null 형식 리더에 의해 처리되지 않음 GetText가 텍스트 아티팩트를 작성
간단한 사전 검사 없음 페이지 수와 크기 게이트 작동

모든 Parser와 TextReader를 Dispose하십시오. 야간 대량 처리 전에 라이선스를 적용하거나 temporary license를 사용하십시오. 업로드는 신뢰할 수 없는 입력으로 간주하고 격리된 워커에서 파싱하십시오.

직접 파일에 적용해 보기

parse-docx-to-markdown-chunks-dotnet 저장소를 클론하고, GroupDocs.Parser 26.10.0을 복원한 뒤 documents/sample.docx에 대해 실행합니다. 그런 다음 동일한 네 가지 메서드를 여러분의 매뉴얼 중 하나에 적용하고 생성된 chunk-*.md 파일을 열어 보세요.