Use this file to discover all available pages before exploring further.
Esta guía evalúa las APIs de búsqueda de MKA1 frente a un conjunto de datos estándar de recuperación de información.
Demuestra RAG con múltiples tecnologías de almacenamiento (Text Store y Tables) y procesamiento de documentos a gran escala — indexando miles de documentos, ejecutando consultas y midiendo precisión y latencia en cada etapa del flujo.El benchmark utiliza SciFact de la suite BEIR — 5,183 resúmenes científicos con 300 consultas de prueba y juicios de relevancia anotados por humanos.
Todas las incrustaciones se generan con meetkai:functionary-es-mini (4,096 dimensiones).
Una consulta de recuperación pasa por dos etapas: inferencia de incrustación (convertir el texto de la consulta en un vector) y búsqueda en la base de datos (encontrar los vectores más cercanos en el almacén). El tiempo total de respuesta es la suma de ambas.
Métrica
Text Store
Tables
NDCG@10
72.4
71.8
Recall@10
83.1
82.6
MRR@10
68.9
68.3
Latencia
Text Store
Tables
Inferencia de incrustación (por consulta)
12 ms
12 ms
Búsqueda en base de datos p50 (lado servidor)
8 ms
6 ms
Búsqueda en base de datos p95 (lado servidor)
14 ms
11 ms
Respuesta extremo a extremo p50 (red + embed + búsqueda)
45 ms
38 ms
Respuesta extremo a extremo p95 (red + embed + búsqueda)
82 ms
71 ms
Rendimiento de indexado (5,183 docs)
182 docs/seg
166 docs/seg
La latencia de búsqueda en base de datos es reportada por el propio servidor (search_time_ms en el cuerpo de la respuesta) y excluye la sobrecarga de red y la inferencia de incrustación. El tiempo de respuesta extremo a extremo incluye todo lo que mediría un cliente.El resto de esta guía muestra cómo se producen estos números, paso a paso.
Cada solicitud de búsqueda devuelve un campo search_time_ms — la duración de la búsqueda en base de datos del lado del servidor, excluyendo el viaje de ida y vuelta de red y cualquier procesamiento adicional.
Medimos tanto este tiempo del servidor como el tiempo de respuesta extremo a extremo observado por el cliente.
const K = 10;const results: Record<string, Record<string, number>> = {};const endToEndLatencies: number[] = [];const dbLatencies: number[] = [];console.log(`Ejecutando ${queries.length} consultas contra 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 a IDs de documentos del corpus por coincidencia de 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); // puntuación por ranking } }}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 — tiempo de respuesta extremo a extremo (${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 — latencia de búsqueda en base de datos (search_time_ms del 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`);
Salida esperada
Ejecutando 300 consultas contra text store (top-10)...Text Store — tiempo de respuesta extremo a extremo (300 consultas): p50: 45 ms p95: 82 ms p99: 110 msText Store — latencia de búsqueda en base de datos (search_time_ms del servidor): p50: 8 ms p95: 14 ms p99: 18 ms
La diferencia entre la latencia extremo a extremo y la de base de datos es el viaje de ida y vuelta de red y la sobrecarga del gateway.
Ejecutando 300 consultas contra tabla (vector_search, top-10)...Tables — tiempo de respuesta extremo a extremo (300 consultas): p50: 38 ms p95: 71 ms p99: 95 msTables — latencia de búsqueda en base de datos (searchTimeMs del servidor): p50: 6 ms p95: 11 ms p99: 15 ms
const textStoreMetrics = computeMetrics(results, qrels, K);const tableMetrics = computeMetrics(tableResults, qrels, K);console.log('=== Precisión de Recuperación (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('=== Desglose de Latencia ===');console.log('');console.log(`Etapa Text Store Tables`);console.log(`Inferencia de incrustación (por c) ${perQueryEmbedMs.toFixed(0)} ms ${perQueryEmbedMs.toFixed(0)} ms`);console.log(`Búsqueda BD p50 (servidor) ${percentile(dbLatencies, 0.5).toFixed(0)} ms ${percentile(tableDbLatencies, 0.5).toFixed(0)} ms`);console.log(`Búsqueda BD p95 (servidor) ${percentile(dbLatencies, 0.95).toFixed(0)} ms ${percentile(tableDbLatencies, 0.95).toFixed(0)} ms`);console.log(`Respuesta extremo a extremo p50 ${percentile(endToEndLatencies, 0.5).toFixed(0)} ms ${percentile(tableEndToEnd, 0.5).toFixed(0)} ms`);console.log(`Respuesta extremo a extremo p95 ${percentile(endToEndLatencies, 0.95).toFixed(0)} ms ${percentile(tableEndToEnd, 0.95).toFixed(0)} ms`);console.log(`Rendimiento de indexado ${(corpus.length / (indexMs / 1000)).toFixed(0)} docs/s ${(corpus.length / (tableIndexMs / 1000)).toFixed(0)} docs/s`);
Salida esperada
=== Precisión de Recuperación (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=== Desglose de Latencia ===Etapa Text Store TablesInferencia de incrustación (por c) 12 ms 12 msBúsqueda BD p50 (servidor) 8 ms 6 msBúsqueda BD p95 (servidor) 14 ms 11 msRespuesta extremo a extremo p50 45 ms 38 msRespuesta extremo a extremo p95 82 ms 71 msRendimiento de indexado 182 docs/s 166 docs/s
Inferencia de incrustación es la misma para ambos backends — ejecuta el mismo modelo.
Búsqueda BD es el tiempo puro de base de datos reportado por el servidor (search_time_ms / searchTimeMs). Aquí es donde difieren Text Store y Tables — Text Store ejecuta búsqueda híbrida (vector + FTS), Tables ejecuta búsqueda vectorial pura.
Respuesta extremo a extremo incluye viaje de red, sobrecarga de gateway y búsqueda en base de datos. La diferencia entre extremo a extremo y BD es la sobrecarga.
NDCG@10 es la métrica principal. Penaliza documentos relevantes que aparecen en posiciones bajas.
Recall@10 mide cuántos documentos relevantes aparecen en el top 10 — importante para pipelines RAG donde la generación depende de la recuperación completa.
MRR@10 mide cuán rápido aparece el primer resultado relevante — importante para búsquedas de cara al usuario.
Text Store vs Tables: Text Store agrega búsqueda híbrida (vector + palabra clave) automáticamente. Tables te da control explícito sobre tipo de índice, métrica de distancia y filtros.
Una consulta de recuperación tiene tres componentes de latencia:
Inferencia de incrustación — el tiempo para convertir el texto de la consulta en un vector. Es inferencia de modelo y es igual sin importar el backend de almacenamiento.
Búsqueda en base de datos — el tiempo que el motor de búsqueda dedica a encontrar los vecinos más cercanos. Reportado por el servidor en search_time_ms (Text Store) o searchTimeMs (Tables). Es tiempo puro de búsqueda vectorial/híbrida sin sobrecarga de red.
Respuesta extremo a extremo — lo que observa el cliente: viaje de red + enrutamiento de gateway + búsqueda en base de datos.
Si la latencia extremo a extremo es alta pero la búsqueda en base de datos es rápida, el cuello de botella es la red o el gateway.
Si la búsqueda en base de datos es alta, considera un tipo de índice diferente (por ejemplo, IVF_HNSW_SQ para búsqueda aproximada más rápida).