제6부 생성형 AI 플랫폼
6.10 RAG II — 파이프라인·평가
6.10.1 이 장에서 배우는 것 / 선수 지식
6.9에서 RAG의 검색 절반(임베딩·청킹·벡터DB·리랭킹)을 만들었다. 이 장은 그것을 생성과 연결한 엔드투엔드 RAG(검색 → 문맥 구성 → grounding 프롬프트 → 생성 → 인용)를 완성하고, RAG의 실질적 난제 — 평가 — 를 판다. RAG 묶음(6.9~6.10)의 마지막.
핵심 통찰: RAG는 평가 없이는 개선할 수 없다. 검색·청킹·프롬프트를 바꿔도 "더 나아졌나"를 못 재면 추측일 뿐이다. 그리고 RAG 실패는 두 곳에서 온다 — 검색이 정답을 못 가져옴(retrieval miss), 또는 LLM이 가져온 문맥을 무시하고 환각(hallucination). 이 둘을 분리해 진단해야 올바른 곳을 고친다. 평가를 못 하면 "검색을 고쳐야 하는데 프롬프트를 만지는" 무익한 작업을 한다.
배우는 것:
- 엔드투엔드 파이프라인 — 문맥 구성(순서·중복·토큰 예산·lost-in-the-middle), grounding 프롬프트, 생성, 인용.
- RAG 평가의 두 층 — 검색 평가(recall@k·MRR·NDCG)와 생성 평가(충실성/groundedness·답 관련성·문맥 관련성).
- RAG triad — 문맥 관련성·groundedness·답 관련성으로 실패를 국소화.
- 평가 방법 — LLM-as-judge(주의)·인간 평가·참조 기반, 평가셋 구축.
- 실패 모드·진단 루프 — retrieval miss vs hallucination을 분리해 고치기.
- 운영 — 재인덱싱·신선도·production RAG 품질 모니터링.
선수 지식: 6.9(검색 — 이 장의 입력), 6.7(LLM·임베딩·리랭킹 NIM), 6.1(지식=RAG), 6.5(평가 규율·LLM-judge), 6.6(decontamination·정직한 평가). 가드레일은 6.11, MLOps 관측은 7.7. 환경은 6.9.
정직: RAG 평가 프레임워크(Ragas류)·LLM-judge·메트릭은 활발한 연구·도구 영역으로 버전·접근이 다양하다. LLM-judge는 편향·불안정이 있다. 이 장은 평가의 원리·실패 분리·진단 루프를 가르치고 특정 도구는 중립적으로. 모든 점수는 환경 의존, 인간 평가로 검증.
6.10.2 엔드투엔드 파이프라인
6.9의 검색을 생성과 잇는다:
검색 단계(질의 → 임베딩 → ANN 검색 → 리랭킹)는 6.9, 문맥 구성·grounding 생성·답+인용은 이 장이 다룬다.
각 단계는 NIM family(6.7)로: 임베딩 NIM(검색)·리랭킹 NIM·LLM NIM(생성). LangChain·LlamaIndex 같은 오케스트레이션으로 묶거나 직접 구성.
6.10.3 문맥 구성 — 검색 결과를 프롬프트로
리랭킹된 top-n 청크를 어떻게 프롬프트에 넣느냐가 답 품질을 좌우한다.
| 고려사항 | 내용 |
|---|---|
| 토큰 예산 | 문맥 윈도(5.7)에 들어갈 만큼만. top-n 청크 + 질의 + 지시가 한도 내 |
| 순서(lost in the middle) | LLM은 문맥 '중간'의 정보를 놓치기 쉬움(처음·끝에 주목) → 가장 관련 높은 청크를 앞·뒤에 배치(리랭킹 점수 순 활용) |
| 중복 제거 | 비슷한 청크가 여러 개면 토큰 낭비 → dedup |
| 메타데이터 | 출처·날짜를 청크와 함께 넣어 인용·최신성 판단에 활용 |
| 충돌 처리 | 모순된 청크가 섞이면 LLM 혼란 → 최신·권위 우선, 또는 명시 |
lost in the middle은 중요한 실전 함정이다 — 긴 문맥의 중간에 정답이 있으면 LLM이 놓치기 쉽다. 그래서 맹목적으로 많은 청크를 넣지 말고(top-n을 적정하게), 관련도 순으로 배치한다. 토큰 예산도 KV·지연(5.7)에 직결 — 긴 문맥은 비용이 크다.
6.10.4 grounding 프롬프트 — 환각 줄이기
LLM이 가져온 문맥에만 근거하도록 프롬프트로 제약한다(grounding):
시스템 프롬프트(예):
"아래 '문맥'만을 근거로 질문에 답하라.
문맥에 답이 없으면 '제공된 자료에서 찾을 수 없습니다'라고 답하라.
추측하지 말고, 답의 근거가 된 출처를 [1][2]로 인용하라."
문맥:
[1] (청크1 + 출처)
[2] (청크2 + 출처)
...
질문: {사용자 질의}
grounding의 핵심:
- "문맥만 근거"·"없으면 모른다": 환각을 크게 줄인다 — 모델이 자기 지식으로 지어내지 않고 검색된 근거로만.
- 인용 요구: 답의 출처를 제시해 검증·신뢰. groundedness 평가(6.10.6)와 연결.
- 추측 금지: 불확실하면 거부하도록 — 틀린 답보다 "모른다"가 나은 도메인(의료·법률·정책)에 중요.
핵심: grounding 프롬프트는 환각 통제의 1차 방어선이다. 그러나 프롬프트만으로 완벽하지 않다(모델이 무시할 수 있음) — 평가로 groundedness를 측정하고, 필요하면 가드레일(6.11)로 출력 검증. 그리고 grounding이 좋아도 검색이 정답을 못 가져오면 "모른다"가 최선(retrieval을 고쳐야).
6.10.5 RAG 평가의 두 층 — 검색 vs 생성
RAG 실패는 두 곳에서 온다. 분리해 평가해야 한다.
왜 분리가 중요한가:
분리 안 하면 '검색 문제를 프롬프트로 고치려는' 무익한 작업이 된다.
6.10.6 RAG triad — 실패 국소화
생성 평가의 실용 틀: 세 관계를 본다(질문·문맥·답의 삼각형).
세 변을 각각 점수화하면 어느 변이 낮은지로 실패 원인을 국소화할 수 있다:
- context relevance 낮음 → 검색 문제(6.9: 청킹·임베딩·리랭킹)
- groundedness 낮음 → 환각(프롬프트·모델·가드레일)
- answer relevance 낮음 → 질문 이해·프롬프트
이 RAG triad가 진단의 핵심 도구다 — "답이 나쁘다"를 세 변으로 분할해 무엇을 고칠지를 가리킨다. 검색을 고칠지 생성을 고칠지를 데이터로 결정한다.
6.10.7 평가 방법·평가셋
평가셋 구축(가장 중요·어려움):
- 대표 질문 집합(실제 사용자 질의 분포 반영)
- 각 질문에 대해(가능하면):
- 정답 청크(검색 평가용 ground-truth)
- 참조 답(correctness용)
- decontamination(6.6): 평가 질문이 학습/인덱스에 누출되지 않게(정직성)
평가 방법:
| 방법 | 무엇을 | 주의 |
|---|---|---|
| 참조 기반 | 정답 청크·참조 답과 비교(recall·correctness) | ground-truth 라벨 필요(비쌈) |
| LLM-as-judge | LLM이 groundedness·관련성 점수 | 편향·불안정 — 보정·인간 검증 필요 |
| 인간 평가 | 사람이 답·근거 판정 | 가장 신뢰, 비쌈·느림 |
| 자동 메트릭 | 임베딩 유사도 등 | 보조, 단독 신뢰 금지 |
정직: LLM-as-judge는 편리하나 편향(자기 선호·위치·장황함 편향)이 있다 — 보정(여러 judge·기준 프롬프트)하고 인간 평가로 주기적 검증한다. 자동 메트릭만으로 RAG 품질을 단정하지 말 것. 평가셋이 운영 분포를 대표하고 누출이 없어야(decontamination) 점수가 정직하다.
6.10.8 워크스루 — 진단 루프
RAG를 측정·진단·개선하는 루프.
# 진단의 개념(LLM-judge 예시 — 편향 주의, 인간 검증 병행)
for item in eval_set:
ctx = retrieve(item.query) # 6.9 검색
answer = llm_generate(ctx, item.query) # grounding 프롬프트
metrics = {
"recall@k": recall(ctx, item.gold_chunks), # 검색
"context_rel": judge_context_relevance(item.query, ctx),
"grounded": judge_groundedness(answer, ctx), # 환각 탐지
"answer_rel": judge_answer_relevance(item.query, answer),
}
log(metrics) # 낮은 변(variable)이 어디인지 집계 → 무엇을 고칠지
핵심: 한 번에 하나만 바꿔 재측정(A/B)한다 — 청킹·임베딩·프롬프트를 동시에 바꾸면 무엇이 효과인지 모른다. RAG triad로 어느 변이 병목인지 보고 그 변에 해당하는 레버를 조정한다. production 피드백을 평가셋으로 환류해 지속 개선(라이프사이클 순환, 6.1).
6.10.9 중간 점검 (체크포인트)
- [ ] 엔드투엔드 RAG 파이프라인과 문맥 구성(토큰 예산·lost-in-the-middle·순서·중복·충돌)을 설명한다.
- [ ] grounding 프롬프트("문맥만·없으면 모른다·인용")가 환각을 줄이는 1차 방어선임을 안다.
- [ ] RAG 평가의 두 층(검색 vs 생성) 을 분리하고, 각 메트릭(recall@k·groundedness 등)을 제시한다.
- [ ] RAG triad(context relevance·groundedness·answer relevance)로 실패를 국소화한다.
- [ ] LLM-judge의 편향·인간 평가·평가셋 구축(누출 방지)을 안다.
- [ ] 진단 루프(측정 → triad 국소화 → 한 가지 변경 → 재측정 → 운영 피드백)를 수행한다.
증상→의심: 답이 틀림 → triad로 분리: context_rel 낮음=검색(6.9), grounded 낮음=환각, answer_rel 낮음=질문 이해. 문맥에 정답 있는데 LLM이 무시·환각 → grounding 프롬프트 약함·lost-in-the-middle → 프롬프트 강화·순서·top-n 축소. 검색이 정답 못 가져옴 → 청킹·임베딩·recall·리랭킹(6.9). 평가 점수와 실사용 괴리 → 평가셋 비대표·누출 → 평가셋 갱신·decontam. LLM-judge 점수 불안정 → judge 편향 → 인간 검증·보정. 시간 지나며 품질 저하 → 인덱스 staleness → 재인덱싱(신선도).
6.10.10 트레이드오프·대안
RAG 개선 레버.
| 변(triad) | 레버 | 트레이드오프 |
|---|---|---|
| context relevance↓ | 청킹·임베딩·ANN recall·리랭킹·하이브리드(6.9) | 정밀↑·비용↑ |
| groundedness↓ | grounding 프롬프트·"모른다"·가드레일(6.11)·모델 | 보수적(거부↑) |
| answer relevance↓ | 프롬프트·query rewriting·멀티홉 | 복잡·지연↑ |
| 토큰/지연 | top-n·청크 크기 | 문맥↑·비용/지연↑(5.7) |
| 평가 | LLM-judge vs 인간 | 비용이 낮고 빠름·편향 vs 신뢰·비쌈 |
견해: 검색을 먼저 고쳐라 — RAG 실패의 다수는 검색(context relevance)이고, 검색이 정답을 못 주면 grounding·모델로 못 메운다("모른다"가 최선). 검색이 맞는데 환각이면 grounding·가드레일. 한 번에 하나, 평가로 검증이 철칙. 평가는 LLM-judge로 빠르게 + 인간으로 주기 검증. 정밀도가 critical하면 리랭킹·하이브리드·강한 grounding·가드레일을 적층.
비엔비디아 정직: RAG 파이프라인·평가는 공개 연구·도구 생태계다(LangChain·LlamaIndex·Ragas·TruLens 등). 엔비디아 스택의 강점은 GPU 가속 검색(6.9)·NIM family·통합이고, 평가·오케스트레이션은 도구 중립이다. RAG triad·검색/생성 분리·진단 루프는 어느 스택에서나 동일한 본질 — 그것을 이해하는 것이 핵심. 모든 점수는 인간 평가로 검증.
6.10.11 흔한 함정
- 평가 없이 튜닝. 청킹·프롬프트를 바꿔도 측정 못 하면 추측. RAG triad·recall로 측정.
- 검색/생성 미분리. "답이 틀림"을 하나로 보면 검색 문제를 프롬프트로 고치는 무익한 작업. 분리 진단.
- lost in the middle 무시. 청크를 맹목적으로 많이 넣으면 중간 정답을 LLM이 놓침. top-n 적정·관련도 순 배치.
- grounding 프롬프트 누락. "문맥만·모르면 거부"가 없으면 LLM이 자기 지식으로 환각. 추가.
- LLM-judge 맹신. 편향·불안정 — 인간 검증·보정 없이 단독 신뢰 금지.
- 평가셋 누출·비대표. 평가 질문이 인덱스·학습에 누출되거나 운영 분포와 다르면 점수가 거짓(6.6). decontam·대표성.
- 인덱스 staleness. 문서 갱신을 재인덱싱 안 하면 옛 정보 → 신선도 파이프라인.
- 여러 레버 동시 변경. 효과를 분리 못 함. A/B로 하나씩.
- 충돌·중복 문맥 방치. 모순·중복 청크가 LLM을 혼란·토큰 낭비 → dedup·최신 우선.
6.10.12 연습문제
연습 1 (실패 분리). RAG 답이 자주 틀린다. RAG triad로 어떻게 원인을 셋으로 나눠 진단하고, 각각 어디를 고치는지 설명하라.
정답
RAG triad로 세 변을 점수화: ① context relevance 낮음(검색 문맥이 질문과 무관) → 검색 문제 → 청킹·임베딩 모델·ANN recall·리랭킹·하이브리드 수정(6.9). 정답이 인덱스에 있어도 못 가져온 것. ② groundedness 낮음(답이 검색 문맥에 의해 뒷받침 안 됨 = 환각) → 생성 문제 → grounding 프롬프트 강화("문맥만·모르면 거부"), lost-in-the-middle 완화(top-n·순서), 모델·가드레일(6.11). ③ answer relevance 낮음(답이 질문에 동문서답) → 질문 이해 문제 → 프롬프트·query rewriting·멀티홉. 분리의 가치: "답이 틀림"을 하나로 보면 검색 문제를 프롬프트로 고치려는 무익한 작업 — triad로 병목 변을 찾아 해당 레버만 조정한다. 한 번에 하나 바꿔 재측정.
연습 2 (grounding). grounding 프롬프트("문맥만 근거, 없으면 모른다고")가 환각을 줄이는 원리와, 그래도 환각이 남는 두 경우와 대응을 설명하라.
정답
원리: grounding 프롬프트는 LLM에게 "자기 사전 지식이 아니라 제공된 문맥만 근거로, 문맥에 답이 없으면 거부하라"고 지시 → 모델이 지어내는 대신 검색된 근거에 묶여 환각이 크게 줄고, 인용 요구로 검증 가능. 그래도 남는 경우: ① 검색이 틀린 문맥을 줌 — 검색이 무관/오류 청크를 가져오면 LLM이 그 잘못된 근거로 "충실하게" 틀린 답(groundedness는 높아도 정답이 아님). 대응: 검색을 고침(6.9, context relevance), "모른다"가 나오도록. ② 모델이 지시를 무시·과신 — 프롬프트에도 불구하고 사전 지식으로 보충하거나 문맥을 왜곡. 대응: 더 강한 grounding·작은 top-n(lost-in-the-middle)·가드레일로 출력 검증(6.11, groundedness 체크)·더 충실한 모델. 핵심: grounding은 1차 방어선이나 검색 오류·모델 불순종을 못 막으니 평가(groundedness)로 측정 + 검색 수정 + 가드레일을 함께.
연습 3 (lost in the middle). 검색 recall을 높이려 top-20 청크를 모두 문맥에 넣었더니 답이 오히려 나빠졌다. 원인과 해결을 설명하라.
정답
원인: ① lost in the middle — LLM은 긴 문맥의 중간 정보를 처음·끝보다 잘 놓친다. top-20을 다 넣으면 정답 청크가 중간에 묻혀 무시될 수 있음. ② 무관·중복 청크 희석 — top-20엔 관련 낮은 청크가 다수 섞여(리랭킹 없이) 문맥이 노이즈로 흐려지고 LLM이 혼란. ③ 토큰·지연·비용↑(5.7 KV). 해결: 리랭킹으로 top-n을 줄임(예 top-20 검색→리랭킹→top-5만 문맥, 6.9), 관련도 순 배치(가장 관련 청크를 앞·뒤에), 중복 제거, 적정 top-n으로 노이즈·중간 묻힘 방지. recall은 1단계(검색)에서 충분히 확보하되 LLM에 넣는 것은 정밀하게 추린 소수. "많이 넣으면 좋다"는 틀림 — 정밀한 소수가 낫다.
연습 4 (평가셋·LLM-judge). RAG를 LLM-as-judge로 평가해 groundedness 점수가 높게 나왔다. 이를 그대로 신뢰하면 안 되는 이유와 올바른 평가 절차를 제시하라.
정답
신뢰 못 하는 이유: LLM-judge는 편향·불안정하다 — 자기 선호(같은 모델 계열 선호), 위치 편향, 장황한 답 선호, 프롬프트 민감성 등으로 점수가 실제 품질과 어긋날 수 있다. 또 judge가 groundedness를 "그럴듯함"으로 잘못 판정할 수 있음. 올바른 절차: ① 평가셋의 대표성·누출 점검(운영 분포 반영, decontamination 6.6 — 평가 질문이 인덱스에 누출 안 됨). ② LLM-judge는 보조로 쓰되 기준 프롬프트·여러 judge·일관성 체크로 보정. ③ 인간 평가로 주기적 검증(judge 점수가 인간과 상관하는지) — 가장 신뢰. ④ 가능하면 참조 기반(정답 청크 recall·참조 답 correctness)을 병행. ⑤ production 실제 피드백을 평가셋에 환류. 핵심: 자동 점수 단독 신뢰 금지, 인간 검증으로 보정.
연습 5 (진단 루프). RAG 품질을 개선하라는 과제다. 측정→진단→개선→재측정의 루프를 설계하고, "한 번에 하나만 바꾼다"가 왜 중요한지 설명하라.
정답
루프: ① 측정 — 대표 평가셋으로 검색(recall@k)·생성(RAG triad: context relevance·groundedness·answer relevance) 점수. ② 진단 — triad에서 가장 낮은 변을 찾아 병목 국소화(context rel↓=검색, grounded↓=환각, answer rel↓=질문 이해). ③ 개선 — 그 변에 해당하는 레버만 조정(검색이면 청킹·임베딩·recall·리랭킹·하이브리드 6.9; 환각이면 grounding·가드레일 6.11; 질문 이해면 프롬프트·query rewriting). ④ 재측정 — 같은 평가셋으로 그 변경의 효과 확인 → 개선이면 채택, 아니면 롤백. ⑤ 운영 피드백 — production 질의·실패를 평가셋에 갱신, 신선도(재인덱싱)·드리프트 추적(7.7). "한 번에 하나"가 중요한 이유: 청킹·임베딩·프롬프트를 동시에 바꾸면 어느 것이 효과(또는 악화)인지 분리 불가 → 무엇을 유지·되돌릴지 모름. A/B로 하나씩 바꿔야 인과를 알고 누적 개선 가능. RAG 개선은 과학적 실험처럼 변수 통제.
6.10.13 요약 · 다음 장(RAG 묶음 마무리)
- 엔드투엔드 RAG는 검색(6.9) → 문맥 구성(토큰 예산·lost-in-the-middle·순서·중복·충돌) → grounding 프롬프트("문맥만·모르면 거부·인용") → 생성·인용으로 잇는다. NIM family로 구성.
- RAG는 평가 없이 개선 불가. 실패는 검색(context relevance) 과 생성(groundedness·answer relevance) 두 곳에서 오므로 분리해 진단한다 — 검색 문제를 프롬프트로 고치는 무익한 작업을 피한다.
- RAG triad(문맥 관련성·groundedness·답 관련성)로 실패를 국소화하고, 낮은 변의 레버만 조정한다. 한 번에 하나, 평가로 검증.
- 평가는 참조 기반 + LLM-judge(편향 주의·보정) + 인간 검증, 평가셋은 대표성·누출 방지(decontamination). production 피드백을 환류해 순환(6.1)·신선도(재인덱싱) 관리.
- 검색을 먼저 고친다 — 검색이 정답을 못 주면 grounding·모델로 못 메운다("모른다"가 최선). 정직: 평가 도구는 생태계 의존·도구 중립, RAG triad·진단은 본질, 점수는 인간 검증.
다음 장: 6.11 가드레일·에이전트·안전. 제6부의 마지막. RAG·생성형 시스템에 안전·정책 통제(NeMo Guardrails — 입출력 필터·주제 제한·환각/groundedness 체크)를 붙이고, 모델이 도구를 호출하며 다단계로 행동하는 에이전트 워크플로와 그 안전을 본다. 이로써 생성형 AI 플랫폼(제6부, 6.1~6.11)을 마무리한다.