LLM 평가 - 답변 품질을 어떻게 측정할까
프롬프트를 고치고, RAG를 붙이고, 모델을 바꿉니다. 그런데 정말 나아진 걸까요? 일반 소프트웨어라면 테스트가 초록불이면 됩니다. 하지만 LLM은 같은 질문에 매번 다른 문장으로 답하고, 정답도 하나가 아닙니다.
이 글에서는 왜 LLM 평가가 어려운지, 그리고 실무에서 품질을 수치로 관리하는 방법을 정리합니다.
1. 왜 평가가 어려운가
전통적인 테스트는 expected === actual 로 끝납니다. LLM은 그게 안 됩니다.
- 정답이 여럿이다. "환불 방법 알려줘"에 대한 좋은 답은 수십 가지 표현이 가능합니다. 문자열 일치로는 못 잡습니다.
- 비결정적이다. temperature가 0이 아니면 같은 입력에도 출력이 흔들립니다.
- 품질이 다차원이다. 정확성, 관련성, 완결성, 말투, 안전성, 형식 준수 — 하나만 봐선 안 됩니다.
- "그럴듯함"이 함정. 문장은 매끄러운데 사실은 틀린(할루시네이션) 답을 사람이 대충 보면 통과시키기 쉽습니다.
비유하자면, 객관식 채점이 아니라 논술 채점입니다. 채점 기준(루브릭)을 먼저 정하지 않으면 평가 자체가 흔들립니다.
2. 먼저 오프라인 평가셋을 만든다
개선의 출발점은 항상 고정된 평가셋(evaluation set) 입니다. "질문 – 기대 답변/근거 – 채점 기준"을 모아 둔 데이터입니다.
[평가 항목 예시]
question: "결제 취소는 며칠 안에 가능한가요?"
reference: "결제 후 7일 이내"
context: "환불 정책 문서 §3"
criteria: "7일이라는 숫자를 정확히 포함할 것"
- 실제 사용 로그에서 뽑는다. 상상한 질문이 아니라 진짜 들어온 질문이어야 의미가 있습니다.
- 엣지 케이스를 일부러 넣는다. 답할 수 없는 질문, 애매한 질문, 민감한 질문을 섞어야 안전성까지 봅니다.
- 작게 시작해도 된다. 50~100개만 잘 골라도 회귀를 잡는 데 충분합니다. 커버리지는 나중에 늘립니다.
이 평가셋이 곧 LLM판 테스트 스위트입니다.
3. 규칙 기반 평가
가능한 부분은 결정적 규칙으로 채점하는 게 가장 싸고 안정적입니다. LLM에 물어보기 전에 이걸로 걸러낼 수 있는 건 다 거릅니다.
def evaluate_rule_based(answer: str, item: dict) -> dict:
return {
# 반드시 포함해야 할 키워드
"has_keyword": item["reference"] in answer,
# JSON 형식을 지켰는가
"valid_json": is_valid_json(answer) if item["expect_json"] else True,
# 금칙어가 없는가
: (w answer w item[]),
: (answer) <= item[],
}