รัน RAG ในเครื่องด้วย Ollama, ChromaDB และ LangChain ให้ AI ตอบคำถามจากคู่มือ 2,111 หน้า โดยไม่ส่งข้อมูลออกนอกเครื่อง
สร้างระบบ RAG รันในเครื่องด้วย Ollama, ChromaDB และ LangChain ให้ AI ช่วยตอบคำถามจากคู่มือ PDF 2,111 หน้า โดยไม่ต้องส่งเอกสารออกไปคลาวด์ พร้อมสรุปวิธีติดตั้งและ 3 ปัญหาจริงที่พบระหว่างพัฒนา

เราสามารถสร้างผู้ช่วย AI ตอบคำถามจากคู่มือ PDF ของบริษัทได้ด้วยเครื่องมือ 3 ตัว คือ Ollama, ChromaDB และ LangChain โดยรันทุกอย่างจบในเครื่องเดียว และไม่มีข้อความแม้แต่บรรทัดเดียวหลุดออกไปหาคลาวด์
โจทย์นี้เริ่มจากบริษัทซอฟต์แวร์แห่งหนึ่งที่วางระบบบัญชี งานบุคคล และคลังสินค้าให้หน่วยงานรัฐ ทุกครั้งที่มีคนสอบถามเข้ามา ทีมช่างเทคนิคต้องคอยไล่เปิดคู่มือ PDF ทีละหน้าจากทั้งหมดหลายร้อยหน้าเพื่อหาคำตอบ แต่เนื่องจากเอกสารชุดนี้มีตัวเลขการเงินของหน่วยงานที่รับเงินบริจาคจากต่างประเทศ กฎเหล็กจึงห้ามส่งข้อมูลออกนอกเครื่องเด็ดขาด ไม่ว่าจะเป็น OpenAI, Anthropic หรือบริการคลาวด์รายไหนก็ตาม
งานทั้งหมดนี้เป็นโปรเจกต์จบปริญญาโทด้าน AI และ Big Data ของ TAGBA G-Josaphat ที่หยิบโจทย์จากงานจริงมาทำ พร้อมบันทึกทั้งขั้นตอนการประกอบระบบและปัญหาที่พังระหว่างทางเอาไว้ ผลลัพธ์ที่ได้ไม่ใช่แชตบอตที่ตอบเร็วทันใจ แต่เป็นผู้ช่วยที่อ้างอิงคำตอบจากเอกสารจริงของบริษัท และระบุได้ชัดเจนว่าข้อมูลมาจากคู่มือเล่มไหน
ปัญหาไม่ใช่ AI ไม่ฉลาด แต่มันไม่เคยเห็นคู่มือของเรา
โมเดลภาษาขนาดใหญ่ (LLM) ที่อยู่เบื้องหลังผู้ช่วย AI ทั่วไปเก่งเรื่องภาษาก็จริง แต่มันไม่เคยเห็นคู่มือภายในของบริษัทมาก่อน เพราะเอกสารเหล่านั้นไม่ได้อยู่ในชุดข้อมูลที่ใช้เทรนโมเดลตั้งแต่แรก
ปัญหาคือเมื่อถามเรื่องที่โมเดลไม่รู้ มันจะไม่ยอมเงียบ แต่จะเดาขั้นตอนออกมาให้อย่างมั่นใจ อาการนี้เรียกว่า hallucination ซึ่งสำหรับการทำบัญชีในโครงการที่ใช้เงินบริจาค การเดาขั้นตอนผิดไปเพียงข้อเดียวไม่ใช่เรื่องที่จะหัวเราะกันได้
ทางออกของโปรเจกต์นี้จึงไม่ใช่การหาโมเดลที่ฉลาดขึ้น แต่เป็นการเปลี่ยนวิธีส่งคำถามแทน
RAG คือการยื่นเอกสารให้อ่านตอนถาม ไม่ใช่ให้ท่องจำ
RAG ย่อมาจาก Retrieval-Augmented Generation มีหลักการทำงานที่เข้าใจง่ายกว่าชื่อมาก แทนที่จะคาดหวังให้โมเดลรู้ทุกเรื่องตั้งแต่แรก ระบบจะคัดเฉพาะย่อหน้าในเอกสารที่ตรงกับคำถามนั้น แล้วแนบไปพร้อมกับคำถามก่อนส่งให้โมเดลประมวลผลคำตอบ
หากเปรียบกับพนักงานใหม่ เราไม่ได้สั่งให้เขาท่องคู่มือทั้งเล่มจนจำได้ก่อนเริ่มงาน แต่ใช้วิธีหยิบเอกสาร 3 หน้าที่ตรงกับคำถามมาวางตรงหน้า แล้วกำชับให้ตอบเฉพาะข้อมูลใน 3 หน้านี้เท่านั้น
โมเดลไม่ได้จดจำเอกสารเข้าไปเก็บไว้ในตัว แต่จะเปิดอ่านใหม่จากข้อความที่แนบไปให้ทุกครั้ง แนวทางนี้มีประโยชน์หลัก 2 ข้อ ข้อแรกคือไม่ต้องทำ fine-tune หรือปรับแต่งเทรนโมเดลเพิ่มด้วยข้อมูลของบริษัท ข้อสองคือเมื่อมีคู่มือเวอร์ชันใหม่ ก็แค่อัปโหลดไฟล์ใหม่เข้าระบบ โดยไม่ต้องเสียเวลารื้อเทรนโมเดลใหม่ทั้งตัว
สองเฟส เก็บครั้งเดียว แล้วถามได้ทุกวัน

เฟสแรกคือ ingestion ซึ่งทำเพียงครั้งเดียวตอนตั้งระบบ โดยนำไฟล์ PDF ทั้งหมดมาตัดเป็นก้อนย่อย ก้อนละ 300 ตัวอักษร แล้วแปลงแต่ละก้อนเป็นชุดตัวเลขยาวเพื่อแทนความหมายของข้อความ (embedding) ก่อนนำไปเก็บไว้ใน ChromaDB สำหรับโปรเจกต์นี้ เอกสาร 10 ไฟล์ รวม 2,111 หน้า หั่นแบ่งออกมาได้ทั้งหมด 9,669 ก้อน
เฟสที่สองคือ query ซึ่งเกิดขึ้นใหม่ทุกครั้งที่มีคนพิมพ์ถาม ระบบจะแปลงคำถามเป็นชุดตัวเลขด้วยโมเดลตัวเดิมที่ใช้ตอนเก็บข้อมูล แล้วสั่งให้ ChromaDB ค้นหาก้อนเนื้อหาที่มีค่าตัวเลขใกล้เคียงกับคำถามมากที่สุด 3 ก้อน จากนั้นระบบจะวางเนื้อหาทั้ง 3 ก้อนไว้ด้านหน้าคำถาม แล้วส่งทั้งหมดไปให้ Llama 3 ประมวลผล พร้อมกำชับคำสั่งไว้อย่างชัดเจนว่า ให้ตอบเฉพาะจากบริบทที่แนบไปเท่านั้น ระบุที่มาของข้อมูล และหากไม่มีคำตอบในบริบท ให้แจ้งออกมาตรงๆ
สี่โปรแกรมใน Docker ที่ทำงานคนละหน้าที่

ทั้งระบบไม่ได้รันเป็นโปรแกรมเดียว แต่ประกอบด้วยโปรแกรม 4 ตัวที่ทำงานแยกกันภายในเครื่องแล้วสื่อสารกันเอง โดยมี Docker ทำหน้าที่ห่อแต่ละโปรแกรมไว้ในคอนเทนเนอร์ของตัวเอง ส่วน Docker Compose คือไฟล์เดียวที่สั่งให้ทั้ง 4 โปรแกรมเปิดทำงานขึ้นมาพร้อมกัน
| โปรแกรม | หน้าที่ | พอร์ต |
|---|---|---|
| Ollama | รัน Llama 3 อยู่ในเครื่อง | 11434 |
| ChromaDB | เก็บเวกเตอร์ของทุกก้อนเอกสาร | 8001 |
| FastAPI | เปิดขั้นตอน RAG ทั้งสายให้เรียกใช้จากภายนอก | 8000 |
| Streamlit | หน้าเว็บให้พิมพ์คำถาม | 8501 |
โปรแกรมแรกที่ต้องดาวน์โหลดมาติดตั้งคือ Ollama ซึ่งทำหน้าที่ดึงโมเดลภาษามาประมวลผลในเครื่อง ส่วน ChromaDB คือฐานข้อมูลสำหรับเก็บชุดตัวเลขโดยเฉพาะ ทำให้ค้นหาข้อมูลจากความหมายที่ใกล้เคียงกันได้ แทนที่จะต้องค้นหาด้วยคีย์เวิร์ดตรงตัวเป๊ะ
อีกส่วนที่ไม่ได้อยู่ในตารางแต่ขาดไม่ได้เลยคือ LangChain ที่รับหน้าที่เป็นไลบรารีเชื่อมต่อทุกขั้นตอนเข้าด้วยกัน ตั้งแต่ดึงเอกสาร ประกอบชุดคำสั่งส่งให้โมเดล เรียกใช้งานโมเดล ไปจนถึงจัดรูปแบบคำตอบก่อนส่งกลับมาให้ผู้ใช้
เริ่มจริงด้วยห้าคำสั่ง
สิ่งที่ต้องเตรียมก่อนเริ่มงานตามที่ repository ระบุไว้ คือ Docker Desktop กับ Python เวอร์ชัน 3.10 ขึ้นไป ส่วนเครื่องควรมี RAM ตั้งแต่ 8 GB ขึ้นไป โดยแนะนำที่ 16 GB ส่วนโค้ดทั้งหมดเปิดให้ดาวน์โหลดในโปรเจกต์ Assistant-Intelligent-RAG บน GitHub โดยมีขั้นตอนการติดตั้งเริ่มต้นเพียงเท่านี้
git clone https://github.com/josaphatstar/Assistant-Intelligent-RAG
docker-compose up -d
docker exec -it tomate-ollama ollama pull llama3
# คัดลอกไฟล์ PDF ของเราลงโฟลเดอร์ data/documents/ ก่อนสั่งบรรทัดสุดท้าย
docker exec -it tomate-api python ingestion.pyคำสั่งบรรทัดสุดท้ายคือการรันเฟส ingestion ตามที่เล่าไป ยิ่งมีเอกสารมากเท่าไรก็ยิ่งใช้เวลานานขึ้น เพราะระบบต้องแปลงเนื้อหาทุกก้อนเป็นชุดตัวเลขทีละก้อนด้วย CPU
สามอย่างที่พังจริง และวิธีแก้
ผู้เขียนระบุเองว่า รายละเอียดตอนระบบพังมักไม่ค่อยมีใครหยิบมาเล่า โดยปัญหาทั้ง 3 ข้อต่อไปนี้คือสิ่งที่เกิดขึ้นจริงระหว่างการพัฒนา และมีโอกาสเจอได้เช่นกันหากลองทำตาม
ChromaDB บอกว่าเก็บครบ 9,669 ก้อน แต่ในฐานมี 0
ในช่วงแรก โค้ดเชื่อมต่อ ChromaDB ด้วยไวยากรณ์รุ่นเก่าที่ส่งค่าผ่าน client_settings ส่งผลให้ข้อมูลไปเก็บบนเครื่องเงียบๆ โดยไม่ได้ส่งไปยังเซิร์ฟเวอร์ที่กำหนดไว้ แม้ระบบจะรันจนจบโดยไม่แสดง error และแจ้งว่าเก็บครบ 9,669 ก้อนแล้ว แต่เมื่อลองใช้งานจริงกลับไม่ได้คำตอบใดๆ เพราะในฐานข้อมูลมีเวกเตอร์เก็บอยู่เพียง 0 ตัว
วิธีแก้ไขคือระบุการเชื่อมต่อให้ชัดเจนด้วย chromadb.HttpClient(host="chromadb", port=8000) แทนการปล่อยให้ระบบเดาปลายทางเอง และหากต้องการตรวจสอบว่า ChromaDB ยังทำงานอยู่หรือไม่ ให้ส่งคำขอไปที่ /api/v2/heartbeat แทน endpoint เดิมอย่าง /api/v1/heartbeat ที่เลิกใช้งานไปแล้ว
LangChain ย้ายบ้านโมดูลบ่อยกว่าที่คิด
โค้ดเดิมที่เคย import โมดูลจาก langchain.prompts หรือ langchain.schema.runnable เกิดข้อผิดพลาด ModuleNotFoundError ทันทีหลังอัปเดตเวอร์ชัน ทั้งที่ก่อนหน้านี้เคยรันได้ตามปกติ
ส่วนที่ทีมพัฒนาปรับให้เสถียรได้ย้ายไปรวมกันอยู่ใต้ langchain_core เช่น langchain_core.prompts หรือ langchain_core.runnables หากพบ error ลักษณะนี้ ให้เข้าไปตรวจสอบที่ตำแหน่งดังกล่าวก่อนเป็นอันดับแรก
Llama 3 บน CPU ช้ากว่าที่คาดไว้มาก
เรื่องความเร็วเป็นประเด็นที่ต้องทำใจล่วงหน้า เพราะโมเดล Llama 3 ขนาด 8B พารามิเตอร์ เมื่อรันบน CPU จะสร้างคำตอบได้เพียง 2-5 โทเคนต่อวินาที (โทเคนคือชิ้นส่วนคำที่โมเดลทยอยสร้างออกมาทีละชิ้น) ส่งผลให้คำตอบยาวประมาณ 200 คำ ต้องใช้เวลาประมวลผลนานกว่า 2 นาที ซึ่งเกินกว่าค่า timeout ที่ตั้งไว้เดิม 120 วินาทีไปมาก
แนวทางแก้ปัญหาที่ช่วยได้จริงมี 3 ข้อ ข้อแรกคือลดจำนวนก้อนเนื้อหาที่ดึงมาใช้ตอบจาก 5 ก้อนเหลือ 3 ก้อน เพื่อให้ชุดคำสั่งสั้นลงและเริ่มสร้างคำตอบได้เร็วขึ้น ข้อสองคือใส่พารามิเตอร์ num_predict=250 เพื่อจำกัดความยาวคำตอบ เพราะหากไม่กำหนด โมเดลจะสร้างข้อความยาวต่อเนื่องไปเรื่อยๆ ข้อสามคือเพิ่มขนาด RAM ให้ Docker เพื่อป้องกันไม่ให้ระบบต้องสลับบันทึกข้อมูลระหว่างหน่วยความจำกับดิสก์
สี่บทเรียนที่ทำให้ไม่ต้องเจ็บซ้ำ
- โมเดลที่ใช้แปลงข้อความต้องเป็นตัวเดียวกันทั้งสองฝั่ง โปรเจกต์นี้ใช้
all-MiniLM-L6-v2ทั้งขั้นตอนจัดเก็บและค้นหา หากใช้โมเดลคนละตัว เวกเตอร์ที่ได้จะอยู่คนละระบบพิกัด ทำให้ผลการค้นหาคลาดเคลื่อนแบบเงียบๆ โดยไม่แสดง error เตือนเลย - ขนาดของการแบ่งก้อนเนื้อหามีผลมากกว่าที่คิด สำหรับเอกสารเทคนิคชุดนี้ การหั่นเนื้อหาก้อนละ 300 ตัวอักษร ให้ผลการค้นหาแม่นยำกว่าการหั่นก้อนละ 500 เพราะก้อนที่สั้นกว่าโฟกัสเฉพาะเรื่องได้ตรงกว่า
- กำกับ metadata บอกชื่อไฟล์ต้นทางไว้กับทุกก้อนตั้งแต่ตอนนำเข้า การติดป้ายกำกับนี้ช่วยให้ระบบระบุได้ชัดเจนว่าคำตอบมาจากคู่มือเล่มใด แทนที่จะแสดงเฉพาะข้อความลอยๆ
- คอนเทนเนอร์แต่ละตัวใน Docker ห้ามคุยกันผ่าน
localhostต้องอ้างอิงด้วยชื่อ service ที่กำหนดไว้ในไฟล์docker-compose.ymlเช่นchromadbหรือollama
หากเอกสารที่มีไม่ได้มากถึงระดับหลายพันหน้า ยังมีทางเลือกอย่างวิธีให้ AI ค่อยๆ เขียน wiki เก็บความรู้เป็นไฟล์ markdown ซึ่งไม่จำเป็นต้องพึ่งพาฐานข้อมูลเวกเตอร์เลยแม้แต่น้อย
ตอบได้ และกล้าบอกว่าไม่รู้
เมื่อติดตั้งระบบเสร็จสิ้น AI สามารถตอบคำถามอ้างอิงจากคู่มือได้อย่างแม่นยำ ตัวอย่างเช่น เมื่อถามถึงขั้นตอนปิดงวดเงินเดือนประจำเดือน ระบบจะดึงขั้นตอนจากคู่มือฝ่ายบุคคลมาตอบเป็นข้อๆ หรือเมื่อถามถึงเมนูกดเปิดบัญชีใหม่ในผังบัญชี ระบบก็ระบุเส้นทางกดให้อย่างชัดเจน พร้อมแจ้งชื่อเอกสารต้นทางประกอบ
จุดเด่นสำคัญที่สุดของระบบไม่ได้อยู่ที่คำถามที่ตอบได้ แต่อยู่ที่เมื่อไม่พบข้อมูลในเอกสาร ระบบจะแจ้งตรงๆ ว่าไม่มีข้อมูลในคู่มือ แทนที่จะแต่งขั้นตอนขึ้นมาเองให้ดูน่าเชื่อถือ ซึ่งนี่คือเป้าหมายหลักของการพัฒนาระบบ RAG ตั้งแต่เริ่มต้น
ช้าจริง และเหมาะกับงานแบบไหน
ตัวเลขความเร็วข้างต้นเกิดจากการรันบน CPU เพียงอย่างเดียว การตอบคำถามแต่ละครั้งใช้เวลาราว 1-2 นาที จนโค้ดฝั่งหน้าเว็บต้องตั้งค่า timeout เผื่อไว้สูงถึง 600 วินาที แม้ความเร็วระดับนี้จะเพียงพอกับงานภายในองค์กรที่ไม่เร่งด่วน เช่น ระบบช่วยค้นหาคำตอบสำหรับพนักงานหรือทีมสนับสนุน แต่ไม่เหมาะกับแชตบอตบริการลูกค้าหน้าร้านที่คนถามรอคำตอบนานเป็นนาทีไม่ไหว
แนวทางการรันโมเดลในเครื่องลักษณะนี้มีข้อดีข้อเสียต่างกันไป อย่างเช่น โปรเจกต์ที่ปล่อยให้ Ollama ไล่อ่านหน้าสมัครงานข้ามคืน แม้จะช่วยประหยัดค่า API ได้เช่นกัน แต่ก็ต้องใช้เครื่องที่มีการ์ดจอประสิทธิภาพสูงเข้ามาทดแทน
ผลงานนี้เป็นโปรเจกต์ระดับปริญญาโทที่ต่อยอดจากโจทย์ฝึกงาน จึงไม่ใช่เฟรมเวิร์กสำเร็จรูปสำหรับระบบโปรดักชันที่มีทีมคอยดูแลอัปเดตเวอร์ชัน ทั้งนี้ ตัวระบบยังมีข้อจำกัดตามที่ผู้เขียนระบุไว้ คือระบบจะทำกระบวนการเดิมเสมอด้วยการค้นหาเอกสารแล้วตอบคำถาม โดยไม่มีกลไกวิเคราะห์ล่วงหน้าว่าคำถามแต่ละประเภทควรรับมือด้วยวิธีใด ส่วนแผนในอนาคตที่จะนำ LangGraph มาช่วยตัดสินใจเลือกกระบวนการทำงานนั้น ยังเป็นเพียงแนวคิดที่เกริ่นไว้ และยังไม่ได้เริ่มพัฒนาในรอบนี้
ค่าบริการ API ที่ประหยัดได้จากการรันระบบเอง ไม่ได้หายไปไหน แต่เปลี่ยนรูปแบบไปเป็นเวลารอคำตอบครั้งละ 2 นาที รวมถึงเวลาที่เสียไปกับการหาสาเหตุว่าทำไมฐานข้อมูลถึงว่างเปล่า ทั้งที่หน้าจอแจ้งว่าบันทึกครบแล้ว สำหรับใครที่ยอมรับเงื่อนไขเหล่านี้ได้ ก็จะได้ระบบผู้ช่วยที่เก็บรักษาข้อมูลความลับขององค์กรไว้ภายในเครื่องได้อย่างแท้จริง
ที่มา:
- บทความ I Built a Local RAG Assistant with Ollama, ChromaDB and LangChain. Here's What I Learned จาก dev.to
- โปรเจกต์ Assistant-Intelligent-RAG บน GitHub
ชอบเรื่องแนวนี้ มีอีบุ๊คฟรีให้อ่านต่อ
NotebookLM ฉบับเข้าใจง่าย โยนเอกสารให้ AI อ่าน แล้วได้สรุป พอดแคสต์ และคลังความรู้ส่วนตัว
กดสมัครแล้วเราจะส่งเทคนิค AI และของแจกใหม่ๆ ให้ทางอีเมล เลิกรับได้ตลอด
Claude Cowork · The Business Playbook

ฉบับภาษาไทย 15 บท เรียนรู้ผ่านโปรเจกต์จำลองต่อเนื่องทั้งเล่ม ตั้งแต่ตั้งค่า Workspace จัดการไฟล์ เชื่อมแอป ตั้งระบบอัตโนมัติ จนถึงสร้าง Plugin


