RAG2026-5일36차시 · 평가 실습5 / 18← 이전목차다음 →MetaContents

36차시. 평가 실습

2. 실습 ① — 검색 평가

출처: 원본 PDF 36차시_평가실습.pdf 4쪽 · 쪽 그림 4쪽

LLM을 부르지 않으므로 비용이 0입니다. 몇 번이든 돌릴 수 있습니다.

📝 eval/retrieval.py

Python
import json
from nodes.retriever import retriever_node
def eval_retrieval(dataset, k=5):
    rows = []
    for d in dataset:
        if not d["answerable"]:
            continue                       # 부재 질문은 검색 평가 제외
        s = {"question": d["question"], "query": d["question"],
             "top_k": k}
        r = retriever_node(s)
        pages = [doc.metadata["page_no"] for doc in r["documents"]]
        # Hit — 정답 페이지가 하나라도 포함됐나
        hit = False
        for p in pages:
            if p in d["gold_pages"]:
                hit = True
                break
        # Rank — 정답이 몇 번째로 나왔나
        rank = 0
        for i, p in enumerate(pages, 1):
            if p in d["gold_pages"]:
                rank = i
                break
        rows.append({
            "id": d["id"], "type": d["type"],
            "difficulty": d["difficulty"],
            "hit": hit, "rank": rank,
            "rr": 1.0 / rank if rank else 0.0,
            "score": r["best_score"],
            "status": r["retrieval"],
            "found": pages, "gold": d["gold_pages"],
        })
    return rows
def summarize_retrieval(rows, k=5):
    n = len(rows)
    hit_rate = sum(r["hit"] for r in rows) / n
    mrr      = sum(r["rr"] for r in rows) / n
    print(f"■ 검색 평가 (n={n}, k={k})")
    print(f"   Hit Rate@{k} : {hit_rate*100:5.1f}%")
    print(f"   MRR         : {mrr:5.3f}")
    # 1위로 맞힌 개수, 아예 못 찾은 개수 세기
    rank1 = 0
    missed = 0
    for r in rows:
        if r["rank"] == 1:
            rank1 += 1
        if not r["hit"]:
            missed += 1
    print(f"   1위 정답     : {rank1}건")
    print(f"   미검출       : {missed}건")
    return {"hit_rate": hit_rate, "mrr": mrr}
if __name__ == "__main__":
    dev = json.load(open("data/eval_dev.json", encoding="utf-8"))
    rows = eval_retrieval(dev)
    summarize_retrieval(rows)
    print("\n■ 검색 실패 질문")
    for r in rows:
        if not r["hit"]:
            print(f"   {r['id']} [{r['difficulty']}] "
                  f"찾음{r['found']} 정답{r['gold']} "
                  f"점수{r['score']:.2f} ({r['status']})")
← 이전 절36차시 · 1. 오늘의 작업 순서다음 절 →36차시 · 3. 검색 평가 결과 읽기