들어가기전에..

타짜에 이런 명대사가 있습니다.
"구라를 치려고 마음을 먹었을 땐 상대방 눈을 쳐다보지마라"
우리가 즐겨쓰는 LLM은 이 말을 모르는 것 같습니다. 틀린 말을 할 때도 눈 하나 깜짝하지 않거든요.
지금까지 RAG 시스템을 구성하는 여러 요소를 다뤘습니다. 문서를 어떻게 청킹할지, 데이터를 어떻게 정제할지, 검색을 어떻게 개선할지, 등등을 말이죠. 그럼에도 불구하고 이 모든 노력을 기울여도 결국 남는 질문이 있습니다.
'LLM이 생성한 답변을 얼마나 믿을 수 있을까?'
LLM은 그럴듯하게 들리지만 틀린 내용을 자신 있게 말하는 경향이 있습니다. 이것이 그 유명한 Hallucination(환각)입니다.
RAG가 이 문제를 완화해주지만 완전히 해결하지는 못합니다. 검색된 문서가 있어도 LLM이 그 내용을 벗어난 답변을 생성할 수 있고, 사용자는 그 답변이 신뢰할 수 있는지 판단하기 어렵습니다.
이번 글에서는 LLM 신뢰성을 다루는 세 가지 접근을 정리해보고자 합니다.
RAG 시스템을 평가하는 RAGAS 프레임워크, 신뢰성을 높이는 프롬프트 패턴, 그리고 Hallucination을 감지하는 SelfCheckGPT를 정리해보겠습니다!
RAGAS — RAG 시스템을 어떻게 평가할까?
평가가 왜 어려운가?
RAG 시스템을 만들었을 때 '잘 동작하고 있는가'를 어떻게 확인할 수 있을까요?
가장 쉬운 방법은 직접 질문해보고 답변이 좋아 보이면 된다고 생각하는 것입니다. 하지만 이 방식은 몇 가지 문제가 있습니다.
답변이 '좋아 보인다'는 것은 어디까지나 주관적입니다. 그리고 RAG 파이프라인에는 여러 단계가 있는데 어느 단계가 문제인지 알기 어렵습니다. 검색이 잘못된 문서를 가져온 건지 아니면 좋은 문서를 가져왔는데 LLM이 잘못 활용한 건지를 구분해야 개선 방향을 잡을 수 있습니다.
기존의 BLEU, ROUGE 같은 텍스트 유사도 지표는 RAG에 적합하지 않습니다. 정답이 하나가 아닌 경우가 많고 표현이 달라도 의미가 같을 수 있는데 이를 포착하지 못합니다.
RAGAS의 접근
RAGAS(Retrieval Augmented Generation Assessment)는 2023년 발표된 RAG 전용 평가 프레임워크입니다.
핵심 철학은 정답 레이블 없이도 평가할 수 있어야 한다는 것입니다. 실제 서비스에서 모든 질문에 정답을 달아두기는 현실적으로 불가능하기 때문입니다.
RAGAS는 RAG 파이프라인을 두 축으로 평가합니다.
검색(Retrieval) 품질 평가
- Context Precision: 검색된 문서들이 실제로 답변에 필요한 내용을 담고 있는가?
- Context Recall: 답변에 필요한 내용이 검색된 문서에 빠짐없이 포함되어 있는가?
생성(Generation) 품질 평가
- Faithfulness: 생성된 답변이 검색된 문서의 내용에 근거하고 있는가?
- Answer Relevancy: 생성된 답변이 원래 질문에 얼마나 적절한가?
Faithfulness vs Answer Relevancy
이 두 지표가 가장 핵심적이므로 차이를 명확히 이해하는 것이 중요합니다.
Faithfulness(충실성) 는 답변이 검색된 문서를 얼마나 충실히 반영하는지를 측정합니다.
계산 방식은 이렇습니다. 답변에서 개별 주장(claim)을 추출한 뒤 각 주장이 검색된 문서에서 추론 가능한지 확인하죠.
Faithfulness = 문서로 뒷받침되는 주장 수 / 전체 주장 수
예를 들어 답변에 세 가지 주장이 있는데 두 가지만 문서에 근거가 있다면 Faithfulness는 2/3 ≈ 0.67입니다.
나머지 하나는 LLM이 자체적으로 만들어낸 내용, 즉 Hallucination일 가능성이 있습니다.
Answer Relevancy(답변 관련성) 는 답변이 질문에 얼마나 잘 대응하는지를 측정합니다. 계산 방식이 독특하죠?
먼저 생성된 답변을 거꾸로 보고 '이 답변이 나올 만한 질문은 무엇일까'를 LLM에게 여러 개 생성하게 한 뒤 그 역생성 질문들이 원래 질문과 얼마나 유사한지를 임베딩 코사인 유사도로 계산합니다.
Answer Relevancy = mean(cosine_similarity(원래 질문, 역생성 질문들))
직관적으로 답변이 질문에 정확히 대응했다면 그 답변으로부터 역으로 추론한 질문도 원래 질문과 비슷해야 합니다.
답변이 질문과 무관하거나 불완전하다면 역생성 질문이 원래 질문과 멀어집니다.
여기까지해서 두 지표의 조합이 중요한 이유를 표로 정리해보겠습니다.
| Faithfulness 높음 | Faithfulness 낮음 | |
| Relevancy 높음 | 이상 | 관련은 있지만 문서 근거 없음 |
| Relevancy 낮음 | 문서 기반이지만 질문에 안 맞음 | 최악 |
Faithfulness가 낮다면 LLM이 Hallucination을 하고 있다는 신호입니다. Relevancy가 낮다면 검색이 잘못된 문서를 가져오고 있거나 LLM이 핵심을 빗나간 답변을 하고 있다는 신호가 되는 것이죠. 이 두 지표를 함께 보면 파이프라인의 어느 단계에 문제가 있는지 진단할 수 있습니다.
코드로 살펴볼까요?
from ragas import evaluate
from ragas.metrics import Faithfulness, ResponseRelevancy, ContextPrecision
# 평가 데이터셋 구성
from datasets import Dataset
data = {
"user_input": ["RAG가 무엇인가요?"],
"response": ["RAG는 검색 증강 생성으로, 외부 문서를 검색해 LLM 답변에 활용합니다."],
"retrieved_contexts": [["RAG는 Retrieval-Augmented Generation의 약자입니다..."]],
}
dataset = Dataset.from_dict(data)
# 평가 실행
result = evaluate(
dataset=dataset,
metrics=[
Faithfulness(),
ResponseRelevancy(),
ContextPrecision(),
]
)
print(result)
# {'faithfulness': 0.92, 'response_relevancy': 0.87, 'context_precision': 0.95}
RAGAS는 평가 자체에도 LLM을 사용합니다. 기본값은 GPT-4이지만 다른 모델로 교체할 수도 있죠.
평가 비용이 발생하므로 전체 데이터가 아닌 샘플링으로 주기적으로 측정하는 패턴을 권장합니다.
프롬프트 설계만으로 Hallucination을 줄일 수 있을까?
RAGAS가 사후 평가 도구라면 프롬프트 설계는 사전 예방에 해당합니다. 잘 설계된 프롬프트는 LLM이 Hallucination을 덜 하게 만들고, 답변의 근거를 명확히 남기게 합니다.
Chain-of-Thought(CoT) 프롬프팅
CoT는 LLM에게 최종 답변 이전에 추론 과정을 먼저 쓰도록 유도하는 방식입니다.
쉽게 말해서 '생각하면서 답하라'는 지시입니다.
prompt = """다음 문서들을 바탕으로 질문에 답하세요.
[문서]
{context}
[질문]
{question}
답변 전에 다음 단계를 따르세요:
1. 질문과 관련된 문서의 핵심 내용을 정리하세요.
2. 각 문서가 질문에 어떻게 관련되는지 분석하세요.
3. 분석을 바탕으로 최종 답변을 작성하세요.
[추론 과정]
(여기에 단계별 추론을 작성)
[최종 답변]
(여기에 답변 작성)
"""
CoT가 신뢰성을 높이는 이유는 두 가지입니다.
첫째로 추론 과정을 명시적으로 작성하게 하면 LLM이 자신이 무엇을 알고 모르는지를 더 정확히 인식하는 경향이 있습니다.
둘째로 추론 과정이 남아 있어서 답변이 어떤 근거에서 나왔는지 사람이 확인할 수 있습니다.
Source Citation(출처 인용) 패턴
검색된 문서를 번호로 식별하고, 답변의 각 문장이 어느 문서에서 나왔는지 명시하도록 강제하는 방식입니다.
prompt = """다음 문서들을 참고하여 질문에 답하세요.
[문서 1]: {doc1}
[문서 2]: {doc2}
[문서 3]: {doc3}
[규칙]
- 답변의 모든 주장은 반드시 위 문서에 근거해야 합니다.
- 각 주장 뒤에 출처를 [문서 N] 형식으로 표시하세요.
- 문서에 없는 내용은 '문서에서 확인되지 않습니다'라고 명시하세요.
- 문서들이 서로 상충되는 경우 그 사실을 언급하세요.
[질문]: {question}
[답변]:
"""
이 패턴의 핵심은 LLM이 문서에 없는 내용을 생성하기 어렵게 만드는 것입니다. 출처를 명시해야 하는 규칙이 있으면 출처 없는 주장을 만들기 위한 심리적 장벽이 생길 뿐만 아니라 사용자가 답변을 받았을 때 [문서 2]를 직접 확인해볼 수 있어 투명성이 높아집니다.
CoT + Citation 결합 패턴
두 기법을 결합하면 더 강력한 효과를 얻을 수 있습니다.
system_prompt = """당신은 주어진 문서만을 근거로 답변하는 전문 어시스턴트입니다.
답변 형식:
1. [추론] 관련 문서를 분석하고 핵심 내용을 정리합니다.
2. [답변] 분석을 바탕으로 답변하되, 각 주장에 출처를 명시합니다.
3. [한계] 문서에서 확인되지 않는 내용이 있다면 명시합니다.
중요: 문서에 없는 내용을 추측하거나 생성하지 마세요."""
[한계] 섹션을 추가하는 것이 특히 중요합니다. LLM이 모든 질문에 답하려는 경향이 있는데 모른다고 명시할 공간을 만들어주면 Hallucination이 줄어듭니다.
같은 말을 반복 못 하면 거짓말이다
평가 프레임워크와 프롬프트 패턴으로도 Hallucination을 완전히 막을 수는 없습니다. 그렇다면 이미 생성된 답변이 Hallucination인지 아닌지를 어떻게 감지할 수 있을까요?
외부 데이터베이스로 사실 검증을 하자니 모든 도메인에 적용하기 어렵고, 모델 내부의 확률값을 보자니 GPT-4 같은 API 기반 블랙박스 모델에는 접근할 수 없습니다.
그래서 이 문제를 단순하면서도 영리한 방식으로 푼 것이 SelfCheckGPT(Manakul et al., 2023, Cambridge)입니다.
SelfCheckGPT의 아이디어는 이렇습니다.
LLM이 어떤 사실을 정말 알고 있다면 같은 질문을 여러 번 해도 일관된 답변을 할 것이다.
반대로 Hallucination이라면 매번 다른 내용을 생성할 것이다.
예를 들어볼까요? 만약'아인슈타인의 생년월일을 묻는다면 LLM이 이 사실을 학습 데이터에서 충분히 본 경우 여러 번 물어도 '1879년 3월 14일'이라고 일관되게 답할 것입니다.
하지만 존재하지 않는 논문의 저자를 지어내는 경우라면요? 학습 데이터에 근거가 없기 때문에 매번 다른 이름을 생성할 가능성이 높습니다. 즉 일관성이 없다는 것 자체가 Hallucination의 신호가 되는 것이죠.
동작 방식
1단계: 원래 질문으로 답변 생성
질문 → [답변 R0]
2단계: 같은 질문을 N번 더 샘플링 (temperature > 0)
질문 → [샘플 S1]
질문 → [샘플 S2]
질문 → [샘플 S3]
3단계: 원래 답변의 각 문장이
샘플들과 얼마나 일관성 있는지 측정
문장 A ↔ S1, S2, S3 → 일관성 높음 → 사실일 가능성 높음
문장 B ↔ S1, S2, S3 → 일관성 낮음 → Hallucination 의심
일관성을 측정하는 방법으로 논문에서는 여러 변형을 제안합니다. BERTScore로 문장 유사도를 측정하거나 NLI(자연어 추론) 모델로 모순 여부를 판단하거나 LLM에게 직접 '이 문장이 아래 내용과 일치하는가?'를 물어보는 방식입니다.
논문에 따르면 LLM 프롬프팅 방식이 가장 성능이 좋았습니다.
코드로 살펴보죠!
from selfcheckgpt.modeling_selfcheck import SelfCheckNLI
import torch
# NLI 기반 SelfCheckGPT 초기화
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
selfcheck_nli = SelfCheckNLI(device=device)
# 원래 답변의 문장들
sentences = [
"아인슈타인은 1879년 3월 14일에 태어났습니다.",
"그는 1921년 노벨 물리학상을 수상했습니다.",
"그의 대표 저서는 '시간의 역사'입니다.", # 이건 호킹의 책
]
# 같은 질문으로 추가 샘플링한 응답들
sample1 = "아인슈타인은 독일 태생의 물리학자로 상대성 이론으로 유명합니다..."
sample2 = "알베르트 아인슈타인은 1879년에 태어나 광전 효과 연구로..."
sample3 = "아인슈타인은 1879년 3월에 출생했으며 1921년 노벨상을..."
# 각 문장의 Hallucination 점수 계산 (높을수록 Hallucination 가능성 높음)
scores = selfcheck_nli.predict(
sentences=sentences,
sampled_passages=[sample1, sample2, sample3],
)
print(scores)
# [0.05, 0.08, 0.89] ← 세 번째 문장이 Hallucination 의심
세 번째 문장('시간의 역사'는 호킹의 책)은 샘플들과 일관성이 낮아 높은 점수가 나옵니다.
SelfCheckGPT의 장단점
장점으로는 외부 데이터베이스나 모델 가중치 접근 없이도 동작한다는 점입니다. API로만 제공되는 블랙박스 모델(GPT-4 등)에도 적용할 수 있습니다. 어떤 도메인이든 사용 가능한 범용적인 접근이죠.
단점으로는 LLM을 N+1번 호출해야 합니다. 원래 답변 1회 + 샘플링 N회입니다. 논문에서는 N=20을 사용했지만 실험 결과 N=3~5로도 충분히 의미 있는 결과를 얻을 수 있었습니다. 그럼에도 불구하고 비용이 상당히 증가합니다.
그리고 근본적인 한계가 있습니다. LLM이 특정 잘못된 사실을 학습 데이터에서 반복적으로 봤다면 잘못된 내용임에도 일관되게 생성할 수 있습니다. 이 경우 SelfCheckGPT는 그것을 사실로 판단하게 됩니다. 일관성이 곧 정확성은 아닙니다.
정리
| 접근 | 언제 쓸까? | 핵심 |
| RAGAS | 파이프라인 품질 측정 및 개선 방향 파악 | Faithfulness + Relevancy로 어느 단계가 문제인지 진단 |
| CoT + Citation | 답변 생성 시 신뢰성 향상 | 프롬프트로 LLM이 문서 밖을 나가지 못하게 제약 |
| SelfCheckGPT | 생성된 답변의 Hallucination 감지 | 일관성으로 Hallucination 의심 문장 탐지 |
각자 파이프라인의 서로 다른 지점을 커버하고 있는 모습을 보여주고 있죠?
CoT + Citation으로 Hallucination을 줄이고, SelfCheckGPT로 남은 Hallucination을 감지하고, RAGAS로 전체 파이프라인이 얼마나 잘 동작하는지 주기적으로 측정하는 식으로 함께 쓰는 것이 좋습니다.
마치며
글 맨앞에서 타짜의 명대사를 언급하며 AI는 눈 하나 깜짝하지 않고 거짓말을 한다고 말씀드렸습니다.
타짜의 그 말처럼 거짓말치는 사람은 눈을 보면 들킵니다. 그런데 눈도 없는 AI의 거짓말은 어떻게 판별할까요?
저는 그것을 판별할 수 있는 건 그 분야의 지식뿐이라고 생각합니다. (이 부분을 말하고 싶어 타짜의 명대사를 써보았습니다.)
설령 RAGAS가 Faithfulness 점수를 0.3이라고 알려줘도 그 답변이 얼마나 위험한 오류인지는 도메인 전문가만 알 수밖에 없습니다. 뿐만 아니라 SelfCheckGPT가 특정 문장을 Hallucination으로 의심해도 실제로 틀린 건지 아닌지는 그 주제를 아는 사람이 판단해야 합니다. 도구는 의심스러운 부분을 좁혀줄 수 있지만 최종 판단은 사람의 지식에서 나옵니다.
RAG 시스템을 만드는 것과 그 시스템이 내놓는 답변을 신뢰할 수 있는지 판단하는 것은 다른 역량입니다.
전자는 기술로 해결할 수 있겠지만 후자는 결국 그 분야를 아는 사람이 있어야 합니다. 아무리 좋은 도구를 쌓아도 내용을 모르면 AI의 거짓말을 알아챌 수 없습니다.
LLM은 아직 틀린 말을 자신 있게 합니다. 이 문제를 완전히 해결한 방법은 없죠.
하지만 RAGAS로 어디서 문제가 생기는지 측정하고, 프롬프트로 Hallucination을 줄이고, SelfCheckGPT로 의심스러운 답변을 걸러내는 레이어를 쌓으면 신뢰할 수 있는 시스템에 한 걸음 더 가까워질 수 있습니다.
신뢰할 수 없는 답변은 아무리 빠르고 정확하게 검색해도 의미가 없습니다.
참고 자료
'AI' 카테고리의 다른 글
| [바미] RAG도 쓸수록 좋아질 수 있을까? (2) | 2026.04.01 |
|---|---|
| [바미] 텍스트가 아닌 정보를 RAG는 어떻게 읽을까? (2) | 2026.03.31 |
| [바미] 구글도 키워드 검색을 버리지 않은 이유 (하이브리드 검색과 RAG-Fusion) (0) | 2026.03.29 |
| [바미] 내가 크롤링한 결과물이 쓰레기가 되는 이유 (2) | 2026.03.28 |
| [바미] 어떻게 자르느냐가 검색 품질을 결정한다. (0) | 2026.03.27 |