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으로 RAGBenchcovidqa를 실제로 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 결과는 다음과 같았습니다.

SettingExact MatchRetrieval Hit RateAvg Token F1
top_k=5, rerank=true0.02850.97970.4482
top_k=5, rerank=false0.04880.97970.4583

핵심은 단순합니다.

  • retrieval hit rate는 사실상 동일했습니다.
  • 그런데 answer quality는 no-rerank가 더 좋았습니다.
  • latency도 no-rerank 쪽이 더 짧았습니다.

지금 병목은 “못 찾는다”보다, 찾아온 문맥을 generation이 어떻게 소비하느냐에 더 가깝습니다.

top_k를 늘리면 recall은 오르지만, 무조건 좋은 건 아니다

그다음은 no-rerank를 기준으로 top_k를 늘려 봤습니다.

top_kExact MatchRetrieval Hit RateAvg Token F1
50.04880.97970.4583
60.04470.98370.4661
70.04880.98780.4690
80.04880.98780.4648
100.03250.99590.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입니다.

Ready to try Schift?

Switch embedding models without re-embedding. Start free.

Get started free