Belajar ML Engineer - RAG & Knowledge Systems
Episode 16 of 28

Belajar ML Engineer - RAG & Knowledge Systems

Memberi model pengetahuan domain tanpa retraining: memahami embedding dan similarity search, membangun pipeline RAG (ingest, chunking, retrieval, generation), memilih vector database, serta menerapkan hybrid search dan evaluasi retrieval yang ketat

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 15 model LLM kalian melayani aplikasi lewat vLLM, muncul keterbatasan model itu sendiri: model hanya tahu apa yang ada di training data. Tanya soal kebijakan perusahaan terbaru, dokumen internal, atau produk baru yang rilis kemarin — jawabannya salah atau mengarang. Di sinilah RAG (Retrieval-Augmented Generation) menjadi jawaban standar 2026.

RAG menggabungkan retriever (mencari dokumen relevan dari basis pengetahuan) dengan generator (LLM yang menjawab berdasarkan dokumen). Karena pengetahuan diambil dari database saat runtime, RAG memberi keunggulan yang tidak bisa ditandingi fine-tuning: informasi selalu bisa diperbarui tanpa retraining, dan jawaban bisa diberi sumber. Episode ini membangun pipeline RAG lengkap, dari embedding sampai hybrid search.

Embedding: Teks Menjadi Vektor

Retrieval dimulai dari representasi: embedding mengubah teks menjadi vektor numerik di mana teks yang bermakna mirip punya vektor berdekatan.

Membuat embedding
from sentence_transformers import SentenceTransformer
 
model = SentenceTransformer("intfloat/multilingual-e5-small")
vec = model.encode("Prosedur klaim asuransi kesehatan")
print(vec.shape)   # misal (384,) — teks jadi vektor

Pemilihan model embedding sangat menentukan kualitas retrieval:

PertimbanganSaran
BahasaPilih model multilingual (e5, bge-multilingual) untuk dokumen Indonesia
Dimensi384-1024: besar = lebih presisi tapi lebih lambat & boros
KonsistensiModel embedding sama harus dipakai saat ingest & query
NormalisasiNormalisasi vektor agar cosine similarity sederhana

Arsitektur Pipeline RAG

100%

Dua fase dengan karakter berbeda:

  • Ingest (offline): dokumen dipecah (chunking), di-embedding, disimpan di vector DB. Berjalan saat dokumen baru masuk.
  • Query (online): pertanyaan di-embedding, dicari K dokumen paling mirip, lalu prompt berisi konteks dikirim ke LLM.

Chunking dan Penempatan Konteks

Chunking menentukan unit retrieval. Chunk terlalu kecil → konteks terpotong; terlalu besar → pencarian tidak presisi dan memakan context window.

Chunking sederhana dengan overlap
def chunk_text(text: str, size: int = 512, overlap: int = 64) -> list[str]:
    chunks = []
    start = 0
    while start < len(text):
        chunks.append(text[start:start + size])
        start += size - overlap
    return chunks

Overlap menjaga kalimat yang terpotong di tengah chunk tetap ada di chunk berikutnya. Untuk dokumen terstruktur (markdown, HTML, PDF), chunk per heading/section biasanya jauh lebih baik daripada chunk per jumlah karakter — konteks semantik tetap utuh.

Pilihan vector DB populer 2026: pgvector (tambahan PostgreSQL — bagus jika sudah pakai Postgres), ChromaDB (simpel untuk prototyping), Qdrant / Weaviate / Milvus (platform standalone skala besar). Semua menyediakan pencarian kNN / HNSW — menemukan K vektor terdekat.

Namun, pencarian vektor murni punya kelemahan: tidak paham kata eksak & keyword. Pertanyaan "SOP klaim BPJS" mungkin paling cocok dengan dokumen yang mengandung kata "klaim" persis — sesuatu yang bisa dilewatkan embedding. Solusinya hybrid search: gabungkan pencarian vektor dengan pencarian keyword (BM25/Full-text), lalu gabungkan skornya.

Hybrid search: vektor + full-text
# Ilustrasi konsep — gabungkan dua peringkat menjadi satu
vector_scores = vector_search(query_embedding, top_k=20)
keyword_scores = keyword_search(query, top_k=20)
combined = merge_ranked(vector_scores, keyword_scores, alpha=0.6)

Parameter alpha menentukan bobot masing-masing (0.6 vektor / 0.4 keyword adalah titik awal umum). Reranker (cross-encoder) bisa ditambahkan setelah hybrid search untuk mengurutkan ulang hasil dengan presisi lebih tinggi — tapi lebih lambat, jadi hanya untuk top-K kecil.

Membangun RAG System Sederhana

RAG end-to-end
from openai import OpenAI
 
llm = OpenAI(base_url="http://localhost:8000/v1", api_key="x")
 
def rag_answer(question: str, top_k: int = 3) -> str:
    q_vec = embed_model.encode(question)
    hits = vector_db.query(q_vec, top_k=top_k)   # + hybrid search
    context = "\n\n".join(h["text"] for h in hits)
    prompt = f"""Jawab berdasarkan konteks berikut saja.
    Jika konteks tidak memuat jawaban, katakan tidak tahu.
 
    Konteks:
    {context}
 
    Pertanyaan: {question}"""
    resp = llm.chat.completions.create(
        model="Qwen/Qwen2.5-7B-Instruct",
        messages=[{"role": "user", "content": prompt}],
        temperature=0.1,
    )
    return resp.choices[0].message.content

Perhatikan dua disiplin: temperature rendah (jawaban harus faktual, bukan kreatif) dan instruksi "katakan tidak tahu" (mencegah hallucination saat konteks tidak memadai).

Evaluasi RAG: Jangan Berhenti di "Terlihat Baik"

RAG tanpa evaluasi = sistem yang diam-diam menjawab salah. Evaluasi dua lapisan:

LapisanMetrikMengukur
RetrievalRecall@K, MRR, hit rateApakah dokumen relevan ketemu?
GenerationCorrectness, faithfulness, groundednessApakah jawaban benar & bersumber konteks?

Praktik paling penting untuk retrieval: bangun golden set — sekumpulan pasangan pertanyaan → dokumen yang seharusnya ter-retrieve. Lalu ukur recall@K. Teknik evaluasi modern (LLM-as-judge, RAGAS) akan kita dalami di episode 24.

Warning

Dua kegagalan RAG paling umum: chunking yang mengabaikan struktur dokumen (konteks jadi puing-puing) dan tanpa evaluasi retrieval (sistem terlihat jalan tapi jawaban sering salah). Perbaiki keduanya sebelum pindah ke masalah yang lebih "menarik".

Common Pitfalls

PitfallDampakPencegahan
Embedding model beda saat ingest & queryRetrieval kacauSatu model embedding untuk semuanya
Chunk tanpa overlap / tanpa strukturKonteks terpotongChunk per section + overlap
Hanya vector searchKeyword eksak terlewatHybrid search + reranker
RAG tanpa sumberJawaban tidak bisa diverifikasiSertakan reference doc pada output
Tanpa eval retrievalSalah diam-diamGolden set + recall@K

Penutup

Pada episode 16 ini, kalian telah membangun knowledge system:

  • Embedding mengubah teks → vektor; model embedding konsisten di ingest & query.
  • Pipeline RAG: chunking → embedding → vector DB → retrieval → prompt → LLM.
  • Vector DB + hybrid search (BM25) mengatasi kelemahan pencarian vektor murni.
  • Evaluasi retrieval (recall@K) dan generation (groundedness) dengan golden set.

Di episode 17 selanjutnya kita akan membahas Data Pipelines untuk ML — ingestion, processing, dan feature store: bagaimana data mengalir dari sumber mentah menjadi dataset training yang bersih dan feature yang konsisten untuk training maupun serving. Sampai jumpa di episode 17!

Belajar ML Engineer - RAG & Knowledge Systems | Belajar ML Engineer