RAG คืออะไร? ทำไมถึงสำคัญสำหรับ AI
RAG (Retrieval-Augmented Generation) เป็นเทคนิคที่เปลี่ยนวิธีการทำงานของ AI อย่างสิ้นเชิง จากที่เคยตอบคำถามจากความรู้ที่ถูก train มา กลายเป็น AI ที่สามารถค้นหาและใช้ข้อมูลล่าสุดของคุณในการตอบคำถามได้
RAG คืออะไร?
RAG ย่อมาจาก Retrieval-Augmented Generation หมายถึงการเสริมพลังให้ AI ด้วยการ "ดึงข้อมูล" (Retrieval) ที่เกี่ยวข้องมาก่อน แล้วจึง "สร้างคำตอบ" (Generation) จากข้อมูลนั้น
แนวคิดพื้นฐาน
Traditional LLM:
คำถาม → AI (ความรู้จาก Training) → คำตอบ
❌ ข้อมูลอาจล้าสมัย
❌ ไม่รู้จักข้อมูลเฉพาะของคุณ
RAG:
คำถาม → ค้นหาข้อมูลที่เกี่ยวข้อง → AI + ข้อมูล → คำตอบ
✅ ใช้ข้อมูลล่าสุด
✅ รู้จักข้อมูลของคุณ
✅ อ้างอิงแหล่งที่มาได้
สถาปัตยกรรม RAG
┌─────────────────────────────────────────────────────────────────┐
│ RAG Architecture │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ │
│ │ User │ │
│ │ Query │ │
│ └────┬─────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ ┌──────────────────┐ │
│ │ Embedding │────▶│ Vector Database │ │
│ │ Model │ │ (ค้นหาข้อมูล) │ │
│ └──────────────┘ └────────┬─────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ Retrieved │ │
│ │ Documents (Top-K)│ │
│ └────────┬─────────┘ │
│ │ │
│ ┌────────────────────────┼────────────────────────┐ │
│ │ ▼ │ │
│ │ ┌──────────────────────────────────────────┐ │ │
│ │ │ Prompt = Query + Retrieved Documents │ │ │
│ │ └──────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌──────────────────────────────────────────┐ │ │
│ │ │ LLM (GPT-4/Claude) │ │ │
│ │ └──────────────────────────────────────────┘ │ │
│ └────────────────────────┬────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ Generated Answer │ │
│ │ + Source │ │
│ └──────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
ทำไม RAG ถึงสำคัญ?
1. แก้ปัญหา Knowledge Cutoff
LLM ทั่วไปมีจุดตัดความรู้ (Knowledge Cutoff) หมายความว่าไม่รู้จักข้อมูลหลังจากวันที่ถูก train
# Without RAG
# Q: "ราคา Bitcoin วันนี้เท่าไหร่?"
# A: "ผมไม่มีข้อมูลราคาปัจจุบัน ข้อมูลของผมถูกตัดขาดที่..."
# With RAG
# System ค้นหาราคา Bitcoin ล่าสุดจาก database
# Q: "ราคา Bitcoin วันนี้เท่าไหร่?"
# A: "ราคา Bitcoin ณ เวลา 14:00 อยู่ที่ $42,350 (อ้างอิงจาก: CoinGecko API)"
2. ใช้ข้อมูลเฉพาะขององค์กร
# ข้อมูลภายในบริษัทที่ AI ทั่วไปไม่รู้จัก
internal_docs = [
"นโยบายวันลาของบริษัท 2025",
"Product Roadmap Q1 2025",
"Employee Handbook",
"Technical Documentation"
]
# RAG ทำให้ AI ตอบคำถามเกี่ยวกับข้อมูลเหล่านี้ได้
3. Transparency & Traceability
RAG สามารถอ้างอิงแหล่งที่มาได้ ทำให้ตรวจสอบความถูกต้องได้
{
"answer": "พนักงานมีสิทธิ์ลาพักร้อน 15 วันต่อปี",
"sources": [
{
"document": "Employee Handbook 2025",
"page": 23,
"relevance_score": 0.95
}
]
}
4. Cost-Effective
เมื่อเทียบกับ Fine-tuning:
| Aspect | RAG | Fine-Tuning |
|---|---|---|
| ต้นทุนเริ่มต้น | ต่ำ | สูง |
| Update ข้อมูล | ทันที | ต้อง re-train |
| เวลาในการ deploy | นาที | ชั่วโมง-วัน |
| Technical complexity | ปานกลาง | สูง |
การทำงานของ RAG ทีละขั้นตอน
Step 1: Document Ingestion (เตรียมข้อมูล)
from langchain.document_loaders import PyPDFLoader, TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
class DocumentProcessor:
def __init__(self):
self.text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
length_function=len,
separators=["\n\n", "\n", " ", ""]
)
def load_documents(self, file_paths: list) -> list:
"""โหลดเอกสารจากหลายแหล่ง"""
documents = []
for path in file_paths:
if path.endswith('.pdf'):
loader = PyPDFLoader(path)
elif path.endswith('.txt'):
loader = TextLoader(path)
else:
continue
docs = loader.load()
documents.extend(docs)
return documents
def split_documents(self, documents: list) -> list:
"""แบ่งเอกสารเป็น chunks"""
chunks = self.text_splitter.split_documents(documents)
# เพิ่ม metadata
for i, chunk in enumerate(chunks):
chunk.metadata['chunk_id'] = i
chunk.metadata['chunk_size'] = len(chunk.page_content)
return chunks
Step 2: Embedding (แปลงเป็น Vector)
from langchain.embeddings import OpenAIEmbeddings
import numpy as np
class EmbeddingService:
def __init__(self, model="text-embedding-3-small"):
self.embeddings = OpenAIEmbeddings(model=model)
def embed_documents(self, texts: list) -> list:
"""แปลง texts เป็น vectors"""
vectors = self.embeddings.embed_documents(texts)
return vectors
def embed_query(self, query: str) -> list:
"""แปลง query เป็น vector"""
return self.embeddings.embed_query(query)
def compute_similarity(self, vec1: list, vec2: list) -> float:
"""คำนวณ cosine similarity"""
return np.dot(vec1, vec2) / (
np.linalg.norm(vec1) * np.linalg.norm(vec2)
)
Step 3: Vector Storage (เก็บใน Vector Database)
from langchain.vectorstores import Chroma, Pinecone
import chromadb
class VectorStore:
def __init__(self, store_type="chroma"):
self.store_type = store_type
if store_type == "chroma":
self.client = chromadb.Client()
self.collection = self.client.create_collection(
name="knowledge_base",
metadata={"hnsw:space": "cosine"}
)
def add_documents(self, chunks: list, embeddings: list):
"""เพิ่มเอกสารเข้า vector store"""
ids = [f"doc_{i}" for i in range(len(chunks))]
documents = [chunk.page_content for chunk in chunks]
metadatas = [chunk.metadata for chunk in chunks]
self.collection.add(
ids=ids,
embeddings=embeddings,
documents=documents,
metadatas=metadatas
)
def search(self, query_embedding: list, top_k: int = 5) -> list:
"""ค้นหาเอกสารที่เกี่ยวข้อง"""
results = self.collection.query(
query_embeddings=[query_embedding],
n_results=top_k,
include=["documents", "metadatas", "distances"]
)
return results
Step 4: Retrieval (ค้นหาข้อมูล)
class Retriever:
def __init__(self, vector_store, embedding_service):
self.vector_store = vector_store
self.embedding_service = embedding_service
def retrieve(self, query: str, top_k: int = 5) -> list:
"""ค้นหาเอกสารที่เกี่ยวข้องกับ query"""
# 1. แปลง query เป็น embedding
query_embedding = self.embedding_service.embed_query(query)
# 2. ค้นหาใน vector store
results = self.vector_store.search(query_embedding, top_k)
# 3. จัดรูปแบบผลลัพธ์
retrieved_docs = []
for i, doc in enumerate(results['documents'][0]):
retrieved_docs.append({
'content': doc,
'metadata': results['metadatas'][0][i],
'distance': results['distances'][0][i],
'relevance_score': 1 - results['distances'][0][i]
})
return retrieved_docs
Step 5: Generation (สร้างคำตอบ)
from openai import OpenAI
class RAGGenerator:
def __init__(self):
self.client = OpenAI()
def generate(
self,
query: str,
retrieved_docs: list,
model: str = "gpt-4"
) -> dict:
"""สร้างคำตอบจาก query และ retrieved documents"""
# สร้าง context จาก retrieved documents
context = "\n\n---\n\n".join([
f"Document {i+1} (relevance: {doc['relevance_score']:.2f}):\n{doc['content']}"
for i, doc in enumerate(retrieved_docs)
])
# สร้าง prompt
system_prompt = """คุณเป็น AI assistant ที่ตอบคำถามโดยใช้ข้อมูลที่ให้มา
กฎ:
1. ตอบเฉพาะจากข้อมูลที่ให้มาเท่านั้น
2. ถ้าไม่มีข้อมูลเพียงพอ ให้บอกว่าไม่พบข้อมูล
3. อ้างอิงแหล่งที่มาเสมอ
4. ตอบเป็นภาษาไทย"""
user_prompt = f"""ข้อมูลอ้างอิง:
{context}
คำถาม: {query}
กรุณาตอบคำถามโดยใช้ข้อมูลอ้างอิงด้านบน พร้อมระบุแหล่งที่มา"""
response = self.client.chat.completions.create(
model=model,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt}
],
temperature=0.3
)
return {
"answer": response.choices[0].message.content,
"sources": [doc['metadata'] for doc in retrieved_docs],
"model": model
}
RAG Pipeline แบบครบวงจร
class RAGPipeline:
"""Complete RAG Pipeline"""
def __init__(self):
self.doc_processor = DocumentProcessor()
self.embedding_service = EmbeddingService()
self.vector_store = VectorStore()
self.retriever = None
self.generator = RAGGenerator()
def ingest(self, file_paths: list):
"""Ingest documents into the system"""
# 1. โหลดและแบ่ง documents
documents = self.doc_processor.load_documents(file_paths)
chunks = self.doc_processor.split_documents(documents)
print(f"Loaded {len(documents)} documents, split into {len(chunks)} chunks")
# 2. สร้าง embeddings
texts = [chunk.page_content for chunk in chunks]
embeddings = self.embedding_service.embed_documents(texts)
# 3. เก็บใน vector store
self.vector_store.add_documents(chunks, embeddings)
# 4. สร้าง retriever
self.retriever = Retriever(self.vector_store, self.embedding_service)
print("Ingestion complete!")
def query(self, question: str, top_k: int = 5) -> dict:
"""Query the RAG system"""
if not self.retriever:
raise ValueError("Please ingest documents first")
# 1. Retrieve relevant documents
retrieved_docs = self.retriever.retrieve(question, top_k)
# 2. Generate answer
result = self.generator.generate(question, retrieved_docs)
return result
# การใช้งาน
rag = RAGPipeline()
# Ingest documents
rag.ingest([
"documents/employee_handbook.pdf",
"documents/company_policies.pdf",
"documents/product_guide.pdf"
])
# Query
result = rag.query("พนักงานสามารถลาพักร้อนได้กี่วันต่อปี?")
print(result['answer'])
print("Sources:", result['sources'])
Advanced RAG Techniques
1. Hybrid Search (ค้นหาแบบผสม)
รวม Semantic Search และ Keyword Search เพื่อผลลัพธ์ที่ดีขึ้น
from rank_bm25 import BM25Okapi
import numpy as np
class HybridRetriever:
def __init__(self, vector_store, documents):
self.vector_store = vector_store
self.documents = documents
# BM25 for keyword search
tokenized_docs = [doc.split() for doc in documents]
self.bm25 = BM25Okapi(tokenized_docs)
def hybrid_search(
self,
query: str,
query_embedding: list,
top_k: int = 5,
alpha: float = 0.5 # weight between vector and keyword
) -> list:
# Vector search
vector_results = self.vector_store.search(query_embedding, top_k * 2)
# BM25 keyword search
tokenized_query = query.split()
bm25_scores = self.bm25.get_scores(tokenized_query)
bm25_top_k = np.argsort(bm25_scores)[-top_k * 2:][::-1]
# Combine scores with RRF (Reciprocal Rank Fusion)
combined_scores = {}
for rank, idx in enumerate(vector_results['ids'][0]):
combined_scores[idx] = combined_scores.get(idx, 0) + \
alpha * (1 / (rank + 60))
for rank, idx in enumerate(bm25_top_k):
doc_id = f"doc_{idx}"
combined_scores[doc_id] = combined_scores.get(doc_id, 0) + \
(1 - alpha) * (1 / (rank + 60))
# Sort by combined score
sorted_results = sorted(
combined_scores.items(),
key=lambda x: x[1],
reverse=True
)[:top_k]
return sorted_results
2. Re-ranking
ใช้ Cross-encoder เพื่อจัดลำดับผลลัพธ์ใหม่
from sentence_transformers import CrossEncoder
class Reranker:
def __init__(self, model_name="cross-encoder/ms-marco-MiniLM-L-12-v2"):
self.model = CrossEncoder(model_name)
def rerank(
self,
query: str,
documents: list,
top_k: int = 5
) -> list:
"""Rerank documents using cross-encoder"""
# Create query-document pairs
pairs = [[query, doc['content']] for doc in documents]
# Get scores
scores = self.model.predict(pairs)
# Sort by score
ranked_indices = np.argsort(scores)[::-1][:top_k]
reranked_docs = []
for idx in ranked_indices:
doc = documents[idx].copy()
doc['rerank_score'] = float(scores[idx])
reranked_docs.append(doc)
return reranked_docs
3. Query Expansion
สร้างหลาย query จาก query เดียวเพื่อค้นหาได้ครอบคลุมขึ้น
class QueryExpander:
def __init__(self):
self.client = OpenAI()
def expand_query(self, original_query: str, n_expansions: int = 3) -> list:
"""Generate multiple queries from original query"""
response = self.client.chat.completions.create(
model="gpt-4",
messages=[
{
"role": "system",
"content": f"""Generate {n_expansions} alternative queries
that could help find relevant information for the original query.
Return as JSON array of strings."""
},
{"role": "user", "content": original_query}
]
)
expanded_queries = json.loads(response.choices[0].message.content)
return [original_query] + expanded_queries
4. Contextual Compression
บีบอัด context ให้กระชับก่อนส่งให้ LLM
class ContextCompressor:
def __init__(self):
self.client = OpenAI()
def compress(
self,
query: str,
documents: list,
max_tokens: int = 2000
) -> str:
"""Compress retrieved documents to essential information"""
combined_docs = "\n\n".join([doc['content'] for doc in documents])
response = self.client.chat.completions.create(
model="gpt-4",
messages=[
{
"role": "system",
"content": f"""Extract only the information relevant to
answering the query. Keep it under {max_tokens} tokens.
Preserve important facts and details."""
},
{
"role": "user",
"content": f"Query: {query}\n\nDocuments:\n{combined_docs}"
}
]
)
return response.choices[0].message.content
Vector Databases สำหรับ RAG
เปรียบเทียบ Vector Databases
| Database | Open Source | Managed | Best For |
|---|---|---|---|
| Pinecone | No | Yes | Production, Scale |
| Weaviate | Yes | Yes | Hybrid Search |
| Chroma | Yes | No | Prototyping |
| Qdrant | Yes | Yes | Performance |
| Milvus | Yes | Yes | Large Scale |
| pgvector | Yes | - | PostgreSQL users |
อ่านรายละเอียดเพิ่มเติมได้ที่ Vector Database สำหรับ AI
Use Cases ของ RAG
1. Customer Support Chatbot
# Customer support with RAG
support_rag = RAGPipeline()
support_rag.ingest([
"docs/faq.pdf",
"docs/product_manual.pdf",
"docs/troubleshooting.pdf"
])
# Handle customer query
def handle_support_query(query: str):
result = support_rag.query(query)
# Check confidence
if result['sources'][0]['relevance_score'] < 0.7:
return {
"answer": "ขออภัย ไม่พบข้อมูลที่เกี่ยวข้อง กรุณาติดต่อทีม support",
"escalate": True
}
return result
2. Legal Document Analysis
# Legal RAG system
legal_rag = RAGPipeline()
legal_rag.ingest([
"contracts/*.pdf",
"legal_terms/*.pdf",
"case_studies/*.pdf"
])
# Find relevant clauses
def find_relevant_clauses(contract_type: str, topic: str):
query = f"ข้อกำหนดเกี่ยวกับ {topic} ใน {contract_type}"
return legal_rag.query(query, top_k=10)
3. Internal Knowledge Base
# Company knowledge base
kb_rag = RAGPipeline()
kb_rag.ingest([
"hr/policies/*.pdf",
"it/guides/*.pdf",
"operations/sop/*.pdf"
])
# Employee assistant
def ask_hr_question(question: str, employee_id: str):
result = kb_rag.query(question)
# Log query for analytics
log_query(employee_id, question, result)
return result
สรุป
RAG เป็นเทคนิคที่ทรงพลังในการทำให้ AI ฉลาดขึ้นและใช้งานได้จริงในองค์กร โดยไม่ต้อง fine-tune model ใหม่ การเลือกใช้ RAG ที่เหมาะสมจะช่วยให้คุณสร้าง AI application ที่แม่นยำ อัปเดตได้ง่าย และตรวจสอบได้
อ่านบทความที่เกี่ยวข้อง
- Fine-Tuning และ RAG: เทคนิคขั้นสูงในการสอน AI - เปรียบเทียบ RAG กับ Fine-Tuning
- Vector Database สำหรับ AI - เจาะลึก Vector Database
- สร้าง AI Chatbot สำหรับธุรกิจ - นำ RAG ไปใช้กับ Chatbot
พร้อมเริ่มสร้าง RAG System แล้วหรือยัง?
เรียนรู้เพิ่มเติมและรับคำปรึกษาจากทีมผู้เชี่ยวชาญของเราได้ที่ AI Unlocked เราพร้อมช่วยคุณออกแบบและพัฒนา RAG System ที่ตอบโจทย์ธุรกิจของคุณ
เขียนโดย
AI Unlocked Team
บทความอื่นๆ ที่น่าสนใจ
วิธีติดตั้ง FFmpeg บน Windows และ Mac: คู่มือฉบับสมบูรณ์
เรียนรู้วิธีติดตั้ง FFmpeg บน Windows และ macOS พร้อมการตั้งค่า PATH อย่างละเอียด เพื่อใช้งานโปรแกรมตัดต่อวิดีโอและเสียงระดับมืออาชีพ
สร้าง AI-Powered SaaS: จากไอเดียสู่ผลิตภัณฑ์
คู่มือครบวงจรในการสร้าง AI-Powered SaaS ตั้งแต่การวางแผน พัฒนา ไปจนถึง launch และ scale รวมถึง tech stack, pricing และ business model
AI Security: วิธีใช้ AI อย่างปลอดภัย
เรียนรู้แนวทางการใช้ AI อย่างปลอดภัย ครอบคลุม prompt injection, data privacy, API security และ best practices สำหรับองค์กร