LLM 프롬프트 엔지니어링: 퓨샷 예시는 무조건 ‘여기에’ 써라
“Few-shot 예시를 기가 막히게 짰는데, 왜 모델은 헛소리를 할까요?”
“프롬프트 내용을 아무리 수정해도 성능이 제자리걸음인가요?”
그렇다면 여러분은 지금 ‘무엇(What)’을 쓸지가 아니라, ‘어디(Where)’에 쓸지를 고민해야 할 시점입니다.
많은 분들이 프롬프트 엔지니어링을 할 때 예시(Demonstrations)의 ‘텍스트 품질’을 높이는 데에는 밤을 새우지만, 정작 그 예시를 프롬프트의 어느 좌표에 박아 넣을지는 대수롭지 않게 여깁니다. 보통은 그냥 템플릿이 생긴 대로, 관성적으로 배치하죠.
하지만 최신 연구에서는 우리의 이런 안일함을 정면으로 반박합니다. “예시의 내용을 1도 바꾸지 않고, 단지 위치만 바꿨을 뿐인데 정확도가 20% 널뛰기한다”는 사실이 밝혀졌기 때문입니다.
오늘은 이 현상을 설명하는 DPP 편향(Demos Position in Prompt Bias)의 실체와, 돈 한 푼 들이지 않고 모델 성능을 끌어올리는 ‘위치 선정의 기술’을 정리해 드립니다.
DPP 편향: 당신의 예시가 무시당하는 이유
우리는 흔히 LLM이 입력된 텍스트 전체를 공평하게, 골고루 씹어먹을 거라 착각합니다. 하지만 모델도 편식을 합니다. 프롬프트의 구조적 위치에 따라 정보를 받아들이는 가중치가 달라지는데, 이를 DPP 편향(Demo Position in Prompt Bias)이라고 부릅니다.
연구진은 동일한 예시 블록을 프롬프트 내 4가지 서로 다른 위치로 옮겨가며 실험했습니다. 결과는 꽤 충격적입니다.
“위치만 바꿨는데 작업 정확도가 최대 20% 변동했고, 모델의 예측 결과(Prediction)는 절반 가까이 뒤집혔다.”
여러분이 공들여 짠 완벽한 Few-shot 예시가, 단지 ‘잘못된 자리’에 앉아있다는 이유만으로 모델에게 무시당하고 있었다는 뜻입니다.
4가지 핵심 위치: 어디에 두는 게 맞을까?
실험에서는 프롬프트 내 예시의 위치를 다음 4가지로 정의했습니다. 여러분의 코드는 지금 어떤 구조를 따르고 있는지 확인해 보시기 바랍니다.
ssp(Start of System Prompt): 시스템 프롬프트의 맨 앞.esp(End of System Prompt): 시스템 프롬프트의 맨 뒤.sum(Start of User Message): 유저 질문의 맨 앞. (가장 흔한 방식)eum(End of User Message): 유저 질문의 맨 뒤.
대부분의 개발자는 관습적으로 sum (유저 질문 앞에 예시 배치) 방식을 씁니다. 하지만 데이터가 말해주는 정답은 다릅니다.
데이터로 보는 승자와 패자
Llama-3, Qwen, Mistral 등 10개 모델을 갈아 넣어 분석한 결과, 승패는 명확했습니다.
🏆 승자: ‘시스템 프롬프트’ (ssp, esp)
가장 확실한 성능을 보장하는 곳은 프롬프트의 최전방, 시스템 프롬프트 영역입니다.
특히 ssp(시스템 프롬프트 시작) 위치에 예시를 두었을 때, 제로샷(Zero-shot) 대비 MMLU 기준 18% 이상의 정확도 향상을 기록했습니다. 모델이 “아, 이게 내가 따라야 할 기준이구나”라고 가장 강력하게 인지하는 구간입니다.
❌ 패자: ‘유저 메시지 뒤’ (eum)
최악의 수는 유저의 질문 뒤에 예시를 덧붙이는 겁니다.
정확도가 떨어지는 건 둘째치고, 답변의 일관성이 무너지는 변동성(Volatility)이 급증합니다. 모델 입장에선 “질문 다 듣고 나서 뜬금없이 예시가 나오니” 이걸 질문의 연장선으로 봐야 할지, 참고 자료로 봐야 할지 헷갈리는 겁니다.
📉 변수: 모델의 체급 (Size Matters)
여기서 재미있는 건 스케일링 법칙(Scaling Law)입니다.
- 작은 모델 (1.5B ~ 8B): 초두 효과(Primacy Bias)의 노예입니다. 앞쪽에 있는 정보에 절대적인 영향을 받습니다. 따라서 무조건
ssp나esp에 예시를 박아둬야 합니다. - 큰 모델 (70B 이상): 뇌 용량이 커서 그런지 위치에 덜 민감합니다. 우리가 흔히 쓰는
sum위치에서도 잘 작동합니다. 하지만 여전히eum은 피하는 게 상책입니다.
왜 이런 일이 벌어질까? (The Mechanics)
이유는 단순합니다. 트랜스포머(Transformer) 아키텍처의 종특과 학습 방식 때문입니다.
- 초두 효과와 인덕션 헤드(Induction Heads): LLM은 태생적으로 초반 토큰에 강한 주의(Attention)를 기울입니다. 중요한 패턴(예시)을 맨 앞에 배치하면 모델은 이를 강력한 ‘지침’으로 받아들입니다.
- SFT 학습의 관성: 대부분의 모델은 미세 조정(SFT) 단계에서 [시스템 지침] → [대화] 순서로 학습됩니다. 예시를 시스템 영역에 두는 것이 모델이 학습한 데이터 분포와 가장 자연스럽게 맞아떨어지는 겁니다.
Action Plan: 지금 당장 수정할 것
복잡한 이론은 여기까지 하고, 당장 실무에 적용할 수 있는 가이드라인을 드립니다. 수정하는 데 10초면 충분합니다.
✅ Step 1. 모델 사이즈에 따른 전략
- 온디바이스/소형 모델(7B 이하): 선택권이 없습니다. 무조건
ssp(시스템 프롬프트 시작)에 예시를 넣으세요. 유저 메시지와 섞으면 바보가 됩니다. - 거대 모델(GPT-4, Llama-3 70B 등):
sum(유저 메시지 앞)도 괜찮습니다. 하지만 굳이 모험하지 말고 시스템 프롬프트 쪽으로 옮기는 걸 추천합니다.
✅ Step 2. 태스크 유형별 전략
- 분류(Classification) & 추론(Reasoning):
ssp가 가장 안전한 국밥 전략입니다. - 요약(Summarization) 등 생성형: 답변이 널뛰는 걸 막으려면
eum(질문 뒤 배치)은 절대적으로 피하세요.
✅ Step 3. 코드 적용 (Python)
가장 권장하는 ssp 구조는 다음과 같습니다.
prompt = f"""
<|begin_of_text|><|start_header_id|>system<|end_header_id|>
# [1. 예시를 가장 먼저 보여줍니다]
Example 1: ...
Example 2: ...
# [2. 그 다음 페르소나와 지침을 줍니다]
당신은 논리적인 AI 연구원입니다. 위 예시의 논리 구조를 참고하여 답변하세요.
<|eot_id|>
<|start_header_id|>user<|end_header_id|>{user_question}
<|eot_id|>
<|start_header_id|>assistant<|end_header_id|>
"""
마치며
더 좋은 답변을 얻겠다고 프롬프트 텍스트를 깎고 다듬느라 고생 많으셨습니다. 하지만 이 논문이 주는 교훈은 명확합니다.
“이미 가지고 있는 예시를, 더 잘 보이는 곳으로 옮겨라.”
단순한 ‘잘라내기-붙여넣기’ 한 번이 모델의 지능을 20% 올려준다면, 안 할 이유가 없겠죠? 지금 바로 여러분의 코드베이스를 열어 f-string의 순서를 점검해 보시기 바랍니다. 위치가 곧 성능입니다.
