RAG 답변 품질 저하
RAG 답변 품질 저하
요약
3개월 전 도입한 사내 RAG의 👎 비율이 지난 2주 사이 8% → 19%로 상승했다. 같은 기간 변경 이력은 문서 커넥터 추가(새 부서 문서 20만 건)와 LLM 프로바이더 모델 버전 자동 업데이트 두 가지이며, 임베딩 모델·청킹 설정은 바뀌지 않았다. 원인을 진단하고 대응·재발 방지책을 제시한다.
상황 재진술. 2주 기간 안에 두 변경이 겹쳐 있다. 하나는 입력 데이터의 변화(신규 커넥터로 인덱스가 20만 건 증가), 다른 하나는 생성 모델의 변화(LLM 버전)다. 임베딩·청킹이 그대로이므로 검색 알고리즘 자체보다 "인덱스에 무엇이 들어왔는가"와 "생성 모델이 어떻게 달라졌는가"가 1차 용의자다. 진단의 핵심은 두 변경의 효과를 분리하는 것이다.
1. 문제 분리 — 어느 구간이 깨졌는가
결론: 검색 구간과 생성 구간을 3조합 골든셋 재평가로 분리한다. (a) 변경 전 인덱스 스냅샷 + 구 LLM, (b) 신 인덱스 + 구 LLM, © 신 인덱스 + 신 LLM을 같은 골든셋으로 돌리면 (a)→(b)가 데이터 효과, (b)→©가 모델 효과다. 검색은 Recall@20·nDCG@10, 생성은 faithfulness·answer relevancy로 분리 측정한다. 구 인덱스는 blue/green으로 보존된 것 또는 OpenSearch 스냅샷에서 복원한다. 동시에 👎를 부서·질의 유형·시각으로 분해한다. 신규 부서에 집중됐으면 데이터·기대 불일치, 전 부서에 퍼졌으면 모델 또는 인덱스 전역 효과다.
2. 가설 트리
| # | 가설 | 예상 징후 | 검증 방법 | 우선순위 |
|---|---|---|---|---|
| H1 | 신규 20만 건에 동일 문서의 사본·구버전이 섞여 top-k 점유 | 컨텍스트에 같은 제목·다른 버전 청크 복수 포함, 구 규정 인용 | 컨텍스트 청크의 doc_id·version 중복률, sha256·MinHash 근사 중복률 | 높음 |
| H2 | 신규 문서 파싱 실패(HWP·표·OCR)로 깨진 청크 색인 | 텍스트 비율 낮은 청크, 깨진 문자·표 조각이 근거로 인용 | 신규 청크의 텍스트 비율·평균 길이·언어 감지, 샘플 50건 검수 | 높음 |
| H3 | 메타데이터(부서·문서유형·유효기간) 누락으로 필터·라우팅 미작동 | 필터 추출은 됐으나 0건 → 폴백, 엉뚱한 부서 문서 인용 | 신규 문서 메타 NULL률, 필터 질의 0건율 | 중 |
| H4 | ACL 누락·그룹 매핑 오류 → 기본 거부로 적절 문서 제외(또는 혼입) | 신규 부서 사용자의 거부율·“확인 불가” 급증 | acl_principals NULL률, ID 미매핑 건수, 부서별 거부율 |
높음 |
| H5 | 코퍼스 분포 변화로 BM25 IDF·HNSW 그래프 재구성, 샤드 불균형 | 기존 골든셋의 Recall@20이 신 인덱스에서 하락 | 3조합 (a) vs (b) 검색 지표, 샤드별 문서 수·지연 | 중 |
| H6 | LLM 버전 변경으로 프롬프트 호환성 저하(인용 형식 미준수·거부 경향·장황) | 인용 누락률·거부율·평균 답변 길이의 변화 시점이 버전 갱신일과 일치 | 3조합 (b) vs ©, 응답 포맷 검사기 통과율 | 높음 |
| H7 | 신규 문서가 길어 컨텍스트 토큰 증가 → lost-in-the-middle | context recall은 유지되는데 faithfulness·정답률 하락 | 컨텍스트 토큰 수 추이, 근거 위치(앞/중간/끝)별 정답률 | 중 |
| H8 | 신규 부서 질의 유형(예: 표 수치·절차)이 골든셋·프롬프트 설계 범위 밖 | 👎가 신규 부서 사용자·특정 유형에 집중 | 👎 샘플 100건 분류, 골든셋 유형 커버리지 | 높음 |
| H9 | 비공식·초안 문서(회의록) 유입, 숨김 텍스트로 인한 간접 인젝션 | source_tier 낮은 문서 인용, 이상 답변 | 인용 문서의 source_tier 분포, 가드레일 차단 로그 | 낮음 |
3. 진단 절차
| 순서 | 작업 | 소요 | 산출물 |
|---|---|---|---|
| 1 | 👎 샘플 100건을 부서·유형·실패 모드(근거 못 찾음 / 근거 있는데 틀림 / 과도한 거부 / 형식 불량)로 분류 | 2시간 | 실패 모드 분포표 → H1~H9 가중치 |
| 2 | 각 샘플의 트레이스 재생(검색 후보·재순위 점수·컨텍스트 청크·프롬프트·응답) | 반나절 | 샘플별 실패 구간 태그 |
| 3 | 3조합 골든셋 재평가 | 반나절~1일 | 구간별 지표 변화표(데이터 효과 vs 모델 효과) |
| 4 | 신규 커넥터 데이터 품질 프로파일(중복률·파싱 품질·메타/ACL NULL률·문서 길이 분포) | 3시간 | 품질 리포트 |
| 5 | 원인 확정과 대응 우선순위, 예상 효과 추정 | 1시간 | 원인 보고서 |
1·2단계가 먼저인 이유는 트레이스에 "컨텍스트에 정답 청크가 있었는가"가 기록돼 검색 실패와 생성 실패를 건별로 즉시 가를 수 있기 때문이고, 3단계는 이를 모집단 수준에서 확인한다.
4. 대응
- 즉시(당일): LLM 버전을 검증된 이전 버전으로 고정(pin)한다. 신규 부서 문서 중 파싱 실패·메타 누락·ACL 누락 청크를 삭제가 아니라
active = false로 격리해 검색 대상에서 뺀다.source_tier랭킹 가중치를 적용해 공식 문서를 우선한다. - 단기(1~2주): sha256·MinHash 중복 제거와 문서 버전 정책(최신만
active, 구버전은effective_to설정)을 신규 커넥터에 적용한다. 신규 부서 골든셋 50~100건을 추가하고, 프롬프트를 신 LLM 버전에 맞춰 재검증한 뒤 카나리 1~5%로 전환한다. 컨텍스트 예산을 줄이고 상위 근거를 앞·끝에 배치하며, 재순위(cross-encoder) 후보 수를 조정한다. - 구조(1~2개월): 커넥터 온보딩 표준을 만든다 — 파싱 품질 게이트(텍스트 비율·표 수), 필수 메타·ACL 필드, 중복 검사를 통과해야 색인한다. 인덱스 변경은 blue/green alias로 하고 구 인덱스를 보존 기간 동안 유지해 즉시 롤백할 수 있게 한다.
5. 재발 방지
- 모든 변경(커넥터·모델·프롬프트·인덱스·청킹)에 골든셋 자동 평가 게이트를 둔다. 임계 예: nDCG@10 −2pp, faithfulness −3pp, 거부 정확도 −5pp에 걸리면 배포 차단.
- LLM 프로바이더의 자동 업데이트를 금지하고 버전 고정 + 카나리 트래픽 + 회귀 통과 후 승격으로 바꾼다.
- 품질 대시보드에 👎율·거부율·인용 누락률·컨텍스트 토큰·파싱 실패율·중복률을 부서·커넥터 차원으로 두고 임계 알림을 건다.
- 커넥터별 데이터 컨트랙트에 필수 메타·ACL·파싱 품질 SLA를 명시한다.
결론. 가장 유력한 원인은 둘이다. 첫째, 신규 커넥터의 데이터 품질(H1 중복·구버전, H2 파싱, H4 ACL) — 임베딩·청킹이 그대로인데 검색 품질이 바뀌었다면 입력 데이터가 바뀐 것이고, 20만 건은 기존 코퍼스 대비 유의미한 비중이다. 둘째, LLM 버전 변경(H6) — 인용 형식·거부 경향은 모델 버전에 민감하고 변경 시점이 2주 기간과 일치한다. 두 효과는 3조합 재평가로 하루 안에 분리되며, 즉시 조치(버전 고정·불량 청크 격리)만으로도 👎율의 상당 부분을 되돌릴 수 있다.