Saya pernah menghabiskan dua hari mengganti model LLM untuk memperbaiki kualitas RAG — dari GPT-3.5 ke GPT-4, lalu ke Claude. Hasilnya nyaris tidak berubah.
Masalah sebenarnya ada di chunking strategy yang salah. Setelah saya fix chunk size dan overlap, akurasi retrieval naik 40% — tanpa ganti model apapun. Kualitas RAG jauh lebih bergantung pada bagaimana Anda memotong dokumen daripada model LLM yang Anda pakai.
Apa Itu RAG dan Mengapa Dibutuhkan
RAG (Retrieval-Augmented Generation) adalah pattern di mana LLM tidak hanya mengandalkan training data-nya, tapi mencari informasi relevan dari knowledge base eksternal sebelum menjawab.
Tanpa RAG, LLM tidak tahu tentang dokumen internal perusahaan, kebijakan terbaru, atau SOP spesifik organisasi Anda. RAG menyelesaikan ini — tapi implementasinya jauh lebih nuanced dari yang terlihat di tutorial sederhana.
Chunking — Bagian yang Paling Sering Salah
Chunking adalah proses memotong dokumen menjadi potongan kecil yang bisa disimpan di vector database. Ini satu keputusan paling berdampak pada kualitas RAG, dan paling sering diabaikan.
Chunk Size: Bukan Semakin Kecil Semakin Baik
- Chunk terlalu kecil → kehilangan konteks. "Limit transaksi adalah 10 juta" tanpa kalimat sebelumnya tidak bermakna.
- Chunk terlalu besar → noise tinggi. LLM mendapat terlalu banyak informasi tidak relevan, jawaban kurang fokus.
- Sweet spot: 300–800 token untuk prose, 50–150 token untuk code snippets.
Overlap: Jangan Sampai Konteks Terpotong
Selalu gunakan overlap antar chunk. Kalimat penting yang kebetulan ada di batas potongan akan muncul di kedua chunk berkat overlap, sehingga tidak hilang dari retrieval.
Rule of thumb: overlap 10–20% dari chunk size. Untuk chunk 512 karakter, gunakan overlap 50–64 karakter.
from langchain.text_splitter import RecursiveCharacterTextSplitter
# Untuk prose / dokumen biasa
splitter = RecursiveCharacterTextSplitter(
chunk_size=512, # ~400 token untuk Bahasa Indonesia
chunk_overlap=64, # ~12% overlap — jangan biarkan nol
separators=["\n\n", "\n", ".", " "]
)
# JANGAN ini — memotong tanpa mempertimbangkan semantik kalimat
# bad = CharacterTextSplitter(chunk_size=100)Overlap 10–20% dari chunk size memastikan kalimat penting yang kebetulan ada di batas potongan tetap muncul di salah satu chunk. Tanpa overlap, informasi di batas chunk bisa hilang dan tidak ter-retrieve.
Embedding Model — Pilihan yang Sering Diabaikan
Embedding adalah representasi vektor dari teks. Kualitas embedding menentukan seberapa akurat retrieval menemukan dokumen yang relevan.
| Model | Bahasa Indonesia | Cost | Rekomendasi |
|---|---|---|---|
| OpenAI text-embedding-3-small | △ Cukup | $0.02/1M token | Default untuk mulai |
| OpenAI text-embedding-3-large | ✓ Baik | $0.13/1M token | Jika akurasi kritis |
| Cohere embed-multilingual-v3 | ✓ Terbaik | $0.10/1M token | Konten Indonesia heavy |
| sentence-transformers (local) | △ Varies | Gratis | Self-hosted, latency tinggi |
Full Pipeline: Dari PDF ke Query
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
# 1. Load dokumen
docs = PyPDFLoader("sop-penanganan-keluhan.pdf").load()
# 2. Chunk
chunks = RecursiveCharacterTextSplitter(
chunk_size=512, chunk_overlap=64
).split_documents(docs)
# 3. Embed + simpan ke vector store
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./chroma_db"
)
# 4. Retriever dengan MMR — hindari hasil yang redundan
retriever = vectorstore.as_retriever(
search_type="mmr",
search_kwargs={"k": 4, "fetch_k": 20}
)
results = retriever.invoke("SLA untuk kerusakan kategori minor?")
for doc in results:
print(doc.page_content)
print(f"Source: {doc.metadata['source']}, page {doc.metadata['page']}")Maximum Marginal Relevance menghindari mengambil chunk yang redundan. Dari 20 candidate hasil similarity search, MMR memilih 4 yang paling diverse — memberikan LLM konteks yang lebih kaya.
Evaluasi — Jangan Skip Bagian Ini
Kesimpulan
Urutan prioritas saat RAG tidak berfungsi baik: 1) Chunking strategy → 2) Embedding model → 3) Retrieval method → 4) Prompt → 5) LLM model. Jangan mulai dari nomor 5.
Ganti LLM adalah langkah terakhir, bukan pertama. Perbaiki chunking dan retrieval dulu — itu yang paling sering jadi akar masalahnya.
Episode berikutnya: LangGraph State Machine — cara membangun agentic workflow yang lebih kompleks dengan state machine pattern, checkpoint, dan human-in-the-loop.