Use this file to discover all available pages before exploring further.
Este guia avalia as APIs de busca do MKA1 em relação a um conjunto de dados padrão de recuperação de informações.
Ele demonstra RAG com múltiplas tecnologias de armazenamento (Text Store e Tables) e processamento de documentos em alto volume — indexando milhares de documentos, executando consultas e medindo precisão e latência em cada etapa do pipeline.O benchmark utiliza o SciFact da suíte BEIR — 5.183 resumos científicos com 300 consultas de teste e julgamentos de relevância anotados por humanos.
Todas as embeddings são geradas com meetkai:functionary-pt (4.096 dimensões).
Uma consulta de recuperação passa por duas etapas: inferência de embedding (convertendo o texto da consulta em um vetor) e busca no banco de dados (encontrando os vetores mais próximos no repositório). O tempo total de resposta é a soma de ambos.
Métrica
Text Store
Tables
NDCG@10
72.4
71.8
Recall@10
83.1
82.6
MRR@10
68.9
68.3
Latência
Text Store
Tables
Inferência de embedding (por consulta)
12 ms
12 ms
Busca no banco p50 (lado do servidor)
8 ms
6 ms
Busca no banco p95 (lado do servidor)
14 ms
11 ms
Resposta ponta a ponta p50 (rede + embed + busca)
45 ms
38 ms
Resposta ponta a ponta p95 (rede + embed + busca)
82 ms
71 ms
Vazão de indexação (5.183 docs)
182 docs/seg
166 docs/seg
A latência de busca no banco de dados é reportada pelo próprio servidor (search_time_ms no corpo da resposta) e exclui a sobrecarga de rede e a inferência de embedding. O tempo de resposta ponta a ponta inclui tudo o que um cliente mediria.O restante deste guia mostra como esses números são produzidos, passo a passo.
Cada requisição de busca retorna um campo search_time_ms — a duração da busca no banco do lado do servidor, excluindo o tempo de ida e volta da rede e qualquer processamento upstream.
Medimos tanto esse tempo do lado do servidor quanto o tempo total ponta a ponta observado pelo cliente.
const K = 10;const results: Record<string, Record<string, number>> = {};const endToEndLatencies: number[] = [];const dbLatencies: number[] = [];console.log(`Executando ${queries.length} consultas no text store (top-${K})...`);for (let i = 0; i < queries.length; i++) { const q = queries[i]; const qVec = queryEmbeddings[i]; const start = performance.now(); const res = await fetch( `${BASE_URL}/api/v1/search/text-store/stores/${TEXT_STORE_NAME}/search`, { method: 'POST', headers: HEADERS, body: JSON.stringify({ query: q.text, vector: qVec, limit: K }), }, ); const searchResult = await res.json(); const elapsed = performance.now() - start; endToEndLatencies.push(elapsed); dbLatencies.push(searchResult.search_time_ms ?? 0); // Mapear resultados de volta para os IDs dos documentos do corpus comparando o texto results[q._id] = {}; const hits = searchResult.results ?? []; for (let rank = 0; rank < hits.length; rank++) { const hitText = hits[rank].text; const doc = corpus.find((d) => `${d.title} ${d.text}` === hitText); if (doc) { results[q._id][doc._id] = 1.0 / (rank + 1); // pontuação por posição } }}function percentile(arr: number[], p: number) { const sorted = [...arr].sort((a, b) => a - b); return sorted[Math.floor(sorted.length * p)];}console.log(`\nText Store — tempo de resposta ponta a ponta (${queries.length} consultas):`);console.log(` p50: ${percentile(endToEndLatencies, 0.5).toFixed(0)} ms`);console.log(` p95: ${percentile(endToEndLatencies, 0.95).toFixed(0)} ms`);console.log(` p99: ${percentile(endToEndLatencies, 0.99).toFixed(0)} ms`);console.log(`\nText Store — latência de busca no banco (search_time_ms do servidor):`);console.log(` p50: ${percentile(dbLatencies, 0.5).toFixed(0)} ms`);console.log(` p95: ${percentile(dbLatencies, 0.95).toFixed(0)} ms`);console.log(` p99: ${percentile(dbLatencies, 0.99).toFixed(0)} ms`);
Saída esperada
Executando 300 consultas no text store (top-10)...Text Store — tempo de resposta ponta a ponta (300 consultas): p50: 45 ms p95: 82 ms p99: 110 msText Store — latência de busca no banco (search_time_ms do servidor): p50: 8 ms p95: 14 ms p99: 18 ms
A diferença entre a latência ponta a ponta e a latência do banco de dados é o tempo de ida e volta da rede e a sobrecarga do gateway.
Executando 300 consultas na tabela (vector_search, top-10)...Tables — tempo de resposta ponta a ponta (300 consultas): p50: 38 ms p95: 71 ms p99: 95 msTables — latência de busca no banco (searchTimeMs do servidor): p50: 6 ms p95: 11 ms p99: 15 ms
const textStoreMetrics = computeMetrics(results, qrels, K);const tableMetrics = computeMetrics(tableResults, qrels, K);console.log('=== Precisão da Recuperação (SciFact, 5.183 docs, 300 consultas) ===');console.log('');console.log(`Métrica Text Store Tables (vector_search)`);console.log(`NDCG@10 ${textStoreMetrics.ndcg.toFixed(1)} ${tableMetrics.ndcg.toFixed(1)}`);console.log(`Recall@10 ${textStoreMetrics.recall.toFixed(1)} ${tableMetrics.recall.toFixed(1)}`);console.log(`MRR@10 ${textStoreMetrics.mrr.toFixed(1)} ${tableMetrics.mrr.toFixed(1)}`);console.log('');console.log('=== Quebra de Latência ===');console.log('');console.log(`Etapa Text Store Tables`);console.log(`Inferência de embedding (por q) ${perQueryEmbedMs.toFixed(0)} ms ${perQueryEmbedMs.toFixed(0)} ms`);console.log(`Busca no BD p50 (servidor) ${percentile(dbLatencies, 0.5).toFixed(0)} ms ${percentile(tableDbLatencies, 0.5).toFixed(0)} ms`);console.log(`Busca no BD p95 (servidor) ${percentile(dbLatencies, 0.95).toFixed(0)} ms ${percentile(tableDbLatencies, 0.95).toFixed(0)} ms`);console.log(`Resposta ponta a ponta p50 ${percentile(endToEndLatencies, 0.5).toFixed(0)} ms ${percentile(tableEndToEnd, 0.5).toFixed(0)} ms`);console.log(`Resposta ponta a ponta p95 ${percentile(endToEndLatencies, 0.95).toFixed(0)} ms ${percentile(tableEndToEnd, 0.95).toFixed(0)} ms`);console.log(`Vazão de indexação ${(corpus.length / (indexMs / 1000)).toFixed(0)} docs/s ${(corpus.length / (tableIndexMs / 1000)).toFixed(0)} docs/s`);
Saída esperada
=== Precisão da Recuperação (SciFact, 5.183 docs, 300 consultas) ===Métrica Text Store Tables (vector_search)NDCG@10 72.4 71.8Recall@10 83.1 82.6MRR@10 68.9 68.3=== Quebra de Latência ===Etapa Text Store TablesInferência de embedding (por q) 12 ms 12 msBusca no BD p50 (servidor) 8 ms 6 msBusca no BD p95 (servidor) 14 ms 11 msResposta ponta a ponta p50 45 ms 38 msResposta ponta a ponta p95 82 ms 71 msVazão de indexação 182 docs/s 166 docs/s
Inferência de embedding é igual para ambos os backends — utiliza o mesmo modelo.
Busca no BD é o tempo puro de banco de dados reportado pelo servidor (search_time_ms / searchTimeMs). Aqui é onde Text Store e Tables diferem — Text Store executa busca híbrida (vetor + FTS), Tables executa busca vetorial pura.
Resposta ponta a ponta inclui ida e volta de rede, sobrecarga do gateway e busca no banco. A diferença entre ponta a ponta e busca no BD é a sobrecarga.
NDCG@10 é a principal métrica. Penaliza documentos relevantes que aparecem em posições inferiores.
Recall@10 mede quantos documentos relevantes aparecem entre os 10 primeiros — importante para pipelines RAG onde a geração depende da completude da recuperação.
MRR@10 mede quão rapidamente o primeiro resultado relevante aparece — importante para buscas voltadas ao usuário.
Text Store vs Tables: Text Store adiciona busca híbrida (vetor + palavra-chave) automaticamente. Tables oferece controle explícito sobre tipo de índice, métrica de distância e filtros.
Uma consulta de recuperação tem três componentes de latência:
Inferência de embedding — tempo para converter o texto da consulta em um vetor. Isso é inferência de modelo e é igual independentemente do backend de armazenamento.
Busca no banco de dados — tempo que o mecanismo de busca leva para encontrar os vizinhos mais próximos. Reportado pelo servidor em search_time_ms (Text Store) ou searchTimeMs (Tables). É o tempo puro de busca vetorial/híbrida sem sobrecarga de rede.
Resposta ponta a ponta — o que o cliente observa: ida e volta de rede + roteamento do gateway + busca no banco.
Se a latência ponta a ponta for alta mas a busca no banco for rápida, o gargalo está na rede ou no gateway.
Se a busca no banco for alta, considere um tipo de índice diferente (por exemplo, IVF_HNSW_SQ para busca aproximada mais rápida).