LLM 회상과 정보 검색¶
개요¶
LLM에 장문의 문서를 입력할 때, 모델이 모든 정보를 동등하게 처리하지 않는다는 사실을 아시나요? 특히 문서의 중간에 있는 정보는 시작이나 끝의 정보보다 훨씬 잘 기억하지 못합니다. 이를 "Lost in the Middle" 문제라고 부릅니다.
2024년의 Machlab과 Battle 연구는 이 현상을 체계적으로 분석하고, 프롬프트 설계를 통해 이 문제를 해결할 수 있음을 보여주었습니다.
"Lost in the Middle" 문제¶
위치 편향 (Position Bias) 현상¶
기본 개념¶
LLM의 정보 회상 능력:
위치 [시작] [초반] [중간] [후반] [끝]
회상률 85% 75% 30% 70% 85%
↑ ↓ ↑
매우 높음 매우 낮음 매우 높음
발견: 문서 시작/끝의 정보는 잘 기억하지만,
중간의 정보는 무시하는 경향 있음
실험 결과 (Machlab & Battle, 2024)¶
10개의 "바늘(Needle)" 테스트
- 각 위치에 중요한 정보 1개씩 숨김
- 모델에 문서 전체 입력 후 그 정보 회상 요청
결과:
┌─────────────────────────────────────────┐
│ 위치 1 (시작) ████████░░ 85% │
│ 위치 3 ███████░░░░ 70% │
│ 위치 5 (중간) ██░░░░░░░░░ 20% │
│ 위치 7 ███████░░░░ 70% │
│ 위치 10 (끝) ████████░░ 85% │
└─────────────────────────────────────────┘
현상: 중간 위치가 극단적으로 성능 저하
원인 분석¶
1. 어텐션 메커니즘의 한계¶
어텐션(Attention) 계산:
Query: 현재 토큰 (회상 질문)
Key/Value: 모든 이전 토큰들 (문서)
Attention_weight = softmax(Query · Key^T)
문제:
- 시작/끝 토큰: 많은 Attention 수신
- 중간 토큰: Attention 분산/감소
- 특히 문서가 길수록 악화
2. 위치 인코딩의 영향¶
위치 인코딩(Positional Encoding):
위치 0: PE₀ (가장 특이한 신호)
위치 50000 (중간): PE₅₀₀₀₀ (흐릿한 신호)
위치 100000: PE₁₀₀₀₀₀ (다시 특이한 신호)
결과: 중간 위치는 모델이 구분하기 어려움
특이한 위치(시작/끝)는 명확히 구분
3. 교육 데이터의 편향¶
LLM 학습 데이터 분석:
- 문서 시작: 중요한 정보 (요약, 제목 등)
- 문서 중간: 세부 내용
- 문서 끝: 결론, 중요한 정보
모델은 학습 중:
"문서 시작/끝에 중요한 정보가 자주 있다"
→ 이 위치에 더 높은 가중치 할당
한국 뉴스 기사 구조:
제목 (매우 중요) → 리드 문단 (중요) → 본문 (세부)
→ 한국어 문서는 이 패턴이 더욱 뚜렷
회상 문제 실제 예시¶
시나리오: 계약서 검토¶
한국어 예제: 중요한 조항을 놓치다
입력 (100페이지 계약서):
┌─────────────────────────────────────┐
│ 계약 제1조: 당사자
│ A회사와 B회사는 다음의 계약을 체결한다.
│ (중요도: ⭐)
└─────────────────────────────────────┘
↓ [50페이지의 일반 조항들]
┌─────────────────────────────────────┐
│ 중요한 특례 조항: 개인정보 처리
│ 본 계약에서 개인정보 보호는
│ GDPR이 아닌 한국 개인정보보호법 적용
│ (중요도: ⭐⭐⭐⭐⭐ - 규제 위험)
└─────────────────────────────────────┘
↓ [40페이지의 일반 조항들]
┌─────────────────────────────────────┐
│ 제99조: 종료 조건
│ 본 계약은 2026년 12월 31일 종료.
│ (중요도: ⭐⭐)
└─────────────────────────────────────┘
질문: "개인정보 처리는 어느 법을 따릅니까?"
LLM 기본 응답:
"죄송하지만 문서에 명시되어 있지 않습니다."
→ 실제로는 명시되어 있음 (중간에, 놓침)
회상률: 30% 정도 (중간 위치라서 낮음)
규제 위반 위험: 매우 높음! (개인정보 처리가 가장 중요)
시나리오: 고객 지원 이력 분석¶
고객 대화 기록 (1년, 50개 메시지):
[ 초기 - 잘 기억함 ]
고객: "배송이 안 왔어요"
지원: "배송 확인해드리겠습니다"
[ 중간 - 놓치는 부분 ]
고객: "혹시 청구 주소가 잘못됐나요?
주소: 서울시 강남구 테헤란로 123"
← 이 정보가 가장 중요한데!
[ 최근 - 다시 잘 기억함 ]
고객: "환불 받고 싶어요"
지원: "처리하겠습니다"
질문: "고객의 정확한 배송 주소는?"
응답: "기억이 안 납니다" → 틀린 답변!
(50개 메시지 중 25번째 정보 = 중간 위치)
비즈니스 영향:
- 배송 재시도 실패
- 고객 만족도 저하
- 추가 지원 비용 발생
문제 해결 전략¶
전략 1: 중요 정보 배치 최적화¶
방법 A: 중요 정보를 시작/끝에 배치¶
기존 (비효율):
문서 = [일반정보] + [중요정보] + [일반정보]
↓ (중간 = 회상 30%)
최적화:
문서 = [중요정보] + [일반정보]
↑ (시작 = 회상 85%)
또는:
문서 = [일반정보] + [중요정보]
↑ (끝 = 회상 85%)
한국 사례: 보도자료 작성 시¶
기존 구조 (손실):
제목 → 리드 → 일반정보 (500단어) → [핵심수치 (손실)]
최적화된 구조:
제목 → [핵심수치 (강조)] → 리드 → 일반정보
이유: 한국 언론은 역피라미드 구조지만,
AI 활용 시 핵심을 더 앞에 배치하면
회상률 2배 이상 향상
💡 실전 팁: 문서 재구성
전략 2: 재구성 기반 회상 (RAG - Retrieval Augmented Generation)¶
개념¶
기존 방식 (실패):
사용자 질문 → [전체 문서] → LLM
(중간 정보 손실 위험)
RAG 방식 (성공):
사용자 질문
↓
관련 섹션만 추출 (검색)
↓
추출된 관련 부분만 + 질문 → LLM
(정보 손실 없음)
장점:
- 문서 크기 제한 완화
- 회상률 95% 이상 보장
- 비용 절감 (토큰 수 감소)
구현 예시¶
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
from langchain.chains import RetrievalQA
from langchain.chat_models import ChatOpenAI
# 1단계: 문서를 벡터로 변환 (임베딩)
embeddings = OpenAIEmbeddings()
vector_store = FAISS.from_documents(
documents=loaded_documents,
embedding=embeddings
)
# 2단계: 사용자 질문과 관련된 부분만 검색
retriever = vector_store.as_retriever(
search_kwargs={"k": 3} # 상위 3개 관련 섹션 검색
)
# 3단계: 검색된 부분만으로 답변 생성
qa = RetrievalQA.from_chain_type(
llm=ChatOpenAI(),
chain_type="stuff",
retriever=retriever
)
# 결과
answer = qa.run("개인정보 처리는 어느 법을 따릅니까?")
# 결과: 매우 높은 정확도 (99%+)
RAG의 장점¶
비교:
직접 입력 (Lost in the Middle):
계약서 크기: 100페이지
토큰 수: ~100K
비용: ~$10
회상률: 30-40% (위치 의존)
RAG 방식:
전체 계약서 인덱싱: 1회
각 질문당 관련 부분만 추출: ~10 페이지
토큰 수: ~10K (90% 감소!)
비용: ~$1 (90% 절감!)
회상률: 95-98% (거의 완벽)
전략 3: 프롬프트 구조 최적화¶
방법 1: 명시적 지시사항 배치¶
비효율적:
사용자: "이 문서를 읽고 분석해줄 수 있나요?
[100페이지 문서]
특별히 중요한 부분이 중간쯤 있으니 꼭 찾아줘"
효율적:
사용자: "주의: 이 문서의 'X 조항'이 가장 중요합니다.
이것을 중심으로 분석해주세요.
[100페이지 문서]
질문: X 조항의 영향을 분석하세요"
이유: 지시사항을 앞에 배치하면
모델이 중요성 순서를 인지
방법 2: 청킹 (Chunking)¶
한 번에 100페이지 처리 (손실 위험)
vs
섹션별 처리:
Q: 제1부(10페이지)의 주요 내용은?
Q: 제2부(10페이지)의 주요 내용은?
...
Q: 전체 종합 분석은?
장점:
- 각 섹션에서 중간 정보도 회상 가능
- 종합적 이해 가능
- 비용 약간 증가 (충분히 가치 있음)
⚠️ 주의: 청킹의 한계
청킹으로 섹션 간 맥락 손실 가능:
전략 4: 프롬프트 순서 최적화¶
구조¶
# 최적 프롬프트 구조
optimized_prompt = f"""
[1단계: 컨텍스트 설정]
당신은 전문 법률 검토 전문가입니다.
[2단계: 핵심 지시]
다음 계약서를 분석하고, 특히 다음 항목을 중점 검토하세요:
- 개인정보 처리 조항
- 법적 관할권
- 손해배상 책임
[3단계: 문서 제공]
{document_content}
[4단계: 구체 질문]
위 계약서에서:
1. 개인정보는 어느 법을 따르나요?
2. 손해배상 책임의 한도는?
3. 해지 조건은?
"""
response = llm(optimized_prompt)
위치 편향 극복 기법¶
기법 1: 인텔리전트 리래그(Intelligent Re-ranking)¶
기본 RAG의 문제:
검색: "개인정보" → [섹션 A, 섹션 B, 섹션 C]
문제: 관련성 순서가 항상 정확하지 않음
해결:
검색 후 LLM 재평가:
"이 3개 섹션 중 '개인정보 법적 기준'을
가장 잘 설명하는 것은?"
장점: 검색 정확도 2배 향상
기법 2: 하이라키컬 요약 (Hierarchical Summarization)¶
긴 문서:
문서 (100페이지)
↓
1단계 요약: 각 장별 요약 (10 페이지)
↓
2단계 요약: 전체 요약 (2 페이지)
↓
3단계 요약: 핵심 1페이지
사용자 질문 → 계층적 검색:
질문 난이도에 따라 적절한 요약 수준 사용
예:
"계약의 대략적 내용" → 1페이지 요약 (빠름)
"개인정보 조항의 상세" → 원문 섹션 (정확함)
한국 비즈니스에서의 활용¶
사례 1: 금융 기관의 규정 준수¶
한국 은행의 상황:
매일 수십 개의 시행령/공시 업데이트
- 1페이지 ~ 50페이지
- 중간에 중요한 변경사항 있음
전략:
1. RAG로 모든 규정 인덱싱
2. 새 규정 업데이트 시:
"이전 규정과 다른 점은?"
3. 변경사항 자동 추출
4. 컴플라이언스팀에 알림
효과:
- 규제 위반 위험 90% 감소
- 검토 시간 80% 단축
사례 2: 의료 기관의 임상 문서 검토¶
의료 AI 시스템:
상황:
- 환자 의료 기록: 50-100페이지
- 알레르기 정보가 기록 중간에 있음
- "Lost in the Middle"으로 놓칠 위험
해결:
1. 의료 기록 구조화:
[환자 기본정보]
→ [중요: 알레르기] ← 시작에 배치
→ [진단 이력]
→ [약물 이력]
2. 또는 RAG:
의약품 처방 시:
"알레르기 확인" (자동 검색)
→ 정확한 정보 회상
효과:
- 의약품 부작용 사고 99% 방지
사례 3: 법률 서비스의 판례 검색¶
한국 로펌의 상황:
대법원 판례 1,000개 분석
- 각 판례: 10-50페이지
- 중요한 법적 선례가 중간에 있음
기존 방식 (손실):
변호사가 수동 검토 → 일부 사례 놓침
RAG 방식:
"계약 해지 관련 판례"
→ 1000개 판례에서 관련 부분만 검색
→ 가장 유사한 5개 선례 추출
→ 각 판례의 핵심 부분만 분석
효과:
- 법적 근거 검색 시간 90% 단축
- 더 정확한 법적 자문 제공
성능 평가¶
회상 메트릭¶
# 회상 능력 측정
from langchain.evaluation import QAEvalChain
def evaluate_recall(documents, questions, expected_answers):
"""
실제 회상률 측정
"""
correct = 0
total = len(questions)
for question, expected in zip(questions, expected_answers):
answer = llm(document + "\n\nQ: " + question)
if expected in answer:
correct += 1
recall_rate = (correct / total) * 100
return recall_rate
# 테스트
basic_llm_recall = evaluate_recall(
documents=test_doc,
questions=questions,
expected_answers=answers
)
# 결과: 35% (Lost in the Middle 문제)
rag_recall = evaluate_recall_with_rag(
documents=test_doc,
questions=questions,
expected_answers=answers
)
# 결과: 97% (RAG 개선)
💡 실전 팁: 회상 테스트 자동화
def test_recall_performance():
"""
정기적으로 회상 능력 모니터링
"""
test_cases = [
{
"position": "시작",
"info": "중요한 정의",
"expected_recall": 85
},
{
"position": "중간",
"info": "숨겨진 조항",
"expected_recall": 30 # 주의!
},
{
"position": "끝",
"info": "결론",
"expected_recall": 85
}
]
results = []
for case in test_cases:
score = run_needle_test(
document=create_test_doc(case["info"]),
question=f"문서에서 '{case['info']}'는?",
position=case["position"]
)
results.append({
"position": case["position"],
"actual": score,
"expected": case["expected_recall"]
})
return results
📝 핵심 정리¶
핵심 개념¶
- Lost in the Middle: 문서의 중간 정보를 LLM이 회상하지 못하는 현상
- 위치 편향: 시작(85%) > 중간(30%) < 끝(85%)의 비대칭 패턴
- 회상률: 특정 정보를 정확히 찾아내는 능력 (%)
원인¶
- 어텐션 메커니즘의 한계
- 위치 인코딩의 비선형 특성
- 학습 데이터의 구조 편향 (시작/끝이 중요)
해결책 (우선순위)¶
- RAG (추천): 관련 부분만 검색 후 처리 (회상률 97%+)
- 문서 재구성: 중요 정보를 시작/끝에 배치
- 프롬프트 최적화: 명시적 지시사항 앞에 배치
- 청킹: 긴 문서를 섹션별로 처리
한국 비즈니스 영향¶
- 금융: 규정 변경 자동 추출 및 컴플라이언스
- 의료: 환자 알레르기/중요 정보 확실한 회상
- 법률: 판례 검색 및 법적 근거 제시 정확성 증대
측정 및 모니터링¶
- 정기적인 Needle-in-Haystack 테스트
- 각 위치별 회상률 추적
- RAG 도입 후 개선도 검증
실무 체크리스트¶
- ☑️ 현재 회상 성능 평가 (위치별)
- ☑️ 중요 정보의 위치 검토 및 재구성
- ☑️ RAG 시스템 도입 검토
- ☑️ 정기적인 회상 테스트 실행
- ☑️ 사용자 피드백 수집 (놓친 정보 추적)
Last Updated: 2026년 2월 | Reference: Machlab & Battle, "LLM In-Context Recall is Prompt Dependent" (2024)