หลังจากใช้เวลาสี่เดือนในการเปลี่ยนผ่าน RAG pipeline จาก Jupyter notebook ไปสู่การใช้งานจริง (live service) ผู้เขียนได้ระบุถึงห้าทางเลือกที่เป็นรูปธรรมซึ่งเปลี่ยนจากเดโมที่ดูดีให้กลายเป็นระบบที่ผู้ใช้สามารถพึ่งพาได้จริง ความแตกต่างนี้เห็นได้ชัดจากตัวเลข: เพียงแค่เปลี่ยนวิธีการแบ่งข้อความ (text splitting) ก็สามารถเพิ่มอัตราการค้นพบข้อมูลที่ถูกต้อง (retrieval hit rate) จาก 61% เป็น 83% และชุดข้อมูลประเมินผล (evaluation set) ขนาดเล็กที่มีคำถามจริง 200 รายการ ก็สามารถตรวจพบข้อผิดพลาด (regressions) ส่วนใหญ่ได้ก่อนที่จะถึงมือลูกค้า

ทำไมเรื่องนี้ถึงสำคัญ

เดโมของ RAG มักจะดูน่าประทับใจ—มันสามารถดึงข้อความและสร้างคำตอบที่ดูสมเหตุสมผลได้ภายในไม่กี่วินาที แต่ในการใช้งานจริง วิธีการแบบเดียวกันนี้มักจะให้ข้อมูลที่ล้าสมัย ข้ามรหัสข้อผิดพลาด หรือสร้างประโยคที่ผิดเพี้ยน ซึ่งทำลายความเชื่อมั่นของผู้ใช้ คอขวดมักไม่ใช่ตัวโมเดลภาษา (language model) แต่เป็นวิธีการนำเข้าข้อมูล (ingestion) การทำดัชนี (indexing) และการให้บริการข้อมูล (serving) การจัดการ pipeline ให้ถูกต้องอาจหมายถึงความแตกต่างระหว่างผลิตภัณฑ์ที่สร้างมูลค่า กับผลิตภัณฑ์ที่เป็นภาระ

1. เลิกใช้การแบ่งส่วนข้อมูลแบบขนาดคงที่ (fixed-size chunks)

หลายโปรโตไทป์ใช้วิธีหั่นทุกเอกสารออกเป็นบล็อกขนาด 512 โทเคน ซึ่งอาจใช้ได้กับข้อความสั้นๆ แต่จะทำให้คู่มือทางเทคนิค เธรดการสนับสนุน และโค้ดสั้นๆ (code snippets) เสียหาย ประโยคจะถูกตัดขาด หัวข้อหายไป และเอนจินการค้นหา (retrieval engine) ไม่สามารถจับคู่บริบทที่ผู้ใช้คาดหวังได้

เปลี่ยนมาใช้การแบ่งส่วนข้อมูลโดยคำนึงถึงโครงสร้าง (structure-aware chunking)—เช่น แบ่งตามหัวข้อ, ขอบเขตการสนทนา หรือ code fences—เพื่อรักษาหน่วยความหมาย (semantic units) เอาไว้ ในระบบของผู้เขียน เพียงแค่การเปลี่ยนวิธีนี้ก็ช่วยเพิ่มสัดส่วนของคำถามที่ค้นพบข้อความที่เกี่ยวข้องจาก 61% เป็น 83% การปรับปรุงนี้เกิดจากการเปลี่ยนรูปแบบข้อมูล โดยที่โมเดลพื้นฐานยังคงเป็นตัวเดิม

การค้นหาแบบเวกเตอร์ล้วน (pure vector search หรือการหาความคล้ายคลึงด้วย embedding) นั้นยอดเยี่ยมในการค้นหาข้อความที่มีความหมายเหมือนกัน แต่จะติดขัดเมื่อต้องค้นหาตัวระบุที่เจาะจง (exact identifiers) เช่น รหัสข้อผิดพลาด, หมายเลขเวอร์ชัน หรือคำศัพท์เฉพาะทาง ผู้ใช้ที่กำลังมองหารหัสข้อผิดพลาดอย่าง “ERR-XXXX” อาจได้รับย่อหน้าที่ความหมายใกล้เคียงกันแต่ไม่มีรหัสที่ต้องการอยู่เลย

การค้นหาแบบไฮบริด (hybrid search) จะรวมดัชนีเวกเตอร์แบบหนาแน่น (dense vector index) เข้ากับดัชนี BM25 แบบดั้งเดิม (ที่อิงตามความถี่ของคำ) การให้น้ำหนักคะแนนจากทั้งสองแบบจะช่วยให้ระบบค้นหาข้อมูลที่ทั้งมีความหมายใกล้เคียงและมีคำที่ผู้ใช้พิมพ์มาอย่างถูกต้อง สำหรับการใช้งานจริง การค้นหาแบบไฮบริดคือข้อกำหนดพื้นฐาน ไม่ใช่แค่ฟีเจอร์เสริมที่มีก็ดี

3. จัดการกับข้อมูลที่ล้าสมัย

ตารางราคา เอกสารนโยบาย หรือบันทึกการปล่อยเฟิร์มแวร์ที่ล้าสมัยสามารถทำลายความน่าเชื่อถือได้อย่างรวดเร็ว สามขั้นตอนที่ทำได้จริงเพื่อรักษาความสดใหม่ของดัชนี ได้แก่:

  • ติดแท็กทุกเอกสารด้วยเวอร์ชันหรือการประทับเวลา (timestamp)
  • ใช้การเพิ่มน้ำหนักความใหม่ (recency boost) ในระหว่างการให้คะแนน เพื่อให้ข้อมูลที่ใหม่กว่ามีลำดับสูงกว่าข้อมูลเก่า
  • ทำการทำดัชนีใหม่แบบเพิ่มส่วนต่าง (incremental re-indexing) ทุกคืน เพื่อดึงการเปลี่ยนแปลงจากระบบต้นทาง

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

4. ใช้การจัดลำดับใหม่ (Rerank) แทนการอัปเกรดโมเดล

การอัปเกรดโมเดล embedding ให้ผลลัพธ์ด้านคุณภาพเพียงเล็กน้อย ในขณะที่การเพิ่ม cross-encoder reranker จะให้การก้าวกระโดดของคุณภาพที่มากกว่าในต้นทุนที่ต่ำกว่า

ขั้นตอนการทำงานในระบบจริงจะดึงรายการที่ผ่านการคัดเลือก (candidates) ที่ราคาถูกมา 20 รายการโดยใช้ hybrid search จากนั้นจึงส่งผ่าน reranker เพื่อเลือก 5 อันดับแรก แนวทางแบบสองขั้นตอน (two-stage approach) นี้ให้คุณภาพที่สูงขึ้นมากโดยใช้ค่าใช้จ่ายเพียงเศษเสี้ยวของการอัปเกรดโมเดลเต็มรูปแบบ

5. สร้างชุดข้อมูลประเมินผลที่ใช้งานจริง

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

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

ขั้นตอนการทำงานของ production pipeline ในทางปฏิบัติ

  • Ingest: การแบ่งส่วนข้อมูลแบบ structure-aware ช่วยรักษาหัวข้อ, บล็อกโค้ด และลำดับการสนทนา
  • Index: จัดเก็บทั้ง dense embeddings และสถิติคำแบบ BM25
  • Retrieve: การค้นหาแบบ hybrid search จะคืนค่ารายการที่ผ่านการคัดเลือก 20 รายการ โดยสร้างสมดุลระหว่างความคล้ายคลึงทางความหมายและการจับคู่คำที่ตรงกัน
  • Rerank: ใช้ cross-encoder เพื่อคัดกรองรายการให้เหลือเพียง 5 ข้อความที่มีแนวโน้มดีที่สุด
  • Generate: LLM จะได้รับข้อความ (chunks) ระดับบนสุดเหล่านี้พร้อมกับ metadata เพื่อสร้างคำตอบสุดท้าย
  • Evaluate: ทุกการตอบกลับจะถูกบันทึกไว้ และความล้มเหลวจะถูกส่งกลับไปยังชุดทดสอบ 200 คำถาม

ความเสี่ยงและข้อแลกเปลี่ยน (Stakes and trade-offs)

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

สิ่งที่ควรจับตามองต่อไป

เมื่อ embeddings แบบโอเพนซอร์สและ vector databases พัฒนาจนสมบูรณ์ เส้นแบ่งระหว่างการดึงข้อมูลแบบ “dense” และ “sparse” จะเริ่มเลือนลางลง แต่หลักการของการผสมผสานการจับคู่เชิงความหมาย (semantic) และการจับคู่แบบตรงตัว (exact matching) ยังคงเดิม

บทสรุป: ในระบบ RAG ตัวโมเดลภาษาแทบจะไม่ใช่คอขวด งานที่แท้จริงอยู่ที่วิธีที่คุณแบ่งส่วน (slice), ทำดัชนี (index) และนำเสนอ (surface) เนื้อหาพื้นฐาน การตัดสินใจในส่วนนี้ให้ถูกต้องจะเปลี่ยนจากเดโมที่ดูหวือหวาให้กลายเป็นผลิตภัณฑ์ที่เชื่อถือได้