Lost in the Middle: 왜 에이전트에게 더 많은 컨텍스트를 제공할수록 더 멍청해지는가
요약
LLM이 컨텍스트 중간에 위치한 정보를 제대로 활용하지 못하는 'Lost in the Middle' 현상을 분석합니다. 컨텍스트 윈도우가 길어질수록 모델의 성능이 U자형 곡선을 그리며 저하되는 구조적 원인과 주의점을 다룹니다.
핵심 포인트
- 컨텍스트 중간에 위치한 정보는 모델의 회상 성능이 급격히 저하됨
- 컨텍스트 윈도우 크기와 실질적인 정보 검색 능력은 별개의 문제임
- 단순히 top_k 값을 높이는 것이 RAG 성능 향상을 보장하지 않음
- 셀프 어텐션과 위치 인코딩의 구조적 특성으로 인해 발생하는 현상임
문제점
당신은 RAG (Retrieval-Augmented Generation) 파이프라인을 구축합니다. 3개의 검색된 문서로 테스트했을 때 정답이 문서 2에 있었고, 모델은 매번 완벽하게 맞혔습니다. 기분이 좋아진 당신은 "안전하게" 가자는 생각으로, 더 많은 컨텍스트가 도움이 될 것이라 판단하여 top_k 값을 3에서 15로 높입니다.
정확도가 떨어집니다. 시스템이 충돌하거나, 타임아웃이 발생하거나, 로그에 에러가 찍히는 것도 아닙니다. 모델은 그저 자신 있게 틀린 답을 내놓거나, 당신이 보낸 프롬프트(Prompt) 내 텍스트에 명확히 적혀 있는 사실을 놓치기 시작합니다. 컨텍스트 윈도우(Context Window)를 직접 눈으로 다시 읽어보면 정답은 바로 거기에 있습니다. 모델은 그것을 보았습니다. 단지 사용하지 않았을 뿐입니다.
만약 이런 상황을 겪었다면, 당신이 잘못된 리트리버(Retriever)를 만든 것이 아닙니다. 당신은 잘 문서화되어 있으며 모델에 구애받지 않는(Model-agnostic) 실패 모드에 직면한 것입니다. LLM (Large Language Models)은 컨텍스트 윈도우 전체에 걸쳐 정보를 균일하게 회상하지 않습니다. 그들은 시작 부분과 끝 부분을 회상합니다. 중간 부분은 정보가 죽으러 가는 곳입니다.
발생하는 이유
이것은 소문이 아니라 직접 측정된 사실입니다. Liu 등의 "Lost in the Middle" 연구 (2023)는 컨텍스트 길이에 따른 통제된 검색 테스트를 수행하였고, 일관된 U자형 정확도 곡선을 발견했습니다. 관련 사실이 컨텍스트의 맨 처음이나 맨 끝에 있을 때 성능이 가장 높았으며, 중간에 파묻혀 있을 때는 성능이 급격히 떨어졌습니다(때로는 무작위 추측에 가까운 수준까지 떨어집니다). 이는 특정 업체의 특이 사항이 아니라 여러 모델 제품군 전체에서 공통적으로 나타났습니다.
이 메커니즘은 패치로 수정할 수 있는 버그가 아니라 구조적인 문제입니다. 셀프 어텐션 (Self-attention)은 토큰 위치 전체에 걸쳐 회상을 균등하게 분배하지 않습니다. 모델은 훈련 과정에서 단거리 의존성 (Short-range dependencies)에 대해 집중적으로 노출되지만 (다음 단어는 보통 근처의 단어에 의존함), 길고 구조화되지 않은 구간의 기하학적 중간 지점에서 정밀한 검색을 보상하는 훈련 신호는 상대적으로 적습니다. 위치 인코딩 (Positional encodings)이 이를 가중시킵니다. 대부분의 방식은 어텐션 (Attention)을 강력한 국소적 최신성 (Local recency)과, 별개로 시퀀스의 시작점(자연스러운 앵커 포인트) 쪽으로 편향되게 만들며, 결과적으로 중간 부분은 구조적으로 주의를 덜 받게 됩니다.
실제 운영 환경에서 정말로 뼈아프게 다가오는 부분은 바로 이것입니다. 광고되는 컨텍스트 창(context window)과 실질적으로 사용 가능한 컨텍스트 창은 서로 다른 숫자이며, 벤더(vendor)들은 전자를 보고합니다. "1M 토큰 컨텍스트"를 가진 모델이라고 해서 1M 토큰 전체에 걸쳐 신뢰성 있게 정보를 검색한다는 의미가 아닙니다. 이는 단지 1M 토큰에 도달하기 전까지 에러가 발생하지 않는다는 의미일 뿐입니다. 이 두 가지는 동일한 주장이 아니며, 이 둘 사이의 간극이 바로 "데모에서는 작동했지만, 운영 환경에서는 불안정하다"라는 버그가 발생하는 정확한 지점입니다.
그리고 이는 설계상 침묵을 유지합니다. 잡아낼 수 있는 예외(exception)가 없습니다. 리트리버(retriever)는 제 역할을 다했고, 프롬프트 조립(prompt assembly)도 제 역할을 다했으며, 토큰들은 컨텍스트 내에 명확히 존재합니다. 실패의 원인은 순수하게 모델이 무엇에 주의(attend)하기로 선택하느냐에 달려 있으며, 이는 특정 테스트를 수행하지 않는 한 외부에서는 보이지 않습니다.
해결 방법
top_k를 안전장치(safety dial)처럼 취급하는 것을 멈추세요. 더 많은 검색 청크(retrieved chunks)가 반드시 재현율(recall)을 단조 증가시키는 것은 아닙니다. 특정 지점을 넘어서면 오히려 단 하나의 정답 청크를 데드 존(dead zone)으로 더 깊숙이 밀어 넣어 버립니다. top_k를 높이지 말고 낮추면서 측정하십시오.
단순히 검색만 하지 말고 순서를 재배치하세요. 랭킹(ranking)을 매긴 후에는, 검색된 순서대로 위에서 아래로 배치하는 것이 아니라 신뢰도가 가장 높은 청크들을 컨텍스트의 시작과 끝에 배치하십시오. 리트리버에 의해 1위로 랭킹된 청크라도 프롬프트의 정중앙에 위치한다면, 가장자리에 배치된 4위 청크보다 성능이 떨어질 것입니다.
리랭커(reranker) 단계를 추가하세요. 초기 검색 후에 저렴한 크로스 인코더(cross-encoder) 리랭크 과정을 거쳐, 상위 몇 개의 청크만을 위치를 고려한 순서(position-aware order)로 프롬프트에 입력하는 방식이 "넓게 검색해서 전부 다 집어넣고 모델이 알아서 하게 두는" 방식보다 일관되게 더 나은 성능을 보여줍니다.
자신만의 '건초더미 속 바늘(needle-in-a-haystack)' 평가를 구축하세요. 여러분의 워크로드에 대해 벤더(vendor)가 제공하는 긴 컨텍스트(long-context) 벤치마크를 맹신하지 마세요. 위치 민감도(position sensitivity)는 모델별로, 모델의 버전(model version)별로(조용한 업데이트로 인해 성능이 퇴보할 수 있음) 다를 수 있으며, 여러분이 사용하는 특정 문서의 구조에 따라서도 달라집니다. 로그에서 실제 쿼리를 가져와서, 정답이 확실한 사실을 일반적인 컨텍스트 길이의 10%, 50%, 90% 위치에 심어둔 뒤, 각 위치에서의 정확도를 측정하세요. 모델을 교체할 때마다 이 과정을 반복하세요.
범위를 넓히기 전에 좁히는 것을 고려하세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기