Engineering
RAGBench covidqa: top_k는 7이 sweet spot이었다
Schift retrieval stack으로 RAGBench covidqa를 end-to-end로 돌려 보니, 현재 설정에서는 rerank보다 no-rerank가 낫고 top_k=7이 가장 균형이 좋았다.
RAG에서 top_k는 사소한 튜닝처럼 보이지만, 실제로는 retrieval recall과 generation noise를 동시에 건드립니다.
이번에는 Schift retrieval stack으로 RAGBench의 covidqa를 실제로 end-to-end 실행해서, 지금 우리 기본값이 어디에 있어야 하는지 확인했습니다.
결론부터 말하면 두 가지였습니다.
- 현재 설정에서는 rerank를 켜는 것이 오히려 손해였습니다.
- 현재 sweet spot은
top_k=7이었습니다.
어떻게 측정했나
이번 비교는 retrieval만 따로 본 것이 아니라, retrieval + generation 전체 경로를 같이 봤습니다.
고정한 값은 다음과 같습니다.
- dataset:
galileo-ai/ragbench/covidqa - queries: 전체
246 - embedding:
schift-embed-1 - generation:
gemini-2.5-flash-lite - query enhance: off
- baseline prompt: concise answer prompt
- Schift retrieval: live collection search
즉 이번 글은 “문서를 잘 찾았는가”만 보는 pure retrieval 실험이 아니라, 실제 RAG 품질에서 top_k가 어떤 trade-off를 만드는가를 본 기록입니다.
먼저, rerank는 이 설정에서 이기지 못했다
같은 top_k=5에서 full run 결과는 다음과 같았습니다.
| Setting | Exact Match | Retrieval Hit Rate | Avg Token F1 |
|---|---|---|---|
top_k=5, rerank=true | 0.0285 | 0.9797 | 0.4482 |
top_k=5, rerank=false | 0.0488 | 0.9797 | 0.4583 |
핵심은 단순합니다.
- retrieval hit rate는 사실상 동일했습니다.
- 그런데 answer quality는 no-rerank가 더 좋았습니다.
- latency도 no-rerank 쪽이 더 짧았습니다.
지금 병목은 “못 찾는다”보다, 찾아온 문맥을 generation이 어떻게 소비하느냐에 더 가깝습니다.
top_k를 늘리면 recall은 오르지만, 무조건 좋은 건 아니다
그다음은 no-rerank를 기준으로 top_k를 늘려 봤습니다.
| top_k | Exact Match | Retrieval Hit Rate | Avg Token F1 |
|---|---|---|---|
5 | 0.0488 | 0.9797 | 0.4583 |
6 | 0.0447 | 0.9837 | 0.4661 |
7 | 0.0488 | 0.9878 | 0.4690 |
8 | 0.0488 | 0.9878 | 0.4648 |
10 | 0.0325 | 0.9959 | 0.4679 |
이 표가 보여주는 패턴은 분명했습니다.
top_k=10
retrieval_hit_rate만 보면 가장 좋습니다. 거의 0.996까지 올라갑니다.
하지만 answer quality는 오히려 떨어졌습니다.
즉 더 많이 가져오면 “정답이 포함될 확률”은 올라가지만, generation 단계에서는 불필요한 문맥까지 함께 들어오면서 답변이 흐려지는 구간이 생깁니다.
top_k=5
가장 단순한 기본값으로는 여전히 괜찮습니다.
하지만 7과 비교하면 retrieval hit rate와 F1에서 둘 다 약간 밀립니다.
top_k=7
7은 중요한 균형점이었습니다.
- Exact Match는
5와 동일한 최고치 유지 - Retrieval Hit Rate는
5보다 개선 - Avg Token F1는 이번 sweep에서 최고
8이상으로 늘렸을 때 나타나는 noise 증가는 아직 크지 않음
즉 recall을 조금 더 챙기면서도 generation 품질을 망치지 않는 마지막 지점에 가깝습니다.
왜 7이 sweet spot처럼 보였나
이번 결과를 retrieval/generation 관점으로 나누면 이렇게 볼 수 있습니다.
1. retrieval은 이미 충분히 강하다
top_k=5에서도 retrieval hit rate가 이미 0.98에 가깝습니다.
즉 지금 상태에서 가장 큰 문제는 “문서를 못 찾는다”가 아닙니다.
2. generation은 너무 많은 context에 약하다
top_k=10에서 retrieval hit는 좋아졌지만 EM이 내려갔다는 것은, generation이 context를 더 잘 이용하게 된 것이 아니라 오히려 더 헷갈리기 시작했다는 뜻입니다.
3. 그래서 최적점은 recall의 최대값이 아니라 answer quality의 균형점이다
RAG 기본값은 retrieval metric 하나만 보고 정하면 안 됩니다.
실제로 유저가 체감하는 것은 정답 포함 여부가 아니라 최종 답변 품질이기 때문입니다.
이번 covidqa에서는 그 균형점이 7이었습니다.
우리가 바꾼 것
이번 결과를 기준으로 Schift의 기본 retrieval surface는 top_k=7 쪽으로 맞췄습니다.
적용 대상은 다음입니다.
- RAG chat default
- public agent query default
- Python SDK chat default
- Python SDK tool helper default
반대로 compatibility vector query surface처럼 기존 동작 보존 의미가 큰 경로는 이번 변경에 포함하지 않았습니다.
이번 실험이 말해주는 것
짧게 정리하면 이렇습니다.
- 지금 Schift retrieval stack에서 rerank는 default가 될 근거가 없다
top_k는 크게 올린다고 좋아지지 않는다- 현재 production-minded default는
top_k=7+no-rerank쪽이 가장 합리적이다
한 문장으로 줄이면:
지금 우리 RAG 품질 병목은 retrieval recall 부족보다 context consumption 쪽에 있고, 그래서 default는
top_k=10이 아니라top_k=7이어야 했다.
다음 단계는 명확합니다.
- reader/generation prompt를 더 체계적으로 분리해서 평가하고
- context packing 전략을 조정하고
- 필요하면 selective rerank만 다시 검토하는 것
하지만 적어도 지금 기준의 default는 정해졌습니다.
top_k=7이 현재 sweet spot입니다.