긴 계약서 요약에서 중간 조항이 누락되는 lost in the middle, 모델 교체로 줄였지만 근본 해법은 청킹이었다
정유나
@yuna_ai
40페이지가 넘어가는 계약서를 한 번에 요약시키면 중간쯤 위치한 조항이 통째로 누락되는 현상을 한동안 겪었습니다. 프롬프트에 "모든 조항을 빠짐없이"라고 아무리 강조해도 문서 길이의 60% 지점부터 슬슬 빠지기 시작했습니다. 전형적인 lost in the middle 패턴이었습니다.
모델을 바꿔봤다
생성 모델을 GPT-4o에서 Claude Sonnet으로 옮겼더니 누락이 눈에 띄게 줄었습니다. 정량 측정까지는 안 했고, 출력물을 사람이 검수하면서 빨간펜 칠 일이 줄었다는 체감 수준입니다. 같은 시스템 프롬프트를 매 요청에 붙이는 구조라 prompt caching이 잘 먹혀서 인풋 비용이 오히려 내려간 건 의외의 수확이었습니다.
| 항목 | GPT-4o | Claude Sonnet |
|---|---|---|
| 긴 문서 중간 조항 누락 | 60% 지점부터 빈번 | 체감상 줄어듦(정량 X) |
| JSON 강제 | structured output이 안정적 | tool로 박아야 안정 |
| prompt caching | 반복 prefix에서 인풋 절감 | 동일하게 효과 |
JSON 강제는 OpenAI structured output 쪽이 편했습니다. Claude는 요약 본문 뒤에 사족을 붙이려다 파싱이 깨진 적이 있어서, 결국 응답을 tool 호출로 박아 스키마를 강제하는 방식으로 바꿨습니다.
다만 모델 교체는 임시방편이었다
솔직히 말하면 모델을 바꾼 건 증상 완화였지 근본 해결은 아니었습니다. 컨텍스트 길이가 늘어나면 어느 모델이든 중간이 묻히는 경향은 남습니다. 결국 입력을 통째로 던지는 구조 자체가 문제였습니다.
지금은 계약서를 조 단위로 청킹한 뒤 map 단계에서 각 청크를 개별 요약하고, reduce 단계에서 그걸 합치는 구조로 바꿨습니다. 조항 하나가 청크 경계에서 잘리지 않도록 헤딩(제N조) 기준으로 분할한 게 핵심이었습니다. 이렇게 하니 한 청크 안에 들어가는 조항 수가 적어져서, 모델이 "빠짐없이"를 지킬 수 있는 범위 안에서만 일하게 됩니다.
정리하면, 긴 문서 요약에서 중간 누락이 보인다면 모델 교체로 어느 정도 완화는 됩니다. 하지만 문서가 더 길어질수록 같은 문제가 다시 올라오므로, 청킹과 map-reduce로 입력 단위를 쪼개는 게 결국 정석이라고 봅니다. 모델은 그 위에서 고르는 변수입니다.