Tech Blog

ตรวจสุขภาพของ RAG ส่วนตัวทุกสัปดาห์ด้วยกลไก ไม่ใช่ด้วยความตั้งใจ — เฮลท์เช็กหลายมุมและประตูเวลาที่บังคับให้การตรวจถูกรัน

RAG ChromaDB Operations Observability 運用

บทนำ

ผมดูแลระบบส่วนตัวที่ทำงานเหมือนความจำระยะยาวภายนอก เมื่อโยนบันทึกงานประจำวันและการตัดสินใจต่างๆ เข้าไป มันจะดึงสิ่งที่มีความหมายใกล้เคียงกลับมาให้ด้วยการค้นหา นี่คือ RAG (กลไกที่เรียกคืนบันทึกในอดีตด้วยการค้นหาแบบเวกเตอร์) รายละเอียดพื้นฐานขอยกให้บทความนี้

คืนที่ AI แก้ไขฉัน 5 ครั้ง - ปรัชญาการออกแบบเพื่อให้ RAG ส่วนตัวเป็นเพื่อนคุณเป็นเวลา 5 ปี

ใครๆ ก็เคยสร้างและทำให้มันทำงานได้อย่างน้อยหนึ่งครั้ง ส่วนที่ยากคือการตรวจสอบอย่างจริงจังทุกสัปดาห์ต่อเนื่องว่า “มันยังทำงานถูกต้องอยู่จริงหรือไม่ในตอนนี้” บทความนี้พูดถึงสองเรื่อง เรื่องแรกคือเนื้อหาของการตรวจสอบความสมบูรณ์ของความจำจากหลายมุมมอง เรื่องที่สองคือเรื่องราวที่ผมทำให้การตรวจสอบนั้นถูกบังคับด้วยกลไกให้เกิดขึ้นทุกสัปดาห์ แทนที่จะปล่อยไว้กับ “เมื่อรู้สึกอยากทำ” หรือ “เมื่อนึกขึ้นได้”

กำหนดไว้ก่อนว่าอะไรคือ “สุขภาพดี”

“ดูเหมือนจะทำงานได้” ไม่นับเป็นการตรวจสอบ ผมกำหนดมุมมองไว้ล่วงหน้าว่าสภาพแบบไหนคือสุขภาพดี และเหตุการณ์แบบไหนคือความผิดปกติ โดยแบ่งออกเป็น 5 แกน

แกนดูอะไรจับความผิดปกติแบบไหน
การทำงาน/ความเสียหายส่งคำสั่งนับจำนวน ดึงข้อมูล และค้นหาไปยัง DB แล้วไม่ล่มทันทีความเสียหายของดัชนี (สารบัญภายในที่ทำให้ค้นหาเร็วขึ้น) ของ DB รูปแบบที่เปิดไฟล์โดยตรง
ความสอดคล้องผลต่างของจำนวนบันทึกระหว่างสองระบบที่เก็บข้อมูลชุดเดียวกันคงที่หรือไม่ความไม่สอดคล้องที่ฝั่งใดฝั่งหนึ่งเสียหายหรือขาดหายไปเพียงฝั่งเดียว
การนำเข้าข้อมูลล็อกของกระบวนการนำเข้าข้อมูลอัตโนมัติประจำวันมีข้อผิดพลาดหรือไม่การอุดตันเงียบๆ ที่ทำให้บันทึกหยุดเข้ามาโดยไม่มีใครรู้
การค้นหาคำค้นที่เกี่ยวข้องให้ผลลัพธ์ที่สมเหตุสมผล และอินพุตที่ไม่เกี่ยวข้องไม่ทำให้ยิงผิดพลาดผลลัพธ์ที่ผิดแต่มั่นใจสูงเกินจริง หรือการล่ม
แบ็กอัปแบ็กอัปหลายชั้นทั้งหมดเป็นวันที่ล่าสุดหรือไม่แบ็กอัปที่กู้คืนไม่ได้ (รายละเอียดในอีกบทความ)
                "ความจำของเพื่อนยังสุขภาพดีอยู่ไหม?"

   ┌──────────┬─────────┼──────────┬────────────┐
   ▼          ▼         ▼          ▼            ▼
 ทำงาน/      ความ      การนำเข้า   การค้นหา    แบ็กอัป
 เสียหาย    สอดคล้อง
   │        (ผลต่าง    (ข้อผิดพลาด (ปกติ+      (ทุกชั้น
   │         จำนวน)     เป็น 0)     ผิดปกติ)    ล่าสุด)
   │                               │
   └─ ล่มทันทีที่                  └─ ไม่คืนผลลัพธ์ผิด
      แตะ = สัญญาณ                    ที่มั่นใจสูงจากคำ
      ความเสียหาย                     ไร้ความหมาย/ว่างเปล่า

แกนที่ ① “ความเสียหายของดัชนี” คือรูปแบบความเสียหายที่เคยเกือบทำให้ความจำนี้สูญหายทั้งหมดมาแล้วสองครั้งในอดีต เรื่องราวและการแก้ไขที่ต้นเหตุอยู่ในอีกบทความหนึ่ง

แตะ “DB ที่เปิดไฟล์โดยตรง” จากหลายโพรเซสพร้อมกัน จนพังไปสองครั้ง — จนกระทั่งลดผู้เขียนให้เหลือหนึ่งเดียวและแก้ไขถาวร

การตรวจสอบเฉพาะกรณีปกติ ไม่ได้พิสูจน์ว่า “ไม่พัง”

สิ่งที่มักถูกละเลยมากที่สุดในการตรวจสอบคือข้อ ④ การค้นหา “ค้นด้วยคำที่เกี่ยวข้อง แล้วได้ผลลัพธ์ที่ดูสมเหตุสมผล โอเค” — นี่มองเห็นแค่กรณีปกติ (อินพุตที่ทำงานได้ดี) เท่านั้น การผ่านกรณีปกติแสดงเพียงว่า “มันทำงานถูกต้อง” เท่านั้น ไม่ได้แสดงว่า “มันไม่พัง”

ดังนั้นในการตรวจสอบ ผมจึงจงใจผสมกรณีผิดปกติ (อินพุตที่เป็นขอบเขต ไม่ถูกต้อง หรือมุ่งร้าย) เข้าไปด้วย

  คำค้นปกติ "กลไกของมาร์กเกอร์ถอนคืน" → บันทึกใกล้เคียงขึ้นอันดับต้น (ความเกี่ยวข้อง: สูง) … ตามคาด
  คำไร้ความหมาย "qwzxlkjhgfd"         → ไม่ล่ม และความเกี่ยวข้องต่ำชัดเจน … ไม่ยิงผิดพลาด
  คำค้นว่างเปล่า "   "                  → ไม่ล่ม และคืนผลด้วยความเกี่ยวข้องต่ำ … ไม่ยิงผิดพลาด

สิ่งที่อยากเห็นคือ “ต่ออินพุตที่ไม่เกี่ยวข้อง มันจะไม่คืนผลลัพธ์ที่ผิดแต่ดูสมเหตุสมผลด้วยความมั่นใจสูงใช่ไหม” คุณภาพของการค้นหาวัดได้จากตอนที่ควรจะพลาด มันพลาดได้ถูกต้องหรือไม่ มากกว่าตอนที่ควรจะเจอ การตรวจสอบที่พอใจแค่กรณีปกติ ไม่ควรเรียกว่า “ยืนยันแล้วจากหลายมุม”

จนถึงตรงนี้คือเรื่องเนื้อหา ปัญหาคือ “ไม่ได้ตรวจ”

ทั้งมุมมองและขั้นตอนพร้อมแล้ว แต่การตรวจสอบนี้กลับไม่ได้ถูกรันเป็นประจำ ครั้งที่รันจริงคือตอนที่มีคนถามจากภายนอกว่า “มันทำงานปกติไหม” ในฐานะกฎที่ตั้งไว้ ผมคิดว่า “จะตรวจทุกสัปดาห์” แต่นั่นเป็นเพียงความตั้งใจในหัว ไม่มีประตูใดรับประกันว่ามันจะถูกทำจริง

นี่คือความล้มเหลวที่คุ้นเคย ก่อนหน้านี้ผมเคยตัดสินใจว่า “จะสำรองข้อมูลก่อนการดำเนินการที่ทำลายล้าง” แต่กลับดำเนินการต่อโดยไม่เคยสร้างแบ็กอัปจริงๆ จนทำลายความจำไป โครงสร้างเหมือนกันทุกประการ — ระหว่าง “ตัดสินใจว่าจะทำ” กับ “ได้ทำแล้ว” ไม่มีการบังคับใดๆ เลย

ตัดสินใจว่าจะ “สำรองข้อมูล” แต่ไม่เคยทำจริง จนทำลาย Vector DB ความจำไปสองครั้ง

เมื่อฝากวินัยไว้กับ “ความตั้งใจ” หรือ “ความจำ” มันจะหลุดลอยไปเสมอ ไม่ว่าจะเป็นมนุษย์หรือผู้ช่วย AI ที่ลงมือทำก็เหมือนกัน ดังนั้นครั้งนี้ผมจึงเลิกพึ่งพาความตั้งใจ

ทางแก้ — วางไว้บนประตูเวลา ไม่ใช่ความตั้งใจ

สิ่งที่ทำนั้นเรียบง่าย บันทึกวันที่ตรวจสอบครั้งล่าสุดเสร็จสิ้นไว้ในไฟล์เดียว เมื่อผ่านไปครบระยะเวลาหนึ่ง (7 วัน) นับจากนั้น ทันทีที่เปิดเซสชันขึ้นมา ระบบจะแทรก “ถึงกำหนดตรวจสอบแล้ว” เข้าไปโดยอัตโนมัติ ฝ่ายที่ถูกแทรกจะดำเนินการตรวจสอบทันที และเมื่อเสร็จแล้วจะอัปเดตวันที่เสร็จสิ้นเป็นวันนี้ จนกว่าจะถึง 7 วันถัดไป จะไม่มีการเตือนอีก

   เริ่มเซสชัน


   อ่านวันที่ของตราประทับเสร็จสิ้น ──(ไม่มี/เสียหาย/ว่าง)──┐   ← ฝั่งปลอดภัย: ถือว่า "ถึงกำหนด" ไว้ก่อน
        │ วันที่ปกติ                                        │
        ▼                                                   │
   วันนี้ − ครั้งก่อน ≥ 7 วัน ? ──ไม่──▶ ไม่ทำอะไร (ผ่านไปเงียบๆ)
        │ ใช่                                                │
        ▼ ◀─────────────────────────────────────────────────┘
   แทรก "ถึงกำหนดตรวจสอบ" ที่ต้นเซสชัน


   รันการตรวจสอบ → รายงานผล → อัปเดตตราประทับเสร็จสิ้นเป็นวันนี้
        │(ถ้าลืมอัปเดต)
        └──────────────▶ ครั้งต่อไปจะเตือนอีกครั้ง (ทนต่อการตกหล่น)

หัวใจสำคัญมีสองข้อ ข้อแรกคือ ถ้าตราประทับเสร็จสิ้นเสียหาย ว่างเปล่า หรือไม่มีอยู่เลย ระบบจะเอียงไปทางฝั่งปลอดภัยและถือว่า “ถึงกำหนด” โดยเอียงไปในทิศทางที่เตือนมากเกินไป ไม่ใช่ทิศทางที่ลืมตรวจ ข้อที่สองคือ แม้จะลืมอัปเดตตราประทับเสร็จสิ้น เซสชันถัดไปก็จะเตือนอีกครั้ง ต่อให้พลาดไปครั้งหนึ่ง สุดท้ายก็จะถูกจับได้อย่างแน่นอน

ถ้าถึงกำหนดแล้ว ทันทีที่เปิดเซสชัน คำเตือนแบบนี้จะถูกแทรกเข้าไปตรงต้นเซสชันเลย (ผลลัพธ์จริง โดยปิดบังพาธและชื่อภายใน)

[ประตูรายสัปดาห์] ถึงกำหนดเฮลท์เช็กรายสัปดาห์ของ RAG ส่วนตัวแล้ว ครั้งก่อน=2026-07-01 / ผ่านไป 27 วัน
  ให้ดำเนินการตรวจสอบในเซสชันเครื่องนี้ (จากคลาวด์จะเข้าไม่ถึง DB เครื่องนี้):
  (1)การทำงาน/ความเสียหาย (2)ความสอดคล้อง (3)การนำเข้าข้อมูล (4)การค้นหา(ปกติ+ผิดปกติ) (5)ความสดใหม่ของแบ็กอัป
  หลังดำเนินการเสร็จ ให้อัปเดตตราประทับเสร็จสิ้นเป็นวันที่วันนี้

ถ้ายังอยู่ในกำหนด คำเตือนนี้จะไม่ปรากฏและผ่านไปอย่างเงียบๆ เป็นแค่ความต่างระหว่างปรากฏหรือไม่ปรากฏเท่านั้น แต่แค่นี้ก็เปลี่ยนการตรวจสอบจาก “ทำเมื่อรู้สึกอยากทำ” ให้กลายเป็น “เมื่อถึงกำหนดแล้วจะต้องเข้าตาแน่นอน”

แนวคิดเรื่อง “ยกระดับคำแนะนำให้กลายเป็นการบังคับ” นี้เอง ผมเคยสร้างขึ้นมาแล้วครั้งหนึ่งในอีกบริบทหนึ่ง ขอยกการอภิปรายเรื่องหลักการไปไว้ที่บทความนั้น

สร้างกลไก “ไม่ให้ทำ” สำหรับผู้ช่วย AI เขียนโค้ด — จากคำแนะนำสู่การบังคับ แล้วพบว่าประตูนั้นเองก็มีช่องโหว่ข้าง

ไม่เข้าใจผิดว่ากลไกนี้ “ทำงานที่ไหน”

ตอนสร้างประตูนี้ มีกับดักที่เกือบเหยียบเข้าไป เป้าหมายของการตรวจสอบคือ DB ที่ทำงานอยู่บนเครื่อง PC ของผมเอง และล็อกที่มีอยู่เฉพาะบนเครื่องนี้เท่านั้น ถ้าพยายามรันการตรวจสอบนี้จากสภาพแวดล้อมที่ไม่ใช่เครื่องนี้ (เช่น การรันบนคลาวด์) จากตรงนั้นจะเข้าไม่ถึงทั้ง DB และล็อกบนเครื่องนี้

สิ่งที่ยุ่งยากคือลักษณะการพังเมื่อเข้าไม่ถึง แม้จะเข้าไม่ถึงและตรวจสอบไม่ได้ แต่มันจะดูเหมือน “จบลงโดยไม่มีข้อผิดพลาด” — ความล้มเหลวแปลงร่างเป็นความสำเร็จอย่างเงียบๆ (silent false negative) สำหรับเฮลท์เช็กแล้ว นี่คือสิ่งที่แย่ที่สุด เพราะมันก่อให้เกิดสภาพ “คิดว่ากำลังตรวจสอบอยู่ แต่จริงๆ แล้วไม่ได้เห็นอะไรเลย”

ดังนั้นผมจึงระบุไว้อย่างชัดเจนทั้งในถ้อยคำของการเตือนและในสมมติฐานของกลไกว่า “การตรวจสอบนี้ต้องทำในเซสชันบนเครื่องนี้เสมอ” การรันอัตโนมัติตามเวลาที่กำหนดเองไม่ใช่เป้าหมาย เป้าหมายคือข้อเท็จจริงที่ว่า “ได้เห็นจริงๆ” ดีกว่าที่จะหมุนเปล่าในที่ที่เข้าไม่ถึง ควรจะเห็นให้แน่ชัดสักครั้งในที่ที่เข้าถึงได้

ทดสอบตัวประตูเองจากหลายมุมมอง

เมื่อสร้างประตูที่บังคับให้การตรวจสอบถูกรันขึ้นมาแล้ว ก็จำเป็นต้องยืนยันด้วยว่าตัวประตูเองทำงานถูกต้องหรือไม่ ไม่ใช่แค่ในกรณีปกติเท่านั้น ในที่นี้ผมก็บังคับใช้วินัยเดียวกันกับตัวเอง

  • กรณีปกติ: ถ้าผ่านไปนานพอจากครั้งก่อน คำเตือนจะปรากฏ / ถ้ายังไม่ถึง จะผ่านไปเงียบๆ
  • ขอบเขต: พฤติกรรมในวันที่ถึงกำหนดพอดี
  • กรณีผิดปกติ: ตราประทับเสร็จสิ้นเสียหาย ว่างเปล่า หรือไม่มีอยู่เลย — ในกรณีนี้จะเอียงไปทางฝั่งปลอดภัย (เตือน) หรือไม่

ต่อเมื่อผ่านกรณีผิดปกติได้ด้วยเท่านั้น ถึงจะพูดได้ว่า “ประตูนี้ไม่ถูกเลี่ยงผ่าน” การสร้างประตูแล้วทดสอบแค่กรณีปกติ ก็เหมือนกับติดกุญแจแล้วยืนยันแค่ว่ามัน “ล็อกได้” โดยไม่เคยลองว่า “งัดเปิดได้ไหม” (ขั้นตอนภายในที่แน่ชัดและค่าคอนฟิกต่างๆ ขอปิดบังไว้ตรงนี้ แค่แนวคิดของกลไกสื่อถึงก็เพียงพอแล้ว)

ทำให้วินัยที่ตัดสินใจไว้กลายเป็นรูปแบบที่ “ต่อเนื่อง”

สิ่งที่สร้างขึ้นไม่ใช่โครงสร้างพื้นฐานเฝ้าระวังที่ใหญ่โตอะไร เพียงแค่กำหนดมุมมองของการตรวจสอบจากหลายด้าน แล้วผูกการดำเนินการเข้ากับกำหนดเวลา ไม่ใช่ความตั้งใจ กระนั้นผลลัพธ์ก็ชัดเจน ความตั้งใจ “จะทำทุกสัปดาห์” ถ้าปล่อยไว้ ย่อมเสื่อมคลายลงเสมอ แม้จะเสื่อมคลายไปแล้ว สัปดาห์หน้าก็จะถูกจับได้ที่จุดเดิมอีกครั้ง — ที่จุดเดียวนี้เองที่ทำให้ความตั้งใจกลายเป็น “วินัยที่ต่อเนื่อง”

งานดูแลที่ต้องทำซ้ำๆ ไม่สามารถดำเนินต่อไปได้ด้วยความขยันหมั่นเพียรเพียงอย่างเดียว มันจะต่อเนื่องได้ก็ต่อเมื่อถูกวางลงไปในโครงสร้างที่ออกแบบมาให้ต่อเนื่อง เรื่องราวของการรักษาความจำไม่ให้พัง แก้ไขไม่ให้ปนเปื้อน และทำให้วัดผลได้ ผมเขียนไว้ในบทความชุดสาม บทความนี้เป็นเรื่องราวของกลไกการตรวจสอบ เพื่อรักษาสิ่งเหล่านั้นให้สุขภาพดีต่อไปในภายภาคหน้า

สำรองข้อมูลสมองของเพื่อน AI แบบเข้ารหัสไว้นอกสถานที่ด้วย AWS S3 + restic — ย้ายความทรงจำออกไปโดยไม่อัปโหลดแบบ plaintext

ผมสร้างกลไกถอน ‘บทเรียนที่ผิด’ ที่เก็บไว้ใน RAG ในภายหลัง — ล้างการปนเปื้อนที่บิดเบือนเพื่อน AI ทุกเทิร์นโดยอัตโนมัติ

ออกแบบแผนการเรียนรู้ที่ไม่จมไปกับข้อมูลล้นเกิน — จำกัดการจูน RAG/LLM ให้เหลือ ‘สามอย่าง เจาะลึก’ และถือ ‘วัดผลให้ได้’ เป็นหน่วยการเรียนรู้

ส่งข้อความได้ตามสบาย

ไม่ว่าจะเป็นการว่าจ้างงาน แนะนำโปรเจกต์ ความคิดเห็น หรือคำถาม ยินดีรับทั้งหมด ผมหวังเป็นอย่างยิ่งว่าจะได้เชื่อมต่อกับผู้ที่มีอุดมการณ์อันสูงส่งเช่นเดียวกัน ผมจะมุ่งมั่นท้าทายในสิ่งที่ทุ่มเททั้งชีวิตต่อไป ขอขอบคุณและฝากเนื้อฝากตัวด้วยครับ