OSS · CLI em Python

rag-retriever-bench

Problemas de retrieval se disfarçam de problemas de LLM.

Meça seu retriever antes de culpar seu LLM. Sete bancos vetoriais avaliados com o mesmo corpus, as mesmas queries e as mesmas métricas: recall, nDCG e latência, sem juiz LLM.

Ver no GitHub Relatório da execução de 100 mil →

  • Escolha o banco vetorial certo 7 bancos, 9 configurações, um placar só
  • Confie no seu recall recall@k, MRR e nDCG contra o gabarito completo
  • Pegue a degradação silenciosa o self_check confirma o uso real do índice
  • Entregue com latência conhecida p50 / p95 / p99 medidos em 100 mil passagens
  • Open Source · MIT
  • Sem juiz LLM
  • Relatório público de 100 mil passagens
  • Criado por Ken Imoto
Demo no terminal: saída de ajuda do rag-retriever-bench, seguida do relatório de uma execução real com 100 mil passagens MIRACL-ja comparando 9 configurações de backend em recall, nDCG e latência

Três passos

  1. rag-retriever-bench prepare Baixe o dataset, amostre o corpus e gere os embeddings uma vez (com cache).
  2. rag-retriever-bench run Faça benchmark das 9 configurações com as mesmas queries.
  3. results/*.md Compare o placar: qualidade, latência, ingestão e evidência de self_check por backend.

Para quem é

  • Engenheiros de IA escolhem banco vetorial com números medidos em vez de benchmarks de fornecedor
  • Desenvolvedores de RAG e busca confirmam que o índice funciona antes de mexer em qualquer prompt
  • Times de plataforma de IA padronizam um único benchmark entre os backends que operam
  • Pesquisadores de LLM precisam de baselines de retrieval reproduzíveis com gabarito completo

Quando usar

  • Antes de mexer em prompts: descarte o retriever primeiro e pare de depurar a camada errada
  • Antes de trocar de banco vetorial: decida com seus próprios números medidos em vez de benchmarks de fornecedor
  • Antes do deploy em produção: confirme com o self_check que o índice não está sendo ignorado em silêncio
  • Quando a busca parece estranha sem nenhum erro: os três casos de degradação silenciosa abaixo são exatamente isso

Instalação

git clone https://github.com/kenimo49/rag-retriever-bench
cd rag-retriever-bench
pip install -e ".[all]"

docker compose up -d
cp .env.example .env   # OPENAI_API_KEY (embeddings only)

Backends de servidor (pgvector, ClickHouse, Qdrant, Weaviate, Milvus) sobem via docker compose; Chroma e LanceDB são embutidos e dispensam serviços.

O que ele mede

  • Qualidade de retrieval: recall@k, hit@k, MRR@k, nDCG@k contra julgamentos de relevância anotados por humanos, sem juiz LLM
  • Latência de query: p50 / p95 / p99 / média no lado do cliente, com serialização incluída
  • Ingestão: segundos de carga em lote e de construção de índice por backend
  • 7 backends, 9 configurações: pgvector, ClickHouse (HNSW ×2 + força bruta), Qdrant, Weaviate, Milvus, Chroma, LanceDB
  • Um self_check por backend: sonda de EXPLAIN ou de estatísticas do servidor que confirma o uso real do índice ANN
  • Parâmetros HNSW alinhados entre backends (m=16, ef_construction=64, ef_search=100): a diferença reflete o motor, e a diferença de tuning fica de fora
  • Dataset MIRACL-ja: o corpus amostrado sempre contém todas as passagens positivas, então o recall é medido contra o gabarito completo

Resultados medidos (100 mil passagens)

MIRACL-ja, 100 mil passagens · 860 queries · text-embedding-3-small · top_k=10 · medido em 2026-07-11, nó único.

Backends de servidor (com salto de rede)

backendrecall@10nDCG@10p50 (ms)p95 (ms)
pgvector (HNSW)0.9360.8784.86.1
ClickHouse (HNSW)0.9230.86643.151.5
ClickHouse (HNSW, g=128)0.9210.86611.513.1
ClickHouse (brute force)0.9520.89165.986.7
Qdrant (HNSW)0.9470.8883.34.1
Weaviate (HNSW)0.9290.8731.82.1
Milvus (HNSW)0.9400.8822.02.3

Backends embutidos (in-process; latência incomparável com backends de servidor)

backendrecall@10nDCG@10p50 (ms)p95 (ms)
Chroma (HNSW, embedded)0.9290.8711.71.9
LanceDB (IVF_HNSW_SQ, embedded)0.8110.7771.81.9

A força bruta define o teto de qualidade com recall 0.952; a configuração ANN mais próxima é o Qdrant com 0.947. Nessa escala, os motores HNSW se diferenciam principalmente em latência: Weaviate e Milvus respondem abaixo de 2.5 ms no p95, e o ClickHouse leva de 13 a 52 ms conforme a granularidade do índice.

Quanto uma única escolha move os números

Mesmo corpus, mesmos embeddings, mesmo orçamento de HNSW. Só a decisão abaixo mudou.

Escolha do índice

recall@10 0.811 → 0.947

LanceDB IVF_HNSW_SQ vs Qdrant HNSW: uma diferença de recall de 0.136 sem nenhum erro levantado em nenhum dos lados.

Um parâmetro de índice

p95 51.5 ms → 13.1 ms

ClickHouse HNSW com granularidade de índice 128: a latência cai para um quarto e o recall fica praticamente igual (0.923 → 0.921).

Uso

# smoke run com 10 mil passagens (MIRACL-ja baixa no primeiro uso)
rag-retriever-bench run -c configs/miracl-ja.yaml --corpus-size 10000

# execução completa com 100 mil
rag-retriever-bench run -c configs/miracl-ja.yaml

# só preparação: baixar dataset, amostrar corpus, gerar embeddings
rag-retriever-bench prepare -c configs/miracl-ja.yaml
Captura de tela do terminal ao fim de uma execução com 100 mil passagens: duas tabelas listando cada backend com recall@10, nDCG@10, MRR@10, hit@10, latência p50/p95/p99, segundos de carga e de construção de índice
A saída de uma execução concluída: uma linha de placar por backend, do relatório real de 100 mil.

O que ele pegou

Três das nove configurações tinham um caminho para degradar em silêncio, sem levantar nenhum erro. A sonda self_check pegou as três durante o desenvolvimento:

  • ClickHouse HNSW: pular o passo OPTIMIZE FINAL faz as queries caírem quietamente para força bruta. A sonda de EXPLAIN pegou a degradação antes de ela virar um resultado de "ClickHouse é lento".
  • Qdrant: com indexing_threshold_kb acima do tamanho do corpus, o índice nunca é construído; a coleção reporta indexed_vectors_count = 0 e as buscas rodam no segmento bruto.
  • Milvus: depois de um flush, podia carregar um snapshot desatualizado sem os segmentos selados e devolver resultados parciais sem erro algum.

Todos esses caminhos de degradação produziam números de aparência plausível. Os relatórios saem em results/ como Markdown + JSONL, uma linha por backend com qualidade, latência, ingestão e a evidência de verificação do índice.

Os números são de MIRACL-ja + text-embedding-3-small em um único nó. Backends embutidos e de servidor aparecem em tabelas separadas porque a latência deles é incomparável de forma direta. Meça seus próprios dados antes de decidir.

Por que esta ferramenta existe

A maioria dos times de RAG otimiza prompts antes de verificar a qualidade do retrieval. Quando a resposta sai errada, o modelo leva a culpa e o prompt é reescrito, enquanto o retriever que devolveu as passagens erradas segue sem ser questionado. Este harness existe porque erros de retrieval são confundidos com falhas do LLM o tempo todo. Três das nove configurações acima podiam degradar sem levantar nenhum erro; nada nas respostas apontaria para o índice. Meça o retrieval primeiro.

Ao lado de RAGAS e DeepEval

São camadas complementares. RAGAS e DeepEval pontuam os contexts e as respostas que o seu pipeline devolve; este harness mede o backend de retrieval por baixo, antes de você se comprometer com um.

rag-retriever-benchRAGASDeepEval
O que avalia O próprio backend de retrieval Contexts e respostas que seu pipeline devolve Contexts e respostas que seu pipeline devolve
Sobe bancos vetoriais reais ✓ 7 backends via docker compose
Gabarito Qrels anotados por humanos, sem juiz LLM Principalmente juiz LLM; há variantes não LLM e por ID Baseado em juiz LLM
Latência e ingestão ✓ p50 / p95 / p99 + ingestão
CLI
Licença MIT Apache-2.0 Apache-2.0

O travessão indica ausência de menção nos docs oficiais em julho de 2026: os dois frameworks foram desenhados para pontuar o que o seu pipeline devolve, e essa é a divisão de trabalho esperada. Escolha o backend aqui e pontue seu pipeline com eles.

FAQ

Preciso de uma chave da API da OpenAI?

Só para gerar embeddings (text-embedding-3-small por padrão). Os embeddings ficam em cache como .npy, então reexecuções não chamam a API, e o benchmark em si nunca chama um LLM.

Posso usar modelos de embedding locais, como sentence-transformers ou Ollama?

Na v0.1, não. Os embeddings vêm apenas da API da OpenAI; trocar entre modelos de embedding da OpenAI funciona via config.

Há suporte a BM25 ou busca híbrida?

Ainda não. A v0.1 é só vetorial; o modo híbrido (vetor + full-text) está no roadmap da v0.2.

Posso comparar modelos de embedding com ele?

Isso fica fora do escopo por design: todos os backends recebem embeddings idênticos, então a diferença de score reflete o motor. Para comparar modelos de embedding, MTEB e JMTEB são as ferramentas certas.

Posso rodar o benchmark no meu próprio corpus?

Ainda não. A v0.1 usa MIRACL-ja fixo, em que o corpus amostrado sempre contém todas as passagens positivas, então o recall é medido contra o gabarito completo. Suporte a corpus próprio está no roadmap.

Por que só o retriever? Por que não avaliar o pipeline RAG inteiro?

Porque retrieval e geração quebram de formas diferentes e pedem consertos diferentes. Separar os dois vem se tornando prática aceita na avaliação de RAG: se as passagens certas nunca saem do banco de dados, nenhuma troca de prompt ou de modelo conserta a resposta. Este harness isola essa camada para você saber qual metade depurar.

Por que não usar só o RAGAS?

Use o RAGAS, só que para outra pergunta. O RAGAS pontua os contexts e as respostas que seu pipeline devolve; ele não sobe bancos vetoriais nem mede a latência deles. Este harness trabalha uma camada antes: qual banco e qual índice, verificados contra qrels anotados por humanos e sem juiz LLM.

Por que não o DeepEval?

A mesma divisão de trabalho. O DeepEval testa sua aplicação LLM em estilo de teste unitário, com métricas majoritariamente de juiz LLM, o que ajuda depois que o pipeline existe. Decidir qual banco vetorial deve ficar embaixo dele, com HNSW igualado e p95 medido, é a parte que este harness cobre.

Sobre o autor

Criado por Ken Imoto: mais de 300 artigos técnicos em Zenn, Qiita, Dev.to e neste site, mais de 40 livros em 4 idiomas, mais de 400 mil pageviews em Zenn e Qiita, 4 artigos de pesquisa no Zenodo e criador do LLMO Framework.

Relacionado

As medições deste harness alimentam o rag-db-advisor, um advisor MCP/CLI que responde perguntas sobre stack de RAG a partir da evidência medida.

Ferramentas relacionadas para devs

Todos os produtos →

← Todos os produtos