สิ่งที่ Gemini มีแต่ผมไม่มี — รู้ตัวก็ต่อเมื่อใช้งานจริง
สิ่งที่ Gemini มีแต่ผมไม่มี — รู้ตัวก็ต่อเมื่อใช้งานจริง
สิ่งที่รู้ได้เมื่อลองรันจริงเท่านั้น
เริ่มใช้งาน my-rag-brain จริงๆ แล้วพบสิ่งที่ไม่สะดวก
เมื่อดึงบันทึกเก่าด้วย search_memory ไม่รู้ว่าเนื้อหานั้นมาจากบทสนทนาใด ผลการค้นหาแสดงข้อความของบทเรียนและข้อสรุปได้ แต่ไม่มีทางกลับไปดูบริบทเดิม ซึ่งเป็นปัญหาที่มีอยู่และกระบวนการที่นำไปสู่ข้อสรุปนั้น
ไม่มี file path ไม่มีเบาะแสนอกจากวันที่
นี่คือช่องว่างการออกแบบเทียบกับ Gemini
ตรวจสอบ spec ของ Gemini
Gemini มี RAG Engine, MemoryCorpus และ Sources: Previous chats ไม่เพียงแค่ค้นหาบทสนทนาเก่า แต่ยังส่งคืนบทสนทนาเองในฐานะแหล่งที่มาได้ “ข้อมูลนี้มาจากไหน” ถูกเก็บรักษาไว้เสมอผ่าน Grounding
นั่นคือสิ่งที่ขาดหายไปในระบบของผม
vault (entry ที่กลั่นกรองแล้วเช่น lesson และ conclusion) ขาดการเชื่อมต่อกับไฟล์บทสนทนาต้นฉบับ การกลั่นกรองบีบอัดข้อมูลแต่ตัดแหล่งที่มาออก
นำ source_origin มาใช้งาน
การเปลี่ยนแปลงครอบคลุม 4 ไฟล์ ก่อนอื่นสรุปบทบาทของแต่ละไฟล์:
| ไฟล์ | บทบาท |
|---|---|
store.py | ชั้นเขียนข้อมูลลง ChromaDB จัดการ metadata ของ chunk ทั้งหมด |
note_writer.py | จุดเข้าสำหรับการบันทึก ถูกเรียกจาก MCP server และ CLI เรียก store.py |
distill_v2.py | pipeline ที่เลื่อนโน้ตดิบใน diary ไปเป็น Lesson/Conclusion |
server.py | ตัว MCP server หลัก มี logic การค้นหาและแสดงผลสำหรับ search_memory |
흐름การเขียนคือ distill_v2.py → note_writer.py → store.py → ChromaDB และการอ่านคือ server.py → ChromaDB
① store.py — เพิ่ม field ใน ChromaDB metadata
เพิ่ม source_origin ใน metadata ของทุก chunk ที่เขียนลง ChromaDB
meta = {
"source_type": source_type,
"source_file": str(path),
"source_ref": source_ref,
"source_origin": source_origin, # บันทึก path ของไฟล์ต้นทาง
"title": title,
"date": date_str,
...
}
② note_writer.py — เพิ่ม argument ให้ฟังก์ชันเขียน
เพิ่ม source_origin เป็น argument ใน write_note() และส่งต่อไปยัง store.py
def write_note(text: str, source_type: str, ref: str = "",
priority: str = "", source_origin: str = ""):
...
ingest_file(str(target_file), source_type, ..., source_origin=source_origin)
③ distill_v2.py — ส่ง path ไฟล์ต้นทางตอนกลั่นกรอง
เมื่อเขียนเนื้อหา diary ที่กลั่นกรองแล้วลงใน vault จะส่ง path ไฟล์ diary ต้นทางเป็น source_origin ทำให้บันทึกได้ว่าบทเรียนนั้นมาจากบทสนทนาวันใด
write_note(
text=body,
source_type=note_type,
ref=f"distill_v2:{source_date}:{time_str}",
source_origin=str(md_path), # เช่น data/diary/2026-05-27.md
)
④ server.py — แสดงแหล่งที่มาในผลการค้นหา
เมื่อประกอบผลลัพธ์ search_memory ถ้ามี source_origin จะแสดงท้ายผลลัพธ์
source_origin = meta.get("source_origin", "")
...
if source_origin:
lines.append(f"📄 ที่มา: {Path(source_origin).name}")
ตอนนี้ผลการค้นหาแสดง 📄 ที่มา: 2026-05-27.md ท้ายรายการ มีเส้นทางกลับไปยังบทสนทนาต้นฉบับแล้ว
ทำไม Grounding ถึงสำคัญ
มีบันทึกอยู่แล้ว แต่ถ้ากลับไปดูบริบทของบันทึกไม่ได้ ความรู้ก็กลายเป็นแค่ป้ายกำกับที่โดดเดี่ยว
เมื่อวิศวกรออกแบบระบบ คุณภาพของการตัดสินใจแตกต่างกันระหว่างการมีแค่เอกสาร requirements กับการมีบริบทว่าทำไม requirements เหล่านั้นถึงเกิดขึ้น RAG ก็เช่นกัน
Gemini ไม่ปล่อยแหล่งที่มาทิ้ง ระบบของผมก็ควรเป็นแบบนั้น
บทความที่เกี่ยวข้อง
- เรื่องที่สังเกตว่าพฤติกรรมของ Gemini ตรงกับปรัชญาการออกแบบ RAG ของตัวเอง อยู่ใน AI ไปถึงแนวคิดการออกแบบเดียวกับที่ผมมี
- เรื่องการ fine-tune RAG ส่วนตัวตัวเดียวกันด้วย GPU ในเครื่องเท่านั้น อยู่ใน Fine-Tune RAG ส่วนตัวด้วยแค่แล็ปท็อป RTX 2070
- บันทึกการยกระดับคุณภาพการค้นหาแบบขับเคลื่อนด้วยการวัดผล อยู่ใน RAG ที่มีแค่ vector search “ลืมในตอนที่สำคัญที่สุด” — ทำให้ recall ขึ้นจาก 0.2 เป็น 1.0 ด้วย hybrid search + การวัดผล
- ปรัชญาการออกแบบเบื้องหลัง RAG ส่วนตัวทั้งหมดนี้ อยู่ใน คืนที่ AI แก้ไขฉัน 5 ครั้ง - ปรัชญาการออกแบบเพื่อให้ RAG ส่วนตัวเป็นเพื่อนคุณเป็นเวลา 5 ปี