지금까지 아홉 편은 전부 질문 하나를 가정했다. 그런데 실제로 출시되는 RAG는 대부분 챗봇이고, 두 번째 질문은 이렇게 온다 — "그거 환불돼요?" 여기서 무너지는 방식이 단일 턴과는 완전히 다르다.
39%는 어디로 사라지는가 — 무너지는 건 능력이 아니라 일관성
Microsoft·Salesforce가 20만 건 이상의 시뮬레이션 대화를 분석한 "LLMs Get Lost in Multi-Turn Conversation"이 기준점이다. 같은 과제를 한 번에 주느냐 여러 턴에 나눠 주느냐만 바꿨을 때 6개 태스크 평균 39% 성능 하락이 나왔다. 중요한 건 분해다:
- 능력치(aptitude) 하락은 16% — 최상위 성능은 크게 안 떨어진다.
- 비신뢰도(unreliability)는 112% 증가 — 같은 과제를 반복했을 때 최고와 최저의 격차가 두 배 이상 벌어진다.
즉 "못 하게 되는" 게 아니라 "될 때도 있고 안 될 때도 있게 된다." QA에서 재현이 안 되는 버그 리포트의 정체가 이것이다. 모델 크기나 추론 능력과 무관하게 테스트한 15개 모델 전부에서 나타났다. 원인으로 지목된 행동은 넷 — 정보가 부족한데 성급히 답을 시도하고, 이전 시도에 기대어 답이 계속 길어지고, 마지막 턴에 과잉 반응하며 중간 턴을 잊고, 장황한 답변이 새 가정을 주입한다. 모델은 자기가 만든 잘못된 가정을 히스토리에 "사실"로 박아 두고 그 위에 계속 쌓는다.
진짜 범인은 리트리버다
IBM의 멀티턴 RAG 벤치마크 MTRAG(사람이 만든 110개 대화, 평균 7.7턴, 4개 도메인)이 결정적 숫자를 준다. 같은 코퍼스, 같은 리트리버인데:
| 조건 | Recall@5 |
|---|---|
| 첫 턴 | 0.89 |
| 이후 턴 (마지막 발화만 검색) | 0.47 |
| 이후 턴 + 질의 재작성 | 0.52 |
검색 리콜이 절반으로 떨어진다. 데모는 통과하고 실사용 3턴째부터 무너지는 이유가 여기 있다. 그리고 MTRAG의 결론은 명확하다 — 질의 재작성이 모든 리트리버에서 마지막 턴만 던지는 것보다 일관되게 낫다. 난이도를 더 높이는 건 토픽 전환이다. TopiOCQA(대화당 평균 13턴, 4개 토픽을 넘나듦)에서 같은 기법의 NDCG@3이 QReCC 39.1 → 24.3으로 떨어진다. 배송 → 환불 → 회원등급 → 다시 배송으로 오가는 상담봇이 정확히 이 유형이다.
재작성의 가격표, 그리고 "사람만큼"이 목표가 아닌 이유
구현별 비용은 이렇다. LangChain의 create_history_aware_retriever는 첫 턴 0회, 2턴부터 매 턴 LLM 1회(히스토리가 비면 원문을 그대로 검색하는 분기가 있다). LlamaIndex의 CondensePlusContext는 턴당 2회(축약 1 + 생성 1). Bedrock Knowledge Bases는 관리형인데도 오케스트레이션 프롬프트가 "사용자 프롬프트를 검색 질의로 바꾼다"고 문서에 적혀 있고, 질의 분해를 켜면 검색 호출이 N배가 된다. "알아서 해준다"는 "청구서에 숨어 있다"는 뜻이다.
목표 설정도 다시 해야 한다. 흔히 "사람이 쓴 재작성문만큼 하면 된다"고 하는데, ConvGQR은 QReCC NDCG@3에서 사람 재작성 35.6을 39.1로 넘었고, LLM4CS는 CAsT-19에서 사람 0.461 대비 0.515를 냈다. 리트리버가 좋아하는 질의와 사람이 읽기 좋은 질의는 다르다. 다만 LLM4CS는 턴당 LLM 5회에 임베딩 5~10회라 비용이 5배다. 비용 관점의 정답에 가장 가까운 건 RetPO 노선 — 큰 모델로 후보를 잔뜩 만들고 리트리버의 실제 검색 성능을 피드백으로 작은 재작성기를 오프라인에서 증류하는 것. 런타임 추가 비용이 사실상 0에 수렴한다.
요약하지 마라 — 프롬프트 캐시가 순위를 뒤집는다
토큰 총량만 보면 대화 요약을 유지하는 방식(running summary)이 가장 싸 보인다. 턴이 늘어도 상수니까. 그런데 프롬프트 캐시를 넣는 순간 순위가 뒤집힌다. 캐시 읽기는 정가의 0.1배인데, 요약은 프롬프트 앞부분을 매 턴 갱신하므로 매 턴 전체를 정가로 다시 계산한다. OpenAI 문서도 compaction을 명시적 캐시 무효화 요인으로 규정한다.
턴 20 기준으로 계산하면 append-only 히스토리의 실효 비용이 약 2,850토큰 상당, running summary가 약 5,700토큰 상당 — 두 배 차이가 반대 방향으로 난다. 품질도 마찬가지다. 매 턴 전체를 재진술하는 SNOWBALL 방식조차 멀티턴 열화를 15~20%만 회복한다. 캐시 90% 할인을 통째로 버리고 사는 이득치고는 작다.
실전에서 한 줄만 고칠 수 있다면 블록 순서다.
- ❌
[system][검색 청크][히스토리][질의]— 청크가 매 턴 바뀌므로 뒤의 히스토리 전체가 매 턴 무효화된다. - ✅
[system][히스토리][검색 청크][질의]— 안정적인 히스토리까지 캐시에 태우고, 변동하는 청크는 마지막에.
재작성 호출을 싼 모델로 돌릴 때는 최소 캐시 프리픽스를 확인해야 한다 — 모델마다 512~4,096토큰으로 다르고, 미달이면 에러 없이 조용히 캐시가 안 된다(캐싱 시리즈 ④편). 그리고 재작성 호출 하나로 세 가지를 흡수할 수 있다: 출력 스키마를 {standalone_query, hypothetical_answer, stepback_query}로 확장하면 추가 호출 0회로 HyDE와 step-back(④편)까지 얻는다. 별도 호출로 쌓으면 턴당 3~4회가 된다.
한국어에서 더 나쁜 이유, 그리고 무엇을 계측할까
영어 "Is it refundable?"에는 치환할 앵커(it)가 있다. 한국어 "환불돼요?"에는 슬롯 자체가 표면에 없다. 한국어는 주어·목적어가 문맥에서 복원되면 아예 나타나지 않는 언어라, 영어권 재작성 프롬프트를 번역만 하면 모델이 "바꿀 대명사가 없다"고 판단해 원문을 그대로 뱉는다. "생략된 주어와 목적어를 복원하라"를 명시해야 하고, 격조사가 사라지면 주제와 주어가 뒤섞인다는 점도 감안해야 한다("배송은 언제요?"의 생략어가 "제 주문의"인데 "배송 정책의"로 복원되면 완전히 다른 청크를 검색한다).
계측에는 함정이 하나 있다. 재작성이 실패해 엉뚱한 청크를 가져와도, 모델이 그 엉뚱한 청크에 충실하게 답하면 Faithfulness는 오히려 높게 나온다. 진짜 신호는 Context Recall/Precision이다. 더 흔한 버그는 평가 파이프라인에 재작성된 질의를 사용자 입력으로 넣는 것 — "그거"가 이미 "제품 A 환불 정책"으로 바뀌어 있으니 재작성 실패가 지표에서 사라진다. 반드시 원 발화로 채점할 것.
마지막으로 한국어 자원의 공백을 짚어 둔다. ⑨편에서 본 한국어 RAG 리더보드(300문항)는 단일 턴이고 한국어판 MTRAG는 없다. 0.847이라는 점수로 프로덕션을 예측하면 안 된다는 뜻이다. 재작성기 학습 시드로는 AI Hub의 민원·콜센터 데이터(약 110만 대화쌍)가 현실적 1순위이고, 사내 평가셋에는 턴 인덱스별 리콜 리포트를 필수 산출물로 넣어야 한다. KPI도 턴별 정확도 평균보다 CRAG-MM 방식의 대화 생존율(2턴 연속 오답이면 이탈로 간주)이 현실에 가깝다. 다음 글은 사내 RAG 파일럿을 실제로 중단시키는 문제 — 권한이다.
— RAG 종류 총정리 시리즈 ⑩ / 다음 글: 권한 인식 검색과 보안 — 인사팀 문서가 영업 답변에 섞이면
댓글 없음:
댓글 쓰기
국정원의 댓글 공작을 지탄합니다.