종종 RAG 서비스를 만들다 보면 최종 답변이 마음에 들지 않을 때 가장 먼저 프롬프트를 수정하고 싶어진다.
나도 처음에는 생성된 문장이 이상하면 자연스럽게 LLM 쪽을 먼저 봤다.
프롬프트에 조건을 하나 더 넣어보고, 추천 이유를 더 구체적으로 작성하라고 지시하거나, 답변 형식을 바꾸는 식이다.
그런데 도서 검색·추천 서비스를 실제로 구성하면서는 문제를 보는 순서가 달라졌다.
그래서 지금은 답변이 이상하면 반드시 가장 먼저 다음 질문부터 한다.
LLM에게 어떤 책을 넘겼는가?
왜냐하면 RAG에서는 LLM이 최종 답변을 생성하기 전에 이미 검색 단계에서 사용할 정보의 범위가 상당 부분 결정되기 때문이다.
Elastic의 RAG 구조 역시 기본적으로 사용자 질문 → 관련 문서 검색 → 검색 결과를 LLM Context로 전달 → 답변 생성 순서로 설명된다.
따라서 첫 번째 단계에서 관련 없는 문서를 가져왔다면 뒤에서 아무리 프롬프트를 잘 작성해도 좋은 답변을 만들기 어렵다.
이 글에서는 RAG 답변이 이상할 때 왜 프롬프트보다 검색 결과부터 확인하는지, 그리고 실제 서비스에서는 어느 단계에서 문제가 발생했는지를 어떻게 구분하는지 정리해보려고 한다.
내가 만든 서비스에서는 한 번의 검색 요청이 여러 단계를 지난다
내가 만들던 도서 검색·추천 API에서는 사용자가 자연어로 검색한다.
예를 들어:
요즘 회사 생활이 너무 지쳐서
부담 없이 읽으면서 조금 위로받을 수 있는 책
같은 문장이 들어올 수 있다.
API 구조를 단순화하면 다음에 가깝다.
사용자 질문
↓
검색 조건 처리
↓
Elasticsearch 검색
↓
실제 도서 후보
↓
LLM에 전달할 정보 구성
↓
추천 문장 생성
↓
최종 응답
Elasticsearch 검색에는 텍스트 기반 검색과 KNN을 사용할 수 있도록 검색 모드를 분리해 두었고, 사용자가 선택한 도서관을 기준으로 libCode 조건도 함께 사용했다.
최종 응답에는 단순히 책 제목만 반환하는 것이 아니라 다음과 같은 정보도 만들어야 했다.
추천 이유
책을 어떻게 활용할 수 있는지
읽었을 때 기대할 수 있는 점
추천 문장
후속 질문
즉 LLM의 역할은 분명히 존재한다.
하지만 LLM이 어떤 책에 대해서 이런 문장을 작성할지는 이미 검색 단계에서 결정된다.
이 부분 때문에 RAG 문제를 생성 모델 하나의 문제로 보면 원인을 놓치기 쉽다.
예를 들어 검색 단계에서 잘못된 책이 들어오면 어떻게 될까
사용자가 다음과 같이 검색했다고 하자.
파이썬을 처음 공부하는 사람이
어렵지 않게 읽을 책
내가 기대하는 검색 결과는 대략 이런 성격일 것이다.
Python 입문
프로그래밍 기초
초보자 대상
예제가 쉬운 책
그런데 Elasticsearch가 상위 후보로 다음과 같은 책을 가져왔다고 생각해보자.
Python 내부 구현
고급 데이터 엔지니어링
머신러닝 최적화
알고리즘 고급 활용
이 상태에서 LLM에:
이 사용자에게 가장 적합한 책을 추천하고 친절하게 이유를 설명해라.
라고 프롬프트를 작성해도 문제가 해결되지 않는다.
LLM에게 주어진 선택지가 이미 잘못됐기 때문이다.
구조를 보면 더 명확하다.
사용자 질문
"Python 초보 책"
↓
검색 결과
고급 Python 책
머신러닝 책
알고리즘 책
↓
LLM
"초보자에게 적합한 책을 추천해줘"
LLM은 어려운 상황에 놓인다.
검색 결과 밖의 책을 자유롭게 만들어내도록 허용한다면 RAG를 사용하는 의미가 약해진다.
반대로 검색된 데이터만 이용하도록 제한한다면 잘못된 후보 중에서 가장 그럴듯한 답을 골라야 한다.
어느 쪽이든 좋은 결과를 기대하기 어렵다.
그래서 이런 상황에서 프롬프트를:
초보자에게 반드시 쉬운 책을 추천하세요.
라고 더 강하게 만드는 것은 근본적인 해결 방법이 아니다.
먼저 왜 검색 단계에서 초보자용 책이 후보에 들어오지 않았는지를 봐야 한다.
Retrieval에서 빠진 정보는 Generation 단계에서 복구하기 어렵다
이게 RAG 디버깅에서 가장 중요하게 보는 부분이다.
RAG를 사용하는 목적 중 하나는 모델이 외부 데이터에서 검색한 정보를 근거로 답하도록 만드는 것이다. Elastic 역시 RAG를 외부 데이터에서 관련 Context를 검색한 뒤 이를 모델의 Context Window에 제공하는 방식으로 설명한다.
그렇다면 좋은 문서가 Retrieval 단계에서 빠졌다는 것은 무엇을 의미할까?
관련 도서 A
관련 도서 B
관련 도서 C
가 실제 데이터에는 존재한다고 하자.
그런데 검색 결과는:
관련 없는 D
관련 없는 E
관련 없는 F
만 반환했다.
LLM에게 전달되는 Context에도 결국:
D
E
F
만 들어간다.
LLM 입장에서는 A, B, C가 존재한다는 사실을 알 수 없다.
따라서 정상적인 grounded RAG를 유지하려면 A, B, C를 갑자기 만들어내서 추천해서도 안 된다.
즉:
Retrieval에서 누락
↓
Context에도 없음
↓
Generation에서 사용할 근거 없음
이라는 구조가 된다.
그래서 나는 RAG 최종 답변 품질의 상한선이 상당 부분 Retrieval 품질에 의해 결정된다고 본다.
그렇다고 검색 결과가 좋으면 항상 좋은 답변이 나오는 것도 아니다
반대 방향도 중요하다.
검색된 책들이 모두 적절하다고 해서 최종 답변이 반드시 좋아지는 것은 아니다.
예를 들어 Elasticsearch에서는 다음 책을 제대로 찾았다고 하자.
도서 A
도서 B
도서 C
그런데 LLM에는 제목만 전달했다.
[
{
"title": "도서 A"
},
{
"title": "도서 B"
},
{
"title": "도서 C"
}
]
사용자 질문은:
이 책이 직장 스트레스를 줄이는 데
왜 도움이 될 수 있는지 설명해줘.
이다.
제목만 가지고는 책의 실제 내용과 사용자 질문을 연결하기 어렵다.
반면 다음 정보를 같이 전달하면 상황이 달라진다.
{
"title": "...",
"author": "...",
"keywords": ["...", "..."],
"description": "...",
"pubYear": "..."
}
검색은 정상인데 LLM에 전달하는 정보가 부족하면 최종 답변은 또 다른 이유로 얕아질 수 있다.
그래서 나는 RAG 문제를 최소한 세 단계로 구분하는 편이 낫다고 생각한다.
1. Retrieval
2. Context Construction
3. Generation
첫 번째 문제: Retrieval 실패
가장 먼저 확인하는 것은 Retrieval이다.
질문은 단순하다.
검색 단계에서 내가 기대했던 책이 실제로 나왔는가?
예를 들어 사용자 질문이:
주식을 처음 공부하는 사람이
읽기 좋은 책
이라고 하자.
내가 기대하는 관련 도서 몇 권을 미리 알고 있다면 Elasticsearch 결과를 직접 확인한다.
검색 결과 Top 10
에서 기대 도서가 전혀 없다면 그 시점에서는 LLM을 볼 필요가 없다.
검색 문제다.
여기에서 확인해야 할 원인은 여러 가지다.
검색 대상 데이터에 책이 실제로 있는가
가장 먼저 확인해야 하는데 의외로 놓치기 쉽다.
내가 기대하는 책이 Elasticsearch index 자체에 없다면 어떤 파라미터를 조정해도 검색되지 않는다.
libCode 필터에서 제외되지 않았는가
내 서비스에서는 특정 도서관의 도서만 검색하도록 libCode 조건을 적용한다.
따라서 전체 데이터에는 책이 존재해도 사용자가 선택한 도서관 데이터에는 없을 수 있다.
이 상황에서는 검색 결과에 나오지 않는 것이 정상이다.
문서 embedding이 존재하는가
KNN 검색을 사용한다면 해당 도서의 embedding 필드가 정상적으로 생성되어 있는지도 확인해야 한다.
벡터가 없다면 의미 검색 대상이 될 수 없다.
문서 embedding에 무엇을 넣었는가
이것도 중요하다. 간단히 살펴보면
예를 들어 책의 embedding을 만들 때 제목만 사용했다면:
title
사용자가:
사람 관계 때문에 지친 사람이 읽으면 좋은 책
이라고 검색했을 때 실제 책의 내용을 표현할 정보가 부족할 수 있다.
반면:
title
keywords
description
을 적절하게 사용했다면 책의 의미를 표현할 정보가 더 많아진다.
Hybrid Search와 KNN 중 어느 쪽에서 문제가 발생하는가
내 검색 API에서는 검색 방식을 비교할 수 있도록 hybrid와 knn 모드를 분리했다.
이 구조는 RAG 디버깅에서도 유용하다.
같은 검색어에서:
Hybrid → 원하는 책이 나옴
KNN → 원하는 책이 없음
이라면 벡터 검색 쪽을 먼저 의심할 수 있다.
반대로:
KNN → 적절함
Hybrid → 이상함
이라면 title boost나 keywords, description 같은 텍스트 검색 신호를 확인할 수 있다.
Elastic 역시 Elasticsearch 기반 RAG에서 full-text, vector, hybrid search 등 여러 검색 접근법으로 관련 문서를 먼저 확보한 뒤 LLM에 Context를 전달하는 구조를 지원한다.
두 번째 문제: 검색은 맞는데 Context를 잘못 만드는 경우
이 단계는 생각보다 많이 놓친다.
Elasticsearch에서는 좋은 책을 찾았다.
그런데 LLM에 전달하는 과정에서 정보가 빠진다.
예를 들어 검색 결과는:
{
"title": "도서 A",
"author": "저자 A",
"keywords": [
"직장생활",
"번아웃",
"감정관리"
],
"description": "..."
}
인데 실제 프롬프트에는:
도서 A
만 들어갔다고 하자.
검색 시스템은 자신의 역할을 제대로 했다.
하지만 Context Construction 단계에서 중요한 정보를 버렸다.
이 상황에서 답변이 얕게 나온다고 Elasticsearch Query를 바꿔도 해결되지 않는다.
반대로 프롬프트 문장만 바꿔도 해결되지 않을 수 있다.
모델에게 필요한 근거 자체를 충분히 전달해야 한다.
Context를 많이 넣으면 무조건 좋아지는 것도 아니다
여기서 또 반대 문제가 생긴다.
정보가 부족하니 모든 것을 넣으면 되지 않을까 생각할 수 있다.
예를 들어 검색된 책 30권의:
title
author
description
keywords
reviews
category
publication information
을 모두 LLM에 넣는 식이다.
그러면 정보량은 많아진다.
하지만 모든 정보가 사용자의 질문과 관련 있는 것은 아니다.
관련성이 낮은 문서까지 Context에 대량으로 들어오면:
필요한 근거
+
애매한 근거
+
관련 없는 근거
가 한꺼번에 모델에 제공된다.
이 경우 단순히 Context 양이 많은 것이 장점이라고 볼 수 없다.
RAG에서는 결국 필요한 정보를 충분히 제공하면서 불필요한 정보는 제한하는 것이 중요하다.
그래서 Retrieval의 Top K와 Context에 실제로 넣는 문서 수를 무조건 동일하게 볼 필요도 없다.
예를 들어 검색에서는 10개를 확보한 뒤:
Top 10 Retrieval
↓
조건 확인 / 후처리
↓
Top 3~5 Context
↓
LLM
처럼 사용할 수도 있다.
최근 Elasticsearch에서는 여러 retrieval 전략을 조합하거나 reranking하는 retriever 구조도 제공한다. 이는 첫 단계에서 후보를 수집한 후 다른 방식으로 결과를 다시 정렬하는 검색 파이프라인을 구성할 수 있게 한다.
세 번째 문제: 검색과 Context는 정상인데 Generation이 이상한 경우
마지막으로 여기까지 정상이라면 그때 LLM과 프롬프트를 본다.
예를 들어 검색 결과가:
직장인 번아웃 관련 도서
감정 회복 관련 도서
인간관계 관련 도서
로 적절하다.
LLM에도 책의:
title
keywords
description
이 정상적으로 전달됐다.
그런데 최종 답변이:
이 책은 투자 방법을 배우는 데 도움이 됩니다.
처럼 Context와 맞지 않는다면 이때는 Generation 문제를 의심할 수 있다.
여기에서 확인할 것이 프롬프트다.
예를 들어:
검색된 도서 정보만 이용하는가?
검색 결과에 없는 정보를 만들어도 되는가?
추천 이유와 사실 설명을 구분하는가?
책마다 어떤 필드를 근거로 설명하도록 했는가?
출력 형식을 모델이 이해할 수 있는가?
등을 본다.
Elastic의 RAG 기본 흐름에서도 검색된 Context를 모델에 전달한 뒤 별도의 instruction을 이용해 최종 답변 형식을 통제하는 단계를 구분한다.
이때 비로소 Prompt Engineering이 의미가 있다.
그래서 나는 이상한 RAG 답변을 세 가지 유형으로 나눈다
지금 같은 서비스를 다시 디버깅한다면 최종 답변만 보고 수정하지 않을 것이다.
먼저 문제를 분류한다.
유형 A — 책 자체가 이상하다
예:
사용자:
Python 입문책 추천
검색:
고급 머신러닝
CUDA 최적화
분산 시스템
이건 Retrieval 문제다.
유형 B — 책은 맞는데 설명 근거가 부족하다
검색된 책:
적절함
Context:
제목만 전달
답변:
굉장히 추상적
이건 Context Construction 문제일 가능성이 크다.
유형 C — 검색과 데이터 모두 맞는데 설명이 틀린다
검색:
정상
Context:
충분함
생성:
Context에 없는 내용 추가
이 경우 Generation과 Prompt를 본다.
이렇게 나누는 것만으로도 디버깅 범위가 상당히 줄어든다.
최종 답변만 로그로 남기면 원인을 찾기 어렵다
RAG를 운영하면서 중요하게 보는 것 중 하나가 로그다.
예를 들어 다음 정보만 저장한다고 하자.
사용자 질문
최종 답변
나중에 이상한 답변을 발견하면 다음 질문에 답할 수 없다.
당시 어떤 책이 검색됐는가?
Hybrid였나 KNN이었나?
검색 결과 순위는 어땠는가?
어떤 정보를 Context에 넣었는가?
그러면 결국 같은 요청을 다시 실행해서 재현해야 한다.
하지만 검색 index나 데이터가 변경됐다면 당시 결과와 완전히 똑같이 재현되지 않을 수도 있다.
그래서 RAG 로그는 생성 결과만 남겨서는 부족하다.
내가 다시 로그를 설계한다면 최소한 이것을 남긴다
검색 요청 하나를 기준으로 다음과 같은 정보를 연결해두고 싶다.
request_id
사용자 검색어
libCode
검색 mode
k
num_candidates
검색된 도서 ISBN
검색된 도서 제목
검색 결과 순위
score
LLM에 실제 전달한 도서
최종 추천 결과
응답시간
오류
예를 들어 개념적으로는 다음과 같은 로그를 생각할 수 있다.
{
"request_id": "...",
"query": "파이썬 처음 공부할 책",
"libCode": "128057",
"mode": "knn",
"retrieved": [
{
"rank": 1,
"isbn13": "...",
"title": "...",
"score": 0.82
},
{
"rank": 2,
"isbn13": "...",
"title": "...",
"score": 0.79
}
],
"context_books": [
"...",
"..."
],
"generated_result": "..."
}
이런 로그가 있으면 최종 답변에 문제가 생겼을 때 역으로 추적할 수 있다.
최종 답변 이상
↓
Context 확인
↓
Retrieval 확인
↓
검색 설정 확인
이게 RAG를 운영하면서 굉장히 중요하다.
내가 기존 검색 로그를 더 활용하려는 이유도 이것이다
내 서비스에서는 검색과 추천 문장에 관련된 로그를 별도로 저장하는 구조를 사용했다.
이런 데이터를 단순히 사용 횟수를 세기 위한 통계로만 보면 아깝다.
실제로는 검색 품질 평가 데이터로 사용할 수 있다.
예를 들어 특정 검색어가 반복적으로 들어오는데 매번 결과가 좋지 않다면 그 검색어를 테스트 세트에 추가할 수 있다.
실제 사용자 검색어
↓
검색 실패 사례 수집
↓
평가 Query Set
↓
검색 알고리즘 개선
↓
전후 비교
이렇게 하면 개발자가 임의로 만든 검색어보다 실제 사용자가 어려움을 겪었던 검색어를 가지고 개선할 수 있다.
“좋은 답변인가?”만 평가하면 어느 부분이 좋아졌는지 알 수 없다
RAG 시스템을 한 개의 점수로 평가하고 싶은 유혹도 있다.
예를 들어:
답변 품질 8점
처럼 평가한다.
하지만 시스템 개선에는 부족하다.
답변이 나쁜 이유가 Retrieval인지 Generation인지 구분되지 않기 때문이다.
그래서 평가도 단계별로 나누는 것이 좋다.
Retrieval 평가
관련 도서가 Top K에 들어왔는가?
기대 도서의 순위는 얼마인가?
관련 도서를 얼마나 놓쳤는가?
Context 평가
필요한 필드가 전달됐는가?
관련 없는 문서가 너무 많이 들어가지 않았는가?
동일한 내용이 중복되지 않았는가?
Generation 평가
검색 데이터에 근거해 답했는가?
존재하지 않는 도서 정보를 만들지 않았는가?
사용자 질문에 실제로 답했는가?
추천 이유가 제공된 Context와 연결되는가?
이렇게 나눠야 검색 설정을 바꿨을 때 정말 Retrieval이 좋아졌는지, 프롬프트를 바꿨을 때 Generation이 좋아졌는지 구분할 수 있다.
Retrieval을 평가하려면 결국 정답에 가까운 데이터를 만들어야 한다
예를 들어 다음 질문이 있다고 하자.
Python을 처음 공부하는 사람에게
적합한 책
평가하려면 최소한:
이 질문에서는
A, B, C 정도가 관련 도서라고 판단한다.
같은 기준이 필요하다.
그러면 Top 5에 A, B, C 중 몇 권이 포함됐는지 볼 수 있다.
다음처럼 비교도 가능하다.
Hybrid
A
B
D
E
F
KNN
B
C
G
A
H
이런 결과가 있어야:
Hybrid가 더 좋다.
또는:
KNN이 더 좋다.
를 느낌이 아니라 질문 유형별로 판단할 수 있다.
정답 후보가 전혀 없는 상태에서 검색 결과를 눈으로 몇 번 보고 튜닝하면 개발자의 개인적인 인상에 지나치게 의존하게 된다.
실제 사용자의 검색 실패가 좋은 테스트 데이터가 된다
운영 서비스에서는 오히려 실패 사례가 중요한 자산이 될 수 있다.
예를 들어 로그를 보다가 다음 검색어를 발견했다고 하자.
아이가 책을 싫어하는데
흥미를 붙이기 좋은 책
현재 검색 결과가 만족스럽지 않다면 이 검색어를 버릴 필요가 없다.
오히려 테스트 데이터로 저장한다.
그리고:
현재 Hybrid 결과
현재 KNN 결과
내가 기대하는 책
문제점
을 기록한다.
검색 설정을 변경한 뒤 같은 질문을 다시 실행한다.
이렇게 하면 실제 서비스 개선 여부를 직접 비교할 수 있다.
내가 지금 다시 검색·추천 시스템을 운영한다면 사용자 실패 Query를 지속적으로 평가 데이터로 전환하는 구조를 만들고 싶다.
프롬프트 수정은 마지막에 하는 편이 원인을 찾기 쉽다
RAG 답변이 이상할 때 처음부터 여러 가지를 동시에 수정하면 문제가 하나 더 생긴다.
예를 들어 한 번에:
KNN num_candidates 변경
Document Embedding 변경
Top K 변경
Prompt 변경
을 모두 한다고 하자.
결과가 좋아졌다.
그런데 무엇 때문에 좋아졌는지 알 수 없다.
반대로 나빠져도 어느 변경이 원인인지 알 수 없다.
그래서 나는 가능하면 하나씩 분리해서 보는 것이 좋다고 생각한다.
1. Retrieval 고정
→ Generation 테스트
2. Prompt 고정
→ Retrieval 테스트
3. Query 고정
→ k / num_candidates 테스트
이런 식이다.
검색 결과 자체를 고정한 뒤 프롬프트만 변경하면 생성 단계의 차이를 볼 수 있다.
반대로 프롬프트를 고정한 뒤 검색 결과만 바꾸면 Retrieval 영향에 더 집중할 수 있다.
좋은 프롬프트가 나쁜 Retrieval을 가리기도 한다
이 부분도 조심해야 한다.
성능 좋은 LLM은 부족한 Context가 주어져도 상당히 그럴듯한 답변을 만들 수 있다.
이 때문에 오히려 문제가 숨어버릴 수 있다.
예를 들어 검색 결과가 사용자의 질문과 완전히 맞지는 않지만 모델이 일반 지식을 이용해 자연스러운 설명을 추가했다고 하자.
사용자가 읽을 때는 꽤 좋아 보인다.
하지만 서비스에서 원하는 것이:
우리 도서관 데이터에 근거한 추천
이라면 이것은 원하는 성공이 아닐 수 있다.
RAG의 목적은 모델이 알아서 부족한 검색 결과를 메우도록 두는 것이 아니라, 검색된 근거를 이용해 신뢰할 수 있는 답을 만드는 것이기 때문이다. Elastic 역시 RAG를 외부의 검증 가능한 정보로 모델 응답을 grounding하는 접근으로 설명한다.
그래서 자연스러운 문장만 보고 검색 품질까지 좋다고 판단하면 안 된다.
내가 RAG 문제를 볼 때 사용하는 순서
현재 같은 서비스를 다시 디버깅한다면 다음 순서로 본다.
1. 사용자 입력 확인
실제로 어떤 검색어가 들어왔는가?
전처리 과정에서 원문이 달라지지 않았는지도 확인한다.
2. Retrieval 결과 확인
Top K에 무엇이 나왔는가?
기대 도서가 존재하는지 본다.
3. 검색 조건 확인
mode
libCode
k
num_candidates
같은 조건을 확인한다.
4. 검색 대상 데이터 확인
원하는 책이 실제 index에 있는가?
embedding이 있는가?
필터를 통과하는가?
를 본다.
5. Context 확인
검색된 책 중 무엇을 LLM에 전달했는가?
어떤 필드를 전달했는가?
를 본다.
6. 마지막으로 Prompt와 Generation 확인
이전 단계가 모두 정상일 때:
프롬프트
출력 형식
grounding 조건
추천 문장
을 확인한다.
이 순서를 사용하면 최소한 검색 문제를 프롬프트로 해결하려고 시간을 쓰는 일을 줄일 수 있다.
RAG에서 검색은 단순한 전처리가 아니다
처음에는 Elasticsearch 검색을 LLM 호출 전에 필요한 전처리 단계 정도로 생각하기 쉽다.
하지만 실제로는 다르다.
RAG에서 Retrieval은:
LLM이 어떤 세계를 보고 답할 것인지 결정하는 단계
에 가깝다.
검색 결과가:
A
B
C
라면 LLM이 바라보는 데이터 세계는 A, B, C다.
검색 결과가:
D
E
F
라면 아무리 같은 질문이라도 모델이 보는 근거는 완전히 달라진다.
그래서 RAG를 운영하면 검색 시스템과 생성 시스템을 따로 볼 수 없다.
Retrieval 품질
↓
Context 품질
↓
Generation 품질
↓
최종 답변 품질
앞 단계가 뒤 단계의 입력이 된다.
마무리
RAG 답변이 이상하면 LLM부터 의심하기 쉽다.
최종적으로 사용자에게 보이는 것은 LLM이 만든 문장이기 때문이다.
하지만 실제 구조를 보면 그 문장이 만들어지기 전에 이미 많은 것이 결정되어 있다.
검색 시스템이 어떤 문서를 가져왔는지,
그중 어떤 정보를 Context로 전달했는지,
그리고 마지막으로 모델이 그 Context를 어떻게 사용했는지가 순서대로 연결된다.
그래서 지금은 문제를 다음 세 가지로 나눠 본다.
Retrieval Failure
Context Construction Failure
Generation Failure
그리고 반드시 앞에서부터 확인한다.
좋은 책이 검색 단계에서 빠졌다면 먼저 검색을 고친다.
책은 제대로 찾았는데 정보가 부족하게 전달됐다면 Context를 고친다.
그 두 단계가 정상인데도 잘못된 설명이 나온다면 그때 Prompt와 Generation을 본다.
이 순서를 사용하면:
답변이 이상하니 프롬프트를 더 길게 써보자.
라는 방식에서 벗어날 수 있다.
결국 RAG를 안정적으로 운영하려면 좋은 프롬프트 하나보다 어느 단계에서 정보가 틀어졌는지를 다시 추적할 수 있는 구조가 더 중요하다고 생각한다.
그래서 검색어, Retrieval 결과, Context에 사용된 문서, 최종 생성 결과를 서로 연결해서 로그로 남겨두는 것이 필요하다.
그 데이터가 쌓여야 검색 품질과 생성 품질을 각각 개선할 수 있고, 같은 문제가 다시 발생했을 때도 추측이 아니라 당시 실제 데이터를 기준으로 원인을 확인할 수 있기 때문이다.