มหาวิทยาลัยมหามกุฏราชวิทยาลัย · ระบบสาธิต (Demo)
ข้ามไปยังเนื้อหา

แผนการนำเข้าข้อมูล (Data Ingestion Plan)

งวดที่ 2 · ออกแบบ

ดาวน์โหลด .md

แผนการนำเข้าข้อมูล (Data Ingestion Plan)

อ้างอิง TOR: ข้อ 4.5.1 (จัดทำแผนการนำเข้าข้อมูล) และข้อ 7.2.4 (เอกสารส่งมอบงวดที่ 2) ประกอบภาคผนวก ก ข้อ 4.6–4.8 และภาคผนวก ข.1 ฉบับ: 1.0 — วันที่ 3 ตุลาคม พ.ศ. 2569

แผนนี้อธิบายกระบวนการนำเข้าเอกสารเข้าสู่ฐานองค์ความรู้ตามที่ implement จริงในระบบ (src/server/ingestion/*, src/domain/ingestion/*) สถานะความครอบคลุมล่าสุดที่วัดจากฐานข้อมูลดูได้ที่ /documents/ingestion-report (สร้างอัตโนมัติด้วย npm run report:ingestion) และแบบสดที่ /admin/knowledge-base


1. วัตถุประสงค์และขอบเขต

  1. นำเข้าพระไตรปิฎกและอรรถกถาแปล ฉบับมหามกุฏราชวิทยาลัย 91 เล่ม (ภาคผนวก ข.1: พระวินัยปิฎก เล่ม 1–10, พระสุตตันตปิฎก เล่ม 11–74, พระอภิธรรมปิฎก เล่ม 75–91) และเอกสารประกอบ (ฎีกา ตำราร่วมสมัย ธรรมะพ่อแม่ครูอาจารย์)
  2. ทุก chunk ต้องมี metadata ครบพอสร้าง Citation รูปแบบมาตรฐานและตรวจสอบย้อนกลับถึงเล่ม/ข้อ/หน้าได้ (ก.3.6.3, ก.4.8.3)
  3. ห้ามตัดตอนเนื้อหาพระไตรปิฎกกลางข้อ (ก.4.6.2, ก.4.8.2)
  4. ป้องกันคำสั่งแฝงในเอกสาร (indirect prompt injection) ก่อนเข้าดัชนี (ก.4.4.1)
  5. ปรับดัชนีได้อัตโนมัติผ่าน pipeline โดยไม่ต้อง redeploy (4.5.3, ก.4.7.3, ก.6.3.2)

แนวทางตาม TOR ภาคผนวก ข: ระยะแรกใช้พระไตรปิฎกฉบับออนไลน์ แล้วสลับเป็นฉบับ มมร. 91 เล่มเมื่อมหาวิทยาลัยส่งมอบไฟล์ (หรือเมื่อเว็บไซต์คลังปัญญา Dhammaverse พร้อมเป็นแหล่งข้อมูล)


2. รูปแบบไฟล์ที่รองรับ (Parsers)

ตัวแยกวิเคราะห์อยู่ที่ src/server/ingestion/parsers/index.ts (parseFile เลือกตามนามสกุลไฟล์) ขนาดไฟล์อัปโหลดสูงสุด 20MB (MAX_UPLOAD_BYTES ใน src/application/ingestion/kb-admin.ts)

นามสกุลMIMEไลบรารีพฤติกรรม
.pdfapplication/pdfunpdf (extractText, แยกหน้า)ดึงข้อความรายหน้าแล้วต่อกัน; ถ้าไม่มีชั้นข้อความเลยคืนคำเตือน “PDF ไม่มีชั้นข้อความ (อาจเป็นไฟล์สแกน ต้อง OCR ก่อนนำเข้า)” และงานล้มเหลวพร้อมข้อความนี้
.docxapplication/vnd.openxmlformats-officedocument.wordprocessingml.documentmammoth.extractRawTextข้อความล้วน + คำเตือนของ mammoth (สูงสุด 5 รายการ)
.xml (TEI)application/xmlfast-xml-parser (preserveOrder)<div type="volume" n> → เล่ม, <div type="item" n> → ข้อ, <pb n> → หน้า แปลงเป็น marker [เล่ม N][ข้อ N][หน้า N]; <pb> กลางข้อสร้าง marker ข้อเดิมหน้าใหม่ (ChunkingPolicy รวมเป็น chunk เดียวและเก็บหน้าเริ่ม–หน้าจบ); ข้าม <note> และ <teiHeader>; ถ้าไม่พบ <div type="item"> นำเข้าแบบข้อความทั่วไปพร้อมคำเตือน
.txt, .mdtext/plain, text/markdownอ่าน UTF-8 (ตัด BOM)ไฟล์ seed .md ถูกตัด frontmatter ด้วย stripFrontmatter() ก่อนนำเข้า

นามสกุลอื่นถูกปฏิเสธด้วยข้อความ “ไม่รองรับไฟล์ชนิด .xxx (รองรับ PDF, TXT, TEI-XML, DOCX)” ไฟล์ตัวอย่างสำหรับทดสอบทั้ง 4 ชนิดอยู่ที่ tests/fixtures/kb/ (รวม no-text.pdf สำหรับกรณีไฟล์สแกน)


3. ขั้นตอนของ Pipeline

ไฟล์หลัก: src/server/ingestion/pipeline.ts

flowchart LR
  U["อัปโหลด / seed / reindex"] --> J["IngestionJob + IngestionJobItem (queued)"]
  J --> P1["parse<br/>parseFile + stripFrontmatter"]
  P1 --> P2["sanitize<br/>sanitizeText"]
  P2 --> UW["unwrapLines<br/>(tipitaka/atthakatha)"]
  UW --> P3["chunk<br/>chunkText → ChunkingPolicy"]
  P3 --> P4["embed<br/>pseudo-embedding 512 มิติ"]
  P4 --> P5["index<br/>transaction Chunk + reindexDocument"]
  P5 --> D["done (status indexed)"]
  P1 -. error .-> F["failed + errorMsg"]
  P3 -. error .-> F
Stage (IngestionJobItem.stage)การทำงาน
queuedสร้างงานด้วย createJob(type, requestedBy, docs) ชนิด ingest / reindex_all / reindex_selected / delete
parseอ่านไฟล์ต้นฉบับจาก sourceFile (ใต้ STORAGE_DIR ค่าเริ่มต้น storage/uploads หรือ seed/knowledge/) แล้วแยกข้อความ
sanitizesanitizeText() (หัวข้อ 7) และนับ removedLines
chunkข้อความพระไตรปิฎกออนไลน์ที่ตัดบรรทัดกลางประโยคถูกต่อกลับด้วย unwrapLines() (ใช้ความกว้างบรรทัด p90) แล้วแบ่งด้วย chunkText() → chunkDocument(); ไฟล์ที่ marker ซ้ำหลายบล็อก (อรรถกถา/ฉบับแปลที่ผูกกับข้อเดียวกัน) แยกแต่ละบล็อกเป็น chunk ที่อ้างข้อเดียวกัน; ไม่มีเนื้อหา → ล้มเหลว “ไม่พบเนื้อหาที่นำเข้าได้ในไฟล์”
embedคำนวณ pseudo-embedding 512 มิติ (feature hashing FNV-1a, ปัดทศนิยม 4 ตำแหน่ง) เก็บเป็น JSON ใน Chunk.embedding เป็น cache
indexใน transaction เดียว: chunk ที่ลำดับและเนื้อหาเหมือนเดิม คง id เดิม (อัปเดตเฉพาะ metadata) เพื่อไม่ให้ Citation ในประวัติและ expectedRefs ของชุดทดสอบหลุด; ลบเฉพาะ chunk ที่เนื้อหาเปลี่ยน (พร้อม Citation ที่อ้างถึง) แล้วสร้างใหม่; ตั้งเอกสารเป็น indexed พร้อม chunkCount, sanitizedLines; อัปเดตดัชนีในหน่วยความจำด้วย reindexDocument()
done / failedบันทึก chunkCount, durationMs หรือ errorMsg

Job runner: งานถูกต่อคิวแบบ promise chain ใน process เดียว (enqueueJob) ประมวลผลทีละ item; item ที่ล้มเหลวไม่หยุดทั้งงาน สถานะงานสุดท้ายเป็น completed (ไม่มีล้มเหลว), partial (สำเร็จบางส่วน) หรือ failed (ล้มเหลวทั้งหมด) และเมื่อมีรายการล้มเหลวระบบส่งแจ้งเตือนชนิด ingestion_failed (บันทึก AlertEmailLog หรือส่ง SMTP) — ใน Production ใช้ BullMQ + worker แยก (ingestion service ใน Helm chart)

การลบ: งานชนิด delete ถอดเอกสารออกจากดัชนีค้นหาและตั้งสถานะ deleted + deletedAt (soft delete) เอกสารที่ถูกลบแล้วไม่สามารถนำเข้า/ทำดัชนีซ้ำได้


4. นโยบายการแบ่ง Chunk (Chunking Policy)

ไฟล์: src/domain/ingestion/chunking-policy.ts (pure TypeScript ทดสอบใน tests/unit/chunking-policy.test.ts)

ค่าคงที่ (CHUNKING)ค่าความหมาย
oversizedTokens3,000เกินค่านี้ติดธง oversized แต่ ไม่แบ่ง ข้อพระไตรปิฎก
targetTokens400ขนาดเป้าหมายของ semantic chunk
minTokensForTopicCut120ต้องสะสมอย่างน้อยเท่านี้ก่อนตัดเพราะหัวข้อเปลี่ยน
topicShiftCosine0.35cosine ระหว่างย่อหน้าติดกันต่ำกว่านี้ = หัวข้อเปลี่ยน
maxHeadingChars200ข้อความก่อน marker แรกที่สั้นกว่านี้ใช้เป็นหัวข้อของ chunk แรก

การประมาณโทเคน: ceil(จำนวนอักขระ / 3) (เหมาะกับภาษาไทย deterministic)

4.1 โหมด marker (docType tipitaka และ atthakatha)

  • ค้นหา marker [เล่ม N][ข้อ N][หน้า N] (รองรับเลขไทย ๐–๙ และหน้าเว้นว่าง)
  • 1 ข้อ = 1 chunk: block ติดกันที่เป็น (เล่ม, ข้อ) เดียวกันถูกรวม — ข้อที่คร่อมหลายหน้าเก็บ page (หน้าแรก) และ pageEnd (หน้าสุดท้าย)
  • หน้า 0 หรือไม่มีหน้า → page = null
  • บรรทัดหัวข้อ Markdown ท้าย block กลายเป็น heading ของข้อถัดไป
  • ข้อความนำหน้า marker แรกที่ยาวเกิน 200 อักขระเป็น chunk ของตัวเอง (item = null)
  • ถ้าเอกสารประเภทนี้ไม่มี marker เลย ใช้โหมด semantic แทน

4.2 โหมด semantic (docType อื่น)

  • แยก section ตามหัวข้อ Markdown (heading เป็นลำดับชั้น ก > ข)
  • แยกย่อหน้า → ย่อหน้าที่ยาวเกิน 400 tokens แบ่งตามประโยค (Intl.Segmenter("th", sentence)) → วรรค → อักขระ ตามลำดับ
  • สะสมหน่วยจนเกิน 400 tokens หรือ ตัดเมื่อหัวข้อเปลี่ยน (cosine ของ pseudo-embedding < 0.35 และสะสม ≥120 tokens) — ไม่ได้ตัดตามจำนวนโทเคนล้วน

4.3 สถิติขนาด chunk ปัจจุบัน

จากฐานข้อมูลสาธิต ณ วันที่จัดทำ (อ่านแบบ read-only): chunk ทั้งหมด 777 รายการ, ติดธง oversized 5 รายการ, ขนาดสูงสุด 17,848 tokens (ข้อพระไตรปิฎกที่ยาวมาก ยังคงเป็น chunk เดียวตาม ก.4.6.2) — ตัวเลขทางการที่สร้างอัตโนมัติอยู่ใน /documents/ingestion-report

เมื่อส่ง chunk ยาวมากเป็นบริบทให้ LLM ระบบย่อเฉพาะตอนสร้าง prompt (bestWindow() เลือกช่วงที่ตรงคำถามมากที่สุด 2,400 อักขระสำหรับถาม-ตอบ / 4,500 สำหรับ Dhamma Talk) ส่วนดัชนีและ Citation ยังอ้างข้อเต็ม


5. Metadata และรูปแบบ Citation

5.1 ฟิลด์ metadata (KnowledgeDocument / Chunk)

ฟิลด์ระดับตัวอย่างหมายเหตุ
titleเอกสารมงคลสูตรบังคับ
docTypeเอกสารtipitakatipitaka | atthakatha | tika | contemporary | teacher_dhamma (DOC_TYPES)
editionเอกสารไทย, บาลี, มมร., English (Sujato, CC0)ใช้ในวงเล็บของ citation
pitakaเอกสารvinaya | sutta | abhidhamma
nikaya, suttaเอกสารขุททกนิกาย ขุททกปาฐะ / มงคลสูตร
volumeเอกสาร/chunk25เล่มของฉบับที่นำเข้า (ฉบับหลวง 45 เล่ม สำหรับข้อมูลออนไลน์)
mbuVolumeเอกสาร39เล่มในฉบับ มมร. 91 เล่ม — ใช้คำนวณ coverage ภาคผนวก ข
abbreviationเอกสารขุ.ขุ.ตัวย่อคัมภีร์สำหรับ citation
item, page, pageEnd, headingchunk5 / 3 / 3จาก marker
paliAliasesเอกสาร/chunkmaṅgala|mangala suttaคำบาลี/อังกฤษ ช่วยค้นข้ามภาษา (น้ำหนักสูงใน BM25)
precedenceScoreเอกสาร1.00–2 ปรับได้ใน admin
sourceType, sourceFile, sourceUrl, sourceNoteเอกสารseed / online / uploadที่มาและหมายเหตุสิทธิ์
oversized, tokenCountchunk

5.2 รูปแบบ Citation

สร้างโดย formatCitationLabel() ใน src/domain/ai/citation.ts:

{abbreviation} ({edition}) {volume}/{item}/{page}
ตัวอย่าง: ขุ.ขุ. (ไทย) 25/5/3
  • ส่วนท้ายที่ไม่มีค่าถูกตัด (ไม่มีหน้า → 25/5); ส่วนกลางที่ไม่มีค่าแสดง -
  • ไม่มี abbreviation ใช้ title แทน
  • LLM อ้างด้วย [[cite:<chunkId>]] หรือ [[cite:<n>]] แล้วโหนด outputGuardrail แปลงเป็น label และตัดการอ้างที่ไม่อยู่ในรายการอ้างอิง

5.3 ประเภทเอกสารและลำดับความสำคัญ (Precedence)

ค่าเริ่มต้นใน DEFAULT_PRECEDENCE (src/domain/retrieval/relevance-scoring.ts) ใช้คูณคะแนนหลัง rerank (ก.4.8.3(3)):

docTypeความหมายprecedence เริ่มต้น
tipitakaพระไตรปิฎก1.0
atthakathaอรรถกถา0.9
tikaฎีกา0.8
contemporaryตำรา/พระนิพนธ์ร่วมสมัย0.7
teacher_dhammaธรรมะพ่อแม่ครูอาจารย์0.6

ผู้ดูแลปรับรายเอกสารได้ (0–2) ที่ /admin/knowledge-base → แก้ metadata (PATCH /api/admin/knowledge-base/[id]) ระบบอัปเดตดัชนีในหน่วยความจำทันทีและบันทึก audit before/after


6. รูปแบบ marker และไฟล์ต้นฉบับ

ไฟล์ seed ทุกไฟล์ใน seed/knowledge/ เป็น Markdown ที่มี frontmatter บรรทัดเดียวต่อคีย์ (รายละเอียดใน scripts/data/README.md):

---
title: "มงคลสูตร"
docType: tipitaka
edition: "ไทย"
pitaka: sutta
nikaya: "ขุททกนิกาย ขุททกปาฐะ"
sutta: "มงคลสูตร"
volume: 25
mbuVolume: 39
abbreviation: "ขุ.ขุ."
sourceUrl: "https://84000.org/tipitaka/read/byitem.php?book=25&item=5"
sourceNote: "..."
paliAliases: "maṅgala|mangala sutta|..."
---
[เล่ม 25][ข้อ 5][หน้า 3]
<ข้อความทั้งข้อ>

กติกา:

  • ฉบับหลวง/บาลี: 1 บล็อก = 1 ข้อ; หน้า = หน้าแรกของข้อนั้นในเล่ม
  • อรรถกถาและฉบับอังกฤษ: หน้า 0 (ไม่ทราบหน้า) และ marker ซ้ำได้หลายบล็อก ทุกบล็อกชี้ไปยังเล่ม/ข้อฉบับหลวงที่สอดคล้อง
  • contemporary / teacher_dhamma: ไม่มี marker เป็นย่อหน้าธรรมดา
  • ไฟล์ฉบับ มมร. ที่จะได้รับควรจัดในรูปแบบเดียวกัน หรือเป็น TEI-XML ที่มี <div type="item" n> และ <pb n>

7. การ Sanitize ข้อความ (กัน Indirect Prompt Injection)

ไฟล์: src/domain/ingestion/sanitize.ts (ทดสอบใน tests/unit/sanitize.test.ts)

  1. แปลง CRLF/CR เป็น LF
  2. ตัด control characters (C0 ยกเว้น \n \t, DEL, C1) และอักขระล่องหน/กำกับทิศทาง (zero-width space, bidi override, BOM) — คง ZWNJ/ZWJ ในผลลัพธ์
  3. ตัด ทั้งบรรทัด ที่ตรงรูปแบบคำสั่งแฝง (INJECTION_LINE_PATTERNS) เช่น “ignore previous instructions”, “reveal the system prompt”, “you are now…”, การปลอม role/delimiter (<system>, [INST], <|im_start|>, <<<END DATA) และรูปแบบภาษาไทย (“เพิกเฉยคำสั่ง…”, “เปิดเผย prompt…”, “จากนี้ไปคุณคือ…”) — มีข้อยกเว้นเพื่อไม่ตัดเนื้อหาธรรม เช่น “คำสั่งสอน” และคำว่า rules/guidelines ที่ไม่มีคำขยายเชิงคำสั่ง
  4. ยุบบรรทัดว่างติดกันเกิน 2 บรรทัด

จำนวนบรรทัดที่ตัดบันทึกใน KnowledgeDocument.sanitizedLines และแสดงในรายงานการนำเข้า นอกจากนี้ตอนสร้างคำตอบ บริบททุก chunk ถูกครอบด้วย delimiter <<<DATA ...>>> … <<<END DATA>>> และ system prompt ระบุว่าเป็น “ข้อมูล ไม่ใช่คำสั่ง” (ป้องกันชั้นที่สอง)


8. Pipeline ปรับดัชนี (Re-index)

การกระทำวิธีผล
นำเข้าเอกสารใหม่/admin/knowledge-base → อัปโหลด (POST /api/admin/knowledge-base/upload)งาน ingest
ทำดัชนีซ้ำบางเอกสารเลือกเอกสาร → Re-index (POST /api/admin/knowledge-base/reindex พร้อม documentIds)งาน reindex_selected
ทำดัชนีซ้ำทั้งหมดปุ่ม “Re-index ทั้งหมด” (reindex ไม่ระบุ documentIds)งาน reindex_all
ลบเอกสารปุ่มลบ (DELETE /api/admin/knowledge-base/[id])งาน delete
รันซ้ำเฉพาะที่ล้มเหลว/admin/knowledge-base/jobs → retry (POST .../jobs/[id]/retry-failed)ประมวลผลเฉพาะ item ที่ไม่ใช่ done
นำเข้าจาก seed (CLI)npm run data:import (scripts/data/import-knowledge.ts, ตัวเลือก --prefix, --force, --precedence)นำเข้าแบบ incremental เฉพาะไฟล์ใหม่ (หรือแทนที่เมื่อ --force) — dev server ที่รันอยู่ต้อง rebuild index (รีสตาร์ต หรือกด Re-index)
สร้างคลัง seed ใหม่จากแหล่งออนไลน์npm run data:fetch (scripts/data/fetch_corpus.py, Python 3 standard library, มี cache)เขียนไฟล์ seed/knowledge/*.md + _manifest.json

ดัชนีค้นหาในหน่วยความจำ (KnowledgeIndex singleton ใน globalThis.__mbuIndex) สร้างครั้งแรกจากเอกสารสถานะ indexed และอัปเดตแบบ incremental รายเอกสาร (BM25 ปรับ document frequency แบบ incremental ไม่ต้อง rebuild ทั้งดัชนี) — Production แทนที่ด้วย Elasticsearch (ElasticsearchSearchAdapter)


9. การตรวจสอบความครบถ้วน (Completeness Verification)

ระดับวิธีตรวจหลักฐาน
ไฟล์ → เอกสารทุกไฟล์มีระเบียน KnowledgeDocument สถานะ indexed; เทียบจำนวนไฟล์ใน seed/knowledge/_manifest.json กับจำนวนเอกสาร/documents/ingestion-report
เอกสาร → chunkKnowledgeDocument.chunkCount เท่ากับจำนวนแถวใน Chunk; ไม่มีเอกสาร pending/failed ค้างการ์ด coverage ที่ /admin/knowledge-base, GET /api/admin/knowledge-base/coverage
ข้อ → chunkจำนวน marker ข้อในไฟล์ต้นฉบับ (ฉบับหลวง/บาลี) ≈ จำนวน chunk ของเอกสาร (marker ซ้ำของข้อเดียวกันถูกรวม)ตรวจได้จาก /admin/knowledge-base/[id] (รายการ chunk พร้อมเล่ม/ข้อ/หน้า)
เล่ม → 91 เล่มนับ mbuVolume ที่ไม่ซ้ำของเอกสารที่ทำดัชนีแล้ว เทียบ 91 เล่ม แยกตามปิฎก และเทียบเป้า 20% ของงวดที่ 2 (TOR_PHASE2_TARGET_PERCENT)src/application/ingestion/coverage.ts
ฉบับหลวง 45 เล่มนับ volume ของเอกสารพระไตรปิฎกที่ไม่ใช่ฉบับ มมร.coverage report (ส่วน royal)
คุณภาพการค้นคืนRecall@5 ของชุด RET-1/2/3 (300 คำถามที่สร้างจากข้อความจริงในคลัง)/admin/evaluation, /documents/baseline-evaluation-report
ความถูกต้องของเนื้อหาสุ่มเปิดเนื้อหาเต็มผ่าน Citation Modal เทียบต้นฉบับ (sourceUrl)ขั้นตอน UAT กับผู้เชี่ยวชาญของมหาวิทยาลัย

10. สถานะคลังข้อมูลปัจจุบัน (ฉบับออนไลน์ระยะแรก)

นับจากไฟล์ใน seed/knowledge/ ณ วันที่จัดทำเอกสาร (ไม่รวม _manifest.json):

รายการจำนวน
ไฟล์เอกสาร169
— tipitaka (ไทย 138, บาลี 6, English Sujato CC0 7)151
— atthakatha (ฉบับ มมร.)4
— contemporary (นวโกวาท ฉบับ มมร. พ.ศ. ๒๕๑๓)11
— teacher_dhamma (เว็บไซต์ มมร.)3
เอกสารแยกตามปิฎก: วินัย / สุตตันตะ / อภิธรรม13 / 131 / 7
เล่มฉบับหลวงที่มีข้อมูล1, 4, 10, 11, 12, 16, 17, 19, 20, 25, 34, 35 (12 เล่ม บางข้อ)
เล่มฉบับ มมร. ที่ระบุใน metadata (mbuVolume)6, 14, 16, 34, 39, 40 (6 จาก 91 เล่ม)
บล็อก marker ข้อในไฟล์721
ขนาดข้อความรวมประมาณ 0.97 ล้านอักขระ (ไฟล์รวม 3.0 MB)
ตัวย่อคัมภีร์ที่ใช้24 ค่า (เช่น วิ.มหา., วิ.ม., ที.ม., ม.มู., สํ.นิ., องฺ.ติก., ขุ.ขุ., ขุ.ธ., อภิ.สํ., อภิ.วิ., DN 22, SN 56.11)

แหล่งข้อมูลและสิทธิ์ (จาก scripts/data/README.md): พระไตรปิฎกฉบับหลวงและบาลีฉบับสยามรัฐจาก 84000.org, อรรถกถาแปลฉบับ มมร. จาก 84000.org, คำแปลอังกฤษของภิกษุสุชาโต (CC0) จาก SuttaCentral, นวโกวาท (สาธารณสมบัติ) จากวิกิซอร์ซ และเนื้อหาจากเว็บไซต์ www.mbu.ac.th

ความครอบคลุมเทียบ 91 เล่มที่วัดจากฐานข้อมูลจริงอยู่ที่ /documents/ingestion-report (สถานะ ณ การสร้างรายงานล่าสุด: 6 จาก 91 เล่ม = 6.6% ซึ่ง ยังต่ำกว่าเป้าหมาย ≥20% ของงวดที่ 2 ตาม TOR 7.2.5 — ข้อ 7.2.5, 4.5.2, ข.1 จึงมีสถานะ partial ในหน้า /tor)


11. แผนนำเข้าพระไตรปิฎกและอรรถกถาฉบับ มมร. 91 เล่ม

ระยะกิจกรรมผลผลิตเกณฑ์สำเร็จ
0 (ดำเนินการแล้ว)ใช้ฉบับออนไลน์บางส่วน + อรรถกถา มมร. จาก 84000.org เพื่อพัฒนา/ทดสอบ pipeline และชุด RET-1..3คลัง seed 169 เอกสารpipeline ผ่านชุดทดสอบ tests/api/knowledge-base.test.ts
1รับไฟล์ต้นฉบับ 91 เล่มจากมหาวิทยาลัย (ต้องการ: PDF ที่มีชั้นข้อความ, DOCX, หรือ TEI-XML) และทำบัญชีไฟล์ (เล่ม/ปิฎก/จำนวนหน้า/checksum)ทะเบียนไฟล์ครบ 91 เล่ม
2ตรวจคุณภาพไฟล์: PDF มีชั้นข้อความหรือไม่ (ระบบแจ้ง “ไม่มีชั้นข้อความ” อัตโนมัติ), การเข้ารหัสอักษรไทย/บาลี, ตำแหน่งเลขข้อ/หน้ารายงานคุณภาพไฟล์ระบุไฟล์ที่ต้อง OCR
3แปลงเป็นรูปแบบมี marker [เล่ม N][ข้อ N][หน้า N] หรือ TEI <div type="item">/<pb> (สคริปต์แปลงเฉพาะรูปแบบไฟล์ที่ได้รับ) ตั้ง metadata edition = มมร., mbuVolume, abbreviationไฟล์พร้อมนำเข้าสุ่มตรวจ 5% ของข้อต่อเล่ม
4นำเข้าทีละปิฎกผ่าน /admin/knowledge-base หรือสคริปต์; งวด 2 อย่างน้อย 19 เล่ม (≥20%), งวด 3 ครบ 91 เล่มงานนำเข้า (IngestionJob)ไม่มี item ล้มเหลวค้าง
5สลับแหล่งข้อมูล: ตั้ง precedence ฉบับ มมร. ให้สูงกว่าฉบับออนไลน์ หรือลบเอกสารฉบับออนไลน์ที่ซ้ำ (งาน delete) และปรับ expectedRefs ของชุด RET ให้อ้างฉบับ มมร.ดัชนีฉบับ มมร.Recall@5 ≥80% ทั้ง 3 ชุด
6เมื่อเว็บไซต์ Dhammaverse พร้อม: เชื่อมเป็นแหล่งข้อมูล (sourceType = online, sourceUrl) ให้ Citation Modal ลิงก์ไปยังหน้าคลังปัญญาลิงก์ย้อนกลับตรวจลิงก์ครบ
7ออกรายงาน npm run report:ingestion ทุกครั้งที่นำเข้าเป็นชุด และแนบในรายงานงวด/documents/ingestion-reportcoverage ตามเป้า

12. ความเสี่ยงและมาตรการ

ความเสี่ยงผลกระทบมาตรการ
ไฟล์ 91 เล่มเป็นภาพสแกน (ไม่มีชั้นข้อความ)นำเข้าไม่ได้/ข้อความผิดparser ตรวจและแจ้งเตือนอัตโนมัติ; ทำ OCR ภาษาไทย-บาลีนอกระบบ (เช่น Tesseract tha) แล้วตรวจทานโดยผู้เชี่ยวชาญก่อนนำเข้า; จัดลำดับเล่มที่มีไฟล์ข้อความก่อน — ระบบสาธิตยังไม่มีขั้น OCR ในตัว
อักษรบาลี (นิคหิต/พินทุ) เข้ารหัสต่างกันค้นไม่เจอnormalizeText ใน tokenizer + char n-gram ใน pseudo-embedding + paliAliases + พจนานุกรม synonym
เลขข้อ/หน้าในต้นฉบับไม่สม่ำเสมอCitation ผิดตรวจ marker ก่อนนำเข้า, สุ่มตรวจผ่าน Citation Modal
ข้อยาวมาก (oversized)บริบทเกินเพดานโทเคนไม่แบ่งข้อในดัชนี; ย่อเฉพาะตอนสร้าง prompt (bestWindow) + fitContext
คำสั่งแฝงในเอกสารAI ถูกชักนำsanitize + delimiter + guardrail
ไฟล์ซ้ำระหว่างฉบับออนไลน์กับฉบับ มมร.ผลค้นซ้ำซ้อนprecedence/ลบฉบับออนไลน์เมื่อสลับ
ดัชนีในหน่วยความจำของระบบสาธิตจำกัดด้วย RAM ของเครื่องเดียวรองรับ 91 เล่มได้ช้าProduction ใช้ Elasticsearch + bge-m3 ตาม Solution Architecture