AI ไปถึงแนวคิดการออกแบบเดียวกับที่ผมมี
AI ไปถึงแนวคิดการออกแบบเดียวกับที่ผมมี
วันที่กลับมาหลังหายไปหนึ่งเดือน
ผมเปิด Gemini เป็นครั้งแรกในรอบนาน
มีเรื่องที่ค้างคาใจมาก่อนหน้านี้ ขึ้นอยู่กับคำถาม Gemini บางครั้งพูดเรื่องผิดๆ ด้วยความมั่นใจเต็มเปี่ยม — ที่เรียกว่าฮาลูซิเนชัน แต่พอกลับมาใช้หลังจากหายไปหนึ่งเดือน มันหายไปแล้ว
คนส่วนใหญ่คงไม่สังเกตความเปลี่ยนแปลงนี้ แค่รู้สึกว่า “ช่วงนี้ดีขึ้นนะ” แล้วก็ผ่านไป
อาจเป็นโรคอาชีพของวิศวกรระบบ แต่ผมสนใจช่วงเวลาที่ข้อบกพร่องที่รู้จักได้รับการแก้ไขมากกว่าตอนที่ระบบทำงานปกติ ฮาลูซิเนชันคือ “บั๊กที่รู้จักอยู่แล้ว” ถ้ามันถูกแก้ไข ผมต้องรู้ว่าอะไรเปลี่ยนไป
ตรวจสอบการออกแบบ
ผมถาม Gemini ตรงๆ ว่าอะไรเปลี่ยนไป
คำอธิบายที่ได้รับคือ: การรวม RAG (Retrieval-Augmented Generation) ซึ่งค้นหาข้อมูลล่าสุดก่อนสร้างคำตอบ เข้ากับ Grounding ที่อ้างอิงแหล่งที่มาอย่างชัดเจน ช่วยลดการเดาโดยไม่มีหลักฐาน
นั่นคือแนวคิดการออกแบบเดียวกับ my-rag-brain ของผมเอง
อยากรู้มากขึ้น ผมถามเพิ่มเรื่องแหล่งที่มา คำตอบที่ได้คือ:
ผมดึงข้อมูลและอัปเดตอยู่เสมอ เนื่องจากรวมถึง Qiita ด้วย จึงสมเหตุสมผลที่จะกล่าวว่ามีความเป็นไปได้ที่ข้อมูลของคุณได้กลายเป็นส่วนหนึ่งของผม
บทความที่ผมเคยเขียนใน Qiita อาจวนเวียนมาเป็นส่วนหนึ่งของ Gemini ยืนยันไม่ได้ แต่เป็นเรื่องที่น่าสนใจ
นำการออกแบบของ Gemini มาใส่ใน my-rag-brain
ถ้าการออกแบบเหมือนกัน สิ่งที่ Gemini ใช้งานแล้วก็ควรใส่ในระบบของผมได้ ผมทำทีละอย่าง
CRAG (Corrective RAG)
เพิ่มเกตประเมินคุณภาพผลลัพธ์การค้นหาจาก ChromaDB ทันทีหลังดึงข้อมูล chunk ที่มีระยะทางโคไซน์เกิน 0.55 จะถูกตัดสินว่า “poor” และไม่ให้ผ่าน
POOR_MATCH_THRESHOLD = 0.55
_best_dist = min(_type_min_dist.values()) if _type_min_dist else None
_poor_quality = _best_dist is not None and _best_dist > POOR_MATCH_THRESHOLD
เมื่อตัดสินว่า poor จะมีกลไก fallback ที่ลบ type filter แล้วค้นหาข้ามประเภท เพื่อช่วยกรณีที่เนื้อหาที่ถูกต้องถูกบันทึกไว้ใน type อื่น
Adaptive Retrieval Depth
การค้นหาทุกคำถามด้วยความลึกเท่ากันนั้นไม่มีประสิทธิภาพ จึงเพิ่มการให้คะแนนความซับซ้อนเพื่อสลับระหว่าง top 5 / 7 / 10 แบบไดนามิก
def _calc_adaptive_top(query: str, user_top: int) -> tuple[int, str]:
score = 0
if len(query) > 60: score += 2
elif len(query) > 30: score += 1
# เพิ่มคะแนนจาก marker เช่น "และ" "เปรียบเทียบ" "ครั้งก่อน"
if score >= 3: return 10, f"wide(score={score})"
elif score >= 1: return 7, f"mid(score={score})"
return 5, ""
Tiny-Critic RAG
ถ้า CRAG คือเกตคุณภาพ Tiny-Critic คือตัวกรองความเกี่ยวข้อง โมเดลขนาดเล็กนี้ตัดสินแบบไบนารีว่า chunk ที่ผ่านเกตคุณภาพมาแล้วนั้น เกี่ยวข้องกับคำถามจริงๆ หรือไม่ และลบอันที่ไม่เกี่ยวออก รายละเอียดการฝึกอยู่ในบทความแยก
ปฏิเสธ Self-RAG
Self-RAG คือสถาปัตยกรรมที่ประเมินคุณภาพผลลัพธ์เองและค้นหาซ้ำหากจำเป็น แต่ผมไม่ใช้ ในโครงสร้างที่ Claude Code เรียกผ่าน MCP server ตัว Claude Code เองทำหน้าที่เกตอยู่แล้ว จึงซ้ำซ้อน
ไปป์ไลน์ทั้งหมดที่นำมาใช้:
graph TD
A[คำถาม] --> B[Adaptive Retrieval Depth<br/>กำหนด top 5 / 7 / 10 ตามคะแนนความซับซ้อน]
B --> C[ChromaDB Search<br/>ดึงผู้สมัครด้วยความคล้ายคลึงเวกเตอร์]
C --> D{CRAG Quality Gate<br/>dist > 0.55?}
D -->|ผ่าน| E[Tiny-Critic<br/>ลบ chunk ที่ไม่เกี่ยวข้อง]
D -->|Poor| F[CRAG Fallback<br/>ค้นหาซ้ำโดยไม่มี type filter]
F --> E
E --> G[สร้างคำตอบ]
ทำไมถึงเขียนเรื่องนี้
งานของวิศวกรคือการสร้างสถานะที่ปัญหาไม่เกิดขึ้นอย่างมีเหตุผล ตั้งแต่การกำหนดความต้องการจนถึงขั้นตอนการออกแบบ และยังหมายถึงการหาสัญญาณในสัญญาณรบกวน และถามต่อเนื่องว่าทำไมมันถึงเป็นแบบนั้น
ครั้งนี้ ผมพบแนวคิดการออกแบบซ่อนอยู่ในสัญญาณรบกวนจากพฤติกรรมที่เปลี่ยนไปของ AI แม้แต่ AI ก็ไม่ใช่ข้อยกเว้น
บทความที่เกี่ยวข้อง
- เรื่องการ fine-tune RAG ส่วนตัวตัวเดียวกันด้วย GPU ในเครื่องเท่านั้น อยู่ใน Fine-Tune RAG ส่วนตัวด้วยแค่แล็ปท็อป RTX 2070
- อีกสิ่งที่เรียนรู้จาก Gemini คือการออกแบบให้กลับไปดูแหล่งที่มาได้ อยู่ใน สิ่งที่ Gemini มีแต่ผมไม่มี — รู้ตัวก็ต่อเมื่อใช้งานจริง
- บันทึกการยกระดับคุณภาพการค้นหาแบบขับเคลื่อนด้วยการวัดผล อยู่ใน RAG ที่มีแค่ vector search “ลืมในตอนที่สำคัญที่สุด” — ทำให้ recall ขึ้นจาก 0.2 เป็น 1.0 ด้วย hybrid search + การวัดผล
- ปรัชญาการออกแบบเบื้องหลัง RAG ส่วนตัวทั้งหมดนี้ อยู่ใน คืนที่ AI แก้ไขฉัน 5 ครั้ง - ปรัชญาการออกแบบเพื่อให้ RAG ส่วนตัวเป็นเพื่อนคุณเป็นเวลา 5 ปี