- มีผู้ใช้บน Hacker News ถามว่าคนอื่น ๆ นำ Retrieval-Augmented Generation (RAG) ไปใช้งานในสภาพแวดล้อมโลคัลอย่างไร
- มีแนวโน้มชัดเจนว่าการทำ RAG แบบโลคัล แม้ไม่มี vector DB ก็ยังใช้งานได้ดีพอด้วยการค้นหาข้อความอย่าง SQLite FTS5, BM25 หรือ grep
- สำหรับการค้นหาโค้ด มีหลายเสียงจากประสบการณ์ตรงว่าการใช้ embedding ช้าและมี noise สูง และมีคนจำนวนมากมองว่าแนวทางแบบคีย์เวิร์ดอย่าง BM25+trigram ดีกว่า
- แม้ในกรณีที่ต้องใช้ vector search ก็ยังมีตัวอย่างจำนวนมากที่แก้ปัญหาด้วย สแตกเบา ๆ เช่น Postgres+pgvector, เก็บ vector BLOB ใน SQLite หรือโหลด FAISS ไว้ในหน่วยความจำ
- คุณภาพการค้นหาสามารถปรับดีขึ้นได้ด้วย hybrid search ที่รวม BM25+vector เข้าด้วยกัน รวมถึงการใช้ RRF (Reciprocal Rank Fusion), reranking และ multi-query expansion
- แทนที่จะยึดติดว่า “RAG=vector DB” มีแนวโน้มให้เลือกแนวทางตามประเภทเอกสาร ขนาดข้อมูล และภาระในการดูแลระบบ ตั้งแต่ simple search → hybrid → agentic
ข้อสรุปร่วมในขั้นตอนการค้นหา
- แทนที่จะตั้งต้นว่าต้องมี vector DB หรือ graph เสมอ หลายคนเลือกแนวทาง เริ่มต้นให้เรียบง่ายตามโครงสร้างพื้นฐานเดิม ชนิดไฟล์ และประสิทธิภาพที่ต้องการ
- มีการกล่าวถึงว่าวิธีที่ agent ไปอ่านไฟล์ระบบหรือเรียก API โดยตรงนั้นตั้งค่าและบำรุงรักษาง่ายกว่า แต่ก็อาจช้าลงเล็กน้อย
- การมองว่า “สิ่งที่ RAG ส่งต่อให้ LLM คือข้อความสั้น ๆ จากผลการค้นหา” ทำให้จุดโฟกัสในการปรับปรุงประสิทธิภาพย้ายไปอยู่ที่ คุณภาพของการค้นหา
- ในเรื่อง “นิยามของ RAG” มีทั้งความเห็นว่า ตราบใดที่มี retrieval+generation ก็ถือเป็น RAG แม้ไม่มี vector DB และอีกด้านหนึ่งก็มองว่าปกติคำนี้มักสื่อถึงการมี vector DB เป็นพื้นฐาน
โมเดล embedding และ vector search
- โมเดล embedding mdbr-leaf-ir ที่พัฒนาโดย MongoDB ทำงานได้บน CPU ล้วน และทำอันดับ 1 บนหลาย leaderboard ในกลุ่มโมเดลขนาดนี้
- บนเซิร์ฟเวอร์มาตรฐาน 2vCPU ประมวลผลเอกสารได้ราว 22 รายการต่อวินาที และคิวรีได้ 120 ครั้งต่อวินาที
- ได้คะแนน 53.55 บน BEIR benchmark (เทียบกับ all-MiniLM-L12-v2 ที่ได้ 42.69)
- static word embedding อย่าง model2vec/minish เร็วกว่าในขั้น inference แต่ความแม่นยำในการค้นหาต่ำกว่า
- เพราะทำเพียง tokenization + lookup table + averaging จึงเร็วกว่าแนวทางที่ใช้ transformer
- ยังมีการใช้งาน Meta-Llama-3-8B เพื่อสร้างเวกเตอร์ต่อ text chunk แล้วเก็บลงใน คอลัมน์ SQLite BLOB จากนั้นใช้ FAISS ค้นหา
- ที่ระดับ 5 ล้าน chunk ใช้หน่วยความจำประมาณ 40GB
- บน A6000 นั้น faiss-gpu เร็วมาก ส่วน faiss-cpu บน M1 Ultra ช้ากว่าแต่ก็เพียงพอสำหรับงานที่คิวรีไม่กี่ครั้งต่อวัน
คำแนะนำสำหรับการค้นหาโค้ด
- สำหรับโค้ด แนะนำให้หลีกเลี่ยง vector database และใช้แนวทาง BM25+trigram
- embedding ช้าและไม่เหมาะกับโค้ด
- หากไม่มี reranker จะมี noise สูง และยังมีภาระเรื่องการ reindex ไฟล์
- ความเร็วตอบสนองของการค้นหาสูง และคุณภาพผลลัพธ์ก็ดี
- บน PostgreSQL สามารถทำ BM25 search ได้ด้วย plpgsql_bm25
- รองรับ hybrid search ร่วมกับ pgvector และ Reciprocal Rank Fusion
- การใช้ embedding กับ path ของไฟล์และ signature แล้วนำไป fusion กับ BM25 ก็ให้ผลลัพธ์ที่ดีได้
- วิธีแบบ agentic ที่รัน gpt-oss 20B ร่วมกับ ripgrep ในลูป while ก็มีรายงานว่าได้ผลดี
โซลูชันที่อิงฐานข้อมูล
- SQLite FTS5: เหมาะกับเอกสารที่เก็บเป็นไฟล์ Markdown และทำ RAG ได้โดยไม่ต้องมี vector DB
- สามารถเพิ่มฟิลด์คำอธิบายสั้น ๆ ให้แต่ละไฟล์ แล้วใช้ keyword search นำทางเอกสาร
- ยังออกแบบให้เก็บ fp16 vector เป็น BLOB ใน SQLite แล้วใช้ filter สร้าง subset ก่อนคำนวณ similarity ในหน่วยความจำได้
- มีตัวเลือกอย่าง sqlite-vec, sqlite-vector, vec0 และ bm25 ของ sqlite
- “SQLite ทำงานได้ดีอย่างน่าประหลาดใจ”
- PostgreSQL + pgvector: ใช้ความรู้ Postgres เดิมได้ และส่งต่องานให้ทีมปฏิบัติการได้ง่าย
- ยังมีไลบรารี llmemory ที่รองรับ hybrid BM25, multi-query expansion และ reranking
- LanceDB: ใช้งานสะดวกในฐานะ embedded vector DB
- ใช้ร่วมกับ embedding nomic-embed-text ของ Ollama
- DuckDB: มีส่วนขยายสำหรับ vector similarity search เหมาะกับโปรเจกต์ขนาดเล็กไม่เกิน 3GB
- Meilisearch, Typesense, Manticore: ดูแลง่ายกว่า Elasticsearch/OpenSearch
การค้นหาแบบ hybrid และ agentic
- nori(usenori.ai): ผสาน semantic search และ word search ด้วย SQLite + vec0 + fts5
- Turbopuffer: รองรับ hybrid search แบบ vector + BM25
- การผสม agentic search กับ text search เพียงอย่างเดียวก็ให้ผลลัพธ์ที่ดีมากได้
- หากเพิ่ม vector search และ graph RAG ก็อาจช่วยเรื่องความเร็วและคุณภาพได้อีกเล็กน้อย
- Claude Code/Codex ใช้ ripgrep ภายใน
- การทำ embedding กับ path ของไฟล์ก็มีประโยชน์ และจะดีขึ้นอีกเมื่อ fusion กับ BM25
ตัวอย่างการใช้งาน BM25
- shebe: เครื่องมือ CLI/MCP สำหรับทำ indexing และค้นหา codebase ด้วย BM25
- มีประโยชน์มากกับ workflow การ refactor (เช่น ไล่หาจุดที่ต้องแก้เมื่ออัปเกรด Istio)
- ใน 85% ของกรณี ไม่ต้องใช้ vector DB เลยก็พอ แค่จับคู่แท็กก็เพียงพอ
- ผู้ดูแลระบบเพิ่มแท็กทั้งในอินพุตและเอกสารจนได้ matching ครบ 100%
- มีความเห็นว่าฐานข้อมูลเวกเตอร์ส่วนใหญ่คือ “ค้อนที่ถูกสร้างมาเพื่อแก้ปัญหาหาไม่เจอ”
เครื่องมือและไลบรารีเฉพาะทาง
- qmd: เครื่องมือ CLI สำหรับค้นหาไฟล์ Markdown ให้ผลลัพธ์ fuzzy query ดีกว่า fzf
- ck: เครื่องมือ semantic grep ที่พัฒนาด้วย Rust
- Kiln: เพิ่มไฟล์แบบลากแล้ววาง และเปรียบเทียบการตั้งค่าได้หลายแบบ
- รองรับการเปรียบเทียบวิธี extract, embedding model และวิธีค้นหา (BM25, hybrid, vector)
- มีความสามารถประเมินความแม่นยำของการค้นหาและสร้าง evaluation dataset อัตโนมัติ
- libragen: CLI/MCP server สำหรับสร้างไลบรารีเนื้อหา RAG ที่มีการจัดการเวอร์ชัน
- สามารถแปลง GitHub repository ให้เป็น RAG DB ได้
- piragi: ไลบรารี Python สำหรับ RAG แบบเรียบง่าย รองรับแหล่งข้อมูลหลายแบบ เช่น local/S3/API
- ragtune: เครื่องมือ CLI สำหรับดีบักและ benchmark การค้นหาใน local RAG
การประมวลผลเอกสารและ OCR
- discovery: ใช้ Qwen-3-VL-8B ทำ OCR เอกสาร และใช้ ChromaDB เก็บเวกเตอร์
- สร้าง hybrid RAG แบบ BM25 + embedding
- docling: เครื่องมือสำหรับดึงข้อมูลจากเอกสาร ถูกใช้งานในหลายโปรเจกต์ RAG
- ตอนแปลง PDF มักจัดการตาราง หลายคอลัมน์ และตารางที่ข้ามหน้าได้ยาก
- โมเดล Mistral OCR ให้ผลลัพธ์ดีที่สุด (เป็นโมเดลปิด)
การจัดการหน่วยความจำและคอนเท็กซ์
- สิ่งที่ RAG ส่งให้ LLM มีเพียง สตริงผลการค้นหาสั้น ๆ
- สำหรับโมเดลขนาดเล็ก TOP_K=5 มักเป็นขีดจำกัด และหากมากกว่านั้นจะเริ่มเกิดการลืมคอนเท็กซ์
- ปรับปรุงได้ด้วยการ สรุปล่วงหน้า ระดับไฟล์และโฟลเดอร์
- อีกแนวทางคือใช้ Sonnet + context window 1M เพื่อยัดทุกอย่างเข้าไปในคอนเท็กซ์
- มีกรณีตัวอย่างของการสร้างระบบ memory สำหรับ Claude Code ด้วย semantic search บนไฟล์ session
การใช้งานระดับองค์กรและขนาดใหญ่
- สำหรับงานที่ต้องประมวลผล customer interaction วันละ 300,000 รายการ latency และ precision สำคัญมาก
- ใช้แนวทาง hybrid ที่รวม embedding + full-text search + IVF-HNSW
- ความท้าทายคือการจัดการการกระจายข้อมูลในระบบกระจายราว 600 ระบบ
- กำลังทดลองแนวทาง KAG (Knowledge Augmented Generation) เพื่อแมป business rule
- มีกรณีที่ทำ local RAG แบบสมบูรณ์สำเร็จบนข่าวมากกว่า 500,000 บทความด้วย Postgres vector DB
เครื่องมือและแนวทางอื่น ๆ
- AnythingLLM: มี vector DB แบบ bundle มาสำหรับเอกสาร
- LibreChat: รวม vector DB สำหรับเอกสารมาให้
- ChromaDB: ใช้สร้าง semantic/hybrid search ผ่านส่วนขยายของ Obsidian
- SurrealDB: ใช้งานร่วมกับการทำเวกเตอร์ในเครื่อง
- OData query interface: มีประสิทธิภาพเมื่อให้ LLM ใช้เป็นเครื่องมือ และวิเคราะห์ Excel ที่มี 40,000 แถวได้
- Nextcloud MCP Server: ใช้ Qdrant เป็น vector DB เพื่อทำ semantic search บนเอกสารส่วนตัว
- LSP (Language Server Protocol): ถูกเพิ่มเข้า Claude Code แล้ว แต่ตอนนี้ยังมีบั๊กอยู่
- TreeSitter อาจมีประโยชน์มากกว่า (ค้นหาด้วยชื่อสัญลักษณ์, ดูตำแหน่งที่ประกาศ/ใช้งาน)
3 ความคิดเห็น
สงสัยว่าใช้ภาษาเกาหลีได้ดีไหม
พอเห็นโพสต์แบบนี้หลังจากได้ดูประสิทธิภาพของระบบ RAG ภายในบริษัทที่ค่อนข้างหยาบ ๆ มุมมองของผมก็เริ่มเปลี่ยนไปทีละนิดเหมือนกัน
ความคิดเห็นจาก Hacker News
ทีมของเราดูแลฐานข้อมูล Q&A อยู่
เราทำดัชนีทั้งคำถามและคำตอบด้วยทั้ง trigram index และ embedding แล้วเก็บไว้ใน Postgres
ตอนค้นหาจะใช้
pgvectorร่วมกับการค้นหาแบบ trigram และรวมผลลัพธ์ด้วย คะแนนความเกี่ยวข้องในขั้นตอน retrieval เราพัฒนาโมเดล text embedding ประสิทธิภาพสูงที่เหมาะกับ CPU
เป็นโมเดล MongoDB/mdbr-leaf-ir ซึ่งได้ อันดับ 1 บน leaderboard ในกลุ่มโมเดลขนาดเดียวกัน
ใช้งานร่วมกับโมเดล Snowflake/snowflake-arctic-embed-m-v1.5 ได้
สามารถเปรียบเทียบ semantic search vs BM25 vs hybrid ได้ผ่าน เดโม search-sensei
ตัวอย่างเช่น โมเดล embedding เข้าใจว่า “j lo” หมายถึง “Jennifer Lopez”
นอกจากนี้ยังเผยแพร่ training recipe ไว้ด้วย และสามารถฝึกได้ค่อนข้างง่ายแม้ใช้ ฮาร์ดแวร์ระดับทั่วไป
ฉันสร้างเวกเตอร์ด้วย Meta-Llama-3-8B มาตั้งแต่เดือนเมษายน 2024
ใช้ Python กับ Transformers บน RTX-A6000 ซึ่งเร็ว แต่มี เสียงดังและความร้อน สูงมาก
หลังจากนั้นย้ายไปใช้ M1 Ultra และไลบรารี MLX ของ Apple ซึ่งความเร็วใกล้เคียงกันแต่เงียบกว่ามาก
โมเดล Llama มีมิติ 4k ดังนั้นที่ fp16 จะเป็น 8KB/ชังก์ และฉันเก็บมันด้วย
numpy.save()ลงในคอลัมน์ BLOB ของ SQLiteตอนค้นหาจะโหลดเวกเตอร์ทั้งหมดจาก SQLite มาสร้างเป็น
numpy.arrayแล้วค้นหาด้วย FAISSfaiss-gpu บน RTX6000 เร็วมาก และ faiss-cpu บน M1 Ultra ก็เร็วพอสำหรับการใช้งานของฉัน (วันละไม่กี่ query)
ที่ 5 ล้านชังก์ ใช้หน่วยความจำประมาณ 40GB ซึ่งทั้งสองเครื่องรองรับได้สบาย
เอกสารที่ซับซ้อนส่วนใหญ่ของฉันเป็นไฟล์ Markdown
ขอแนะนำเครื่องมือ CLI ง่าย ๆ ชื่อ tobi/qmd
แต่ก่อนฉันใช้เวิร์กโฟลว์แบบ fzf แต่เครื่องมือนี้ให้ fuzzy search ที่ดีกว่า
ฉันไม่ได้ใช้มันกับการค้นหาโค้ด
สำหรับการค้นหาโค้ด ขอแนะนำว่า อย่าใช้ vector database
embedding ช้าและไม่เหมาะกับโค้ด
การใช้ BM25 + trigram ให้ผลลัพธ์ดีกว่าและตอบสนองเร็วกว่า
ดูโปรเจกต์ plpgsql_bm25 ได้
มีทั้งตัวอย่างการรวม BM25 กับ pgvector ด้วย Reciprocal Rank Fusion และ Jupyter notebook ให้ด้วย
ถ้าใช้โมเดลที่ไม่ได้ออกแบบมาสำหรับโค้ด การค้นหาแบบเวกเตอร์จะสร้าง noise เยอะ
ตอนนี้การวนลูป
gpt-oss 20Bร่วมกับ ripgrep เร็วและแม่นยำกว่ามากถ้านำไป fusion กับ BM25 จะดีขึ้นอีก
ฉันทำ local-LLM-with-RAG ขึ้นมาเพื่อทดลอง local RAG
ใช้ “nomic-embed-text” ของ Ollama เพื่อสร้าง embedding และใช้ LanceDB เป็น vector DB
ช่วงหลังอัปเดตให้เป็น “agentic RAG” แต่สำหรับโปรเจกต์เล็กอาจจะเกินความจำเป็น
ฉันเก็บเวกเตอร์ fp16 เป็น BLOB ใน SQLite แล้วหลังจากกรองข้อมูลจึงโหลดเข้าเมมโมรีเพื่อคำนวณความคล้ายด้วย matrix-vector multiplication (matvec)
ถ้า numpy หรือ torch ใช้ multithreading/BLAS/GPU ได้ มันจะเร็วมาก
ถ้าเริ่มติดคอขวด ก็คงจะย้ายไปใช้ sqlite-vector
วิธีนี้มีประสิทธิภาพเพราะข้อมูลถูกลดลงมากจากตัวกรองอย่างวันที่หรือตำแหน่ง
backend ถูกซ่อนไว้หลังอินเทอร์เฟซที่เปลี่ยนสลับได้
เอกสารของฉัน 95% เป็นไฟล์ Markdown ขนาดเล็ก จึงใช้ SQLite FTS5 เป็นดัชนีค้นหาข้อความทั่วไป
เพราะมีดัชนีอยู่แล้ว จึงต่อเข้ากับ mastra agent ได้ทันที
แต่ละไฟล์มีฟิลด์คำอธิบายสั้น ๆ ดังนั้นหลังจากค้นหาด้วยคีย์เวิร์ดแล้ว ถ้าคำอธิบายตรงกันก็จะโหลดทั้งเอกสาร
ใช้เวลาตั้งค่าประมาณหนึ่งชั่วโมงและทำงานได้ดีมาก
แม้ว่าการค้นหาด้วย embedding จะพบได้บ่อยกว่า แต่แก่นของมันก็เหมือนกัน
เราคุ้นเคยกับ Postgres เลยเริ่มจาก PGVector
ต่อมาพบว่าคอนเทนต์ของเราตรงกับฟิลด์กึ่งมีโครงสร้างในพรอมป์ต์แบบ 100% พอดี
เพราะผู้ดูแลเริ่มใส่แท็กทั้งฝั่งอินพุตและเอกสาร (มีเอกสารราว 50 ชิ้น)
ดังนั้นเราจึงค้นหาจากฟิลด์ก่อนเพื่อดึงไฟล์นั้นมาใส่ในพรอมป์ต์ แล้วค่อยทำ embedding search หลังจากนั้น
สุดท้ายแล้วใน 85% ของกรณี ไม่จำเป็นต้องมี vectordb
ฉันสร้าง llmemory และใช้อยู่ทั้งในเครื่องตัวเองและในแอปของบริษัท
มันใช้ PostgreSQL + pgvector และมีฟีเจอร์ hybrid BM25, multi-query expansion, และ reranking
นี่เป็นครั้งแรกที่ฉันเผยแพร่มันออกสาธารณะ จึงอาจยังมีบั๊กอยู่บ้าง
แต่ฉันค่อนข้างพอใจกับประสิทธิภาพของมัน