LLM 프롬프트가 실패하는 이유: 무관한 정보가 성능을 35% 떨어뜨린다?
완벽하게 설계했다고 자부한 프롬프트가 실전에서 엉뚱한 대답을 내놓아 당황하신 적 있나요?
특히 RAG(검색 증강 생성) 시스템을 운영하다 보면, 검색된 문서에 섞여 들어온 ‘관련 없는 정보(Irrelevant Context)’ 하나 때문에 전체 답변 논리가 모래성처럼 무너지는 광경을 자주 보게 됩니다.
“요즘 AI가 얼마나 똑똑한데, 그깟 노이즈 하나 구분 못 할까?”라고 생각하실 수도 있습니다. 하지만 Google DeepMind 연구진의 최신 연구에 따르면, 현재 최첨단 LLM들은 우리가 믿는 것보다 훨씬 더 ‘주의 산만(Distractibility)’에 취약합니다.
오늘은 Google DeepMind의 최신 논문을 바탕으로, 왜 프롬프트가 실패하는지 분석하고 이를 즉각 해결할 수 있는 확실한 카드를 소개해 드리겠습니다.
📉 95점짜리 우등생이 60점짜리 낙제생이 되는 과정
데이터로 팩트 체크부터 해보죠. 연구진은 초등 수학 문제(GSM8K)에 문제와 전혀 상관없는 문장 하나를 슬쩍 끼워 넣은 GSM-IC 데이터셋을 만들었습니다.
비교 예시
- 정상 문제: 철수는 사과 5개가 있고, 영희는 철수보다 2개 더 많습니다. 둘이 합쳐 몇 개일까요?
- 노이즈 문제: 철수는 사과 5개가 있고, 영희는 철수보다 2개 더 많습니다. 철수 아빠는 어제 마트에서 감자를 샀습니다. 둘이 합쳐 몇 개일까요?
사람이라면 “감자 산 게 뭐가 중요해?” 하고 무시하겠죠. 하지만 LLM은 다릅니다.
연구 결과, code-davinci-002 모델에 CoT(Chain-of-Thought) 기법을 썼을 때 원래 95%였던 정답률이, 저 문장 하나 때문에 60%대로 수직 하락했습니다. GPT-3.5 역시 노이즈가 섞이자마자 성능이 급격히 저하됐고요. 우리의 LLM 파이프라인이 생각보다 훨씬 ‘유리 멘탈’이라는 증거입니다.
🔍 실패의 해부: 똑똑한 CoT가 함정에 빠지는 법
“생각의 사슬(CoT)로 차근차근 추론하게 하면 괜찮지 않나요?”라고 물으실 수 있습니다. 안타깝게도, 오히려 그 ‘성실한 추론’이 독이 되기도 합니다. 논문에 나온 ‘비누 구매 예시’를 보면 실체가 명확해집니다.
문제 상황
- Maria는 2달에 한 번씩 비누를 $8에 삽니다.
- [방해 문장]: 10달마다 Maria의 이웃은 샴푸를 삽니다.
- [질문]: Maria가 1년 동안 비누에 쓰는 돈은 얼마일까요?
정상적인 사고라면 ‘이웃’과 ‘샴푸’는 필터링해야 합니다. 하지만 모델의 사고 회로를 뜯어보면 이렇습니다.
🤖 모델의 오답 로그
- 비누는 2달마다 $8입니다.
- (방해 문장을 읽고) 10달마다 이웃이 샴푸를 사는군요…
- [논리 붕괴]: 1년은 12달이니까… $8에 12를 곱해서 $96입니다. (정답은 $48)
심지어 더 고도화된 기법(LTM)을 써도, 방해 문장에 나온 숫자 ’10’을 어떻게든 계산식에 쑤셔 넣어 $960라는 황당한 답을 내놓기도 합니다. LLM은 주어진 모든 정보를 “어떻게든 써먹어야 할 소중한 힌트”로 오해하는 경향이 있기 때문입니다.
✅ 해결책: 다수결의 힘, Self-Consistency (자기 일관성)
그럼 이 산만한 AI를 어떻게 바로잡아야 할까요? 가장 확실한 해결책은 ‘자기 일관성(Self-Consistency)’ 전략입니다.
쉽게 말해, 모델에게 한 번만 묻고 끝내는 게 아니라 똑같은 질문을 여러 번 던진 뒤, 가장 많이 나온 답을 선택하는 ‘다수결 원칙’을 적용하는 것입니다.
연구 결과는 드라마틱합니다.
- CoT + Self-Consistency: 정확도가 다시 96%로 회복되었습니다.
- 20번의 답변 중 최소 하나 이상 정답이 포함될 확률은 99.7%에 달했습니다.
LLM이 한두 번은 헛소리를 할 수 있어도, 여러 번 반복해서 생각하게 하면 결국 “아, 아까 그 감자 이야기는 쓸데없는 정보였네”라고 스스로 노이즈를 걸러낼 확률이 비약적으로 높아진다는 것이죠.
💻 실전 적용: Python 예시 코드
from openai import OpenAI
from collections import Counter
import re
def solve_with_self_consistency(prompt, n=20):
"""
Self-Consistency를 적용하여 LLM의 주의 산만을 방지합니다.
Args:
prompt (str): 수학 문제 텍스트
n (int): 생성할 답변 개수 (논문 권장: 20개)
Returns:
str: 다수결로 선정된 최종 답안
"""
client = OpenAI() # OPENAI_API_KEY는 환경 변수로 설정되어 있어야 합니다.
answers = []
# Step 1: 동일한 문제를 n번 독립적으로 풀게 함
for _ in range(n):
response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "초등 수학 문제를 푸는 논리적인 도우미입니다."},
{"role": "user", "content": prompt}
],
temperature=0.7 # 다양한 추론 경로 탐색
)
answers.append(response.choices[0].message.content)
# Step 2: 각 답변에서 최종 숫자만 추출
final_numbers = []
for answer in answers:
# 예: "The answer is 48" 형태에서 숫자만 추출
match = re.search(r'answer is (\d+)', answer, re.IGNORECASE)
if match:
final_numbers.append(match.group(1))
# Step 3: 다수결 투표로 최종 답 결정
if final_numbers:
vote_count = Counter(final_numbers)
winner = vote_count.most_common(1)[0][0]
return winner
return None # 정답을 추출하지 못한 경우
# 사용 예시
if __name__ == "__main__":
problem = """
철수는 사과 5개가 있고, 영희는 철수보다 2개 더 많습니다.
철수 아빠는 어제 마트에서 감자를 샀습니다.
둘이 합쳐 몇 개일까요?
"""
answer = solve_with_self_consistency(problem, n=20)
print(f"정답: {answer}")
요점 정리
LLM은 완벽하지 않습니다. 특히 불필요한 정보가 섞인 환경에서는 쉽게 길을 잃습니다. 프롬프트를 고도화하는 것도 좋지만, 때로는 ‘여러 번 물어보고 다수결을 따르는’ 단순한 전략이 가장 강력한 방어막이 됩니다.
혹시 지금 운영 중인 RAG 시스템의 답변이 들쭉날쭉하다면, 이 ‘자기 일관성’ 로직을 파이프라인에 추가해 보시는 건 어떨까요?
