Belajar Generative AI - RAG: Retrieval-Augmented Generation
Episode 7 of 25

Belajar Generative AI - RAG: Retrieval-Augmented Generation

Membangun RAG (Retrieval-Augmented Generation) dari nol: chunking, indexing, retrieval, dan generation yang grounded pada dokumen. Episode ini juga memandu pipeline PDF/website ke Q&A serta mengevaluasi kualitas retrieval (recall) dan kualitas jawaban terhadap dokumen sumber.

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

Pendahuluan

Setelah di episode 6 kalian menguasai embeddings dan vector databases, episode ini merangkai semuanya menjadi satu pipeline yang mengubah cara aplikasi AI bekerja: RAG (Retrieval-Augmented Generation). RAG adalah alasan mengapa aplikasi AI bisa menjawab pertanyaan tentang data internal perusahaan tanpa fine-tuning — dan pada 2026 ia sudah menjadi standar produksi, bukan sekadar teknik eksperimental.

Mengapa ini penting? Karena LLM polos punya dua masalah fatal di produksi: ia tidak tahu data privat kita, dan ia berhalusinasi. RAG menyelesaikan keduanya sekaligus: kita memberi model konteks yang relevan (dari dokumen kita), sehingga jawabannya grounded — bisa diverifikasi terhadap sumber.

Arsitektur RAG: Empat Tahap

100%

Empat tahapnya:

  1. Ingest: dokumen → chunk (potongan kecil) → embedding → vector index.
  2. Retrieval: query → embedding → ambil K chunk paling relevan.
  3. Augment: susun prompt konteks + pertanyaan.
  4. Generate: LLM menjawab hanya berdasarkan konteks, dengan kutipan sumber.

Tahap 1 dilakukan sekali (offline); tahap 2-4 terjadi setiap query.

Chunking: Memecah Dokumen dengan Benar

Chunking adalah langkah yang paling sering diremehkan, padahal menentukan segalanya. Chunk terlalu besar → top-K memuat banyak teks tidak relevan; chunk terlalu kecil → konteks terpotong.

Chunking sederhana berbasis karakter
def chunk_text(text, size=500, overlap=50):
    chunks = []
    start = 0
    while start < len(text):
        end = min(start + size, len(text))
        chunks.append(text[start:end])
        start = end - overlap
    return chunks
 
paragraphs = chunk_text(open("manual.txt").read())
print(len(paragraphs), "chunk", "contoh:", paragraphs[0][:80])

Kombinasi yang biasa dipakai di produksi:

  • Fixed-size dengan overlap: paling sederhana, cocok untuk teks umum.
  • Semantic chunking: pecah berdasarkan batas makna (paragraf, heading) — lebih akurat tapi lebih lambat.
  • Recursive / document-aware: hormati struktur markdown/PDF (heading, tabel) — detail di episode 8.

Aturan praktis: mulailah dengan 300-800 karakter + overlap 10-20%. Ukur hasilnya, jangan menebak.

Indexing: Simpan untuk Pencarian

Gunakan vector DB dari episode 6 — simpan chunk, embedding, dan metadata (sumber dokumen, halaman, judul bagian) sekaligus:

Indexing chunk ke ChromaDB
import chromadb
from openai import OpenAI
 
client = OpenAI()
vdb = chromadb.PersistentClient(path="./rag-db")
col = vdb.get_or_create_collection("manual")
 
ids, vectors, metas, texts = [], [], [], []
for i, chunk in enumerate(chunks):
    ids.append(f"chunk-{i}")
    vectors.append(client.embeddings.create(
        model="text-embedding-3-small", input=chunk).data[0].embedding)
    metas.append({"source": "manual.txt", "chunk": i})
    texts.append(chunk)
 
col.add(ids=ids, embeddings=vectors, metadatas=metas, documents=texts)

Metadata source dan chunk ini penting: nanti dipakai untuk citation — pengguna harus bisa melihat dari dokumen mana jawaban berasal.

Retrieval & Generation

Saat query masuk, kita ambil K chunk paling relevan lalu susun prompt yang memaksa model menjawab dari konteks:

Pipeline RAG lengkap
def ask_rag(question, k=4):
    qv = client.embeddings.create(
        model="text-embedding-3-small", input=question).data[0].embedding
 
    hits = col.query(query_embeddings=[qv], n_results=k)
    context = "\n\n---\n\n".join(
        f"[{m['source']} #{m['chunk']}]\n{d}"
        for d, m in zip(hits["documents"][0], hits["metadatas"][0])
    )
 
    resp = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system",
             "content": "Jawab HANYA berdasarkan konteks berikut. "
                        "Jika jawaban tidak ada di konteks, katakan "
                        "'Tidak ditemukan di dokumen'. Kutip sumber: [source #chunk]."},
            {"role": "user", "content": f"Konteks:\n{context}\n\nPertanyaan: {question}"},
        ],
    )
    return resp.choices[0].message.content
 
print(ask_rag("Bagaimana cara reset password?"))

Perhatikan dua elemen kunci di system prompt: batasan ("hanya berdasarkan konteks") dan citation ("kutip sumber"). Ini fondasi grounded answer — dan pencegah hallucination utama.

Warning

Jangan pernah mengabaikan evaluasi retrieval hanya karena jawaban "terlihat benar". Retrieval yang jelek menghasilkan jawaban yang terlihat meyakinkan tapi salah sumber. Selalu cek: apakah chunk yang diambil benar-benar memuat jawabannya? Evaluasinya di bagian berikut.

Evaluasi RAG: Retrieval & Kualitas Jawaban

Evaluasi Retrieval

Seberapa baik kita menemukan dokumen yang relevan? Dua metrik standar:

  • Recall@K: dari semua dokumen relevan yang ada, berapa proporsi yang berhasil diambil dalam K teratas. Recall rendah = jawaban berpotensi salah karena konteksnya kurang.
  • Precision@K: dari K yang diambil, berapa yang benar-benar relevan. Precision rendah = konteks penuh sampah.

Evaluasi Jawaban (Groundedness)

Apakah jawaban setia pada konteks? Dua istilah yang wajib dikenal:

  • Faithfulness: seberapa besar jawaban didukung oleh konteks yang diberikan (tidak berhalusinasi).
  • Answer relevance: seberapa tepat jawaban menjawab pertanyaan.

Cara praktis mengukurnya tanpa framework: minta LLM judge menilai (pola dari episode 4), atau cek manual dengan golden set kecil. Framework otomatis (RAGAS, DeepEval) kita pakai di episode 15.

Cek groundedness sederhana
judge = client.chat.completions.create(
    model="gpt-4o-mini",
    response_format={"type": "json_object"},
    messages=[{"role": "system",
               "content": "Nilai faithfulness jawaban terhadap konteks. "
                          "Skor 1-5 + daftar klaim yang tidak didukung konteks."},
              {"role": "user",
               "content": f"Konteks: {context}\nJawaban: {answer}"}],
)
print(judge.choices[0].message.content)

Common Pitfalls

  • Chunk tanpa metadata sumber: tidak bisa citation, sulit audit.
  • Meng-embed seluruh dokumen sebagai satu vektor: retrieval jadi tidak berguna — selalu chunk.
  • Prompt tidak membatasi pada konteks: model tetap bisa menambahkan "pengetahuan" dari luar, termasuk hallucination.
  • Tidak mengevaluasi: "jasa retrieval terasa bagus" bukan metrik. Ukur recall & faithfulness.

Penutup

Inti yang harus dibawa pulang:

  • RAG = chunking → indexing → retrieval → grounded generation, dan memberi konteks privat tanpa retrain.
  • Chunking menentukan kualitas; mulai dari 300-800 karakter + overlap.
  • System prompt RAG wajib: batasi pada konteks + minta citation.
  • Evaluasi dua lapis: retrieval (recall/precision) dan jawaban (faithfulness/relevance).

Di episode 8 selanjutnya kita akan mendalami RAG Lanjutan — strategi chunking tingkat lanjut, reranking, GraphRAG, parent-child document, plus multimodal RAG: image/table extraction, vision RAG, dan integrasi OCR. Sampai jumpa di episode 8!