Evaluasi RAG
Setiap keputusan di dua materi sebelumnya — ukuran chunk, hybrid search, reranking — punya banyak variasi yang bisa dicoba. Tanpa metrik yang jelas, menyetelnya jadi trial-and-error tanpa arah.
Intisari
- Evaluasi RAG mengukur dua bagian terpisah: kualitas retrieval (apakah chunk yang ditemukan memang relevan?) dan kualitas generasi (apakah jawaban akhir akurat & berdasarkan chunk itu?).
- Retrieval diukur dengan precision (dari yang diambil, berapa persen relevan) dan recall (dari semua yang relevan, berapa persen berhasil diambil) — butuh dataset uji dengan jawaban benar yang sudah diketahui.
- Faithfulness (kesetiaan) mengukur apakah jawaban model benar-benar didukung oleh konteks yang diambil, bukan mengarang di luar itu — inti dari mendeteksi halusinasi pada RAG.
- Karena jawaban LLM berbentuk teks bebas, banyak metrik ini diukur dengan LLM-as-judge: memakai model (kadang model lain) untuk menilai apakah jawaban faithful/relevan, dengan prompt penilaian yang jelas kriterianya.
- Bangun dataset evaluasi tetap (kumpulan pertanyaan + jawaban ideal) sejak awal — ini yang membuat perubahan ke pipeline RAG bisa dibandingkan sebelum/sesudah secara objektif, bukan sekadar 'terasa lebih baik'.
Dua bagian yang harus dievaluasi terpisah
Jawaban RAG yang buruk bisa berasal dari dua sumber berbeda, dan penting membedakannya supaya tahu bagian mana yang harus diperbaiki:
| Bagian | Pertanyaan yang dijawab | Kalau buruk, artinya |
|---|---|---|
| Retrieval | Apakah chunk yang ditemukan memang relevan dengan pertanyaan? | Perbaiki chunking, embedding model, atau strategi pencarian (materi sebelumnya) |
| Generation | Apakah jawaban akhir akurat & benar-benar berdasarkan chunk yang diberikan? | Perbaiki prompt, atau model tetap berhalusinasi meski konteksnya sudah benar |
Mengukur retrieval: precision & recall
Untuk mengukur retrieval, kamu butuh dataset uji: kumpulan pertanyaan beserta chunk mana saja yang seharusnya ditemukan (ground truth), biasanya disusun manual dari sampel nyata.
dataset_uji = [
{
"pertanyaan": "Berapa lama cuti melahirkan?",
"chunk_relevan_id": ["kebijakan-cuti-3", "kebijakan-cuti-4"], # ground truth, disusun manual
},
# ...
]
def evaluasi_retrieval(dataset, k=5):
precisions, recalls = [], []
for kasus in dataset:
ditemukan = cari_dokumen_mirip(kasus["pertanyaan"], k=k)
id_ditemukan = {c["id"] for c in ditemukan}
id_relevan = set(kasus["chunk_relevan_id"])
benar = id_ditemukan & id_relevan
precisions.append(len(benar) / len(id_ditemukan) if id_ditemukan else 0)
recalls.append(len(benar) / len(id_relevan) if id_relevan else 0)
return {"precision": sum(precisions) / len(precisions), "recall": sum(recalls) / len(recalls)}
| Metrik | Artinya |
|---|---|
| Precision | Dari chunk yang diambil, berapa persen yang benar-benar relevan (sedikit "sampah" ikut terambil) |
| Recall | Dari semua chunk yang seharusnya relevan, berapa persen berhasil ditemukan (tidak ada yang "terlewat") |
Mengukur generation: faithfulness dengan LLM-as-judge
Karena jawaban akhir berbentuk teks bebas (bukan angka yang mudah dibandingkan), pendekatan yang paling praktis adalah memakai LLM sendiri sebagai "juri" — memberi model prompt penilaian yang jelas kriterianya.
def nilai_faithfulness(pertanyaan: str, konteks: str, jawaban: str) -> dict:
prompt = f"""Nilai apakah JAWABAN berikut didukung sepenuhnya oleh KONTEKS yang diberikan.
Jawab dengan JSON: {{"faithful": true/false, "alasan": "..."}}
<konteks>{konteks}</konteks>
<pertanyaan>{pertanyaan}</pertanyaan>
<jawaban>{jawaban}</jawaban>
Faithful = SEMUA klaim di jawaban bisa ditelusuri ke konteks. Kalau jawaban menambahkan
informasi yang tidak ada di konteks, itu TIDAK faithful — meskipun informasinya kebetulan benar."""
hasil = client.messages.create(
model="claude-sonnet-4-5", max_tokens=300, temperature=0,
messages=[{"role": "user", "content": prompt}],
)
return json.loads(hasil.content[0].text)
LLM-as-judge bukan tanpa cela — model penilai juga bisa salah, dan idealnya divalidasi sesekali dengan penilaian manusia untuk memastikan skornya masuk akal. Tapi untuk mengukur tren ("apakah perubahan prompt ini memperbaiki atau memperburuk faithfulness secara rata-rata?") lewat dataset uji yang besar, ini jauh lebih praktis daripada meninjau setiap jawaban secara manual.
Bangun dataset evaluasi sejak awal
Nilai sebenarnya dari metrik-metrik ini muncul saat dipakai untuk membandingkan versi — sebelum dan sesudah mengubah ukuran chunk, menambah reranking, atau mengganti model embedding. Tanpa dataset uji tetap, setiap perubahan jadi "terasa lebih baik" yang subjektif dan tidak bisa diulang.
Latihan: buat dataset uji berisi 5 pertanyaan dari dokumen yang kamu pakai di latihan materi
sebelumnya, lengkap dengan ground truth chunk yang relevan. Jalankan evaluasi_retrieval
dengan ukuran chunk 300 kata, lalu ulangi dengan ukuran chunk 700 kata — bandingkan precision &
recall-nya, dan tentukan mana yang lebih baik untuk dokumenmu.
Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.