70%짜리 검색으로 90%짜리 경험을 만드는 법
정체된 RAG precision 대신 확신에 찬 오답 경험을 문제로 다시 정의하고, 출력 설계와 LLM-as-judge로 품질을 관리한 방법.
앞선 두 글에서 MCP 서버를 출시하고(1편), 질문을 RAG와 Text2SQL로 라우팅하는 Multi-Agent를 짰다(2편)고 했습니다. 그런데 진짜 어려운 질문은 그다음이었습니다. “이게 잘 돌아가는 걸 어떻게 알지?”
1. AI 파이프라인은 평가가 어렵다
일반 소프트웨어는 “입력 A면 출력 B”가 명확합니다. 테스트가 쉽죠. 그런데 자연어 질의응답은 정답이 하나가 아닙니다. 같은 질문에도 좋은 답이 여러 개고, 미묘하게 틀린 답도 여러 개입니다. “그냥 써보니 괜찮은 것 같다”는 감으로는 제품을 못 굴립니다.
그래서 두 층으로 나눠 봤습니다.
- 검색 품질(retrieval): 답을 만들 근거를 제대로 가져왔는가 → precision/recall
- 답변 품질(answer): 가져온 근거로 맞고 유용한 답을 냈는가
2. precision 90% 목표, 70% 실측
RAG의 심장은 검색입니다. 근거를 잘못 가져오면 그 뒤 LLM이 아무리 좋아도 틀립니다. 그래서 retrieval precision 목표를 90%로 잡았는데, Hybrid Search에 Re-ranking까지 붙여도 70% 부근에서 멈췄습니다.
여기서 흔한 반응은 정해져 있습니다. “모델을 더 튜닝하자. 임베딩을 바꾸자. 청킹을 다시 하자.” 저도 몇 번 그 길로 갔습니다. 그런데 투입 대비 개선폭이 빠르게 줄었습니다. 70%를 75%로 만드는 데 드는 노력이, 처음 0%를 60%로 만든 노력보다 컸죠.
3. 질문을 바꿨다 — “사용자를 괴롭히는 게 뭐지?”
정체된 지점에서 저는 지표를 잠깐 내려놓고 물었습니다. “precision 70%가 사용자에게 실제로 어떻게 느껴지지?”
답은 분명했습니다. 사용자를 괴롭히는 건 70이라는 숫자가 아니라, 가끔 나오는 ‘확신에 찬 틀린 답’ 이었습니다. 열 번 중 세 번, 시스템이 당당하게 틀리면 신뢰가 무너집니다. 반대로, 애매할 때 “이건 확실치 않으니 이것도 확인해보세요”라고 말해주면, 같은 70%여도 신뢰는 유지됩니다.
그래서 저는 모델이 아니라 출력을 설계했습니다.
- 검색 근거의 확신도가 낮으면 단정적으로 답하지 않고,
- “관련해서 이 부분도 확인이 필요합니다” 식의 추가 확인 정보(suggestion) 를 함께 제시하도록.
정량 지표(precision 70%)는 그대로였습니다. 하지만 사용자가 체감하는 오답 경험은 사실상 사라졌습니다.
4. 답변 품질은 어떻게 봤나 — LLM을 심판으로
수백 개 답을 사람이 일일이 채점할 순 없었습니다. 그래서 LLM-as-judge를 썼습니다. 질문·근거·생성된 답을 다른 LLM에게 주고, “근거에 충실한가”, “질문에 답했는가”, “환각이 없는가”를 채점하게 한 거죠.
핵심은 심판 프롬프트를 구체적 기준으로 묶는 것이었습니다. “좋은 답인가?“가 아니라 “근거에 없는 사실을 지어냈는가(yes/no)“처럼 판정 가능한 질문으로 쪼갤수록, 자동 평가가 사람 판단에 가까워졌습니다. 이렇게 평가를 자동화하니, 프롬프트를 바꿀 때마다 회귀 테스트처럼 품질을 확인할 수 있었습니다.
# 개념 예시: 판정 가능한 기준으로 쪼갠 LLM-as-judge
def judge(question, context, answer):
prompt = f"""질문/근거/답변을 보고 각 항목을 yes/no로만 판정하세요.
- grounded: 답변이 근거에 있는 내용만 사용했는가?
- answered: 질문에 실제로 답했는가?
- no_hallucination: 근거에 없는 사실을 지어내지 않았는가?
질문: {question}
근거: {context}
답변: {answer}
JSON으로만 답하세요."""
return parse_json(llm(prompt)) # {"grounded": true, ...}
5. 이 시리즈가 남긴 한 문장
세 편에 걸친 이야기를 한 줄로 줄이면 이렇습니다.
지표를 올리는 것과 경험을 개선하는 것은 다른 문제다. 좋은 엔지니어는 둘의 차이를 안다.
precision 70%는 부족한 숫자입니다. 하지만 그 70%를 어떻게 ’전달’하느냐에 따라, 사용자에겐 90%처럼 느껴질 수도, 50%처럼 느껴질 수도 있었습니다. 모델을 붙잡고 씨름하는 대신 문제를 다시 정의한 것 — 그게 이 프로젝트에서 제가 가장 잘한 판단이었다고 생각합니다.
읽어주셔서 감사합니다.