할루시네이션
Hallucination
LLM이 사실이 아닌 내용을 생성하는 현상. RAG, 검증 시스템으로 완화. AI 신뢰성의 핵심 과제.
Hallucination
LLM이 사실이 아닌 내용을 생성하는 현상. RAG, 검증 시스템으로 완화. AI 신뢰성의 핵심 과제.
할루시네이션(Hallucination, 환각)은 대규모 언어 모델(LLM)이 사실이 아닌 정보를 마치 사실인 것처럼 자신 있게 생성하는 현상입니다. 존재하지 않는 논문 인용, 허구의 역사적 사실, 잘못된 법률 조항 등이 대표적입니다. GPT-4, Claude, Gemini 같은 최신 모델에서도 완전히 해결되지 않았으며, AI 신뢰성과 안전성의 가장 큰 도전 과제 중 하나입니다.
할루시네이션이 발생하는 근본 원인은 LLM의 작동 방식에 있습니다. LLM은 학습 데이터에서 통계적 패턴을 학습해 "다음에 올 확률이 높은 토큰"을 예측합니다. 이 과정에서 사실 검증 없이 그럴듯한 텍스트를 생성합니다. 학습 데이터의 오류, 학습 데이터에 없는 정보 요청, 상충되는 정보의 잘못된 조합 등이 할루시네이션을 유발합니다. 특히 모델이 "모른다"고 말하기보다 답변을 생성하도록 학습되면 문제가 심화됩니다.
2024-2025년 현재 할루시네이션 완화를 위한 다양한 기법이 발전했습니다. RAG(검색 증강 생성)는 외부 지식 소스를 검색해 응답의 근거를 제공합니다. 자기 일관성 검사(Self-consistency)는 여러 번 생성 후 일치도를 확인합니다. 인용 생성은 출처를 명시하게 해 검증을 용이하게 합니다. Perplexity AI처럼 답변에 출처 링크를 자동 첨부하거나, Claude처럼 불확실할 때 명시적으로 표현하도록 학습된 모델도 있습니다.
실무에서 할루시네이션 관리는 AI 시스템 설계의 핵심입니다. 의료, 법률, 금융 같은 고위험 도메인에서는 인간 검토(Human-in-the-loop)가 필수입니다. 사실 관계가 중요한 작업에는 RAG를 적용하고, 출력에 신뢰도 점수를 부여하는 것이 좋습니다. 모델이 "잘 모르겠다"고 말할 수 있게 프롬프트를 설계하고, 할루시네이션 탐지 도구(Vectara, Galileo)를 파이프라인에 포함시키는 것도 권장됩니다.
할루시네이션 탐지 및 완화 기법을 구현한 예제입니다.
from openai import OpenAI
from anthropic import Anthropic
import json
from dataclasses import dataclass
from typing import Optional
import re
client = OpenAI()
anthropic = Anthropic()
@dataclass
class HallucinationCheckResult:
"""할루시네이션 검사 결과"""
is_grounded: bool # 근거가 있는지
confidence: float # 신뢰도 (0-1)
issues: list[str] # 발견된 문제점
citations: list[str] # 인용된 출처
# 1. 자기 일관성 검사 (Self-Consistency)
def check_self_consistency(prompt: str, n_samples: int = 5) -> dict:
"""동일 질문에 여러 번 답변 생성 후 일관성 확인"""
responses = []
for _ in range(n_samples):
response = client.chat.completions.create(
model="gpt-4-turbo",
messages=[{"role": "user", "content": prompt}],
temperature=0.7 # 다양성을 위해 temperature 사용
)
responses.append(response.choices[0].message.content)
# 일관성 분석
analysis = client.chat.completions.create(
model="gpt-4-turbo",
messages=[
{
"role": "system",
"content": """다음 여러 응답들의 일관성을 분석하세요.
JSON 형식으로 응답: {
"consistency_score": 0.0-1.0,
"consistent_facts": ["일관된 사실들"],
"inconsistent_facts": ["불일치하는 내용들"],
"recommended_answer": "가장 신뢰할 수 있는 답변"
}"""
},
{
"role": "user",
"content": f"원본 질문: {prompt}\n\n응답들:\n" +
"\n---\n".join(f"응답 {i+1}: {r}" for i, r in enumerate(responses))
}
],
response_format={"type": "json_object"}
)
return json.loads(analysis.choices[0].message.content)
# 2. RAG 기반 근거 검증
def verify_with_rag(
claim: str,
context_documents: list[str]
) -> HallucinationCheckResult:
"""RAG로 검색한 문서와 주장 대조"""
context = "\n\n".join(f"[문서 {i+1}] {doc}" for i, doc in enumerate(context_documents))
response = client.chat.completions.create(
model="gpt-4-turbo",
messages=[
{
"role": "system",
"content": """당신은 사실 검증 전문가입니다.
주어진 컨텍스트를 기반으로 주장의 정확성을 검증하세요.
JSON 형식으로 응답:
{
"is_grounded": true/false,
"confidence": 0.0-1.0,
"supporting_evidence": ["근거가 되는 문서 내용"],
"contradicting_evidence": ["반박되는 내용"],
"unverifiable_claims": ["검증 불가능한 주장"],
"verdict": "SUPPORTED/REFUTED/NOT_ENOUGH_INFO"
}"""
},
{
"role": "user",
"content": f"검증할 주장:\n{claim}\n\n참고 문서:\n{context}"
}
],
response_format={"type": "json_object"}
)
result = json.loads(response.choices[0].message.content)
return HallucinationCheckResult(
is_grounded=result["is_grounded"],
confidence=result["confidence"],
issues=result.get("contradicting_evidence", []) + result.get("unverifiable_claims", []),
citations=result.get("supporting_evidence", [])
)
# 3. 할루시네이션 방지 프롬프트
def generate_with_uncertainty(query: str) -> dict:
"""불확실성을 표현하도록 유도하는 생성"""
response = anthropic.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=2000,
system="""당신은 정확성을 최우선으로 하는 AI 어시스턴트입니다.
다음 규칙을 반드시 따르세요:
1. 확실하지 않은 정보는 "~로 알고 있습니다", "~일 수 있습니다"로 표현
2. 모르는 것은 솔직히 "이 정보는 확인이 필요합니다"라고 말씀
3. 숫자, 날짜, 인용은 특히 신중하게 - 불확실하면 생략
4. 가능하면 검증 가능한 출처 언급
5. 추측과 사실을 명확히 구분
응답 마지막에 [신뢰도: 높음/중간/낮음]을 표시하세요.""",
messages=[{"role": "user", "content": query}]
)
text = response.content[0].text
# 신뢰도 추출
confidence_match = re.search(r'\[신뢰도:\s*(높음|중간|낮음)\]', text)
confidence = confidence_match.group(1) if confidence_match else "중간"
return {
"response": text,
"confidence": confidence,
"has_uncertainty_markers": any(
marker in text for marker in
["~로 알고 있습니다", "~일 수 있습니다", "확인이 필요", "불확실"]
)
}
# 4. 인용 기반 응답 생성
def generate_with_citations(
query: str,
sources: list[dict] # [{"title": "...", "content": "...", "url": "..."}]
) -> dict:
"""출처를 인용하는 응답 생성"""
sources_text = "\n\n".join(
f"[출처 {i+1}] {s['title']}\n{s['content']}"
for i, s in enumerate(sources)
)
response = client.chat.completions.create(
model="gpt-4-turbo",
messages=[
{
"role": "system",
"content": """주어진 출처만을 사용해 질문에 답변하세요.
규칙:
1. 각 주장 뒤에 [출처 N] 형식으로 인용
2. 출처에 없는 정보는 "해당 출처에서 확인되지 않음"으로 표시
3. 여러 출처를 종합할 때 [출처 1, 3] 형식 사용
4. 출처 간 정보가 다르면 양쪽 모두 언급"""
},
{
"role": "user",
"content": f"질문: {query}\n\n{sources_text}"
}
]
)
answer = response.choices[0].message.content
# 인용 추출
citations = re.findall(r'\[출처 (\d+(?:,\s*\d+)*)\]', answer)
return {
"answer": answer,
"citations_used": list(set(
int(c) for citation in citations
for c in re.findall(r'\d+', citation)
)),
"all_sources_cited": len(citations) > 0
}
# 사용 예시
if __name__ == "__main__":
# 자기 일관성 검사
print("=== 자기 일관성 검사 ===")
result = check_self_consistency("대한민국의 수도는 언제 서울로 정해졌나요?")
print(f"일관성 점수: {result['consistency_score']}")
# 불확실성 표현 생성
print("\n=== 불확실성 표현 생성 ===")
response = generate_with_uncertainty("GPT-5는 언제 출시되나요?")
print(f"신뢰도: {response['confidence']}")
print(f"불확실성 표현 포함: {response['has_uncertainty_markers']}")
| 기법 | 효과 | 비용 | 적용 난이도 |
|---|---|---|---|
| RAG (검색 증강 생성) | 높음 | 중간 | 중간 |
| Self-Consistency | 중간 | 높음 (N배 호출) | 쉬움 |
| 인용/출처 강제 | 중간 | 낮음 | 쉬움 |
| Human-in-the-loop | 매우 높음 | 매우 높음 | 어려움 |
| Fine-tuning (RLHF) | 높음 | 매우 높음 | 매우 어려움 |
아무리 최신 모델이라도 할루시네이션이 발생합니다. 숫자, 날짜, 인용, 법률/의료 정보는 반드시 별도 검증하세요. 모델의 자신감 있는 어조에 속지 마세요.
RAG도 잘못된 문서를 검색하거나, 문서 내용을 잘못 해석할 수 있습니다. 검색 품질과 함께 답변-문서 일치도를 함께 확인하는 파이프라인이 필요합니다.
RAG + 인용 강제 + 불확실성 표현 + 탐지 모델 + 선택적 인간 검토를 조합하세요. 단일 기법보다 여러 기법을 함께 쓰면 할루시네이션을 효과적으로 줄일 수 있습니다.