💡 ตัวอย่างทำงานเต็มที่พร้อมบน GitHub:
parse-docx-to-markdown-chunks-dotnet
วิธีเก่าเคยทำให้เจ็บปวด
การแบ่งส่วน Markdown ตามหัวเรื่องเป็นกระบวนการเตรียมข้อมูลดึงข้อมูลใน .NET ที่แปลงไฟล์ Office และ PDF ให้เป็นข้อความขนาดส่วนก่อนที่คุณจะฝัง หากไม่มีขั้นตอนนี้ ทีมมักจะใส่ไฟล์ Word ทั้งหมดลงในเวกเตอร์เดียว ย่อหน้าปกและข้อกำหนดหน้าที่จะแบ่งปันการฝังเดียวกัน ทำให้การค้นหาแบบ cosine ให้ผลลัพธ์ส่วนที่ผิด ฉันเจอปัญหานี้ในคู่มือภายในสามหน้า: ทุกคำถามดึงบล็อกหัวเรื่องแรกก่อน เพราะดัชนีไม่เคยเห็นโครงสร้าง # / ## ที่ผู้เขียนได้เขียนไว้แล้ว
การสร้างตัวแปลง DOCX‑to‑Markdown ด้วยตนเองหมายถึงการเดินตามสไตล์ Open XML, การแมประดับรายการ, และยังล้มเหลวเมื่อการอัปโหลดต่อไปเป็น PDF ที่เส้นทาง Markdown ที่จัดรูปแบบแล้วคืนค่า null หน้าต่างโทเค็นขนาดคงที่มองข้ามหัวเรื่องเหล่านั้น คอร์ปัสที่ทำงานข้ามคืนจึงผสมเปลือกเปล่าเข้ากับคู่มือขนาดใหญ่เพราะไม่มีการกรองตามจำนวนหน้า หรือขนาดก่อน
ต้นทุนจริงของการฝังไฟล์ทั้งหมด: คำตอบจากส่วนที่ผิด, การใช้จ่ายในการสกัดข้อมูลที่เสียเปล่าบนไฟล์อัปโหลดขยะ, และไม่มีไฟล์
chunk-01.mdที่ผู้ปฏิบัติการสามารถเปิดได้ในชุดข้อมูลที่แย่
มีวิธีที่ดีกว่า
GroupDocs.Parser for .NET แทนที่ความสับสนนี้ด้วยสี่การเรียกที่มุ่งเน้น: GetDocumentInfo, GetFormattedText(FormattedTextMode.Markdown), GetText เมื่อ Markdown เป็น null, และตัวเดินหัวเรื่องขนาดเล็กที่เขียน 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 ที่จัดส่ง
ขั้นตอนที่ 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());
บันทึกข้อเท็จจริงเหล่านี้พร้อมกับ job id บน DOCX ตัวอย่างคุณควรเห็น “Microsoft Word Open XML Document”, 3 หน้า, และ 14820 ไบต์
ขั้นตอนที่ 2 - ใช้ Markdown จาก GetFormattedText
สำหรับ 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 อ่านได้
ขั้นตอนที่ 3 - ถอยกลับด้วย GetText สำหรับ PDF
เมื่อโหมด 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 ไม่ใช่หัวเรื่อง # ที่สร้างขึ้น ตัวอย่างโฮสต์จะเขียน Result/sample-pdf.txt สำหรับสาขา PDF
ขั้นตอนที่ 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 ก่อน, ลอง Markdown สำหรับไฟล์ Office, เรียก GetText เมื่อรีดเดอร์ที่จัดรูปแบบเป็น null, และแบ่งเฉพาะเมื่อมีเครื่องหมาย # / ## อยู่ ทิ้งข้อความ PDF ที่ไม่มีโครงสร้างไว้จนกว่าจะเพิ่มนโยบายการแบ่งส่วนแยกต่างหาก ลำดับนี้ตรงกับแอปคอนโซลตัวอย่างและทำให้โหมดความล้มเหลวชัดเจนสำหรับผู้ปฏิบัติการ
สิ่งที่เปลี่ยนแปลงสำหรับผู้ปฏิบัติการ
| ก่อน | หลัง |
|---|---|
| การฝังหนึ่งครั้งต่อไฟล์ | การฝังหนึ่งครั้งต่อบล็อกหัวเรื่อง |
| Open XML Markdown ที่กำหนดเอง | โหมด Markdown ของ GetFormattedText |
| PDF ถูกละทิ้งเมื่อรีดเดอร์จัดรูปแบบเป็น null | GetText เขียนไฟล์ข้อความ |
| ไม่มีการตรวจสอบล่วงหน้าแบบราคาถูก | การตรวจสอบจำนวนหน้าและขนาดทำงานเป็นเกต |
ทำลาย (Dispose) ทุก Parser และ TextReader ใช้ไลเซนส์หรือ temporary license ก่อนปริมาณงานข้ามคืน ปฏิบัติกับการอัปโหลดเป็นอินพุตที่ไม่เชื่อถือและแยกการประมวลผลใน worker แยก
ลองใช้กับไฟล์ของคุณเอง
โคลน parse-docx-to-markdown-chunks-dotnet, รีสโตร์ GroupDocs.Parser 26.10.0, และรันกับ documents/sample.docx จากนั้นชี้เมธอดสี่ตัวเดียวกันไปยังคู่มือของคุณและเปิดไฟล์ chunk-*.md ที่สร้างขึ้น